AIClient-2-API/src/openai/openai-responses-core.mjs
hex2077 dfe7ce914e feat(api): 添加 OpenAI Responses API 支持
新增对 OpenAI Responses API 端点的部分支持,包括请求转换、流式响应处理和供应商适配。主要变更:

- 新增 OpenAIResponsesApiService 核心服务实现
- 实现 Claude/Gemini 到 Responses API 的双向协议转换(能聊天,不能调用工具)
- 添加流式响应状态管理和事件生成机制
- 扩展路由支持 /v1/responses 端点
- 更新文档说明配置方法和使用示例
2025-10-16 23:26:36 +08:00

329 lines
No EOL
7.6 KiB
JavaScript

import { v4 as uuidv4 } from 'uuid';
// 流式处理状态管理
class StreamState {
constructor() {
this.states = new Map(); // 使用Map存储不同请求的状态
}
// 获取或创建状态
getOrCreateState(requestId) {
if (!this.states.has(requestId)) {
this.states.set(requestId, {
id: `resp_${uuidv4().replace(/-/g, '')}`,
msgId: `msg_${uuidv4().replace(/-/g, '')}`,
fullText: '',
sequenceNumber: 0,
model: null,
status: 'in_progress',
startTime: Math.floor(Date.now() / 1000)
});
}
return this.states.get(requestId);
}
// 更新文本内容
updateText(requestId, textDelta) {
const state = this.getOrCreateState(requestId);
state.fullText += textDelta;
state.sequenceNumber += 1;
return state;
}
// 设置模型信息
setModel(requestId, model) {
const state = this.getOrCreateState(requestId);
state.model = model;
return state;
}
// 完成请求
completeRequest(requestId) {
const state = this.getOrCreateState(requestId);
state.status = 'completed';
return state;
}
// 清理状态
cleanup(requestId) {
this.states.delete(requestId);
}
}
// 创建全局流式状态管理器
const streamStateManager = new StreamState();
/**
* Generates a response.created event
*/
function generateResponseCreated(requestId, model) {
const state = streamStateManager.getOrCreateState(requestId);
if (model) {
state.model = model;
}
return {
type: 'response.created',
response: {
id: state.id,
object: 'response',
created_at: state.startTime,
status: 'in_progress',
error: null,
incomplete_details: null,
instructions: '',
max_output_tokens: null,
model: state.model || 'gpt-4.1-2025-04-14',
output: [],
parallel_tool_calls: true,
previous_response_id: null,
reasoning: { },
store: false,
temperature: 1,
text: { format: { type: "text" }},
tool_choice: "auto",
tools: [],
top_logprobs: 0,
top_p: 1,
truncation: "disabled",
usage: null,
user: null,
metadata: {}
}
};
}
/**
* Generates a response.in_progress event
*/
function generateResponseInProgress(requestId) {
const state = streamStateManager.getOrCreateState(requestId);
return {
type: 'response.in_progress',
response: {
id: state.id,
object: 'response',
created_at: state.startTime,
status: 'in_progress',
error: null,
incomplete_details: null,
instructions: '',
max_output_tokens: null,
model: state.model || 'gpt-4.1-2025-04-14',
output: [],
parallel_tool_calls: true,
previous_response_id: null,
reasoning: { },
service_tier: "auto",
store: false,
temperature: 1,
text: { format: { type: "text" }},
tool_choice: "auto",
tools: [],
top_logprobs: 0,
top_p: 1,
truncation: "disabled",
usage: null,
user: null,
metadata: {}
}
};
}
/**
* Generates a response.output_item.added event
*/
function generateOutputItemAdded(requestId) {
const state = streamStateManager.getOrCreateState(requestId);
return {
type: 'response.output_item.added',
output_index: 0,
item: {
id: state.msgId,
summary: [],
type: 'message',
role: 'assistant',
status: 'in_progress',
content: []
}
};
}
/**
* Generates a response.content_part.added event
*/
function generateContentPartAdded(requestId) {
const state = streamStateManager.getOrCreateState(requestId);
return {
type: 'response.content_part.added',
item_id: state.msgId,
output_index: 0,
content_index: 0,
part: {
type: 'output_text',
text: '',
annotations: [],
logprobs: []
}
};
}
/**
* Generates a response.output_text.delta event
*/
function generateOutputTextDelta(requestId, delta) {
const state = streamStateManager.getOrCreateState(requestId);
state.fullText += delta;
return {
type: 'response.output_text.delta',
item_id: state.msgId,
output_index: 0,
content_index: 0,
delta: delta,
logprobs: [],
obfuscation: null
};
}
/**
* Generates a response.output_text.done event
*/
function generateOutputTextDone(requestId) {
const state = streamStateManager.getOrCreateState(requestId);
return {
type: 'response.output_text.done',
item_id: state.msgId,
output_index: 0,
content_index: 0,
text: state.fullText,
logprobs: []
};
}
/**
* Generates a response.content_part.done event
*/
function generateContentPartDone(requestId) {
const state = streamStateManager.getOrCreateState(requestId);
return {
type: 'response.content_part.done',
item_id: state.msgId,
output_index: 0,
content_index: 0,
part: {
type: 'output_text',
text: state.fullText,
annotations: [],
logprobs: []
}
};
}
/**
* Generates a response.output_item.done event
*/
function generateOutputItemDone(requestId) {
const state = streamStateManager.getOrCreateState(requestId);
return {
type: 'response.output_item.done',
output_index: 0,
item: {
id: state.msgId,
summary: [],
type: 'message',
role: 'assistant',
status: 'completed',
content: [
{
type: 'output_text',
text: state.fullText,
annotations: [],
logprobs: []
}
]
}
};
}
/**
* Generates a response.completed event
*/
function generateResponseCompleted(requestId, usage) {
const state = streamStateManager.getOrCreateState(requestId);
return {
type: 'response.completed',
response: {
background: false,
created_at: state.startTime,
error: null,
id: state.id,
incomplete_details: null,
max_output_tokens: null,
max_tool_calls: null,
metadata: {},
model: state.model || 'gpt-4.1-2025-04-14',
object: 'response',
output: [
{
id: state.msgId,
summary: [],
type: 'message',
role: 'assistant',
status: 'completed',
content: [
{
type: 'output_text',
text: state.fullText,
annotations: [],
logprobs: []
}
]
}
],
parallel_tool_calls: true,
previous_response_id: null,
prompt_cache_key: null,
reasoning: {
},
safety_identifier: `user-${uuidv4().replace(/-/g, '')}`, // 随机值
service_tier: "default",
status: "completed",
store: false,
temperature: 1,
text: {
format: { type: "text" }
},
tool_choice: "auto",
tools: [],
top_logprobs: 0,
top_p: 1,
truncation: "disabled",
usage: usage || {
input_tokens: Math.floor(Math.random() * 100) + 20, // 随机值
input_tokens_details: {
cached_tokens: Math.floor(Math.random() * 50) // 随机值
},
output_tokens: state.fullText.split('').length,
output_tokens_details: {
reasoning_tokens: 0
},
total_tokens: Math.floor(Math.random() * 100) + 20 + state.fullText.split('').length // 随机值+文本长度
},
user: null
}
};
}
// 导出流式状态管理器以供外部使用
export { streamStateManager, generateResponseCreated, generateResponseInProgress,
generateOutputItemAdded, generateContentPartAdded, generateOutputTextDelta,
generateOutputTextDone, generateContentPartDone, generateOutputItemDone,
generateResponseCompleted };