@nextclaw/nextclaw-ncp-runtime-codex-sdk 0.1.54 → 0.1.55-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/index.d.ts +4 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +14 -5
  4. package/dist/index.js.map +1 -1
  5. package/dist/services/codex-app-server-client.service.js +242 -0
  6. package/dist/services/codex-app-server-client.service.js.map +1 -0
  7. package/dist/services/codex-app-server-ncp-agent-runtime.service.d.ts +30 -0
  8. package/dist/services/codex-app-server-ncp-agent-runtime.service.d.ts.map +1 -0
  9. package/dist/services/codex-app-server-ncp-agent-runtime.service.js +389 -0
  10. package/dist/services/codex-app-server-ncp-agent-runtime.service.js.map +1 -0
  11. package/dist/types/codex-app-server-runtime.types.d.ts +24 -0
  12. package/dist/types/codex-app-server-runtime.types.d.ts.map +1 -0
  13. package/dist/utils/codex-app-server-item-mapper.utils.js +67 -0
  14. package/dist/utils/codex-app-server-item-mapper.utils.js.map +1 -0
  15. package/dist/utils/codex-app-server-request.utils.js +49 -0
  16. package/dist/utils/codex-app-server-request.utils.js.map +1 -0
  17. package/dist/{codex-openai-responses-bridge-assistant-output.utils.js → utils/codex-openai-responses-bridge-assistant-output.utils.js} +2 -2
  18. package/dist/utils/codex-openai-responses-bridge-assistant-output.utils.js.map +1 -0
  19. package/dist/utils/codex-openai-responses-bridge-request.utils.js.map +1 -1
  20. package/dist/utils/codex-openai-responses-bridge-stream.utils.js +1 -1
  21. package/dist/utils/codex-openai-responses-bridge-stream.utils.js.map +1 -1
  22. package/dist/utils/codex-openai-responses-bridge.utils.js.map +1 -1
  23. package/dist/utils/codex-openai-responses-stream-writer.utils.d.ts.map +1 -1
  24. package/dist/utils/codex-openai-responses-stream-writer.utils.js +2 -9
  25. package/dist/utils/codex-openai-responses-stream-writer.utils.js.map +1 -1
  26. package/dist/utils/codex-openai-sse-chunks.utils.js.map +1 -1
  27. package/package.json +4 -3
  28. package/dist/codex-openai-responses-bridge-assistant-output.utils.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"codex-openai-responses-bridge-request.utils.js","names":[],"sources":["../../src/utils/codex-openai-responses-bridge-request.utils.ts"],"sourcesContent":["import {\n readArray,\n readBoolean,\n readNumber,\n readRecord,\n readString,\n withTrailingSlash,\n type CodexOpenAiResponsesBridgeConfig,\n type OpenAiChatCompletionResponse,\n type OpenResponsesItemRecord,\n} from \"../codex-openai-responses-bridge-shared.utils.js\";\nimport {\n buildChatContent,\n mergeChatContent,\n normalizeToolOutput,\n readAssistantMessageText,\n type OpenAiChatContent,\n} from \"../codex-openai-responses-bridge-message-content.utils.js\";\nfunction stripModelPrefix(model: string, prefixes: string[]): string {\n const normalizedModel = model.trim();\n for (const prefix of prefixes) {\n const normalizedPrefix = prefix.trim().toLowerCase();\n if (!normalizedPrefix) {\n continue;\n }\n const candidatePrefix = `${normalizedPrefix}/`;\n if (normalizedModel.toLowerCase().startsWith(candidatePrefix)) {\n return normalizedModel.slice(candidatePrefix.length);\n }\n }\n return normalizedModel;\n}\nfunction resolveUpstreamModel(\n requestedModel: unknown,\n config: CodexOpenAiResponsesBridgeConfig,\n): string {\n const prefixes = (config.modelPrefixes ?? []).filter((value) => value.trim().length > 0);\n const model =\n stripModelPrefix(readString(requestedModel) ?? \"\", prefixes) ||\n stripModelPrefix(config.defaultModel ?? \"\", prefixes);\n if (!model) {\n throw new Error(\"Codex bridge could not resolve an upstream model.\");\n }\n return model;\n}\nfunction buildOpenAiMessages(input: unknown, instructions: unknown): Array<Record<string, unknown>> {\n return new OpenAiMessagesBuilder(input, instructions).build();\n}\n\nclass OpenAiMessagesBuilder {\n private readonly messages: Array<Record<string, unknown>> = [];\n private readonly assistantTextParts: string[] = [];\n private readonly assistantToolCalls: Array<Record<string, unknown>> = [];\n private assistantReasoningContent = { present: false, value: \"\" };\n private systemContent: OpenAiChatContent;\n\n constructor(\n private readonly input: unknown,\n instructions: unknown,\n ) {\n this.systemContent = readString(instructions) ?? null;\n }\n\n build = (): Array<Record<string, unknown>> => {\n if (typeof this.input === \"string\") {\n this.messages.push({\n role: \"user\",\n content: this.input,\n });\n return this.withSystemMessage();\n }\n\n for (const rawItem of readArray(this.input)) {\n const item = readRecord(rawItem) as OpenResponsesItemRecord | undefined;\n if (!item) {\n continue;\n }\n this.appendItem(item);\n }\n\n this.flushAssistant();\n return this.withSystemMessage();\n };\n\n private appendItem = (item: OpenResponsesItemRecord): void => {\n const type = readString(item.type);\n if (type === \"message\") {\n this.appendMessageInputItem(item);\n } else if (type === \"reasoning\") {\n this.appendReasoningItem(item);\n } else if (type === \"function_call\") {\n this.appendFunctionCallItem(item);\n } else if (type === \"function_call_output\") {\n this.appendFunctionCallOutputItem(item);\n }\n };\n\n private appendMessageInputItem = (item: OpenResponsesItemRecord): void => {\n const role = readString(item.role);\n const content = buildChatContent(item.content);\n if (role === \"assistant\") {\n const text = readAssistantMessageText(content);\n if (text.trim()) {\n this.assistantTextParts.push(text);\n }\n return;\n }\n\n this.flushAssistant();\n const normalizedRole = role === \"developer\" ? \"system\" : role;\n if (normalizedRole === \"system\") {\n this.systemContent = mergeChatContent(this.systemContent, content);\n } else if (normalizedRole === \"user\" && content !== null) {\n this.messages.push({\n role: \"user\",\n content,\n });\n }\n };\n\n private appendReasoningItem = (item: OpenResponsesItemRecord): void => {\n const content = readArray(item.content);\n const reasoningText = content\n .map((entry) => {\n const record = readRecord(entry);\n if (!record || readString(record.type) !== \"reasoning_text\") {\n return \"\";\n }\n return typeof record.text === \"string\" ? record.text : \"\";\n })\n .join(\"\");\n this.assistantReasoningContent = { present: true, value: reasoningText };\n };\n\n private appendFunctionCallItem = (item: OpenResponsesItemRecord): void => {\n const name = readString(item.name);\n const argumentsText = readString(item.arguments) ?? \"{}\";\n if (!name) {\n return;\n }\n const callId =\n readString(item.call_id) ??\n readString(item.id) ??\n `call_${this.assistantToolCalls.length}`;\n this.assistantToolCalls.push({\n id: callId,\n type: \"function\",\n function: {\n name,\n arguments: argumentsText,\n },\n });\n };\n\n private appendFunctionCallOutputItem = (item: OpenResponsesItemRecord): void => {\n this.flushAssistant();\n const callId = readString(item.call_id);\n if (!callId) {\n return;\n }\n this.messages.push({\n role: \"tool\",\n tool_call_id: callId,\n content: normalizeToolOutput(item.output),\n });\n };\n\n private flushAssistant = (): void => {\n if (\n this.assistantTextParts.length === 0 &&\n this.assistantToolCalls.length === 0 &&\n !this.assistantReasoningContent.present\n ) {\n return;\n }\n this.messages.push({\n role: \"assistant\",\n content: this.assistantTextParts.join(\"\\n\").trim() || null,\n ...(this.assistantReasoningContent.present\n ? {\n reasoning_content: this.assistantReasoningContent.value,\n }\n : {}),\n ...(this.assistantToolCalls.length > 0\n ? {\n tool_calls: structuredClone(this.assistantToolCalls),\n }\n : {}),\n });\n this.assistantTextParts.length = 0;\n this.assistantToolCalls.length = 0;\n this.assistantReasoningContent = { present: false, value: \"\" };\n };\n\n private withSystemMessage = (): Array<Record<string, unknown>> =>\n this.systemContent === null\n ? this.messages\n : [\n {\n role: \"system\",\n content: this.systemContent,\n },\n ...this.messages,\n ];\n}\n\nfunction toOpenAiTools(value: unknown): Array<Record<string, unknown>> | undefined {\n const tools: Array<Record<string, unknown>> = [];\n for (const entry of readArray(value)) {\n const tool = readRecord(entry);\n const type = readString(tool?.type);\n const fn = readRecord(tool?.function);\n const name = readString(fn?.name) ?? readString(tool?.name);\n if (type !== \"function\" || !name) {\n continue;\n }\n const description =\n (fn ? readString(fn.description) : undefined) ?? readString(tool?.description);\n const parameters =\n (fn ? readRecord(fn.parameters) : undefined) ?? readRecord(tool?.parameters);\n const strict =\n (fn ? readBoolean(fn.strict) : undefined) ?? readBoolean(tool?.strict);\n tools.push({\n type: \"function\",\n function: {\n name,\n ...(description ? { description } : {}),\n parameters: parameters ?? {\n type: \"object\",\n properties: {},\n },\n ...(strict !== undefined ? { strict } : {}),\n },\n });\n }\n return tools.length > 0 ? tools : undefined;\n}\n\nfunction toOpenAiToolChoice(value: unknown): Record<string, unknown> | string | undefined {\n if (value === \"auto\" || value === \"none\" || value === \"required\") {\n return value;\n }\n const record = readRecord(value);\n const fn = readRecord(record?.function);\n const name = readString(fn?.name) ?? readString(record?.name);\n if (readString(record?.type) === \"function\" && name) {\n return {\n type: \"function\",\n function: {\n name,\n },\n };\n }\n return undefined;\n}\n\nexport async function callOpenAiCompatibleUpstream(params: {\n config: CodexOpenAiResponsesBridgeConfig;\n body: Record<string, unknown>;\n}): Promise<{\n model: string;\n response: OpenAiChatCompletionResponse;\n}> {\n const { model, request } = buildOpenAiCompatibleUpstreamRequest({\n config: params.config,\n body: params.body,\n stream: false,\n });\n const upstreamResponse = await fetch(request.url, request.init);\n const rawText = await upstreamResponse.text();\n let parsed: OpenAiChatCompletionResponse;\n try {\n parsed = JSON.parse(rawText) as OpenAiChatCompletionResponse;\n } catch {\n throw new Error(`Bridge upstream returned invalid JSON: ${rawText.slice(0, 240)}`);\n }\n\n if (!upstreamResponse.ok) {\n throw new Error(\n readString(parsed.error?.message) ??\n rawText.slice(0, 240) ??\n `HTTP ${upstreamResponse.status}`,\n );\n }\n\n return {\n model,\n response: parsed,\n };\n}\n\nexport function buildOpenAiCompatibleUpstreamRequest(params: {\n config: CodexOpenAiResponsesBridgeConfig;\n body: Record<string, unknown>;\n stream: boolean;\n}): {\n model: string;\n request: {\n url: string;\n init: RequestInit;\n };\n} {\n const { body, config, stream } = params;\n const model = resolveUpstreamModel(body.model, config);\n const upstreamUrl = new URL(\n \"chat/completions\",\n withTrailingSlash(config.upstreamApiBase),\n );\n const tools = toOpenAiTools(body.tools);\n const toolChoice = toOpenAiToolChoice(body.tool_choice);\n return {\n model,\n request: {\n url: upstreamUrl.toString(),\n init: {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(config.upstreamApiKey\n ? {\n Authorization: `Bearer ${config.upstreamApiKey}`,\n }\n : {}),\n ...(config.upstreamExtraHeaders ?? {}),\n },\n body: JSON.stringify({\n model,\n messages: buildOpenAiMessages(body.input, body.instructions),\n ...(tools ? { tools } : {}),\n ...(toolChoice ? { tool_choice: toolChoice } : {}),\n ...(config.upstreamReasoningSplit ? { reasoning_split: true } : {}),\n ...(stream ? { stream: true, stream_options: { include_usage: true } } : {}),\n ...(typeof body.max_output_tokens === \"number\"\n ? {\n max_tokens: Math.max(\n 1,\n Math.trunc(readNumber(body.max_output_tokens) ?? 1),\n ),\n }\n : {}),\n }),\n },\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"codex-openai-responses-bridge-request.utils.js","names":[],"sources":["../../src/utils/codex-openai-responses-bridge-request.utils.ts"],"sourcesContent":["import {\n readArray,\n readBoolean,\n readNumber,\n readRecord,\n readString,\n withTrailingSlash,\n type CodexOpenAiResponsesBridgeConfig,\n type OpenAiChatCompletionResponse,\n type OpenResponsesItemRecord,\n} from \"@/codex-openai-responses-bridge-shared.utils.js\";\nimport {\n buildChatContent,\n mergeChatContent,\n normalizeToolOutput,\n readAssistantMessageText,\n type OpenAiChatContent,\n} from \"@/codex-openai-responses-bridge-message-content.utils.js\";\nfunction stripModelPrefix(model: string, prefixes: string[]): string {\n const normalizedModel = model.trim();\n for (const prefix of prefixes) {\n const normalizedPrefix = prefix.trim().toLowerCase();\n if (!normalizedPrefix) {\n continue;\n }\n const candidatePrefix = `${normalizedPrefix}/`;\n if (normalizedModel.toLowerCase().startsWith(candidatePrefix)) {\n return normalizedModel.slice(candidatePrefix.length);\n }\n }\n return normalizedModel;\n}\nfunction resolveUpstreamModel(\n requestedModel: unknown,\n config: CodexOpenAiResponsesBridgeConfig,\n): string {\n const prefixes = (config.modelPrefixes ?? []).filter((value) => value.trim().length > 0);\n const model =\n stripModelPrefix(readString(requestedModel) ?? \"\", prefixes) ||\n stripModelPrefix(config.defaultModel ?? \"\", prefixes);\n if (!model) {\n throw new Error(\"Codex bridge could not resolve an upstream model.\");\n }\n return model;\n}\nfunction buildOpenAiMessages(input: unknown, instructions: unknown): Array<Record<string, unknown>> {\n return new OpenAiMessagesBuilder(input, instructions).build();\n}\n\nclass OpenAiMessagesBuilder {\n private readonly messages: Array<Record<string, unknown>> = [];\n private readonly assistantTextParts: string[] = [];\n private readonly assistantToolCalls: Array<Record<string, unknown>> = [];\n private assistantReasoningContent = { present: false, value: \"\" };\n private systemContent: OpenAiChatContent;\n\n constructor(\n private readonly input: unknown,\n instructions: unknown,\n ) {\n this.systemContent = readString(instructions) ?? null;\n }\n\n build = (): Array<Record<string, unknown>> => {\n if (typeof this.input === \"string\") {\n this.messages.push({\n role: \"user\",\n content: this.input,\n });\n return this.withSystemMessage();\n }\n\n for (const rawItem of readArray(this.input)) {\n const item = readRecord(rawItem) as OpenResponsesItemRecord | undefined;\n if (!item) {\n continue;\n }\n this.appendItem(item);\n }\n\n this.flushAssistant();\n return this.withSystemMessage();\n };\n\n private appendItem = (item: OpenResponsesItemRecord): void => {\n const type = readString(item.type);\n if (type === \"message\") {\n this.appendMessageInputItem(item);\n } else if (type === \"reasoning\") {\n this.appendReasoningItem(item);\n } else if (type === \"function_call\") {\n this.appendFunctionCallItem(item);\n } else if (type === \"function_call_output\") {\n this.appendFunctionCallOutputItem(item);\n }\n };\n\n private appendMessageInputItem = (item: OpenResponsesItemRecord): void => {\n const role = readString(item.role);\n const content = buildChatContent(item.content);\n if (role === \"assistant\") {\n const text = readAssistantMessageText(content);\n if (text.trim()) {\n this.assistantTextParts.push(text);\n }\n return;\n }\n\n this.flushAssistant();\n const normalizedRole = role === \"developer\" ? \"system\" : role;\n if (normalizedRole === \"system\") {\n this.systemContent = mergeChatContent(this.systemContent, content);\n } else if (normalizedRole === \"user\" && content !== null) {\n this.messages.push({\n role: \"user\",\n content,\n });\n }\n };\n\n private appendReasoningItem = (item: OpenResponsesItemRecord): void => {\n const content = readArray(item.content);\n const reasoningText = content\n .map((entry) => {\n const record = readRecord(entry);\n if (!record || readString(record.type) !== \"reasoning_text\") {\n return \"\";\n }\n return typeof record.text === \"string\" ? record.text : \"\";\n })\n .join(\"\");\n this.assistantReasoningContent = { present: true, value: reasoningText };\n };\n\n private appendFunctionCallItem = (item: OpenResponsesItemRecord): void => {\n const name = readString(item.name);\n const argumentsText = readString(item.arguments) ?? \"{}\";\n if (!name) {\n return;\n }\n const callId =\n readString(item.call_id) ??\n readString(item.id) ??\n `call_${this.assistantToolCalls.length}`;\n this.assistantToolCalls.push({\n id: callId,\n type: \"function\",\n function: {\n name,\n arguments: argumentsText,\n },\n });\n };\n\n private appendFunctionCallOutputItem = (item: OpenResponsesItemRecord): void => {\n this.flushAssistant();\n const callId = readString(item.call_id);\n if (!callId) {\n return;\n }\n this.messages.push({\n role: \"tool\",\n tool_call_id: callId,\n content: normalizeToolOutput(item.output),\n });\n };\n\n private flushAssistant = (): void => {\n if (\n this.assistantTextParts.length === 0 &&\n this.assistantToolCalls.length === 0 &&\n !this.assistantReasoningContent.present\n ) {\n return;\n }\n this.messages.push({\n role: \"assistant\",\n content: this.assistantTextParts.join(\"\\n\").trim() || null,\n ...(this.assistantReasoningContent.present\n ? {\n reasoning_content: this.assistantReasoningContent.value,\n }\n : {}),\n ...(this.assistantToolCalls.length > 0\n ? {\n tool_calls: structuredClone(this.assistantToolCalls),\n }\n : {}),\n });\n this.assistantTextParts.length = 0;\n this.assistantToolCalls.length = 0;\n this.assistantReasoningContent = { present: false, value: \"\" };\n };\n\n private withSystemMessage = (): Array<Record<string, unknown>> =>\n this.systemContent === null\n ? this.messages\n : [\n {\n role: \"system\",\n content: this.systemContent,\n },\n ...this.messages,\n ];\n}\n\nfunction toOpenAiTools(value: unknown): Array<Record<string, unknown>> | undefined {\n const tools: Array<Record<string, unknown>> = [];\n for (const entry of readArray(value)) {\n const tool = readRecord(entry);\n const type = readString(tool?.type);\n const fn = readRecord(tool?.function);\n const name = readString(fn?.name) ?? readString(tool?.name);\n if (type !== \"function\" || !name) {\n continue;\n }\n const description =\n (fn ? readString(fn.description) : undefined) ?? readString(tool?.description);\n const parameters =\n (fn ? readRecord(fn.parameters) : undefined) ?? readRecord(tool?.parameters);\n const strict =\n (fn ? readBoolean(fn.strict) : undefined) ?? readBoolean(tool?.strict);\n tools.push({\n type: \"function\",\n function: {\n name,\n ...(description ? { description } : {}),\n parameters: parameters ?? {\n type: \"object\",\n properties: {},\n },\n ...(strict !== undefined ? { strict } : {}),\n },\n });\n }\n return tools.length > 0 ? tools : undefined;\n}\n\nfunction toOpenAiToolChoice(value: unknown): Record<string, unknown> | string | undefined {\n if (value === \"auto\" || value === \"none\" || value === \"required\") {\n return value;\n }\n const record = readRecord(value);\n const fn = readRecord(record?.function);\n const name = readString(fn?.name) ?? readString(record?.name);\n if (readString(record?.type) === \"function\" && name) {\n return {\n type: \"function\",\n function: {\n name,\n },\n };\n }\n return undefined;\n}\n\nexport async function callOpenAiCompatibleUpstream(params: {\n config: CodexOpenAiResponsesBridgeConfig;\n body: Record<string, unknown>;\n}): Promise<{\n model: string;\n response: OpenAiChatCompletionResponse;\n}> {\n const { model, request } = buildOpenAiCompatibleUpstreamRequest({\n config: params.config,\n body: params.body,\n stream: false,\n });\n const upstreamResponse = await fetch(request.url, request.init);\n const rawText = await upstreamResponse.text();\n let parsed: OpenAiChatCompletionResponse;\n try {\n parsed = JSON.parse(rawText) as OpenAiChatCompletionResponse;\n } catch {\n throw new Error(`Bridge upstream returned invalid JSON: ${rawText.slice(0, 240)}`);\n }\n\n if (!upstreamResponse.ok) {\n throw new Error(\n readString(parsed.error?.message) ??\n rawText.slice(0, 240) ??\n `HTTP ${upstreamResponse.status}`,\n );\n }\n\n return {\n model,\n response: parsed,\n };\n}\n\nexport function buildOpenAiCompatibleUpstreamRequest(params: {\n config: CodexOpenAiResponsesBridgeConfig;\n body: Record<string, unknown>;\n stream: boolean;\n}): {\n model: string;\n request: {\n url: string;\n init: RequestInit;\n };\n} {\n const { body, config, stream } = params;\n const model = resolveUpstreamModel(body.model, config);\n const upstreamUrl = new URL(\n \"chat/completions\",\n withTrailingSlash(config.upstreamApiBase),\n );\n const tools = toOpenAiTools(body.tools);\n const toolChoice = toOpenAiToolChoice(body.tool_choice);\n return {\n model,\n request: {\n url: upstreamUrl.toString(),\n init: {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(config.upstreamApiKey\n ? {\n Authorization: `Bearer ${config.upstreamApiKey}`,\n }\n : {}),\n ...(config.upstreamExtraHeaders ?? {}),\n },\n body: JSON.stringify({\n model,\n messages: buildOpenAiMessages(body.input, body.instructions),\n ...(tools ? { tools } : {}),\n ...(toolChoice ? { tool_choice: toolChoice } : {}),\n ...(config.upstreamReasoningSplit ? { reasoning_split: true } : {}),\n ...(stream ? { stream: true, stream_options: { include_usage: true } } : {}),\n ...(typeof body.max_output_tokens === \"number\"\n ? {\n max_tokens: Math.max(\n 1,\n Math.trunc(readNumber(body.max_output_tokens) ?? 1),\n ),\n }\n : {}),\n }),\n },\n },\n };\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { readArray, readNumber, readRecord, readString, writeSseEvent } from "../codex-openai-responses-bridge-shared.utils.js";
2
- import { buildAssistantOutputItems } from "../codex-openai-responses-bridge-assistant-output.utils.js";
2
+ import { buildAssistantOutputItems } from "./codex-openai-responses-bridge-assistant-output.utils.js";
3
3
  //#region src/utils/codex-openai-responses-bridge-stream.utils.ts
4
4
  function buildOpenResponsesOutputItems(response, responseId) {
5
5
  const message = response.choices?.[0]?.message;
@@ -1 +1 @@
1
- {"version":3,"file":"codex-openai-responses-bridge-stream.utils.js","names":[],"sources":["../../src/utils/codex-openai-responses-bridge-stream.utils.ts"],"sourcesContent":["import type { ServerResponse } from \"node:http\";\nimport { buildAssistantOutputItems } from \"../codex-openai-responses-bridge-assistant-output.utils.js\";\nimport {\n readArray,\n readNumber,\n readRecord,\n readString,\n writeSseEvent,\n type OpenAiChatCompletionResponse,\n type OpenResponsesOutputItem,\n} from \"../codex-openai-responses-bridge-shared.utils.js\";\n\nfunction buildOpenResponsesOutputItems(\n response: OpenAiChatCompletionResponse,\n responseId: string,\n): OpenResponsesOutputItem[] {\n const message = response.choices?.[0]?.message;\n if (!message) {\n return [];\n }\n\n const outputItems = buildAssistantOutputItems({\n message,\n responseId,\n });\n\n const toolCalls = readArray(message.tool_calls);\n toolCalls.forEach((entry, index) => {\n const toolCall = readRecord(entry);\n const fn = readRecord(toolCall?.function);\n const name = readString(fn?.name);\n const argumentsText = readString(fn?.arguments) ?? \"{}\";\n if (!name) {\n return;\n }\n const callId =\n readString(toolCall?.id) ??\n `${responseId}:call:${index}`;\n outputItems.push({\n type: \"function_call\",\n id: `${responseId}:function:${index}`,\n call_id: callId,\n name,\n arguments: argumentsText,\n status: \"completed\",\n });\n });\n\n return outputItems;\n}\n\nfunction normalizeUsageValue(value: unknown): number | Record<string, unknown> | null {\n const numericValue = readNumber(value);\n if (numericValue !== undefined) {\n return Math.max(0, Math.trunc(numericValue));\n }\n const record = readRecord(value);\n if (!record) {\n return null;\n }\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n const normalizedEntry = normalizeUsageValue(entry);\n if (normalizedEntry !== null) {\n next[key] = normalizedEntry;\n }\n }\n return Object.keys(next).length > 0 ? next : null;\n}\n\nfunction normalizeUsageRecord(rawUsage: unknown): Record<string, unknown> {\n const usage = readRecord(rawUsage);\n if (!usage) {\n return {};\n }\n const next: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(usage)) {\n const normalizedValue = normalizeUsageValue(value);\n if (normalizedValue === null) {\n continue;\n }\n if (key === \"prompt_tokens\") {\n next.input_tokens = normalizedValue;\n continue;\n }\n if (key === \"completion_tokens\") {\n next.output_tokens = normalizedValue;\n continue;\n }\n if (key === \"prompt_tokens_details\") {\n next.input_tokens_details = normalizedValue;\n continue;\n }\n if (key === \"completion_tokens_details\") {\n next.output_tokens_details = normalizedValue;\n continue;\n }\n next[key] = normalizedValue;\n }\n return next;\n}\n\nexport function buildUsage(response: OpenAiChatCompletionResponse): Record<string, unknown> {\n const promptTokens = Math.max(0, Math.trunc(readNumber(response.usage?.prompt_tokens) ?? 0));\n const completionTokens = Math.max(\n 0,\n Math.trunc(readNumber(response.usage?.completion_tokens) ?? 0),\n );\n const totalTokens = Math.max(\n 0,\n Math.trunc(readNumber(response.usage?.total_tokens) ?? promptTokens + completionTokens),\n );\n return {\n ...normalizeUsageRecord(response.usage),\n input_tokens: promptTokens,\n output_tokens: completionTokens,\n total_tokens: totalTokens,\n };\n}\n\nexport function buildResponseResource(params: {\n responseId: string;\n model: string;\n outputItems: OpenResponsesOutputItem[];\n usage: Record<string, unknown>;\n status?: \"in_progress\" | \"completed\";\n}): Record<string, unknown> {\n const { model, outputItems, responseId, status, usage } = params;\n return {\n id: responseId,\n object: \"response\",\n created_at: Math.floor(Date.now() / 1000),\n status: status ?? \"completed\",\n model,\n output: outputItems,\n usage,\n error: null,\n };\n}\n\nexport function writeStreamError(response: ServerResponse, message: string): void {\n new StreamErrorWriter(response, message).write();\n}\n\nclass StreamErrorWriter {\n constructor(\n private readonly response: ServerResponse,\n private readonly message: string,\n ) {}\n\n write = (): void => {\n this.response.statusCode = 200;\n this.response.setHeader(\"content-type\", \"text/event-stream; charset=utf-8\");\n this.response.setHeader(\"cache-control\", \"no-cache, no-transform\");\n this.response.setHeader(\"connection\", \"keep-alive\");\n writeSseEvent(this.response, \"error\", {\n type: \"error\",\n error: {\n code: \"invalid_request_error\",\n message: this.message,\n },\n });\n this.response.end();\n };\n}\n\nexport function buildBridgeResponsePayload(params: {\n responseId: string;\n model: string;\n response: OpenAiChatCompletionResponse;\n}): {\n outputItems: OpenResponsesOutputItem[];\n usage: Record<string, unknown>;\n responseResource: Record<string, unknown>;\n} {\n const { model, response, responseId } = params;\n const outputItems = buildOpenResponsesOutputItems(response, responseId);\n const usage = buildUsage(response);\n return {\n outputItems,\n usage,\n responseResource: buildResponseResource({\n responseId,\n model,\n outputItems,\n usage,\n }),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"codex-openai-responses-bridge-stream.utils.js","names":[],"sources":["../../src/utils/codex-openai-responses-bridge-stream.utils.ts"],"sourcesContent":["import type { ServerResponse } from \"node:http\";\nimport { buildAssistantOutputItems } from \"./codex-openai-responses-bridge-assistant-output.utils.js\";\nimport {\n readArray,\n readNumber,\n readRecord,\n readString,\n writeSseEvent,\n type OpenAiChatCompletionResponse,\n type OpenResponsesOutputItem,\n} from \"@/codex-openai-responses-bridge-shared.utils.js\";\n\nfunction buildOpenResponsesOutputItems(\n response: OpenAiChatCompletionResponse,\n responseId: string,\n): OpenResponsesOutputItem[] {\n const message = response.choices?.[0]?.message;\n if (!message) {\n return [];\n }\n\n const outputItems = buildAssistantOutputItems({\n message,\n responseId,\n });\n\n const toolCalls = readArray(message.tool_calls);\n toolCalls.forEach((entry, index) => {\n const toolCall = readRecord(entry);\n const fn = readRecord(toolCall?.function);\n const name = readString(fn?.name);\n const argumentsText = readString(fn?.arguments) ?? \"{}\";\n if (!name) {\n return;\n }\n const callId =\n readString(toolCall?.id) ??\n `${responseId}:call:${index}`;\n outputItems.push({\n type: \"function_call\",\n id: `${responseId}:function:${index}`,\n call_id: callId,\n name,\n arguments: argumentsText,\n status: \"completed\",\n });\n });\n\n return outputItems;\n}\n\nfunction normalizeUsageValue(value: unknown): number | Record<string, unknown> | null {\n const numericValue = readNumber(value);\n if (numericValue !== undefined) {\n return Math.max(0, Math.trunc(numericValue));\n }\n const record = readRecord(value);\n if (!record) {\n return null;\n }\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n const normalizedEntry = normalizeUsageValue(entry);\n if (normalizedEntry !== null) {\n next[key] = normalizedEntry;\n }\n }\n return Object.keys(next).length > 0 ? next : null;\n}\n\nfunction normalizeUsageRecord(rawUsage: unknown): Record<string, unknown> {\n const usage = readRecord(rawUsage);\n if (!usage) {\n return {};\n }\n const next: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(usage)) {\n const normalizedValue = normalizeUsageValue(value);\n if (normalizedValue === null) {\n continue;\n }\n if (key === \"prompt_tokens\") {\n next.input_tokens = normalizedValue;\n continue;\n }\n if (key === \"completion_tokens\") {\n next.output_tokens = normalizedValue;\n continue;\n }\n if (key === \"prompt_tokens_details\") {\n next.input_tokens_details = normalizedValue;\n continue;\n }\n if (key === \"completion_tokens_details\") {\n next.output_tokens_details = normalizedValue;\n continue;\n }\n next[key] = normalizedValue;\n }\n return next;\n}\n\nexport function buildUsage(response: OpenAiChatCompletionResponse): Record<string, unknown> {\n const promptTokens = Math.max(0, Math.trunc(readNumber(response.usage?.prompt_tokens) ?? 0));\n const completionTokens = Math.max(\n 0,\n Math.trunc(readNumber(response.usage?.completion_tokens) ?? 0),\n );\n const totalTokens = Math.max(\n 0,\n Math.trunc(readNumber(response.usage?.total_tokens) ?? promptTokens + completionTokens),\n );\n return {\n ...normalizeUsageRecord(response.usage),\n input_tokens: promptTokens,\n output_tokens: completionTokens,\n total_tokens: totalTokens,\n };\n}\n\nexport function buildResponseResource(params: {\n responseId: string;\n model: string;\n outputItems: OpenResponsesOutputItem[];\n usage: Record<string, unknown>;\n status?: \"in_progress\" | \"completed\";\n}): Record<string, unknown> {\n const { model, outputItems, responseId, status, usage } = params;\n return {\n id: responseId,\n object: \"response\",\n created_at: Math.floor(Date.now() / 1000),\n status: status ?? \"completed\",\n model,\n output: outputItems,\n usage,\n error: null,\n };\n}\n\nexport function writeStreamError(response: ServerResponse, message: string): void {\n new StreamErrorWriter(response, message).write();\n}\n\nclass StreamErrorWriter {\n constructor(\n private readonly response: ServerResponse,\n private readonly message: string,\n ) {}\n\n write = (): void => {\n this.response.statusCode = 200;\n this.response.setHeader(\"content-type\", \"text/event-stream; charset=utf-8\");\n this.response.setHeader(\"cache-control\", \"no-cache, no-transform\");\n this.response.setHeader(\"connection\", \"keep-alive\");\n writeSseEvent(this.response, \"error\", {\n type: \"error\",\n error: {\n code: \"invalid_request_error\",\n message: this.message,\n },\n });\n this.response.end();\n };\n}\n\nexport function buildBridgeResponsePayload(params: {\n responseId: string;\n model: string;\n response: OpenAiChatCompletionResponse;\n}): {\n outputItems: OpenResponsesOutputItem[];\n usage: Record<string, unknown>;\n responseResource: Record<string, unknown>;\n} {\n const { model, response, responseId } = params;\n const outputItems = buildOpenResponsesOutputItems(response, responseId);\n const usage = buildUsage(response);\n return {\n outputItems,\n usage,\n responseResource: buildResponseResource({\n responseId,\n model,\n outputItems,\n usage,\n }),\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"codex-openai-responses-bridge.utils.js","names":[],"sources":["../../src/utils/codex-openai-responses-bridge.utils.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport {\n buildOpenAiCompatibleUpstreamRequest,\n callOpenAiCompatibleUpstream,\n} from \"./codex-openai-responses-bridge-request.utils.js\";\nimport {\n buildBridgeResponsePayload,\n writeStreamError,\n} from \"./codex-openai-responses-bridge-stream.utils.js\";\nimport { writeResponsesUpstreamStream } from \"./codex-openai-responses-stream-writer.utils.js\";\nimport {\n readBoolean,\n readRecord,\n type BridgeEntry,\n type CodexOpenAiResponsesBridgeConfig,\n type CodexOpenAiResponsesBridgeResult,\n} from \"../codex-openai-responses-bridge-shared.utils.js\";\nimport type { CodexOpenAiResponsesOutputObserver } from \"./codex-openai-responses-stream-writer.utils.js\";\n\nconst bridgeCache = new Map<string, BridgeEntry>();\n\nexport type CodexOpenAiResponsesBridgeRuntimeConfig = CodexOpenAiResponsesBridgeConfig & {\n outputObserver?: CodexOpenAiResponsesOutputObserver;\n};\n\nfunction toBridgeCacheKey(config: CodexOpenAiResponsesBridgeConfig): string {\n return JSON.stringify({\n upstreamApiBase: config.upstreamApiBase,\n upstreamApiKey: config.upstreamApiKey ?? \"\",\n upstreamExtraHeaders: config.upstreamExtraHeaders ?? {},\n defaultModel: config.defaultModel ?? \"\",\n modelPrefixes: (config.modelPrefixes ?? []).map((prefix) => prefix.trim().toLowerCase()),\n upstreamReasoningSplit: config.upstreamReasoningSplit === true,\n });\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<Record<string, unknown> | null> {\n const chunks: Buffer[] = [];\n for await (const chunk of request) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const rawText = Buffer.concat(chunks).toString(\"utf8\").trim();\n if (!rawText) {\n return {};\n }\n try {\n return readRecord(JSON.parse(rawText)) ?? null;\n } catch {\n return null;\n }\n}\n\nasync function handleResponsesRequest(\n request: IncomingMessage,\n response: ServerResponse,\n config: CodexOpenAiResponsesBridgeRuntimeConfig,\n): Promise<void> {\n await new CodexResponsesBridgeRequestHandler(request, response, config).handle();\n}\n\nclass JsonResponseWriter {\n constructor(private readonly response: ServerResponse) {}\n\n write = (statusCode: number, body: Record<string, unknown>): void => {\n this.response.statusCode = statusCode;\n this.response.setHeader(\"content-type\", \"application/json\");\n this.response.end(JSON.stringify(body));\n };\n}\n\nclass CodexResponsesBridgeRequestHandler {\n private readonly jsonWriter: JsonResponseWriter;\n\n constructor(\n private readonly request: IncomingMessage,\n private readonly response: ServerResponse,\n private readonly config: CodexOpenAiResponsesBridgeRuntimeConfig,\n ) {\n this.jsonWriter = new JsonResponseWriter(response);\n }\n\n handle = async (): Promise<void> => {\n const body = await readJsonBody(this.request);\n if (!body) {\n this.writeErrorJson(400, \"Invalid JSON payload.\");\n return;\n }\n\n try {\n if (readBoolean(body.stream) !== false) {\n await this.writeStreamingResponse(body);\n return;\n }\n await this.writeJsonResponse(body);\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Codex OpenAI bridge request failed.\";\n if (readBoolean(body.stream) !== false) {\n writeStreamError(this.response, message);\n return;\n }\n this.writeErrorJson(400, message);\n }\n };\n\n private writeStreamingResponse = async (body: Record<string, unknown>): Promise<void> => {\n const responseId = randomUUID();\n const upstream = buildOpenAiCompatibleUpstreamRequest({\n config: this.config,\n body,\n stream: true,\n });\n const upstreamResponse = await fetch(upstream.request.url, upstream.request.init);\n if (!upstreamResponse.ok) {\n throw new Error((await upstreamResponse.text()).slice(0, 240));\n }\n await writeResponsesUpstreamStream({\n response: this.response,\n responseId,\n model: upstream.model,\n outputObserver: this.config.outputObserver,\n upstreamResponse,\n });\n };\n\n private writeJsonResponse = async (body: Record<string, unknown>): Promise<void> => {\n const responseId = randomUUID();\n const upstream = await callOpenAiCompatibleUpstream({\n config: this.config,\n body,\n });\n const { responseResource } = buildBridgeResponsePayload({\n responseId,\n model: upstream.model,\n response: upstream.response,\n });\n\n this.jsonWriter.write(200, responseResource);\n };\n\n private writeErrorJson = (statusCode: number, message: string): void => {\n this.jsonWriter.write(statusCode, {\n error: {\n message,\n },\n });\n };\n}\n\nasync function createCodexOpenAiResponsesBridge(\n config: CodexOpenAiResponsesBridgeRuntimeConfig,\n): Promise<CodexOpenAiResponsesBridgeResult> {\n const server = createServer((request, response) => {\n const pathname = request.url\n ? new URL(request.url, \"http://127.0.0.1\").pathname\n : \"/\";\n if (\n request.method === \"POST\" &&\n (pathname === \"/responses\" || pathname === \"/v1/responses\")\n ) {\n void handleResponsesRequest(request, response, config);\n return;\n }\n\n new JsonResponseWriter(response).write(404, {\n error: {\n message: `Unsupported Codex bridge path: ${pathname}`,\n },\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => resolve());\n });\n\n const address = server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"Codex bridge failed to bind a loopback port.\");\n }\n\n return {\n baseUrl: `http://127.0.0.1:${address.port}`,\n };\n}\n\nexport async function ensureCodexOpenAiResponsesBridge(\n config: CodexOpenAiResponsesBridgeRuntimeConfig,\n): Promise<CodexOpenAiResponsesBridgeResult> {\n if (config.outputObserver) {\n return await createCodexOpenAiResponsesBridge(config);\n }\n\n const key = toBridgeCacheKey(config);\n const existing = bridgeCache.get(key);\n if (existing) {\n return await existing.promise;\n }\n\n const promise = createCodexOpenAiResponsesBridge(config);\n bridgeCache.set(key, { promise });\n try {\n return await promise;\n } catch (error) {\n bridgeCache.delete(key);\n throw error;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"codex-openai-responses-bridge.utils.js","names":[],"sources":["../../src/utils/codex-openai-responses-bridge.utils.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport {\n buildOpenAiCompatibleUpstreamRequest,\n callOpenAiCompatibleUpstream,\n} from \"./codex-openai-responses-bridge-request.utils.js\";\nimport {\n buildBridgeResponsePayload,\n writeStreamError,\n} from \"./codex-openai-responses-bridge-stream.utils.js\";\nimport { writeResponsesUpstreamStream } from \"./codex-openai-responses-stream-writer.utils.js\";\nimport {\n readBoolean,\n readRecord,\n type BridgeEntry,\n type CodexOpenAiResponsesBridgeConfig,\n type CodexOpenAiResponsesBridgeResult,\n} from \"@/codex-openai-responses-bridge-shared.utils.js\";\nimport type { CodexOpenAiResponsesOutputObserver } from \"./codex-openai-responses-stream-writer.utils.js\";\n\nconst bridgeCache = new Map<string, BridgeEntry>();\n\nexport type CodexOpenAiResponsesBridgeRuntimeConfig = CodexOpenAiResponsesBridgeConfig & {\n outputObserver?: CodexOpenAiResponsesOutputObserver;\n};\n\nfunction toBridgeCacheKey(config: CodexOpenAiResponsesBridgeConfig): string {\n return JSON.stringify({\n upstreamApiBase: config.upstreamApiBase,\n upstreamApiKey: config.upstreamApiKey ?? \"\",\n upstreamExtraHeaders: config.upstreamExtraHeaders ?? {},\n defaultModel: config.defaultModel ?? \"\",\n modelPrefixes: (config.modelPrefixes ?? []).map((prefix) => prefix.trim().toLowerCase()),\n upstreamReasoningSplit: config.upstreamReasoningSplit === true,\n });\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<Record<string, unknown> | null> {\n const chunks: Buffer[] = [];\n for await (const chunk of request) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const rawText = Buffer.concat(chunks).toString(\"utf8\").trim();\n if (!rawText) {\n return {};\n }\n try {\n return readRecord(JSON.parse(rawText)) ?? null;\n } catch {\n return null;\n }\n}\n\nasync function handleResponsesRequest(\n request: IncomingMessage,\n response: ServerResponse,\n config: CodexOpenAiResponsesBridgeRuntimeConfig,\n): Promise<void> {\n await new CodexResponsesBridgeRequestHandler(request, response, config).handle();\n}\n\nclass JsonResponseWriter {\n constructor(private readonly response: ServerResponse) {}\n\n write = (statusCode: number, body: Record<string, unknown>): void => {\n this.response.statusCode = statusCode;\n this.response.setHeader(\"content-type\", \"application/json\");\n this.response.end(JSON.stringify(body));\n };\n}\n\nclass CodexResponsesBridgeRequestHandler {\n private readonly jsonWriter: JsonResponseWriter;\n\n constructor(\n private readonly request: IncomingMessage,\n private readonly response: ServerResponse,\n private readonly config: CodexOpenAiResponsesBridgeRuntimeConfig,\n ) {\n this.jsonWriter = new JsonResponseWriter(response);\n }\n\n handle = async (): Promise<void> => {\n const body = await readJsonBody(this.request);\n if (!body) {\n this.writeErrorJson(400, \"Invalid JSON payload.\");\n return;\n }\n\n try {\n if (readBoolean(body.stream) !== false) {\n await this.writeStreamingResponse(body);\n return;\n }\n await this.writeJsonResponse(body);\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Codex OpenAI bridge request failed.\";\n if (readBoolean(body.stream) !== false) {\n writeStreamError(this.response, message);\n return;\n }\n this.writeErrorJson(400, message);\n }\n };\n\n private writeStreamingResponse = async (body: Record<string, unknown>): Promise<void> => {\n const responseId = randomUUID();\n const upstream = buildOpenAiCompatibleUpstreamRequest({\n config: this.config,\n body,\n stream: true,\n });\n const upstreamResponse = await fetch(upstream.request.url, upstream.request.init);\n if (!upstreamResponse.ok) {\n throw new Error((await upstreamResponse.text()).slice(0, 240));\n }\n await writeResponsesUpstreamStream({\n response: this.response,\n responseId,\n model: upstream.model,\n outputObserver: this.config.outputObserver,\n upstreamResponse,\n });\n };\n\n private writeJsonResponse = async (body: Record<string, unknown>): Promise<void> => {\n const responseId = randomUUID();\n const upstream = await callOpenAiCompatibleUpstream({\n config: this.config,\n body,\n });\n const { responseResource } = buildBridgeResponsePayload({\n responseId,\n model: upstream.model,\n response: upstream.response,\n });\n\n this.jsonWriter.write(200, responseResource);\n };\n\n private writeErrorJson = (statusCode: number, message: string): void => {\n this.jsonWriter.write(statusCode, {\n error: {\n message,\n },\n });\n };\n}\n\nasync function createCodexOpenAiResponsesBridge(\n config: CodexOpenAiResponsesBridgeRuntimeConfig,\n): Promise<CodexOpenAiResponsesBridgeResult> {\n const server = createServer((request, response) => {\n const pathname = request.url\n ? new URL(request.url, \"http://127.0.0.1\").pathname\n : \"/\";\n if (\n request.method === \"POST\" &&\n (pathname === \"/responses\" || pathname === \"/v1/responses\")\n ) {\n void handleResponsesRequest(request, response, config);\n return;\n }\n\n new JsonResponseWriter(response).write(404, {\n error: {\n message: `Unsupported Codex bridge path: ${pathname}`,\n },\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => resolve());\n });\n\n const address = server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"Codex bridge failed to bind a loopback port.\");\n }\n\n return {\n baseUrl: `http://127.0.0.1:${address.port}`,\n };\n}\n\nexport async function ensureCodexOpenAiResponsesBridge(\n config: CodexOpenAiResponsesBridgeRuntimeConfig,\n): Promise<CodexOpenAiResponsesBridgeResult> {\n if (config.outputObserver) {\n return await createCodexOpenAiResponsesBridge(config);\n }\n\n const key = toBridgeCacheKey(config);\n const existing = bridgeCache.get(key);\n if (existing) {\n return await existing.promise;\n }\n\n const promise = createCodexOpenAiResponsesBridge(config);\n bridgeCache.set(key, { promise });\n try {\n return await promise;\n } catch (error) {\n bridgeCache.delete(key);\n throw error;\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"codex-openai-responses-stream-writer.utils.d.ts","names":[],"sources":["../../src/utils/codex-openai-responses-stream-writer.utils.ts"],"mappings":";KA0CY,kCAAA;EACV,MAAA;EACA,gBAAA,GAAmB,KAAA;EACnB,eAAA;EACA,WAAA,GAAc,KAAA;EACd,UAAA;AAAA"}
1
+ {"version":3,"file":"codex-openai-responses-stream-writer.utils.d.ts","names":[],"sources":["../../src/utils/codex-openai-responses-stream-writer.utils.ts"],"mappings":";KA2CY,kCAAA;EACV,MAAA;EACA,gBAAA,GAAmB,KAAA;EACnB,eAAA;EACA,WAAA,GAAc,KAAA;EACd,UAAA;AAAA"}
@@ -1,4 +1,4 @@
1
- import { nextSequenceNumber, readArray, readNumber, readRecord, readString, writeSseEvent } from "../codex-openai-responses-bridge-shared.utils.js";
1
+ import { nextSequenceNumber, readArray, readNumber, readRawString, readRecord, readString, writeSseEvent } from "../codex-openai-responses-bridge-shared.utils.js";
2
2
  import { buildResponseResource, buildUsage } from "./codex-openai-responses-bridge-stream.utils.js";
3
3
  import { extractContentText, extractReasoningText, readOpenAiSseChunks } from "./codex-openai-sse-chunks.utils.js";
4
4
  //#region src/utils/codex-openai-responses-stream-writer.utils.ts
@@ -162,13 +162,6 @@ var CodexResponsesOpenAiStreamWriter = class {
162
162
  summary_index: 0,
163
163
  delta: reasoningDelta
164
164
  });
165
- this.writeEvent("response.reasoning_text.delta", {
166
- type: "response.reasoning_text.delta",
167
- output_index: state.outputIndex,
168
- item_id: state.itemId,
169
- content_index: 0,
170
- delta: reasoningDelta
171
- });
172
165
  };
173
166
  writeTextDelta = (textDelta) => {
174
167
  if (!textDelta) return;
@@ -188,7 +181,7 @@ var CodexResponsesOpenAiStreamWriter = class {
188
181
  const fn = readRecord(toolCall?.function);
189
182
  const state = this.ensureToolCallState(toolIndex, toolCall ?? {});
190
183
  state.name = readString(fn?.name) ?? state.name;
191
- const argumentsDelta = readString(fn?.arguments) ?? "";
184
+ const argumentsDelta = readRawString(fn?.arguments) ?? "";
192
185
  state.argumentsText += argumentsDelta;
193
186
  if (!argumentsDelta) return;
194
187
  this.writeEvent("response.function_call_arguments.delta", {
@@ -1 +1 @@
1
- {"version":3,"file":"codex-openai-responses-stream-writer.utils.js","names":[],"sources":["../../src/utils/codex-openai-responses-stream-writer.utils.ts"],"sourcesContent":["import type { ServerResponse } from \"node:http\";\nimport {\n buildResponseResource,\n buildUsage,\n} from \"./codex-openai-responses-bridge-stream.utils.js\";\nimport {\n nextSequenceNumber,\n readArray,\n readNumber,\n readRecord,\n readString,\n writeSseEvent,\n type OpenResponsesOutputItem,\n type StreamSequenceState,\n} from \"../codex-openai-responses-bridge-shared.utils.js\";\nimport {\n extractContentText,\n extractReasoningText,\n readOpenAiSseChunks,\n type OpenAiStreamChunk,\n} from \"./codex-openai-sse-chunks.utils.js\";\n\ntype TextStreamState = {\n outputIndex: number;\n itemId: string;\n text: string;\n};\n\ntype ReasoningStreamState = {\n outputIndex: number;\n itemId: string;\n text: string;\n};\n\ntype ToolCallStreamState = {\n outputIndex: number;\n itemId: string;\n callId: string;\n name: string;\n argumentsText: string;\n};\n\nexport type CodexOpenAiResponsesOutputObserver = {\n onDone: () => void;\n onReasoningDelta: (delta: string) => void;\n onReasoningDone: () => void;\n onTextDelta: (delta: string) => void;\n onTextDone: () => void;\n};\n\nexport async function writeResponsesUpstreamStream(params: {\n response: ServerResponse;\n responseId: string;\n model: string;\n outputObserver?: CodexOpenAiResponsesOutputObserver;\n upstreamResponse: Response;\n}): Promise<void> {\n await new CodexResponsesOpenAiStreamWriter(params).write();\n}\n\nclass CodexResponsesOpenAiStreamWriter {\n private readonly sequenceState: StreamSequenceState = { value: 0 };\n private readonly outputItems: OpenResponsesOutputItem[] = [];\n private readonly toolCalls = new Map<number, ToolCallStreamState>();\n private outputCount = 0;\n private textState: TextStreamState | null = null;\n private reasoningState: ReasoningStreamState | null = null;\n private usage: Record<string, unknown> = {};\n\n constructor(\n private readonly params: {\n response: ServerResponse;\n responseId: string;\n model: string;\n outputObserver?: CodexOpenAiResponsesOutputObserver;\n upstreamResponse: Response;\n },\n ) {}\n\n write = async (): Promise<void> => {\n this.writeHeaders();\n this.writeCreatedEvent();\n for await (const chunk of readOpenAiSseChunks(this.params.upstreamResponse)) {\n this.handleChunk(chunk);\n }\n this.finishReasoning();\n this.finishText();\n this.finishToolCalls();\n this.writeCompletedEvent();\n this.params.outputObserver?.onDone();\n this.params.response.end();\n };\n\n private nextOutputIndex = (): number => {\n const value = this.outputCount;\n this.outputCount += 1;\n return value;\n };\n\n private writeEvent = (eventType: string, payload: Record<string, unknown>): void => {\n writeSseEvent(this.params.response, eventType, {\n ...payload,\n sequence_number: nextSequenceNumber(this.sequenceState),\n });\n };\n\n private writeHeaders = (): void => {\n this.params.response.statusCode = 200;\n this.params.response.setHeader(\"content-type\", \"text/event-stream; charset=utf-8\");\n this.params.response.setHeader(\"cache-control\", \"no-cache, no-transform\");\n this.params.response.setHeader(\"connection\", \"keep-alive\");\n };\n\n private writeCreatedEvent = (): void => {\n this.writeEvent(\"response.created\", {\n type: \"response.created\",\n response: buildResponseResource({\n responseId: this.params.responseId,\n model: this.params.model,\n outputItems: [],\n usage: buildUsage({ usage: {} }),\n status: \"in_progress\",\n }),\n });\n };\n\n private ensureTextState = (): TextStreamState => {\n if (this.textState) {\n return this.textState;\n }\n this.textState = {\n outputIndex: this.nextOutputIndex(),\n itemId: `${this.params.responseId}:message:${this.outputCount}`,\n text: \"\",\n };\n this.writeEvent(\"response.output_item.added\", {\n type: \"response.output_item.added\",\n output_index: this.textState.outputIndex,\n item: {\n type: \"message\",\n id: this.textState.itemId,\n role: \"assistant\",\n status: \"in_progress\",\n content: [],\n },\n });\n this.writeEvent(\"response.content_part.added\", {\n type: \"response.content_part.added\",\n output_index: this.textState.outputIndex,\n item_id: this.textState.itemId,\n content_index: 0,\n part: { type: \"output_text\", text: \"\", annotations: [] },\n });\n return this.textState;\n };\n\n private ensureReasoningState = (): ReasoningStreamState => {\n if (this.reasoningState) {\n return this.reasoningState;\n }\n this.reasoningState = {\n outputIndex: this.nextOutputIndex(),\n itemId: `${this.params.responseId}:reasoning:${this.outputCount}`,\n text: \"\",\n };\n this.writeEvent(\"response.output_item.added\", {\n type: \"response.output_item.added\",\n output_index: this.reasoningState.outputIndex,\n item: {\n type: \"reasoning\",\n id: this.reasoningState.itemId,\n status: \"in_progress\",\n content: [],\n summary: [],\n },\n });\n this.writeEvent(\"response.reasoning_summary_part.added\", {\n type: \"response.reasoning_summary_part.added\",\n output_index: this.reasoningState.outputIndex,\n item_id: this.reasoningState.itemId,\n summary_index: 0,\n part: { type: \"summary_text\", text: \"\" },\n });\n return this.reasoningState;\n };\n\n private ensureToolCallState = (\n index: number,\n delta: Record<string, unknown>,\n ): ToolCallStreamState => {\n const existing = this.toolCalls.get(index);\n if (existing) {\n return existing;\n }\n const fn = readRecord(delta.function);\n const state = {\n outputIndex: this.nextOutputIndex(),\n itemId: `${this.params.responseId}:function:${this.outputCount}`,\n callId: readString(delta.id) ?? `${this.params.responseId}:call:${index}`,\n name: readString(fn?.name) ?? \"tool\",\n argumentsText: \"\",\n };\n this.toolCalls.set(index, state);\n this.writeEvent(\"response.output_item.added\", {\n type: \"response.output_item.added\",\n output_index: state.outputIndex,\n item: {\n type: \"function_call\",\n id: state.itemId,\n call_id: state.callId,\n name: state.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n return state;\n };\n\n private handleChunk = (chunk: OpenAiStreamChunk): void => {\n this.usage = chunk.usage ?? this.usage;\n const delta = chunk.choices?.[0]?.delta;\n this.writeReasoningDelta(extractReasoningText(delta));\n this.writeTextDelta(extractContentText(delta?.content));\n for (const rawToolCall of readArray(delta?.tool_calls)) {\n this.writeToolCallDelta(readRecord(rawToolCall));\n }\n };\n\n private writeReasoningDelta = (reasoningDelta: string): void => {\n if (!reasoningDelta) {\n return;\n }\n const state = this.ensureReasoningState();\n state.text += reasoningDelta;\n this.params.outputObserver?.onReasoningDelta(reasoningDelta);\n this.writeEvent(\"response.reasoning_summary_text.delta\", {\n type: \"response.reasoning_summary_text.delta\",\n output_index: state.outputIndex,\n item_id: state.itemId,\n summary_index: 0,\n delta: reasoningDelta,\n });\n this.writeEvent(\"response.reasoning_text.delta\", {\n type: \"response.reasoning_text.delta\",\n output_index: state.outputIndex,\n item_id: state.itemId,\n content_index: 0,\n delta: reasoningDelta,\n });\n };\n\n private writeTextDelta = (textDelta: string): void => {\n if (!textDelta) {\n return;\n }\n const state = this.ensureTextState();\n state.text += textDelta;\n this.params.outputObserver?.onTextDelta(textDelta);\n this.writeEvent(\"response.output_text.delta\", {\n type: \"response.output_text.delta\",\n output_index: state.outputIndex,\n item_id: state.itemId,\n content_index: 0,\n delta: textDelta,\n });\n };\n\n private writeToolCallDelta = (toolCall: Record<string, unknown> | undefined): void => {\n const toolIndex = Math.trunc(readNumber(toolCall?.index) ?? this.toolCalls.size);\n const fn = readRecord(toolCall?.function);\n const state = this.ensureToolCallState(toolIndex, toolCall ?? {});\n state.name = readString(fn?.name) ?? state.name;\n const argumentsDelta = readString(fn?.arguments) ?? \"\";\n state.argumentsText += argumentsDelta;\n if (!argumentsDelta) {\n return;\n }\n this.writeEvent(\"response.function_call_arguments.delta\", {\n type: \"response.function_call_arguments.delta\",\n output_index: state.outputIndex,\n item_id: state.itemId,\n delta: argumentsDelta,\n });\n };\n\n private finishReasoning = (): void => {\n if (!this.reasoningState) {\n return;\n }\n const item = {\n type: \"reasoning\",\n id: this.reasoningState.itemId,\n summary: [{ type: \"summary_text\", text: this.reasoningState.text }],\n content: [{ type: \"reasoning_text\", text: this.reasoningState.text }],\n status: \"completed\",\n };\n this.outputItems[this.reasoningState.outputIndex] = item;\n this.writeEvent(\"response.reasoning_summary_text.done\", {\n type: \"response.reasoning_summary_text.done\",\n output_index: this.reasoningState.outputIndex,\n item_id: this.reasoningState.itemId,\n summary_index: 0,\n text: this.reasoningState.text,\n });\n this.writeEvent(\"response.reasoning_summary_part.done\", {\n type: \"response.reasoning_summary_part.done\",\n output_index: this.reasoningState.outputIndex,\n item_id: this.reasoningState.itemId,\n summary_index: 0,\n part: { type: \"summary_text\", text: this.reasoningState.text },\n });\n this.writeEvent(\"response.reasoning_text.done\", {\n type: \"response.reasoning_text.done\",\n output_index: this.reasoningState.outputIndex,\n item_id: this.reasoningState.itemId,\n content_index: 0,\n text: this.reasoningState.text,\n });\n this.writeEvent(\"response.output_item.done\", {\n type: \"response.output_item.done\",\n output_index: this.reasoningState.outputIndex,\n item,\n });\n this.params.outputObserver?.onReasoningDone();\n };\n\n private finishText = (): void => {\n if (!this.textState) {\n return;\n }\n const item = {\n type: \"message\",\n id: this.textState.itemId,\n role: \"assistant\",\n status: \"completed\",\n content: [{ type: \"output_text\", text: this.textState.text, annotations: [] }],\n };\n this.outputItems[this.textState.outputIndex] = item;\n this.writeEvent(\"response.output_text.done\", {\n type: \"response.output_text.done\",\n output_index: this.textState.outputIndex,\n item_id: this.textState.itemId,\n content_index: 0,\n text: this.textState.text,\n });\n this.writeEvent(\"response.content_part.done\", {\n type: \"response.content_part.done\",\n output_index: this.textState.outputIndex,\n item_id: this.textState.itemId,\n content_index: 0,\n part: { type: \"output_text\", text: this.textState.text, annotations: [] },\n });\n this.writeEvent(\"response.output_item.done\", {\n type: \"response.output_item.done\",\n output_index: this.textState.outputIndex,\n item,\n });\n this.params.outputObserver?.onTextDone();\n };\n\n private finishToolCalls = (): void => {\n for (const state of [...this.toolCalls.values()].sort((a, b) => a.outputIndex - b.outputIndex)) {\n const item = {\n type: \"function_call\",\n id: state.itemId,\n call_id: state.callId,\n name: state.name,\n arguments: state.argumentsText,\n status: \"completed\",\n };\n this.outputItems[state.outputIndex] = item;\n this.writeEvent(\"response.function_call_arguments.done\", {\n type: \"response.function_call_arguments.done\",\n output_index: state.outputIndex,\n item_id: state.itemId,\n arguments: state.argumentsText,\n });\n this.writeEvent(\"response.output_item.done\", {\n type: \"response.output_item.done\",\n output_index: state.outputIndex,\n item,\n });\n }\n };\n\n private writeCompletedEvent = (): void => {\n this.writeEvent(\"response.completed\", {\n type: \"response.completed\",\n response: buildResponseResource({\n responseId: this.params.responseId,\n model: this.params.model,\n outputItems: this.outputItems.filter(Boolean),\n usage: buildUsage({ usage: this.usage }),\n }),\n });\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"codex-openai-responses-stream-writer.utils.js","names":[],"sources":["../../src/utils/codex-openai-responses-stream-writer.utils.ts"],"sourcesContent":["import type { ServerResponse } from \"node:http\";\nimport {\n buildResponseResource,\n buildUsage,\n} from \"./codex-openai-responses-bridge-stream.utils.js\";\nimport {\n nextSequenceNumber,\n readArray,\n readNumber,\n readRecord,\n readRawString,\n readString,\n writeSseEvent,\n type OpenResponsesOutputItem,\n type StreamSequenceState,\n} from \"@/codex-openai-responses-bridge-shared.utils.js\";\nimport {\n extractContentText,\n extractReasoningText,\n readOpenAiSseChunks,\n type OpenAiStreamChunk,\n} from \"./codex-openai-sse-chunks.utils.js\";\n\ntype TextStreamState = {\n outputIndex: number;\n itemId: string;\n text: string;\n};\n\ntype ReasoningStreamState = {\n outputIndex: number;\n itemId: string;\n text: string;\n};\n\ntype ToolCallStreamState = {\n outputIndex: number;\n itemId: string;\n callId: string;\n name: string;\n argumentsText: string;\n};\n\nexport type CodexOpenAiResponsesOutputObserver = {\n onDone: () => void;\n onReasoningDelta: (delta: string) => void;\n onReasoningDone: () => void;\n onTextDelta: (delta: string) => void;\n onTextDone: () => void;\n};\n\nexport async function writeResponsesUpstreamStream(params: {\n response: ServerResponse;\n responseId: string;\n model: string;\n outputObserver?: CodexOpenAiResponsesOutputObserver;\n upstreamResponse: Response;\n}): Promise<void> {\n await new CodexResponsesOpenAiStreamWriter(params).write();\n}\n\nclass CodexResponsesOpenAiStreamWriter {\n private readonly sequenceState: StreamSequenceState = { value: 0 };\n private readonly outputItems: OpenResponsesOutputItem[] = [];\n private readonly toolCalls = new Map<number, ToolCallStreamState>();\n private outputCount = 0;\n private textState: TextStreamState | null = null;\n private reasoningState: ReasoningStreamState | null = null;\n private usage: Record<string, unknown> = {};\n\n constructor(\n private readonly params: {\n response: ServerResponse;\n responseId: string;\n model: string;\n outputObserver?: CodexOpenAiResponsesOutputObserver;\n upstreamResponse: Response;\n },\n ) {}\n\n write = async (): Promise<void> => {\n this.writeHeaders();\n this.writeCreatedEvent();\n for await (const chunk of readOpenAiSseChunks(this.params.upstreamResponse)) {\n this.handleChunk(chunk);\n }\n this.finishReasoning();\n this.finishText();\n this.finishToolCalls();\n this.writeCompletedEvent();\n this.params.outputObserver?.onDone();\n this.params.response.end();\n };\n\n private nextOutputIndex = (): number => {\n const value = this.outputCount;\n this.outputCount += 1;\n return value;\n };\n\n private writeEvent = (eventType: string, payload: Record<string, unknown>): void => {\n writeSseEvent(this.params.response, eventType, {\n ...payload,\n sequence_number: nextSequenceNumber(this.sequenceState),\n });\n };\n\n private writeHeaders = (): void => {\n this.params.response.statusCode = 200;\n this.params.response.setHeader(\"content-type\", \"text/event-stream; charset=utf-8\");\n this.params.response.setHeader(\"cache-control\", \"no-cache, no-transform\");\n this.params.response.setHeader(\"connection\", \"keep-alive\");\n };\n\n private writeCreatedEvent = (): void => {\n this.writeEvent(\"response.created\", {\n type: \"response.created\",\n response: buildResponseResource({\n responseId: this.params.responseId,\n model: this.params.model,\n outputItems: [],\n usage: buildUsage({ usage: {} }),\n status: \"in_progress\",\n }),\n });\n };\n\n private ensureTextState = (): TextStreamState => {\n if (this.textState) {\n return this.textState;\n }\n this.textState = {\n outputIndex: this.nextOutputIndex(),\n itemId: `${this.params.responseId}:message:${this.outputCount}`,\n text: \"\",\n };\n this.writeEvent(\"response.output_item.added\", {\n type: \"response.output_item.added\",\n output_index: this.textState.outputIndex,\n item: {\n type: \"message\",\n id: this.textState.itemId,\n role: \"assistant\",\n status: \"in_progress\",\n content: [],\n },\n });\n this.writeEvent(\"response.content_part.added\", {\n type: \"response.content_part.added\",\n output_index: this.textState.outputIndex,\n item_id: this.textState.itemId,\n content_index: 0,\n part: { type: \"output_text\", text: \"\", annotations: [] },\n });\n return this.textState;\n };\n\n private ensureReasoningState = (): ReasoningStreamState => {\n if (this.reasoningState) {\n return this.reasoningState;\n }\n this.reasoningState = {\n outputIndex: this.nextOutputIndex(),\n itemId: `${this.params.responseId}:reasoning:${this.outputCount}`,\n text: \"\",\n };\n this.writeEvent(\"response.output_item.added\", {\n type: \"response.output_item.added\",\n output_index: this.reasoningState.outputIndex,\n item: {\n type: \"reasoning\",\n id: this.reasoningState.itemId,\n status: \"in_progress\",\n content: [],\n summary: [],\n },\n });\n this.writeEvent(\"response.reasoning_summary_part.added\", {\n type: \"response.reasoning_summary_part.added\",\n output_index: this.reasoningState.outputIndex,\n item_id: this.reasoningState.itemId,\n summary_index: 0,\n part: { type: \"summary_text\", text: \"\" },\n });\n return this.reasoningState;\n };\n\n private ensureToolCallState = (\n index: number,\n delta: Record<string, unknown>,\n ): ToolCallStreamState => {\n const existing = this.toolCalls.get(index);\n if (existing) {\n return existing;\n }\n const fn = readRecord(delta.function);\n const state = {\n outputIndex: this.nextOutputIndex(),\n itemId: `${this.params.responseId}:function:${this.outputCount}`,\n callId: readString(delta.id) ?? `${this.params.responseId}:call:${index}`,\n name: readString(fn?.name) ?? \"tool\",\n argumentsText: \"\",\n };\n this.toolCalls.set(index, state);\n this.writeEvent(\"response.output_item.added\", {\n type: \"response.output_item.added\",\n output_index: state.outputIndex,\n item: {\n type: \"function_call\",\n id: state.itemId,\n call_id: state.callId,\n name: state.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n return state;\n };\n\n private handleChunk = (chunk: OpenAiStreamChunk): void => {\n this.usage = chunk.usage ?? this.usage;\n const delta = chunk.choices?.[0]?.delta;\n this.writeReasoningDelta(extractReasoningText(delta));\n this.writeTextDelta(extractContentText(delta?.content));\n for (const rawToolCall of readArray(delta?.tool_calls)) {\n this.writeToolCallDelta(readRecord(rawToolCall));\n }\n };\n\n private writeReasoningDelta = (reasoningDelta: string): void => {\n if (!reasoningDelta) {\n return;\n }\n const state = this.ensureReasoningState();\n state.text += reasoningDelta;\n this.params.outputObserver?.onReasoningDelta(reasoningDelta);\n this.writeEvent(\"response.reasoning_summary_text.delta\", {\n type: \"response.reasoning_summary_text.delta\",\n output_index: state.outputIndex,\n item_id: state.itemId,\n summary_index: 0,\n delta: reasoningDelta,\n });\n };\n\n private writeTextDelta = (textDelta: string): void => {\n if (!textDelta) {\n return;\n }\n const state = this.ensureTextState();\n state.text += textDelta;\n this.params.outputObserver?.onTextDelta(textDelta);\n this.writeEvent(\"response.output_text.delta\", {\n type: \"response.output_text.delta\",\n output_index: state.outputIndex,\n item_id: state.itemId,\n content_index: 0,\n delta: textDelta,\n });\n };\n\n private writeToolCallDelta = (toolCall: Record<string, unknown> | undefined): void => {\n const toolIndex = Math.trunc(readNumber(toolCall?.index) ?? this.toolCalls.size);\n const fn = readRecord(toolCall?.function);\n const state = this.ensureToolCallState(toolIndex, toolCall ?? {});\n state.name = readString(fn?.name) ?? state.name;\n const argumentsDelta = readRawString(fn?.arguments) ?? \"\";\n state.argumentsText += argumentsDelta;\n if (!argumentsDelta) {\n return;\n }\n this.writeEvent(\"response.function_call_arguments.delta\", {\n type: \"response.function_call_arguments.delta\",\n output_index: state.outputIndex,\n item_id: state.itemId,\n delta: argumentsDelta,\n });\n };\n\n private finishReasoning = (): void => {\n if (!this.reasoningState) {\n return;\n }\n const item = {\n type: \"reasoning\",\n id: this.reasoningState.itemId,\n summary: [{ type: \"summary_text\", text: this.reasoningState.text }],\n content: [{ type: \"reasoning_text\", text: this.reasoningState.text }],\n status: \"completed\",\n };\n this.outputItems[this.reasoningState.outputIndex] = item;\n this.writeEvent(\"response.reasoning_summary_text.done\", {\n type: \"response.reasoning_summary_text.done\",\n output_index: this.reasoningState.outputIndex,\n item_id: this.reasoningState.itemId,\n summary_index: 0,\n text: this.reasoningState.text,\n });\n this.writeEvent(\"response.reasoning_summary_part.done\", {\n type: \"response.reasoning_summary_part.done\",\n output_index: this.reasoningState.outputIndex,\n item_id: this.reasoningState.itemId,\n summary_index: 0,\n part: { type: \"summary_text\", text: this.reasoningState.text },\n });\n this.writeEvent(\"response.reasoning_text.done\", {\n type: \"response.reasoning_text.done\",\n output_index: this.reasoningState.outputIndex,\n item_id: this.reasoningState.itemId,\n content_index: 0,\n text: this.reasoningState.text,\n });\n this.writeEvent(\"response.output_item.done\", {\n type: \"response.output_item.done\",\n output_index: this.reasoningState.outputIndex,\n item,\n });\n this.params.outputObserver?.onReasoningDone();\n };\n\n private finishText = (): void => {\n if (!this.textState) {\n return;\n }\n const item = {\n type: \"message\",\n id: this.textState.itemId,\n role: \"assistant\",\n status: \"completed\",\n content: [{ type: \"output_text\", text: this.textState.text, annotations: [] }],\n };\n this.outputItems[this.textState.outputIndex] = item;\n this.writeEvent(\"response.output_text.done\", {\n type: \"response.output_text.done\",\n output_index: this.textState.outputIndex,\n item_id: this.textState.itemId,\n content_index: 0,\n text: this.textState.text,\n });\n this.writeEvent(\"response.content_part.done\", {\n type: \"response.content_part.done\",\n output_index: this.textState.outputIndex,\n item_id: this.textState.itemId,\n content_index: 0,\n part: { type: \"output_text\", text: this.textState.text, annotations: [] },\n });\n this.writeEvent(\"response.output_item.done\", {\n type: \"response.output_item.done\",\n output_index: this.textState.outputIndex,\n item,\n });\n this.params.outputObserver?.onTextDone();\n };\n\n private finishToolCalls = (): void => {\n for (const state of [...this.toolCalls.values()].sort((a, b) => a.outputIndex - b.outputIndex)) {\n const item = {\n type: \"function_call\",\n id: state.itemId,\n call_id: state.callId,\n name: state.name,\n arguments: state.argumentsText,\n status: \"completed\",\n };\n this.outputItems[state.outputIndex] = item;\n this.writeEvent(\"response.function_call_arguments.done\", {\n type: \"response.function_call_arguments.done\",\n output_index: state.outputIndex,\n item_id: state.itemId,\n arguments: state.argumentsText,\n });\n this.writeEvent(\"response.output_item.done\", {\n type: \"response.output_item.done\",\n output_index: state.outputIndex,\n item,\n });\n }\n };\n\n private writeCompletedEvent = (): void => {\n this.writeEvent(\"response.completed\", {\n type: \"response.completed\",\n response: buildResponseResource({\n responseId: this.params.responseId,\n model: this.params.model,\n outputItems: this.outputItems.filter(Boolean),\n usage: buildUsage({ usage: this.usage }),\n }),\n });\n };\n}\n"],"mappings":";;;;AAmDA,eAAsB,6BAA6B,QAMjC;AAChB,OAAM,IAAI,iCAAiC,OAAO,CAAC,OAAO;;AAG5D,IAAM,mCAAN,MAAuC;CACrC,gBAAsD,EAAE,OAAO,GAAG;CAClE,cAA0D,EAAE;CAC5D,4BAA6B,IAAI,KAAkC;CACnE,cAAsB;CACtB,YAA4C;CAC5C,iBAAsD;CACtD,QAAyC,EAAE;CAE3C,YACE,QAOA;AAPiB,OAAA,SAAA;;CASnB,QAAQ,YAA2B;AACjC,OAAK,cAAc;AACnB,OAAK,mBAAmB;AACxB,aAAW,MAAM,SAAS,oBAAoB,KAAK,OAAO,iBAAiB,CACzE,MAAK,YAAY,MAAM;AAEzB,OAAK,iBAAiB;AACtB,OAAK,YAAY;AACjB,OAAK,iBAAiB;AACtB,OAAK,qBAAqB;AAC1B,OAAK,OAAO,gBAAgB,QAAQ;AACpC,OAAK,OAAO,SAAS,KAAK;;CAG5B,wBAAwC;EACtC,MAAM,QAAQ,KAAK;AACnB,OAAK,eAAe;AACpB,SAAO;;CAGT,cAAsB,WAAmB,YAA2C;AAClF,gBAAc,KAAK,OAAO,UAAU,WAAW;GAC7C,GAAG;GACH,iBAAiB,mBAAmB,KAAK,cAAc;GACxD,CAAC;;CAGJ,qBAAmC;AACjC,OAAK,OAAO,SAAS,aAAa;AAClC,OAAK,OAAO,SAAS,UAAU,gBAAgB,mCAAmC;AAClF,OAAK,OAAO,SAAS,UAAU,iBAAiB,yBAAyB;AACzE,OAAK,OAAO,SAAS,UAAU,cAAc,aAAa;;CAG5D,0BAAwC;AACtC,OAAK,WAAW,oBAAoB;GAClC,MAAM;GACN,UAAU,sBAAsB;IAC9B,YAAY,KAAK,OAAO;IACxB,OAAO,KAAK,OAAO;IACnB,aAAa,EAAE;IACf,OAAO,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;IAChC,QAAQ;IACT,CAAC;GACH,CAAC;;CAGJ,wBAAiD;AAC/C,MAAI,KAAK,UACP,QAAO,KAAK;AAEd,OAAK,YAAY;GACf,aAAa,KAAK,iBAAiB;GACnC,QAAQ,GAAG,KAAK,OAAO,WAAW,WAAW,KAAK;GAClD,MAAM;GACP;AACD,OAAK,WAAW,8BAA8B;GAC5C,MAAM;GACN,cAAc,KAAK,UAAU;GAC7B,MAAM;IACJ,MAAM;IACN,IAAI,KAAK,UAAU;IACnB,MAAM;IACN,QAAQ;IACR,SAAS,EAAE;IACZ;GACF,CAAC;AACF,OAAK,WAAW,+BAA+B;GAC7C,MAAM;GACN,cAAc,KAAK,UAAU;GAC7B,SAAS,KAAK,UAAU;GACxB,eAAe;GACf,MAAM;IAAE,MAAM;IAAe,MAAM;IAAI,aAAa,EAAE;IAAE;GACzD,CAAC;AACF,SAAO,KAAK;;CAGd,6BAA2D;AACzD,MAAI,KAAK,eACP,QAAO,KAAK;AAEd,OAAK,iBAAiB;GACpB,aAAa,KAAK,iBAAiB;GACnC,QAAQ,GAAG,KAAK,OAAO,WAAW,aAAa,KAAK;GACpD,MAAM;GACP;AACD,OAAK,WAAW,8BAA8B;GAC5C,MAAM;GACN,cAAc,KAAK,eAAe;GAClC,MAAM;IACJ,MAAM;IACN,IAAI,KAAK,eAAe;IACxB,QAAQ;IACR,SAAS,EAAE;IACX,SAAS,EAAE;IACZ;GACF,CAAC;AACF,OAAK,WAAW,yCAAyC;GACvD,MAAM;GACN,cAAc,KAAK,eAAe;GAClC,SAAS,KAAK,eAAe;GAC7B,eAAe;GACf,MAAM;IAAE,MAAM;IAAgB,MAAM;IAAI;GACzC,CAAC;AACF,SAAO,KAAK;;CAGd,uBACE,OACA,UACwB;EACxB,MAAM,WAAW,KAAK,UAAU,IAAI,MAAM;AAC1C,MAAI,SACF,QAAO;EAET,MAAM,KAAK,WAAW,MAAM,SAAS;EACrC,MAAM,QAAQ;GACZ,aAAa,KAAK,iBAAiB;GACnC,QAAQ,GAAG,KAAK,OAAO,WAAW,YAAY,KAAK;GACnD,QAAQ,WAAW,MAAM,GAAG,IAAI,GAAG,KAAK,OAAO,WAAW,QAAQ;GAClE,MAAM,WAAW,IAAI,KAAK,IAAI;GAC9B,eAAe;GAChB;AACD,OAAK,UAAU,IAAI,OAAO,MAAM;AAChC,OAAK,WAAW,8BAA8B;GAC5C,MAAM;GACN,cAAc,MAAM;GACpB,MAAM;IACJ,MAAM;IACN,IAAI,MAAM;IACV,SAAS,MAAM;IACf,MAAM,MAAM;IACZ,WAAW;IACX,QAAQ;IACT;GACF,CAAC;AACF,SAAO;;CAGT,eAAuB,UAAmC;AACxD,OAAK,QAAQ,MAAM,SAAS,KAAK;EACjC,MAAM,QAAQ,MAAM,UAAU,IAAI;AAClC,OAAK,oBAAoB,qBAAqB,MAAM,CAAC;AACrD,OAAK,eAAe,mBAAmB,OAAO,QAAQ,CAAC;AACvD,OAAK,MAAM,eAAe,UAAU,OAAO,WAAW,CACpD,MAAK,mBAAmB,WAAW,YAAY,CAAC;;CAIpD,uBAA+B,mBAAiC;AAC9D,MAAI,CAAC,eACH;EAEF,MAAM,QAAQ,KAAK,sBAAsB;AACzC,QAAM,QAAQ;AACd,OAAK,OAAO,gBAAgB,iBAAiB,eAAe;AAC5D,OAAK,WAAW,yCAAyC;GACvD,MAAM;GACN,cAAc,MAAM;GACpB,SAAS,MAAM;GACf,eAAe;GACf,OAAO;GACR,CAAC;;CAGJ,kBAA0B,cAA4B;AACpD,MAAI,CAAC,UACH;EAEF,MAAM,QAAQ,KAAK,iBAAiB;AACpC,QAAM,QAAQ;AACd,OAAK,OAAO,gBAAgB,YAAY,UAAU;AAClD,OAAK,WAAW,8BAA8B;GAC5C,MAAM;GACN,cAAc,MAAM;GACpB,SAAS,MAAM;GACf,eAAe;GACf,OAAO;GACR,CAAC;;CAGJ,sBAA8B,aAAwD;EACpF,MAAM,YAAY,KAAK,MAAM,WAAW,UAAU,MAAM,IAAI,KAAK,UAAU,KAAK;EAChF,MAAM,KAAK,WAAW,UAAU,SAAS;EACzC,MAAM,QAAQ,KAAK,oBAAoB,WAAW,YAAY,EAAE,CAAC;AACjE,QAAM,OAAO,WAAW,IAAI,KAAK,IAAI,MAAM;EAC3C,MAAM,iBAAiB,cAAc,IAAI,UAAU,IAAI;AACvD,QAAM,iBAAiB;AACvB,MAAI,CAAC,eACH;AAEF,OAAK,WAAW,0CAA0C;GACxD,MAAM;GACN,cAAc,MAAM;GACpB,SAAS,MAAM;GACf,OAAO;GACR,CAAC;;CAGJ,wBAAsC;AACpC,MAAI,CAAC,KAAK,eACR;EAEF,MAAM,OAAO;GACX,MAAM;GACN,IAAI,KAAK,eAAe;GACxB,SAAS,CAAC;IAAE,MAAM;IAAgB,MAAM,KAAK,eAAe;IAAM,CAAC;GACnE,SAAS,CAAC;IAAE,MAAM;IAAkB,MAAM,KAAK,eAAe;IAAM,CAAC;GACrE,QAAQ;GACT;AACD,OAAK,YAAY,KAAK,eAAe,eAAe;AACpD,OAAK,WAAW,wCAAwC;GACtD,MAAM;GACN,cAAc,KAAK,eAAe;GAClC,SAAS,KAAK,eAAe;GAC7B,eAAe;GACf,MAAM,KAAK,eAAe;GAC3B,CAAC;AACF,OAAK,WAAW,wCAAwC;GACtD,MAAM;GACN,cAAc,KAAK,eAAe;GAClC,SAAS,KAAK,eAAe;GAC7B,eAAe;GACf,MAAM;IAAE,MAAM;IAAgB,MAAM,KAAK,eAAe;IAAM;GAC/D,CAAC;AACF,OAAK,WAAW,gCAAgC;GAC9C,MAAM;GACN,cAAc,KAAK,eAAe;GAClC,SAAS,KAAK,eAAe;GAC7B,eAAe;GACf,MAAM,KAAK,eAAe;GAC3B,CAAC;AACF,OAAK,WAAW,6BAA6B;GAC3C,MAAM;GACN,cAAc,KAAK,eAAe;GAClC;GACD,CAAC;AACF,OAAK,OAAO,gBAAgB,iBAAiB;;CAG/C,mBAAiC;AAC/B,MAAI,CAAC,KAAK,UACR;EAEF,MAAM,OAAO;GACX,MAAM;GACN,IAAI,KAAK,UAAU;GACnB,MAAM;GACN,QAAQ;GACR,SAAS,CAAC;IAAE,MAAM;IAAe,MAAM,KAAK,UAAU;IAAM,aAAa,EAAE;IAAE,CAAC;GAC/E;AACD,OAAK,YAAY,KAAK,UAAU,eAAe;AAC/C,OAAK,WAAW,6BAA6B;GAC3C,MAAM;GACN,cAAc,KAAK,UAAU;GAC7B,SAAS,KAAK,UAAU;GACxB,eAAe;GACf,MAAM,KAAK,UAAU;GACtB,CAAC;AACF,OAAK,WAAW,8BAA8B;GAC5C,MAAM;GACN,cAAc,KAAK,UAAU;GAC7B,SAAS,KAAK,UAAU;GACxB,eAAe;GACf,MAAM;IAAE,MAAM;IAAe,MAAM,KAAK,UAAU;IAAM,aAAa,EAAE;IAAE;GAC1E,CAAC;AACF,OAAK,WAAW,6BAA6B;GAC3C,MAAM;GACN,cAAc,KAAK,UAAU;GAC7B;GACD,CAAC;AACF,OAAK,OAAO,gBAAgB,YAAY;;CAG1C,wBAAsC;AACpC,OAAK,MAAM,SAAS,CAAC,GAAG,KAAK,UAAU,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE;GAC9F,MAAM,OAAO;IACX,MAAM;IACN,IAAI,MAAM;IACV,SAAS,MAAM;IACf,MAAM,MAAM;IACZ,WAAW,MAAM;IACjB,QAAQ;IACT;AACD,QAAK,YAAY,MAAM,eAAe;AACtC,QAAK,WAAW,yCAAyC;IACvD,MAAM;IACN,cAAc,MAAM;IACpB,SAAS,MAAM;IACf,WAAW,MAAM;IAClB,CAAC;AACF,QAAK,WAAW,6BAA6B;IAC3C,MAAM;IACN,cAAc,MAAM;IACpB;IACD,CAAC;;;CAIN,4BAA0C;AACxC,OAAK,WAAW,sBAAsB;GACpC,MAAM;GACN,UAAU,sBAAsB;IAC9B,YAAY,KAAK,OAAO;IACxB,OAAO,KAAK,OAAO;IACnB,aAAa,KAAK,YAAY,OAAO,QAAQ;IAC7C,OAAO,WAAW,EAAE,OAAO,KAAK,OAAO,CAAC;IACzC,CAAC;GACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"codex-openai-sse-chunks.utils.js","names":[],"sources":["../../src/utils/codex-openai-sse-chunks.utils.ts"],"sourcesContent":["import {\n readArray,\n readRawString,\n readRecord,\n} from \"../codex-openai-responses-bridge-shared.utils.js\";\n\nexport type OpenAiStreamChoiceDelta = Record<string, unknown> & {\n tool_calls?: unknown;\n};\n\nexport type OpenAiStreamChunk = {\n choices?: Array<{\n delta?: OpenAiStreamChoiceDelta;\n finish_reason?: unknown;\n }>;\n usage?: Record<string, unknown>;\n};\n\nexport function extractContentText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n return readArray(content)\n .map((entry) => {\n const record = readRecord(entry);\n return readRawString(record?.text) ?? readRawString(record?.content) ?? \"\";\n })\n .join(\"\");\n}\n\nexport function extractReasoningText(delta: OpenAiStreamChoiceDelta | undefined): string {\n return (\n readRawString(delta?.reasoning_content) ??\n readRawString(delta?.reasoning) ??\n readRawString(delta?.thinking) ??\n \"\"\n );\n}\n\nexport async function* readOpenAiSseChunks(\n upstreamResponse: Response,\n): AsyncGenerator<OpenAiStreamChunk> {\n const stream = upstreamResponse.body;\n if (!stream) {\n return;\n }\n const decoder = new TextDecoder();\n let buffer = \"\";\n for await (const rawChunk of stream as unknown as AsyncIterable<Uint8Array>) {\n buffer += decoder.decode(rawChunk, { stream: true }).replaceAll(\"\\r\\n\", \"\\n\");\n const blocks = buffer.split(\"\\n\\n\");\n buffer = blocks.pop() ?? \"\";\n for (const block of blocks) {\n const data = block\n .split(\"\\n\")\n .filter((line) => line.startsWith(\"data:\"))\n .map((line) => line.slice(5).trimStart())\n .join(\"\\n\")\n .trim();\n if (!data || data === \"[DONE]\") {\n continue;\n }\n yield JSON.parse(data) as OpenAiStreamChunk;\n }\n }\n}\n"],"mappings":";;AAkBA,SAAgB,mBAAmB,SAA0B;AAC3D,KAAI,OAAO,YAAY,SACrB,QAAO;AAET,QAAO,UAAU,QAAQ,CACtB,KAAK,UAAU;EACd,MAAM,SAAS,WAAW,MAAM;AAChC,SAAO,cAAc,QAAQ,KAAK,IAAI,cAAc,QAAQ,QAAQ,IAAI;GACxE,CACD,KAAK,GAAG;;AAGb,SAAgB,qBAAqB,OAAoD;AACvF,QACE,cAAc,OAAO,kBAAkB,IACvC,cAAc,OAAO,UAAU,IAC/B,cAAc,OAAO,SAAS,IAC9B;;AAIJ,gBAAuB,oBACrB,kBACmC;CACnC,MAAM,SAAS,iBAAiB;AAChC,KAAI,CAAC,OACH;CAEF,MAAM,UAAU,IAAI,aAAa;CACjC,IAAI,SAAS;AACb,YAAW,MAAM,YAAY,QAAgD;AAC3E,YAAU,QAAQ,OAAO,UAAU,EAAE,QAAQ,MAAM,CAAC,CAAC,WAAW,QAAQ,KAAK;EAC7E,MAAM,SAAS,OAAO,MAAM,OAAO;AACnC,WAAS,OAAO,KAAK,IAAI;AACzB,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,OAAO,MACV,MAAM,KAAK,CACX,QAAQ,SAAS,KAAK,WAAW,QAAQ,CAAC,CAC1C,KAAK,SAAS,KAAK,MAAM,EAAE,CAAC,WAAW,CAAC,CACxC,KAAK,KAAK,CACV,MAAM;AACT,OAAI,CAAC,QAAQ,SAAS,SACpB;AAEF,SAAM,KAAK,MAAM,KAAK"}
1
+ {"version":3,"file":"codex-openai-sse-chunks.utils.js","names":[],"sources":["../../src/utils/codex-openai-sse-chunks.utils.ts"],"sourcesContent":["import {\n readArray,\n readRawString,\n readRecord,\n} from \"@/codex-openai-responses-bridge-shared.utils.js\";\n\nexport type OpenAiStreamChoiceDelta = Record<string, unknown> & {\n tool_calls?: unknown;\n};\n\nexport type OpenAiStreamChunk = {\n choices?: Array<{\n delta?: OpenAiStreamChoiceDelta;\n finish_reason?: unknown;\n }>;\n usage?: Record<string, unknown>;\n};\n\nexport function extractContentText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n return readArray(content)\n .map((entry) => {\n const record = readRecord(entry);\n return readRawString(record?.text) ?? readRawString(record?.content) ?? \"\";\n })\n .join(\"\");\n}\n\nexport function extractReasoningText(delta: OpenAiStreamChoiceDelta | undefined): string {\n return (\n readRawString(delta?.reasoning_content) ??\n readRawString(delta?.reasoning) ??\n readRawString(delta?.thinking) ??\n \"\"\n );\n}\n\nexport async function* readOpenAiSseChunks(\n upstreamResponse: Response,\n): AsyncGenerator<OpenAiStreamChunk> {\n const stream = upstreamResponse.body;\n if (!stream) {\n return;\n }\n const decoder = new TextDecoder();\n let buffer = \"\";\n for await (const rawChunk of stream as unknown as AsyncIterable<Uint8Array>) {\n buffer += decoder.decode(rawChunk, { stream: true }).replaceAll(\"\\r\\n\", \"\\n\");\n const blocks = buffer.split(\"\\n\\n\");\n buffer = blocks.pop() ?? \"\";\n for (const block of blocks) {\n const data = block\n .split(\"\\n\")\n .filter((line) => line.startsWith(\"data:\"))\n .map((line) => line.slice(5).trimStart())\n .join(\"\\n\")\n .trim();\n if (!data || data === \"[DONE]\") {\n continue;\n }\n yield JSON.parse(data) as OpenAiStreamChunk;\n }\n }\n}\n"],"mappings":";;AAkBA,SAAgB,mBAAmB,SAA0B;AAC3D,KAAI,OAAO,YAAY,SACrB,QAAO;AAET,QAAO,UAAU,QAAQ,CACtB,KAAK,UAAU;EACd,MAAM,SAAS,WAAW,MAAM;AAChC,SAAO,cAAc,QAAQ,KAAK,IAAI,cAAc,QAAQ,QAAQ,IAAI;GACxE,CACD,KAAK,GAAG;;AAGb,SAAgB,qBAAqB,OAAoD;AACvF,QACE,cAAc,OAAO,kBAAkB,IACvC,cAAc,OAAO,UAAU,IAC/B,cAAc,OAAO,SAAS,IAC9B;;AAIJ,gBAAuB,oBACrB,kBACmC;CACnC,MAAM,SAAS,iBAAiB;AAChC,KAAI,CAAC,OACH;CAEF,MAAM,UAAU,IAAI,aAAa;CACjC,IAAI,SAAS;AACb,YAAW,MAAM,YAAY,QAAgD;AAC3E,YAAU,QAAQ,OAAO,UAAU,EAAE,QAAQ,MAAM,CAAC,CAAC,WAAW,QAAQ,KAAK;EAC7E,MAAM,SAAS,OAAO,MAAM,OAAO;AACnC,WAAS,OAAO,KAAK,IAAI;AACzB,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,OAAO,MACV,MAAM,KAAK,CACX,QAAQ,SAAS,KAAK,WAAW,QAAQ,CAAC,CAC1C,KAAK,SAAS,KAAK,MAAM,EAAE,CAAC,WAAW,CAAC,CACxC,KAAK,KAAK,CACV,MAAM;AACT,OAAI,CAAC,QAAQ,SAAS,SACpB;AAEF,SAAM,KAAK,MAAM,KAAK"}
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@nextclaw/nextclaw-ncp-runtime-codex-sdk",
3
- "version": "0.1.54",
3
+ "version": "0.1.55-beta.0",
4
4
  "private": false,
5
5
  "description": "Optional NCP runtime adapter backed by OpenAI Codex SDK.",
6
6
  "type": "module",
7
7
  "exports": {
8
8
  ".": {
9
+ "import": "./dist/index.js",
9
10
  "types": "./dist/index.d.ts",
10
11
  "default": "./dist/index.js"
11
12
  }
@@ -17,7 +18,7 @@
17
18
  ],
18
19
  "dependencies": {
19
20
  "@openai/codex-sdk": "^0.139.0",
20
- "@nextclaw/ncp": "0.6.3"
21
+ "@nextclaw/ncp": "0.6.4-beta.0"
21
22
  },
22
23
  "devDependencies": {
23
24
  "@types/node": "^20.17.6",
@@ -27,7 +28,7 @@
27
28
  "scripts": {
28
29
  "build": "tsdown src/index.ts --dts.sourcemap --clean --target es2022 --no-fixedExtension --unbundle",
29
30
  "lint": "eslint .",
30
- "test": "vitest run src/services/codex-sdk-runtime-thread-metadata.service.test.ts src/utils/codex-model-provider.utils.test.ts src/utils/codex-sdk-ncp-event-mapper.utils.test.ts src/services/codex-live-output-stream.service.test.ts src/utils/codex-openai-sse-chunks.utils.test.ts",
31
+ "test": "vitest run src/services/codex-sdk-runtime-thread-metadata.service.test.ts src/utils/codex-model-provider.utils.test.ts src/utils/codex-sdk-ncp-event-mapper.utils.test.ts src/services/codex-live-output-stream.service.test.ts src/utils/codex-openai-sse-chunks.utils.test.ts src/utils/codex-openai-responses-stream-writer.utils.test.ts",
31
32
  "tsc": "tsc -p tsconfig.json"
32
33
  }
33
34
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"codex-openai-responses-bridge-assistant-output.utils.js","names":[],"sources":["../src/codex-openai-responses-bridge-assistant-output.utils.ts"],"sourcesContent":["import type { ServerResponse } from \"node:http\";\nimport { normalizeAssistantText } from \"@nextclaw/ncp\";\nimport {\n nextSequenceNumber,\n readArray,\n readRecord,\n readRawString,\n readString,\n writeSseEvent,\n type OpenAiChatCompletionChoiceMessage,\n type OpenResponsesOutputItem,\n type StreamSequenceState,\n} from \"./codex-openai-responses-bridge-shared.utils.js\";\n\nfunction extractAssistantText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (!Array.isArray(content)) {\n return \"\";\n }\n return content\n .map((entry) => {\n const record = readRecord(entry);\n if (!record) {\n return \"\";\n }\n const type = readString(record.type);\n if (type === \"text\" || type === \"output_text\") {\n return readString(record.text) ?? \"\";\n }\n return \"\";\n })\n .filter(Boolean)\n .join(\"\");\n}\n\ntype ReasoningExtraction = {\n present: boolean;\n text: string;\n};\n\nfunction readReasoningRecordText(value: unknown): string {\n const record = readRecord(value);\n if (!record) {\n return \"\";\n }\n return (\n readRawString(record.text) ??\n readRawString(record.content) ??\n readRawString(record.reasoning) ??\n readRawString(record.reasoning_content) ??\n readRawString(record.thinking) ??\n \"\"\n );\n}\n\nfunction extractReasoningDetailsText(value: unknown): ReasoningExtraction | undefined {\n const rawString = readRawString(value);\n if (rawString !== undefined) {\n return {\n present: true,\n text: rawString,\n };\n }\n\n const record = readRecord(value);\n if (record) {\n return {\n present: true,\n text: readReasoningRecordText(record),\n };\n }\n\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n const text = readArray(value)\n .map((entry) => readReasoningRecordText(entry))\n .join(\"\");\n return {\n present: true,\n text,\n };\n}\n\nfunction extractContentReasoningText(content: unknown): string {\n if (!Array.isArray(content)) {\n return \"\";\n }\n return content\n .map((entry) => {\n const record = readRecord(entry);\n if (!record) {\n return \"\";\n }\n const type = readString(record.type);\n if (\n type === \"reasoning\" ||\n type === \"reasoning_text\" ||\n type === \"thinking\" ||\n type === \"thinking_text\"\n ) {\n return readReasoningRecordText(record);\n }\n return \"\";\n })\n .join(\"\");\n}\n\nfunction extractExplicitReasoning(\n message: OpenAiChatCompletionChoiceMessage | undefined,\n): ReasoningExtraction | undefined {\n const candidates = [\n message?.reasoning_content,\n message?.reasoning,\n message?.thinking,\n message?.reasoning_details,\n ];\n\n for (const candidate of candidates) {\n const extracted = extractReasoningDetailsText(candidate);\n if (extracted) {\n return extracted;\n }\n }\n\n const contentReasoning = extractContentReasoningText(message?.content);\n return contentReasoning\n ? {\n present: true,\n text: contentReasoning,\n }\n : undefined;\n}\n\nfunction extractAssistantOutput(message: OpenAiChatCompletionChoiceMessage | undefined): {\n text: string;\n reasoning: string;\n reasoningPresent: boolean;\n} {\n const rawText = extractAssistantText(message?.content);\n const normalized = normalizeAssistantText(rawText, \"think-tags\");\n const explicitReasoning = extractExplicitReasoning(message);\n const reasoning = explicitReasoning?.text ?? readString(normalized.reasoning) ?? \"\";\n const reasoningPresent = explicitReasoning?.present === true || Boolean(normalized.reasoning);\n const text =\n explicitReasoning?.present === true\n ? readString(normalized.text) ?? readString(rawText) ?? \"\"\n : normalized.reasoning\n ? readString(normalized.text) ?? \"\"\n : readString(rawText) ?? \"\";\n\n return {\n text,\n reasoning,\n reasoningPresent,\n };\n}\n\nfunction buildInProgressReasoningItem(item: OpenResponsesOutputItem): OpenResponsesOutputItem {\n return {\n ...structuredClone(item),\n status: \"in_progress\",\n content: [],\n summary: [],\n };\n}\n\nexport function buildAssistantOutputItems(params: {\n message: OpenAiChatCompletionChoiceMessage | undefined;\n responseId: string;\n}): OpenResponsesOutputItem[] {\n const { reasoning, reasoningPresent, text } = extractAssistantOutput(params.message);\n const outputItems: OpenResponsesOutputItem[] = [];\n\n if (reasoningPresent) {\n outputItems.push({\n type: \"reasoning\",\n id: `${params.responseId}:reasoning:0`,\n summary: [\n {\n type: \"summary_text\",\n text: reasoning,\n },\n ],\n content: [\n {\n type: \"reasoning_text\",\n text: reasoning,\n },\n ],\n status: \"completed\",\n });\n }\n\n if (text) {\n outputItems.push({\n type: \"message\",\n id: `${params.responseId}:message:${outputItems.length}`,\n role: \"assistant\",\n status: \"completed\",\n content: [\n {\n type: \"output_text\",\n text,\n annotations: [],\n },\n ],\n });\n }\n\n return outputItems;\n}\n\nexport function writeReasoningOutputItemEvents(params: {\n response: ServerResponse;\n item: OpenResponsesOutputItem;\n outputIndex: number;\n sequenceState: StreamSequenceState;\n}): void {\n const itemId = readString(params.item.id);\n const content = readArray(params.item.content);\n const textPart = content.find((entry) => readString(readRecord(entry)?.type) === \"reasoning_text\");\n const text = readString(readRecord(textPart)?.text) ?? \"\";\n const summary = readArray(params.item.summary);\n const summaryIndex = summary.findIndex((entry) => readString(readRecord(entry)?.type) === \"summary_text\");\n const summaryText =\n summaryIndex >= 0 ? readString(readRecord(summary[summaryIndex])?.text) ?? \"\" : \"\";\n\n writeSseEvent(params.response, \"response.output_item.added\", {\n type: \"response.output_item.added\",\n sequence_number: nextSequenceNumber(params.sequenceState),\n output_index: params.outputIndex,\n item: buildInProgressReasoningItem(params.item),\n });\n\n if (itemId && summaryText) {\n writeSseEvent(params.response, \"response.reasoning_summary_part.added\", {\n type: \"response.reasoning_summary_part.added\",\n sequence_number: nextSequenceNumber(params.sequenceState),\n output_index: params.outputIndex,\n item_id: itemId,\n summary_index: summaryIndex,\n part: {\n type: \"summary_text\",\n text: \"\",\n },\n });\n writeSseEvent(params.response, \"response.reasoning_summary_text.delta\", {\n type: \"response.reasoning_summary_text.delta\",\n sequence_number: nextSequenceNumber(params.sequenceState),\n output_index: params.outputIndex,\n item_id: itemId,\n summary_index: summaryIndex,\n delta: summaryText,\n });\n writeSseEvent(params.response, \"response.reasoning_summary_text.done\", {\n type: \"response.reasoning_summary_text.done\",\n sequence_number: nextSequenceNumber(params.sequenceState),\n output_index: params.outputIndex,\n item_id: itemId,\n summary_index: summaryIndex,\n text: summaryText,\n });\n writeSseEvent(params.response, \"response.reasoning_summary_part.done\", {\n type: \"response.reasoning_summary_part.done\",\n sequence_number: nextSequenceNumber(params.sequenceState),\n output_index: params.outputIndex,\n item_id: itemId,\n summary_index: summaryIndex,\n part: {\n type: \"summary_text\",\n text: summaryText,\n },\n });\n }\n\n if (itemId && text) {\n writeSseEvent(params.response, \"response.reasoning_text.delta\", {\n type: \"response.reasoning_text.delta\",\n sequence_number: nextSequenceNumber(params.sequenceState),\n output_index: params.outputIndex,\n item_id: itemId,\n content_index: 0,\n delta: text,\n });\n }\n\n if (itemId) {\n writeSseEvent(params.response, \"response.reasoning_text.done\", {\n type: \"response.reasoning_text.done\",\n sequence_number: nextSequenceNumber(params.sequenceState),\n output_index: params.outputIndex,\n item_id: itemId,\n content_index: 0,\n text,\n });\n }\n\n writeSseEvent(params.response, \"response.output_item.done\", {\n type: \"response.output_item.done\",\n sequence_number: nextSequenceNumber(params.sequenceState),\n output_index: params.outputIndex,\n item: params.item,\n });\n}\n"],"mappings":"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"}