@codehz/ai 0.1.6 → 0.1.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["mergeAuxiliary","rollbackTrailingAssistantMessages","rollbackTrailingAssistantMessages"],"sources":["../src/core/errors.ts","../src/core/validation.ts","../src/core/normalize.ts","../src/core/client.ts","../src/core/event-factory.ts","../src/core/aggregator.ts","../src/core/collect-stream.ts","../src/helpers/mapping.ts","../src/helpers/auxiliary-collector.ts","../src/helpers/adapter-auxiliary.ts","../src/helpers/adapter-base.ts","../src/helpers/usage-mapping.ts","../src/helpers/sse-parser.ts","../src/adapters/responses.ts","../src/adapters/messages.ts","../src/adapters/chat-completions.ts","../src/adapters/ollama.ts","../src/adapters/mock.ts","../src/helpers/synthetic-stream.ts"],"sourcesContent":["/**\n * 公共错误模型\n *\n * 把失败、降级、断流三类情况明确区分:\n * - 致命错误 → 同步抛错或迭代器抛错\n * - 非致命差异 → warning 通道\n * - 流中断 → 不伪造 response.completed\n */\n\n// ── 错误类型 ──────────────────────────────────────────────────\n\nexport type ErrorCode =\n | \"INPUT_EMPTY\"\n | \"TEMPERATURE_OUT_OF_RANGE\"\n | \"MAX_OUTPUT_TOKENS_INVALID\"\n | \"TOOL_CHOICE_NO_TOOLS\"\n | \"TOOL_CHOICE_UNKNOWN_TOOL\"\n | \"PROVIDER_ERROR\"\n | \"AUTH_ERROR\"\n | \"STREAM_ERROR\"\n | \"MAPPING_ERROR\"\n | \"STREAM_INCOMPLETE\"\n | \"LOOKUP_FAILED\"\n | \"LOOKUP_TIMEOUT\"\n | string;\n\nexport class AIError extends Error {\n override readonly name: string;\n\n constructor(\n message: string,\n public readonly code: ErrorCode,\n name?: string,\n ) {\n super(message);\n this.name = name ?? \"AIError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** 请求构造失败 — 参数校验不通过。在进入 adapter 前同步抛错。 */\nexport class AIRequestError extends AIError {\n constructor(message: string, code: ErrorCode) {\n super(message, code, \"AIRequestError\");\n }\n}\n\n/** Provider 调用失败 — HTTP 非 2xx、网络错误。由 AdapterBase 捕获转为 warning。 */\nexport class AIProviderError extends AIError {\n constructor(\n message: string,\n code: ErrorCode,\n public readonly statusCode?: number,\n public readonly responseBody?: string,\n ) {\n super(message, code, \"AIProviderError\");\n }\n}\n\n/** 流协议损坏 — SSE 解析失败、chunk 格式异常。 */\nexport class AIStreamError extends AIError {\n constructor(message: string, code: ErrorCode) {\n super(message, code, \"AIStreamError\");\n }\n}\n\n/** Canonical 映射失败 — 无法将 provider 响应映射到 canonical 类型。 */\nexport class AIMappingError extends AIError {\n constructor(message: string, code: ErrorCode) {\n super(message, code, \"AIMappingError\");\n }\n}\n\n// ── Warning 辅助 ──────────────────────────────────────────────\n\n/**\n * 标准 warning 代码列表。\n * 用于非致命差异的记录。\n */\nexport const WarningCode = {\n /** replay fidelity 低于预期 */\n REPLAY_FIDELITY_LOW: \"REPLAY_FIDELITY_LOW\",\n /** usage 字段缺失 */\n USAGE_MISSING: \"USAGE_MISSING\",\n /** billing 字段缺失 */\n BILLING_MISSING: \"BILLING_MISSING\",\n /** billing 只能给估算值 */\n BILLING_ESTIMATED: \"BILLING_ESTIMATED\",\n /** follow-up lookup 失败 */\n LOOKUP_FAILED: \"LOOKUP_FAILED\",\n /** lookup 超时 */\n LOOKUP_TIMEOUT: \"LOOKUP_TIMEOUT\",\n /** 流提前中断 */\n STREAM_INCOMPLETE: \"STREAM_INCOMPLETE\",\n /** 能力降级 */\n CAPABILITY_DOWNGRADE: \"CAPABILITY_DOWNGRADE\",\n /** 模拟流式 */\n SYNTHETIC_STREAM: \"SYNTHETIC_STREAM\",\n} as const;\n","/**\n * 请求校验\n *\n * 在请求进入 adapter 前对参数合法性做基础检查。\n * 校验失败时抛 AIRequestError。\n */\n\nimport type { AIRequest } from \"../types/index.js\";\nimport { AIRequestError } from \"./errors.js\";\n\nexport type ValidationIssue = {\n field: string;\n code: string;\n message: string;\n};\n\nconst MESSAGE_ROLES = new Set([\"user\", \"assistant\"]);\nconst REASONING_VISIBILITIES = new Set([\"full\", \"summary\", \"redacted\", \"opaque\"]);\nconst TOOL_RESULT_OUTCOMES = new Set([\"success\", \"error\", \"rejected\"]);\nconst INCLUDE_MODES = new Set([\"off\", \"best_effort\"]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction pushIssue(issues: ValidationIssue[], field: string, code: string, message: string): void {\n issues.push({ field, code, message });\n}\n\nfunction validateContentBlock(block: unknown, field: string, issues: ValidationIssue[]): void {\n if (!isRecord(block) || typeof block.type !== \"string\") {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field} must be a valid ContentBlock`);\n return;\n }\n\n switch (block.type) {\n case \"text\":\n if (typeof block.text !== \"string\") {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.text must be a string`);\n }\n return;\n case \"json\":\n if (!(\"json\" in block)) {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.json must be present`);\n }\n return;\n case \"image\":\n if (typeof block.imageUrl !== \"string\" || block.imageUrl.length === 0) {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.imageUrl must be a non-empty string`);\n }\n return;\n case \"binary_ref\":\n if (typeof block.ref !== \"string\" || block.ref.length === 0) {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.ref must be a non-empty string`);\n }\n return;\n case \"opaque\":\n if (!(\"payload\" in block)) {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.payload must be present`);\n }\n return;\n default:\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.type \"${block.type}\" is not supported`);\n }\n}\n\nfunction validateContentArray(content: unknown, field: string, issues: ValidationIssue[], code: string): void {\n if (!Array.isArray(content)) {\n pushIssue(issues, field, code, `${field} must be a ContentBlock[]`);\n return;\n }\n\n for (let i = 0; i < content.length; i++) {\n validateContentBlock(content[i], `${field}[${i}]`, issues);\n }\n}\n\nfunction validateInstructionArray(content: unknown, field: string, issues: ValidationIssue[]): void {\n if (!Array.isArray(content)) {\n pushIssue(issues, field, \"INSTRUCTIONS_INVALID\", `${field} must be an InstructionBlock[]`);\n return;\n }\n\n for (let i = 0; i < content.length; i++) {\n const block = content[i];\n const blockField = `${field}[${i}]`;\n validateContentBlock(block, blockField, issues);\n\n if (!isRecord(block) || typeof block.type !== \"string\") continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n pushIssue(issues, blockField, \"INSTRUCTIONS_INVALID\", `${blockField} only supports text/json blocks`);\n }\n }\n}\n\nfunction validateInputItem(item: unknown, field: string, issues: ValidationIssue[]): void {\n if (!isRecord(item)) {\n pushIssue(issues, field, \"INPUT_INVALID_ITEM\", `${field} must be a valid InputItem`);\n return;\n }\n\n if (typeof item.type !== \"string\") {\n pushIssue(issues, field, \"INPUT_ITEM_UNKNOWN_TYPE\", `${field}.type must be a supported InputItem type`);\n return;\n }\n\n switch (item.type) {\n case \"message\":\n if (typeof item.role !== \"string\" || !MESSAGE_ROLES.has(item.role)) {\n pushIssue(issues, `${field}.role`, \"MESSAGE_ROLE_INVALID\", `${field}.role must be a valid message role`);\n }\n validateContentArray(item.content, `${field}.content`, issues, \"MESSAGE_CONTENT_INVALID\");\n return;\n case \"reasoning\":\n if (typeof item.visibility !== \"string\" || !REASONING_VISIBILITIES.has(item.visibility)) {\n pushIssue(\n issues,\n `${field}.visibility`,\n \"REASONING_VISIBILITY_INVALID\",\n `${field}.visibility must be a valid reasoning visibility`,\n );\n }\n validateContentArray(item.content, `${field}.content`, issues, \"REASONING_CONTENT_INVALID\");\n return;\n case \"tool_call\":\n if (typeof item.id !== \"string\" || item.id.length === 0) {\n pushIssue(issues, `${field}.id`, \"TOOL_CALL_ID_INVALID\", `${field}.id must be a non-empty string`);\n }\n if (typeof item.name !== \"string\" || item.name.length === 0) {\n pushIssue(issues, `${field}.name`, \"TOOL_CALL_NAME_INVALID\", `${field}.name must be a non-empty string`);\n }\n if (typeof item.argumentsText !== \"string\") {\n pushIssue(\n issues,\n `${field}.argumentsText`,\n \"TOOL_CALL_ARGUMENTS_INVALID\",\n `${field}.argumentsText must be a string`,\n );\n }\n return;\n case \"tool_result\":\n if (typeof item.callId !== \"string\" || item.callId.length === 0) {\n pushIssue(\n issues,\n `${field}.callId`,\n \"TOOL_RESULT_CALL_ID_INVALID\",\n `${field}.callId must be a non-empty string`,\n );\n }\n if (typeof item.toolName !== \"string\" || item.toolName.length === 0) {\n pushIssue(\n issues,\n `${field}.toolName`,\n \"TOOL_RESULT_NAME_INVALID\",\n `${field}.toolName must be a non-empty string`,\n );\n }\n if (typeof item.outcome !== \"string\" || !TOOL_RESULT_OUTCOMES.has(item.outcome)) {\n pushIssue(\n issues,\n `${field}.outcome`,\n \"TOOL_RESULT_OUTCOME_INVALID\",\n `${field}.outcome must be success, error, or rejected`,\n );\n }\n validateContentArray(item.content, `${field}.content`, issues, \"TOOL_RESULT_CONTENT_INVALID\");\n return;\n case \"opaque\":\n if (typeof item.source !== \"string\" || item.source.length === 0) {\n pushIssue(issues, `${field}.source`, \"OPAQUE_SOURCE_INVALID\", `${field}.source must be a non-empty string`);\n }\n if (typeof item.purpose !== \"string\" || item.purpose.length === 0) {\n pushIssue(issues, `${field}.purpose`, \"OPAQUE_PURPOSE_INVALID\", `${field}.purpose must be a non-empty string`);\n }\n return;\n default:\n pushIssue(issues, `${field}.type`, \"INPUT_ITEM_UNKNOWN_TYPE\", `${field}.type \"${item.type}\" is not supported`);\n }\n}\n\nfunction validateTools(tools: unknown, issues: ValidationIssue[]): void {\n if (tools === undefined) return;\n if (!Array.isArray(tools)) {\n pushIssue(issues, \"tools\", \"TOOLS_INVALID\", \"tools must be an array\");\n return;\n }\n\n const seenNames = new Set<string>();\n for (let i = 0; i < tools.length; i++) {\n const tool = tools[i];\n const field = `tools[${i}]`;\n if (!isRecord(tool)) {\n pushIssue(issues, field, \"TOOL_INVALID\", `${field} must be a valid ToolDefinition`);\n continue;\n }\n\n if (typeof tool.name !== \"string\" || tool.name.length === 0) {\n pushIssue(issues, `${field}.name`, \"TOOL_NAME_INVALID\", `${field}.name must be a non-empty string`);\n } else {\n if (seenNames.has(tool.name)) {\n pushIssue(issues, `${field}.name`, \"TOOLS_DUPLICATE_NAME\", `tool name \"${tool.name}\" is duplicated`);\n }\n seenNames.add(tool.name);\n }\n\n if (tool.description !== undefined && typeof tool.description !== \"string\") {\n pushIssue(issues, `${field}.description`, \"TOOL_DESCRIPTION_INVALID\", `${field}.description must be a string`);\n }\n\n if (!isRecord(tool.inputSchema)) {\n pushIssue(issues, `${field}.inputSchema`, \"TOOL_INPUT_SCHEMA_INVALID\", `${field}.inputSchema must be an object`);\n }\n }\n}\n\nfunction validateToolChoice(toolChoice: unknown, issues: ValidationIssue[]): void {\n if (toolChoice === undefined) return;\n if (toolChoice === \"auto\" || toolChoice === \"none\") return;\n if (\n !isRecord(toolChoice) ||\n toolChoice.type !== \"tool\" ||\n typeof toolChoice.name !== \"string\" ||\n toolChoice.name.length === 0\n ) {\n pushIssue(issues, \"toolChoice\", \"TOOL_CHOICE_INVALID\", 'toolChoice must be auto, none, or { type: \"tool\", name }');\n }\n}\n\n/**\n * 校验 AIRequest,返回校验问题列表。\n * 空数组表示无问题。\n */\nexport function validateRequest(request: AIRequest): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n\n if (request.instructions !== undefined) {\n if (typeof request.instructions === \"string\") {\n // no-op\n } else if (Array.isArray(request.instructions)) {\n validateInstructionArray(request.instructions, \"instructions\", issues);\n } else {\n pushIssue(issues, \"instructions\", \"INSTRUCTIONS_INVALID\", \"instructions must be a string or InstructionBlock[]\");\n }\n }\n\n // input 非空约束\n if (!Array.isArray(request.input) || request.input.length === 0) {\n pushIssue(issues, \"input\", \"INPUT_EMPTY\", \"input must be a non-empty array\");\n }\n\n // input 元素类型检查\n if (Array.isArray(request.input)) {\n for (let i = 0; i < request.input.length; i++) {\n validateInputItem(request.input[i], `input[${i}]`, issues);\n }\n }\n\n // temperature 范围\n if (request.temperature !== undefined) {\n if (typeof request.temperature !== \"number\" || isNaN(request.temperature)) {\n issues.push({\n field: \"temperature\",\n code: \"TEMPERATURE_NOT_NUMBER\",\n message: \"temperature must be a number\",\n });\n } else if (request.temperature < 0 || request.temperature > 2) {\n issues.push({\n field: \"temperature\",\n code: \"TEMPERATURE_OUT_OF_RANGE\",\n message: \"temperature must be between 0 and 2\",\n });\n }\n }\n\n // maxOutputTokens 合法性\n if (request.maxOutputTokens !== undefined) {\n if (typeof request.maxOutputTokens !== \"number\" || isNaN(request.maxOutputTokens)) {\n issues.push({\n field: \"maxOutputTokens\",\n code: \"MAX_OUTPUT_TOKENS_NOT_NUMBER\",\n message: \"maxOutputTokens must be a number\",\n });\n } else if (!Number.isInteger(request.maxOutputTokens) || request.maxOutputTokens < 1) {\n issues.push({\n field: \"maxOutputTokens\",\n code: \"MAX_OUTPUT_TOKENS_INVALID\",\n message: \"maxOutputTokens must be a positive integer\",\n });\n }\n }\n\n if (request.include !== undefined) {\n if (!isRecord(request.include)) {\n pushIssue(issues, \"include\", \"INCLUDE_INVALID\", \"include must be an object\");\n } else {\n if (request.include.usage !== undefined && !INCLUDE_MODES.has(request.include.usage)) {\n pushIssue(issues, \"include.usage\", \"INCLUDE_USAGE_INVALID\", \"include.usage must be off or best_effort\");\n }\n if (request.include.billing !== undefined && !INCLUDE_MODES.has(request.include.billing)) {\n pushIssue(issues, \"include.billing\", \"INCLUDE_BILLING_INVALID\", \"include.billing must be off or best_effort\");\n }\n if (request.include.providerMetadata !== undefined && !INCLUDE_MODES.has(request.include.providerMetadata)) {\n pushIssue(\n issues,\n \"include.providerMetadata\",\n \"INCLUDE_PROVIDER_METADATA_INVALID\",\n \"include.providerMetadata must be off or best_effort\",\n );\n }\n }\n }\n\n if (request.metadata !== undefined) {\n if (!isRecord(request.metadata)) {\n pushIssue(issues, \"metadata\", \"METADATA_INVALID\", \"metadata must be an object\");\n } else {\n for (const [key, value] of Object.entries(request.metadata)) {\n if (typeof value !== \"string\") {\n pushIssue(issues, `metadata.${key}`, \"METADATA_VALUE_INVALID\", `metadata.${key} must be a string`);\n }\n }\n }\n }\n\n validateTools(request.tools, issues);\n validateToolChoice(request.toolChoice, issues);\n\n // toolChoice 与 tools 的一致性\n if (\n request.toolChoice &&\n typeof request.toolChoice === \"object\" &&\n \"type\" in request.toolChoice &&\n request.toolChoice.type === \"tool\"\n ) {\n const chosenName = request.toolChoice.name;\n if (!request.tools || request.tools.length === 0) {\n issues.push({\n field: \"toolChoice\",\n code: \"TOOL_CHOICE_NO_TOOLS\",\n message: `toolChoice specifies tool \"${chosenName}\" but no tools are defined`,\n });\n } else if (!request.tools.some((t) => t.name === chosenName)) {\n issues.push({\n field: \"toolChoice\",\n code: \"TOOL_CHOICE_UNKNOWN_TOOL\",\n message: `toolChoice specifies tool \"${chosenName}\" which is not in tools array`,\n });\n }\n }\n\n return issues;\n}\n\n/**\n * 校验请求并抛出首个问题。\n * 适用于客户端入口的快速失败检查。\n */\nexport function assertValidRequest(request: AIRequest): void {\n const issues = validateRequest(request);\n const first = issues[0];\n if (first) {\n throw new AIRequestError(first.message, first.code);\n }\n}\n","/**\n * 请求归一化\n *\n * 将 AIRequest + client 配置归一化为 NormalizedRequest,\n * 包括默认值合并、requestId 生成、include 默认值填充。\n */\n\nimport type { AIRequest, NormalizedRequest } from \"../types/index.js\";\nimport { assertValidRequest } from \"./validation.js\";\n\nexport type NormalizeOptions = {\n model: string;\n defaults?: Partial<AIRequest>;\n};\n\nconst DEFAULT_INCLUDE = {\n usage: \"best_effort\" as const,\n billing: \"best_effort\" as const,\n providerMetadata: \"best_effort\" as const,\n};\n\n/**\n * 归一化请求:\n * 1. 合并 defaults\n * 2. 填充 include 默认值\n * 3. 生成 requestId\n * 4. 校验请求合法性\n */\nexport function normalizeRequest(request: AIRequest, options: NormalizeOptions): NormalizedRequest {\n const { model, defaults } = options;\n\n // 合并 defaults(浅合并,input/tools 由 request 完全覆盖)\n const merged: AIRequest = {\n ...defaults,\n ...request,\n include: {\n ...DEFAULT_INCLUDE,\n ...defaults?.include,\n ...request.include,\n },\n };\n\n // 校验\n assertValidRequest(merged);\n\n return {\n ...merged,\n model,\n requestId: crypto.randomUUID(),\n };\n}\n","/**\n * AI 客户端入口\n *\n * 打通 createAIClient() 到 adapter 调用之间的公共入口。\n */\n\nimport type { AIRequest, AIStreamEvent, AIClient, CreateAIClientOptions } from \"../types/index.js\";\nimport { normalizeRequest } from \"./normalize.js\";\n\nexport function createAIClient(options: CreateAIClientOptions): AIClient {\n const { adapter, model, defaults } = options;\n\n const client: AIClient = {\n stream(request: AIRequest): AsyncIterable<AIStreamEvent> {\n const normalized = normalizeRequest(request, { model, defaults });\n return adapter.stream(normalized);\n },\n };\n\n return client;\n}\n\nexport type { AIClient, CreateAIClientOptions } from \"../types/index.js\";\n","/**\n * 共享事件工厂\n *\n * 负责创建带有统一 sequence / timestamp / responseId / backend 的事件对象。\n * 每个 factory 实例管理一个单调递增的 sequence 计数器。\n */\n\nimport type {\n ResponseStartedEvent,\n ResponseWarningEvent,\n ResponseAuxiliaryEvent,\n ResponseCompletedEvent,\n MessageStartedEvent,\n MessageDeltaEvent,\n MessageCompletedEvent,\n ReasoningStartedEvent,\n ReasoningDeltaEvent,\n ReasoningCompletedEvent,\n ToolCallStartedEvent,\n ToolCallDeltaEvent,\n ToolCallCompletedEvent,\n MessageItem,\n ReasoningItem,\n ToolCallItem,\n ContentBlock,\n Usage,\n BillingInfo,\n AuxiliaryInfo,\n AIResponse,\n} from \"../types/index.js\";\n\nexport type EventFactoryBackend = {\n kind: \"chat-completions\" | \"messages\" | \"responses\" | \"ollama\" | \"mock\";\n isSynthetic: boolean;\n};\n\nexport type EventFactoryState = {\n responseId: string;\n backend: EventFactoryBackend;\n};\n\nfunction timestamp(): string {\n return new Date().toISOString();\n}\n\nexport function createEventFactory(state: EventFactoryState) {\n let seq = 0;\n const warnings: string[] = [];\n\n function next(): number {\n return seq++;\n }\n\n function base(): Pick<ResponseStartedEvent, \"responseId\" | \"sequence\" | \"timestamp\" | \"backend\"> {\n return {\n responseId: state.responseId,\n sequence: next(),\n timestamp: timestamp(),\n backend: { ...state.backend },\n };\n }\n\n return {\n // ── 响应级事件 ──────────────────────────────────────────\n\n responseStarted(model: string): ResponseStartedEvent {\n return { ...base(), type: \"response.started\", model };\n },\n\n responseWarning(message: string, code?: string): ResponseWarningEvent {\n warnings.push(message);\n return { ...base(), type: \"response.warning\", message, code };\n },\n\n responseAuxiliary(data: {\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: Partial<AuxiliaryInfo>;\n }): ResponseAuxiliaryEvent {\n return { ...base(), type: \"response.auxiliary\", ...data };\n },\n\n responseCompleted(response: AIResponse): ResponseCompletedEvent {\n return { ...base(), type: \"response.completed\", response };\n },\n\n // ── 消息流事件 ──────────────────────────────────────────\n\n messageStarted(id: string): MessageStartedEvent {\n return { ...base(), type: \"message.started\", item: { id, role: \"assistant\" } };\n },\n\n messageDelta(itemId: string, text: string): MessageDeltaEvent {\n return { ...base(), type: \"message.delta\", itemId, delta: { type: \"text\", text } };\n },\n\n messageCompleted(item: MessageItem): MessageCompletedEvent {\n return { ...base(), type: \"message.completed\", item };\n },\n\n // ── 思维链流事件 ────────────────────────────────────────\n\n reasoningStarted(id: string, visibility: ReasoningItem[\"visibility\"]): ReasoningStartedEvent {\n return { ...base(), type: \"reasoning.started\", item: { id, visibility } };\n },\n\n reasoningDelta(itemId: string, delta: ContentBlock): ReasoningDeltaEvent {\n return { ...base(), type: \"reasoning.delta\", itemId, delta };\n },\n\n reasoningCompleted(item: ReasoningItem): ReasoningCompletedEvent {\n return { ...base(), type: \"reasoning.completed\", item };\n },\n\n // ── 工具调用流事件 ──────────────────────────────────────\n\n toolCallStarted(id: string, name: string): ToolCallStartedEvent {\n return { ...base(), type: \"tool_call.started\", item: { id, name } };\n },\n\n toolCallDelta(itemId: string, delta: { argumentsText?: string }): ToolCallDeltaEvent {\n return { ...base(), type: \"tool_call.delta\", itemId, delta };\n },\n\n toolCallCompleted(item: ToolCallItem): ToolCallCompletedEvent {\n return { ...base(), type: \"tool_call.completed\", item };\n },\n\n /** 返回当前已发出的 sequence 计数(用于断言) */\n get sequence(): number {\n return seq;\n },\n\n /** 返回当前已记录的 warning 副本。 */\n get warnings(): string[] {\n return [...warnings];\n },\n };\n}\n\nexport type EventFactory = ReturnType<typeof createEventFactory>;\n","/**\n * 流聚合器\n *\n * 将 AIStreamEvent 序列聚合为统一的 AIResponse。\n * 职责:\n * - 合并 message.delta / reasoning.delta / tool_call.delta\n * - 合并多次 response.auxiliary 补丁\n * - 生成 output / text / toolCalls\n * - 保持 output 顺序稳定\n *\n * 约束:\n * - replay 由 adapter 显式提供,聚合器不猜测\n * - 不伪造 reasoning\n * - 不解释 opaque payload\n */\n\nimport type {\n AIStreamEvent,\n AIResponse,\n MessageItem,\n ToolCallItem,\n OutputItem,\n Usage,\n BillingInfo,\n AuxiliaryInfo,\n BackendTrace,\n StopReason,\n} from \"../types/index.js\";\n\n// ── 聚合器状态 ────────────────────────────────────────────────\n\nexport interface AggregatorState {\n responseId?: string;\n model?: string;\n backendInfo?: { kind: BackendTrace[\"adapter\"]; isSynthetic: boolean };\n\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary: AuxiliaryInfo;\n warnings: string[];\n warningSet: Set<string>;\n output: OutputItem[];\n textParts: string[];\n toolCalls: ToolCallItem[];\n lastEventType?: AIStreamEvent[\"type\"];\n\n /** adapter 在 response.completed 中提供的 replay */\n replayFromAdapter?: import(\"../types/index.js\").ReplayItem[];\n responseIdFromAdapter?: string;\n stopReasonFromAdapter?: StopReason;\n backendFromAdapter?: BackendTrace;\n}\n\nexport function createAggregatorState(): AggregatorState {\n return {\n auxiliary: {},\n warnings: [],\n warningSet: new Set(),\n output: [],\n textParts: [],\n toolCalls: [],\n };\n}\n\n// ── Event handlers ────────────────────────────────────────────\n\nfunction handleResponseStarted(state: AggregatorState, event: AIStreamEvent & { type: \"response.started\" }): void {\n state.responseId = event.responseId;\n state.model = event.model;\n state.backendInfo = event.backend;\n}\n\nfunction handleResponseWarning(state: AggregatorState, event: AIStreamEvent & { type: \"response.warning\" }): void {\n pushWarnings(state, [event.message]);\n}\n\nfunction handleResponseAuxiliary(state: AggregatorState, event: AIStreamEvent & { type: \"response.auxiliary\" }): void {\n if (event.usage) {\n state.usage = { ...state.usage, ...event.usage };\n }\n if (event.billing) {\n state.billing = { ...state.billing, ...event.billing };\n }\n if (event.auxiliary) {\n state.auxiliary = mergeAuxiliary(state.auxiliary, event.auxiliary);\n }\n}\n\nfunction handleMessageCompleted(state: AggregatorState, event: AIStreamEvent & { type: \"message.completed\" }): void {\n state.output.push(event.item);\n pushMessageText(state, event.item);\n}\n\nfunction handleReasoningCompleted(\n state: AggregatorState,\n event: AIStreamEvent & { type: \"reasoning.completed\" },\n): void {\n state.output.push(event.item);\n}\n\nfunction handleToolCallCompleted(state: AggregatorState, event: AIStreamEvent & { type: \"tool_call.completed\" }): void {\n state.output.push(event.item);\n state.toolCalls.push(event.item);\n}\n\nfunction handleResponseCompleted(state: AggregatorState, event: AIStreamEvent & { type: \"response.completed\" }): void {\n state.replayFromAdapter = event.response.replay;\n state.responseIdFromAdapter = event.response.id;\n state.stopReasonFromAdapter = event.response.stopReason;\n state.backendFromAdapter = event.response.backend;\n\n // 从 response.completed 中提取 usage/billing(适配器可能未发 auxiliary 事件)\n if (event.response.usage) {\n state.usage = { ...state.usage, ...event.response.usage };\n }\n if (event.response.billing) {\n state.billing = { ...state.billing, ...event.response.billing };\n }\n if (event.response.auxiliary) {\n state.auxiliary = mergeAuxiliary(state.auxiliary, event.response.auxiliary);\n }\n if (event.response.warnings) {\n pushWarnings(state, event.response.warnings);\n }\n}\n\n// ── 从聚合状态构建最终 AIResponse ─────────────────────────────\n\nfunction buildResponse(state: AggregatorState): AIResponse {\n // 合并 backend trace\n const backendFromResponse = state.backendFromAdapter;\n const backend: BackendTrace = {\n adapter: backendFromResponse?.adapter ?? state.backendInfo?.kind ?? (\"unknown\" as BackendTrace[\"adapter\"]),\n isSyntheticStream: backendFromResponse?.isSyntheticStream ?? state.backendInfo?.isSynthetic ?? false,\n requestId: backendFromResponse?.requestId ?? state.responseId,\n rawResponseId: backendFromResponse?.rawResponseId,\n metadataSources: backendFromResponse?.metadataSources,\n warnings: backendFromResponse?.warnings,\n };\n\n return {\n id: state.responseIdFromAdapter ?? state.responseId,\n output: state.output,\n replay: state.replayFromAdapter ?? [],\n text: state.textParts.join(\"\"),\n toolCalls: state.toolCalls,\n stopReason: state.stopReasonFromAdapter,\n usage: state.usage,\n billing: state.billing,\n auxiliary: state.auxiliary,\n warnings: state.warnings.length > 0 ? state.warnings : undefined,\n backend,\n };\n}\n\n// ── 公开 API ──────────────────────────────────────────────────\n\n/**\n * 将事件数组聚合为 AIResponse。\n * 适用于测试和离线处理场景。\n */\nexport function aggregateEvents(events: AIStreamEvent[]): AIResponse {\n const state = createAggregatorState();\n for (const event of events) {\n aggregateEvent(state, event);\n }\n return finalizeAggregation(state);\n}\n\nexport function aggregateEvent(state: AggregatorState, event: AIStreamEvent): void {\n state.lastEventType = event.type;\n\n switch (event.type) {\n case \"response.started\":\n handleResponseStarted(state, event);\n break;\n case \"response.warning\":\n handleResponseWarning(state, event);\n break;\n case \"response.auxiliary\":\n handleResponseAuxiliary(state, event);\n break;\n case \"message.started\":\n case \"message.delta\":\n case \"reasoning.started\":\n case \"reasoning.delta\":\n case \"tool_call.started\":\n case \"tool_call.delta\":\n break;\n case \"message.completed\":\n handleMessageCompleted(state, event);\n break;\n case \"reasoning.completed\":\n handleReasoningCompleted(state, event);\n break;\n case \"tool_call.completed\":\n handleToolCallCompleted(state, event);\n break;\n case \"response.completed\":\n handleResponseCompleted(state, event);\n break;\n }\n}\n\nexport function finalizeAggregation(state: AggregatorState): AIResponse {\n if (state.lastEventType !== \"response.completed\") {\n throw new Error(\"Stream must end with response.completed event to produce a valid AIResponse\");\n }\n\n return buildResponse(state);\n}\n\nfunction mergeAuxiliary(base: AuxiliaryInfo, patch: Partial<AuxiliaryInfo>): AuxiliaryInfo {\n const merged: AuxiliaryInfo = {\n ...base,\n ...patch,\n };\n\n if (base.providerMetadata || patch.providerMetadata) {\n merged.providerMetadata = {\n ...base.providerMetadata,\n ...patch.providerMetadata,\n };\n }\n\n return merged;\n}\n\nfunction pushWarnings(state: AggregatorState, warnings: readonly string[]): void {\n for (const warning of warnings) {\n if (!state.warningSet.has(warning)) {\n state.warningSet.add(warning);\n state.warnings.push(warning);\n }\n }\n}\n\nfunction pushMessageText(state: AggregatorState, item: MessageItem): void {\n for (const block of item.content) {\n if (block.type === \"text\") {\n state.textParts.push(block.text);\n }\n }\n}\n","/**\n * collectStream — 流收集 helper\n *\n * 将 AsyncIterable<AIStreamEvent> 消费完毕并聚合力 AIResponse。\n * 适用于不需要逐事件处理的调用方。\n */\n\nimport type { AIStreamEvent, AIResponse } from \"../types/index.js\";\nimport { aggregateEvent, createAggregatorState, finalizeAggregation } from \"./aggregator.js\";\n\nexport async function collectStream(stream: AsyncIterable<AIStreamEvent>): Promise<AIResponse> {\n const state = createAggregatorState();\n\n for await (const event of stream) {\n aggregateEvent(state, event);\n }\n\n return finalizeAggregation(state);\n}\n","/**\n * Adapter 共享映射 helper\n *\n * 提供 adapter 间通用的类型映射函数:\n * - stop reason 映射\n * - content block 映射\n * - item 映射\n * - warning 记录\n * - replay 构造工具\n */\n\nimport type {\n StopReason,\n ContentBlock,\n InstructionBlock,\n MessageItem,\n ReasoningItem,\n ToolCallItem,\n ToolResultItem,\n OpaqueItem,\n InputItem,\n OutputItem,\n ReplayItem,\n} from \"../types/index.js\";\n\n// ── Stop reason 映射 ──────────────────────────────────────────\n\n/**\n * 常见 provider stop_reason / finish_reason 到 canonical StopReason 的映射表。\n * adapter 可先查此表,未覆盖时走 fallback 规则。\n */\nconst STOP_REASON_MAP: Record<string, StopReason> = {\n // OpenAI / Azure\n stop: \"end_turn\",\n length: \"max_output_tokens\",\n content_filter: \"content_filter\",\n tool_calls: \"tool_call\",\n // Anthropic\n end_turn: \"end_turn\",\n max_tokens: \"max_output_tokens\",\n tool_use: \"tool_call\",\n // Generic\n error: \"error\",\n};\n\nexport function mapStopReason(providerReason: string): StopReason {\n return STOP_REASON_MAP[providerReason] ?? \"unknown\";\n}\n\n// ── Reasoning visibility 映射 ──────────────────────────────────\n\nexport function mapReasoningVisibility(hasThinking: boolean, hasRedacted: boolean): ReasoningItem[\"visibility\"] {\n if (hasRedacted) return \"redacted\";\n if (hasThinking) return \"full\";\n return \"opaque\";\n}\n\n// ── Content block 构造 helper ─────────────────────────────────\n\nexport function textBlock(text: string): ContentBlock & { type: \"text\" } {\n return { type: \"text\", text };\n}\n\nexport function jsonBlock(json: unknown): ContentBlock & { type: \"json\" } {\n return { type: \"json\", json };\n}\n\nexport function imageBlock(imageUrl: string): ContentBlock & { type: \"image\" } {\n return { type: \"image\", imageUrl };\n}\n\nexport function opaqueBlock(payload: unknown): ContentBlock & { type: \"opaque\" } {\n return { type: \"opaque\", payload };\n}\n\n// ── Item 构造 helper ──────────────────────────────────────────\n\nexport function messageItem(\n content: ContentBlock[],\n overrides?: Partial<Omit<MessageItem, \"type\" | \"content\">>,\n): MessageItem {\n return {\n type: \"message\",\n role: \"assistant\",\n ...overrides,\n content,\n };\n}\n\nexport function reasoningItem(\n content: ContentBlock[],\n visibility: ReasoningItem[\"visibility\"] = \"full\",\n id?: string,\n): ReasoningItem {\n return {\n type: \"reasoning\",\n id,\n visibility,\n content,\n };\n}\n\nexport function toolCallItem(id: string, name: string, argumentsText: string, argumentsJson?: unknown): ToolCallItem {\n return {\n type: \"tool_call\",\n id,\n name,\n argumentsText,\n argumentsJson,\n };\n}\n\nexport function toolResultItem(\n callId: string,\n toolName: string,\n outcome: ToolResultItem[\"outcome\"],\n content: ContentBlock[],\n): ToolResultItem {\n return {\n type: \"tool_result\",\n callId,\n toolName,\n outcome,\n content,\n };\n}\n\nexport function opaqueItem(\n source: OpaqueItem[\"source\"],\n purpose: OpaqueItem[\"purpose\"],\n payload: unknown,\n id?: string,\n): OpaqueItem {\n return {\n type: \"opaque\",\n id,\n source,\n purpose,\n payload,\n };\n}\n\n// ── Replay 构造工具 ──────────────────────────────────────────\n\n/**\n * 从 output items 构建标准 replay items。\n * 简单场景下 replay 与 output 一致。\n * 复杂场景(需要 opaque continuation)由 adapter 自行扩展。\n */\nexport function replayFromOutput(output: readonly OutputItem[]): ReplayItem[] {\n return output.map((item): InputItem => {\n switch (item.type) {\n case \"message\":\n case \"reasoning\":\n case \"tool_call\":\n return item as InputItem;\n case \"opaque\":\n return item;\n }\n });\n}\n\n// ── Content block 提取 helper ──────────────────────────────────\n\n/**\n * 将单个 ContentBlock 转为纯文本。\n * text 块直接返回文本,json 块序列化,其余返回空串。\n */\nexport function blockToText(b: ContentBlock): string {\n if (b.type === \"text\") return b.text;\n if (b.type === \"json\") return JSON.stringify(b.json);\n return \"\";\n}\n\n/**\n * 将 ContentBlock 数组拼接为纯文本,块间以换行符分隔。\n */\nexport function contentBlocksToText(blocks: ContentBlock[]): string {\n return blocks.map(blockToText).join(\"\\n\");\n}\n\n/**\n * 将 instructions(string | InstructionBlock[])归一化为纯文本。\n */\nexport function instructionsToText(instructions: string | InstructionBlock[]): string {\n return typeof instructions === \"string\" ? instructions : contentBlocksToText(instructions);\n}\n\n// ── Output 文本提取 ───────────────────────────────────────────\n\n/**\n * 从 OutputItem 数组中提取所有 message 类型 item 的文本内容。\n */\nexport function extractText(output: OutputItem[]): string {\n return output\n .filter((item): item is MessageItem => item.type === \"message\")\n .flatMap((m) => m.content)\n .filter((b): b is ContentBlock & { type: \"text\" } => b.type === \"text\")\n .map((b) => b.text)\n .join(\"\");\n}\n","/**\n * 辅助信息采集器 (AuxiliaryCollector)\n *\n * 为 usage、billing、providerMetadata 提供统一的 best-effort 采集。\n *\n * 采集优先级(分层):\n * 1. 主响应 body / terminal event\n * 2. headers / trailers\n * 3. SDK metadata\n * 4. 一次 follow-up lookup\n * 5. derived estimate\n *\n * 约束:\n * - lookup 最多一次有界补查\n * - lookup 失败只记录 warning\n * - 不阻断主生成链路\n */\n\nimport type { Usage, BillingInfo, AuxiliaryInfo } from \"../types/index.js\";\n\n// ── 来源类型 ──────────────────────────────────────────────────\n\nexport type UsageSource = NonNullable<AuxiliaryInfo[\"usageSource\"]>;\nexport type BillingSource = NonNullable<AuxiliaryInfo[\"billingSource\"]>;\n\nexport type LookupResult = {\n usage?: Partial<Usage>;\n billing?: Partial<BillingInfo>;\n providerMetadata?: Record<string, unknown>;\n};\n\n// ── Collector ─────────────────────────────────────────────────\n\nexport class AuxiliaryCollector {\n private usage: Partial<Usage> = {};\n private usageSource: UsageSource | undefined;\n private billing: Partial<BillingInfo> | undefined;\n private billingSource: BillingSource | undefined;\n private providerMetadata: Record<string, unknown> = {};\n private providerUsage: unknown;\n private providerBilling: unknown;\n private warnings: string[] = [];\n private lookupAttempted = false;\n\n // ── 记录方法 ──────────────────────────────────────────────\n\n /**\n * 记录 usage 信息。\n * 后调用的覆盖先调用的(优先级由调用方控制)。\n */\n recordUsage(usage: Partial<Usage>, source: UsageSource, raw?: unknown): this {\n this.usage = { ...this.usage, ...usage };\n this.usageSource = source;\n if (raw !== undefined) this.providerUsage = raw;\n return this;\n }\n\n /**\n * 记录 billing 信息。\n * 后调用的覆盖先调用的。\n */\n recordBilling(billing: Partial<BillingInfo>, source: BillingSource, raw?: unknown): this {\n this.billing = { ...this.billing, ...billing };\n this.billingSource = source;\n if (raw !== undefined) this.providerBilling = raw;\n return this;\n }\n\n /**\n * 记录 provider 元数据(非 canonical 的 key-value 信息)。\n */\n recordMetadata(metadata: Record<string, unknown>): this {\n this.providerMetadata = { ...this.providerMetadata, ...metadata };\n return this;\n }\n\n /**\n * 记录一条 warning。\n */\n recordWarning(message: string): this {\n this.warnings.push(message);\n return this;\n }\n\n // ── 有界 Lookup ───────────────────────────────────────────\n\n /**\n * 执行一次有界 follow-up lookup。\n * 最多调用一次;后续调用被忽略。\n * lookup 失败(抛错)仅记录 warning,不传播异常。\n */\n async tryLookup(lookupFn: () => Promise<LookupResult>, timeoutMs = 5_000): Promise<void> {\n if (this.lookupAttempted) return;\n this.lookupAttempted = true;\n\n try {\n const result = await withTimeout(lookupFn(), timeoutMs);\n if (result.usage) {\n this.recordUsage(result.usage, \"lookup\", result.usage);\n }\n if (result.billing) {\n const bill: Partial<BillingInfo> = {\n ...result.billing,\n source: result.billing?.source ?? \"lookup\",\n };\n this.recordBilling(bill, \"lookup\", result.billing);\n }\n if (result.providerMetadata) {\n this.recordMetadata(result.providerMetadata);\n }\n } catch (err) {\n this.recordWarning(`Auxiliary lookup failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // ── 构建最终结果 ──────────────────────────────────────────\n\n /**\n * 构建最终的 usage / billing / auxiliary。\n * 所有字段均为可选的 — 拿不到就不给。\n */\n build(): { usage?: Usage; billing?: BillingInfo; auxiliary?: AuxiliaryInfo; warnings?: string[] } {\n const result: { usage?: Usage; billing?: BillingInfo; auxiliary?: AuxiliaryInfo; warnings?: string[] } = {};\n\n if (Object.keys(this.usage).length > 0) {\n result.usage = this.usage as Usage;\n }\n\n if (this.billing) {\n result.billing = this.billing as BillingInfo;\n }\n\n const aux: AuxiliaryInfo = {};\n if (this.usageSource) aux.usageSource = this.usageSource;\n if (this.billingSource) aux.billingSource = this.billingSource;\n if (this.providerUsage !== undefined) aux.providerUsage = this.providerUsage;\n if (this.providerBilling !== undefined) aux.providerBilling = this.providerBilling;\n if (Object.keys(this.providerMetadata).length > 0) aux.providerMetadata = this.providerMetadata;\n\n if (Object.keys(aux).length > 0) {\n result.auxiliary = aux;\n }\n\n if (this.warnings.length > 0) {\n result.warnings = [...this.warnings];\n }\n\n return result;\n }\n\n /**\n * 已使用的来源列表(用于 debugging)。\n */\n get sources(): { usage?: UsageSource; billing?: BillingSource } {\n return { usage: this.usageSource, billing: this.billingSource };\n }\n}\n\n// ── Helper ────────────────────────────────────────────────────\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return Promise.race([\n promise,\n new Promise<T>((_, reject) => setTimeout(() => reject(new Error(`Lookup timed out after ${ms}ms`)), ms)),\n ]);\n}\n","import { WarningCode } from \"../core/errors.js\";\nimport type { EventFactory } from \"../core/event-factory.js\";\nimport type {\n AIStreamEvent,\n BillingInfo,\n NormalizedRequest,\n Usage,\n AuxiliaryInfo,\n BackendTrace,\n} from \"../types/index.js\";\nimport { AuxiliaryCollector, type BillingSource, type LookupResult, type UsageSource } from \"./auxiliary-collector.js\";\n\ntype MaybePromise<T> = T | Promise<T>;\n\nexport type BillingPostprocessHook = (context: {\n request: NormalizedRequest;\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: AuxiliaryInfo;\n}) => MaybePromise<Partial<BillingInfo> | undefined>;\n\nexport type AuxiliaryFinalizeOptions = {\n lookup?: () => Promise<LookupResult>;\n lookupTimeoutMs?: number;\n postprocessBilling?: BillingPostprocessHook;\n postprocessBillingSource?: BillingSource;\n};\n\nexport type AuxiliaryFinalizeResult = {\n events: AIStreamEvent[];\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: AuxiliaryInfo;\n warnings?: string[];\n metadataSources?: string[];\n};\n\nexport class AdapterAuxiliaryState {\n private readonly collector = new AuxiliaryCollector();\n private readonly metadataSources = new Set<string>();\n\n constructor(private readonly request: NormalizedRequest) {}\n\n recordUsage(usage: Partial<Usage>, source: UsageSource, raw?: unknown): void {\n if (this.request.include?.usage === \"off\" || isEmptyRecord(usage)) return;\n this.collector.recordUsage(usage, source, raw);\n }\n\n recordBilling(billing: Partial<BillingInfo>, source: BillingSource, raw?: unknown): void {\n if (this.request.include?.billing === \"off\" || isEmptyRecord(billing)) return;\n this.collector.recordBilling(billing, source, raw);\n }\n\n recordProviderMetadata(source: string, metadata: Record<string, unknown> | undefined): void {\n if (this.request.include?.providerMetadata === \"off\" || !metadata || isEmptyRecord(metadata)) return;\n this.collector.recordMetadata(metadata);\n this.metadataSources.add(source);\n }\n\n async finalize(factory: EventFactory, options: AuxiliaryFinalizeOptions = {}): Promise<AuxiliaryFinalizeResult> {\n if (options.lookup && this.shouldAttemptLookup()) {\n await this.collector.tryLookup(options.lookup, options.lookupTimeoutMs);\n }\n\n if (this.request.include?.billing !== \"off\" && options.postprocessBilling) {\n const snapshot = this.collector.build();\n if (!snapshot.billing) {\n const derived = await options.postprocessBilling({\n request: this.request,\n usage: snapshot.usage,\n billing: snapshot.billing,\n auxiliary: snapshot.auxiliary,\n });\n if (derived && !isEmptyRecord(derived)) {\n this.collector.recordBilling(\n {\n ...derived,\n isEstimated: derived.isEstimated ?? true,\n source: derived.source ?? \"derived\",\n },\n options.postprocessBillingSource ?? \"derived\",\n derived,\n );\n }\n }\n }\n\n const built = this.collector.build();\n const events: AIStreamEvent[] = [];\n\n if (built.usage || built.billing || built.auxiliary) {\n events.push(\n factory.responseAuxiliary({\n usage: built.usage,\n billing: built.billing,\n auxiliary: built.auxiliary,\n }),\n );\n }\n\n if (this.request.include?.usage !== \"off\" && !built.usage) {\n events.push(\n factory.responseWarning(\"Usage information was not provided by the provider\", WarningCode.USAGE_MISSING),\n );\n }\n\n if (this.request.include?.billing !== \"off\") {\n if (!built.billing) {\n events.push(\n factory.responseWarning(\"Billing information was not provided by the provider\", WarningCode.BILLING_MISSING),\n );\n } else if (built.billing.isEstimated) {\n events.push(factory.responseWarning(\"Billing amount is an estimate\", WarningCode.BILLING_ESTIMATED));\n }\n }\n\n return {\n events,\n usage: built.usage,\n billing: built.billing,\n auxiliary: built.auxiliary,\n warnings: built.warnings,\n metadataSources: this.metadataSources.size > 0 ? [...this.metadataSources] : undefined,\n };\n }\n\n private shouldAttemptLookup(): boolean {\n if (\n this.request.include?.usage === \"off\" &&\n this.request.include?.billing === \"off\" &&\n this.request.include?.providerMetadata === \"off\"\n ) {\n return false;\n }\n\n const snapshot = this.collector.build();\n return (\n (this.request.include?.usage !== \"off\" && !snapshot.usage) ||\n (this.request.include?.billing !== \"off\" && !snapshot.billing) ||\n (this.request.include?.providerMetadata !== \"off\" && !snapshot.auxiliary?.providerMetadata)\n );\n }\n}\n\nexport function emitMalformedStreamWarning(\n factory: EventFactory,\n options: {\n count: number;\n providerLabel: string;\n transportLabel: string;\n },\n): AIStreamEvent | undefined {\n if (options.count < 1) return undefined;\n return factory.responseWarning(\n `Skipped ${options.count} malformed ${options.providerLabel} ${options.transportLabel}`,\n \"STREAM_ERROR\",\n );\n}\n\nexport function metadataSourceList(\n ...groups: Array<Array<NonNullable<BackendTrace[\"metadataSources\"]>[number]> | undefined>\n): string[] | undefined {\n const sources = new Set<string>();\n\n for (const group of groups) {\n if (!group) continue;\n for (const source of group) {\n sources.add(source);\n }\n }\n\n return sources.size > 0 ? [...sources] : undefined;\n}\n\nfunction isEmptyRecord(value: object): boolean {\n return Object.keys(value).length === 0;\n}\n","/**\n * Adapter 抽象基类\n *\n * 约定 adapter 的内部职责分层(build / invoke / parse / emit):\n * 1. buildRequest — 将 NormalizedRequest 转换为 provider 请求格式\n * 2. invokeProvider — 调用 provider API\n * 3. parseResponse — 解析 provider 响应为 canonical 中间态\n * 4. emitEvents — 产出 canonical 事件流\n *\n * 子类实现 buildRequest() 和 runStream(),\n * runStream 返回 AsyncIterable,事件实时发射给消费者。\n */\n\nimport type {\n NormalizedRequest,\n BackendAdapter,\n AIStreamEvent,\n AIResponse,\n AuxiliaryInfo,\n OutputItem,\n ReplayItem,\n StopReason,\n Usage,\n BillingInfo,\n ToolCallItem,\n} from \"../types/index.js\";\nimport { createEventFactory } from \"../core/event-factory.js\";\nimport { AIMappingError, AIRequestError, AIStreamError } from \"../core/errors.js\";\nimport type { EventFactory } from \"../core/event-factory.js\";\nimport { extractText } from \"./mapping.js\";\nimport { AdapterAuxiliaryState } from \"./adapter-auxiliary.js\";\n\n// ── Adapter 解析中间结果 ──────────────────────────────────────\n\nexport type ProviderResponse = unknown;\n\n/**\n * adapter 完成一轮处理后返回的最终结果。\n * 用于 buildResponse() 构建 AIResponse。\n */\nexport type StreamResult = {\n output: OutputItem[];\n replay: ReplayItem[];\n stopReason?: StopReason;\n usage?: Usage;\n billing?: BillingInfo;\n providerMetadata?: Record<string, unknown>;\n auxiliary?: Partial<AuxiliaryInfo>;\n warnings?: string[];\n metadataSources?: string[];\n rawResponseId?: string;\n};\n\n// ── 抽象基类 ──────────────────────────────────────────────────\n\nexport abstract class AdapterBase implements BackendAdapter {\n abstract readonly kind: \"chat-completions\" | \"messages\" | \"responses\" | \"ollama\" | \"mock\";\n abstract readonly nativeStreaming: boolean;\n\n /**\n * stream 模板方法:\n * 1. 创建事件工厂,发射 response.started\n * 2. 构建 provider 请求\n * 3. 委托 runStream 发射全部流事件(含 response.completed)\n */\n async *stream(request: NormalizedRequest): AsyncIterable<AIStreamEvent> {\n const factory = createEventFactory({\n responseId: request.requestId,\n backend: { kind: this.kind, isSynthetic: !this.nativeStreaming },\n });\n\n yield factory.responseStarted(request.model);\n\n try {\n const providerRequest = await this.buildRequest(request);\n yield* this.runStream(providerRequest, factory, request);\n } catch (err) {\n if (err instanceof AIRequestError || err instanceof AIStreamError || err instanceof AIMappingError) {\n throw err;\n }\n yield factory.responseWarning(err instanceof Error ? err.message : String(err), \"PROVIDER_ERROR\");\n yield factory.responseCompleted(this.buildResponse(request, { output: [], replay: [] }, factory));\n }\n }\n\n // ── 子类必须实现 ──────────────────────────────────────────\n\n /** 将 NormalizedRequest 转换为 provider 请求格式。 */\n protected abstract buildRequest(request: NormalizedRequest): ProviderResponse | Promise<ProviderResponse>;\n\n /**\n * 执行流式请求,发射全部事件(含 response.completed)。\n * 子类负责:\n * - 调用 provider\n * - 解析每个 chunk\n * - 通过 factory 发射 item 事件\n * - 构建 StreamResult\n * - 发射 factory.responseCompleted(buildResponse(…))\n */\n protected abstract runStream(\n providerRequest: ProviderResponse,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent>;\n\n // ── 共享构造方法 ──────────────────────────────────────────\n\n /**\n * 从 StreamResult 构建完整 AIResponse。\n * 子类可在返回前自定义覆盖。\n */\n protected buildResponse(request: NormalizedRequest, result: StreamResult, _factory: EventFactory): AIResponse {\n const text = this.extractText(result.output);\n const warnings = mergeWarnings(result.warnings, _factory.warnings);\n const auxiliary = mergeAuxiliary(\n result.auxiliary,\n result.providerMetadata ? { providerMetadata: result.providerMetadata } : undefined,\n );\n\n return {\n id: request.requestId,\n output: result.output,\n replay: result.replay,\n text,\n toolCalls: result.output.filter((item): item is ToolCallItem => item.type === \"tool_call\"),\n stopReason: result.stopReason,\n usage: result.usage,\n billing: result.billing,\n auxiliary,\n warnings,\n backend: {\n requestId: request.requestId,\n rawResponseId: result.rawResponseId,\n adapter: this.kind,\n isSyntheticStream: !this.nativeStreaming,\n metadataSources: result.metadataSources,\n warnings,\n },\n };\n }\n\n /** 从 output items 中提取文本内容。 */\n protected extractText(output: OutputItem[]): string {\n return extractText(output);\n }\n\n protected createAuxiliaryState(request: NormalizedRequest): AdapterAuxiliaryState {\n return new AdapterAuxiliaryState(request);\n }\n}\n\nfunction mergeAuxiliary(base?: Partial<AuxiliaryInfo>, patch?: Partial<AuxiliaryInfo>): AuxiliaryInfo | undefined {\n if (!base && !patch) return undefined;\n\n const merged: AuxiliaryInfo = {\n ...base,\n ...patch,\n };\n\n if (base?.providerMetadata || patch?.providerMetadata) {\n merged.providerMetadata = {\n ...base?.providerMetadata,\n ...patch?.providerMetadata,\n };\n }\n\n return merged;\n}\n\nfunction mergeWarnings(...groups: Array<string[] | undefined>): string[] | undefined {\n const merged: string[] = [];\n\n for (const group of groups) {\n if (!group) continue;\n for (const warning of group) {\n if (!merged.includes(warning)) {\n merged.push(warning);\n }\n }\n }\n\n return merged.length > 0 ? merged : undefined;\n}\n","/**\n * Provider usage → canonical Usage 映射\n *\n * best-effort 提取 reasoning / cache / billable 等扩展字段。\n */\n\nimport type { Usage } from \"../types/index.js\";\n\nfunction num(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction record(obj: Record<string, number | undefined>): Partial<Usage> {\n const out: Partial<Usage> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n (out as Record<string, number>)[key] = value;\n }\n }\n return out;\n}\n\nfunction billableFromOpenAIStyle(\n inputTokens: number | undefined,\n outputTokens: number | undefined,\n cachedInputTokens: number | undefined,\n reasoningTokens: number | undefined,\n): Pick<Usage, \"billableInputTokens\" | \"billableOutputTokens\"> {\n let billableInputTokens: number | undefined;\n if (inputTokens !== undefined) {\n billableInputTokens =\n cachedInputTokens !== undefined ? Math.max(0, inputTokens - cachedInputTokens) : inputTokens;\n }\n\n let billableOutputTokens: number | undefined;\n if (outputTokens !== undefined) {\n billableOutputTokens =\n reasoningTokens !== undefined ? Math.max(0, outputTokens - reasoningTokens) : outputTokens;\n }\n\n return record({ billableInputTokens, billableOutputTokens });\n}\n\n/** OpenAI Chat Completions `usage` */\nexport function usageFromChatCompletions(raw: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n prompt_tokens_details?: { cached_tokens?: number; [key: string]: unknown };\n completion_tokens_details?: { reasoning_tokens?: number; [key: string]: unknown };\n}): Partial<Usage> {\n const inputTokens = num(raw.prompt_tokens);\n const outputTokens = num(raw.completion_tokens);\n const cachedInputTokens = num(raw.prompt_tokens_details?.cached_tokens);\n const reasoningTokens = num(raw.completion_tokens_details?.reasoning_tokens);\n const totalTokens =\n num(raw.total_tokens) ??\n (inputTokens !== undefined && outputTokens !== undefined ? inputTokens + outputTokens : undefined);\n\n return record({\n inputTokens,\n outputTokens,\n totalTokens,\n cachedInputTokens,\n reasoningTokens,\n ...billableFromOpenAIStyle(inputTokens, outputTokens, cachedInputTokens, reasoningTokens),\n });\n}\n\n/** OpenAI Responses API `usage` */\nexport function usageFromOpenAIResponses(raw: {\n input_tokens?: number;\n output_tokens?: number;\n total_tokens?: number;\n input_tokens_details?: { cached_tokens?: number; [key: string]: unknown };\n output_tokens_details?: { reasoning_tokens?: number; [key: string]: unknown };\n [key: string]: unknown;\n}): Partial<Usage> {\n const inputTokens = num(raw.input_tokens);\n const outputTokens = num(raw.output_tokens);\n const cachedInputTokens = num(raw.input_tokens_details?.cached_tokens);\n const reasoningTokens = num(raw.output_tokens_details?.reasoning_tokens);\n const totalTokens =\n num(raw.total_tokens) ??\n (inputTokens !== undefined && outputTokens !== undefined ? inputTokens + outputTokens : undefined);\n\n return record({\n inputTokens,\n outputTokens,\n totalTokens,\n cachedInputTokens,\n reasoningTokens,\n ...billableFromOpenAIStyle(inputTokens, outputTokens, cachedInputTokens, reasoningTokens),\n });\n}\n\n/** Anthropic Messages `usage`(message_start / message_delta) */\nexport function usageFromAnthropicMessages(raw: {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n [key: string]: unknown;\n}): Partial<Usage> {\n const inputTokens = num(raw.input_tokens);\n const outputTokens = num(raw.output_tokens);\n const cacheWriteInputTokens = num(raw.cache_creation_input_tokens);\n const cachedInputTokens = num(raw.cache_read_input_tokens);\n\n const inputParts = [inputTokens, cacheWriteInputTokens, cachedInputTokens].filter(\n (n): n is number => n !== undefined,\n );\n const summedInput = inputParts.length > 0 ? inputParts.reduce((sum, n) => sum + n, 0) : undefined;\n const totalTokens =\n summedInput !== undefined && outputTokens !== undefined ? summedInput + outputTokens : undefined;\n\n let billableInputTokens: number | undefined;\n if (inputTokens !== undefined || cacheWriteInputTokens !== undefined) {\n billableInputTokens = (inputTokens ?? 0) + (cacheWriteInputTokens ?? 0);\n }\n\n return record({\n inputTokens,\n outputTokens,\n totalTokens,\n cachedInputTokens,\n cacheWriteInputTokens,\n billableInputTokens,\n billableOutputTokens: outputTokens,\n });\n}\n\n/** Ollama 流式 chunk(无 cache / reasoning 细分时仅填基础与 billable 镜像) */\nexport function usageFromOllama(raw: {\n prompt_eval_count?: number;\n eval_count?: number;\n}): Partial<Usage> {\n const inputTokens = num(raw.prompt_eval_count);\n const outputTokens = num(raw.eval_count);\n const totalTokens =\n inputTokens !== undefined && outputTokens !== undefined ? inputTokens + outputTokens : undefined;\n\n return record({\n inputTokens,\n outputTokens,\n totalTokens,\n billableInputTokens: inputTokens,\n billableOutputTokens: outputTokens,\n });\n}","/**\n * 通用 SSE (Server-Sent Events) 解析器\n *\n * 解析标准 SSE 格式(event: + data: 行),适用于:\n * - Anthropic Messages API (messages.ts)\n * - OpenAI Responses API (responses.ts)\n *\n * 注意:OpenAI Chat Completions API 使用简化 SSE(仅有 data: 行),\n * 由 chat-completions.ts 中的 parseChatSSE 处理。\n *\n * 用法:\n * ```ts\n * const { events, rest } = parseSSEEvents(buffer);\n * for (const ev of events) {\n * // ev.type — 事件类型字符串\n * // ev.data — 已解析的 JSON 数据\n * }\n * // rest 是未处理的剩余 buffer,需要累积到下次调用\n * ```\n */\n\nexport type SSEEvent = { type: string; data: unknown };\n\nexport type SSEParseResult = {\n events: SSEEvent[];\n rest: string;\n malformedEvents: number;\n};\n\n/**\n * 将 SSE 文本块解析为事件数组。\n * 累积事件行直到遇到空行,支持 [DONE] 标记。\n * 返回已解析的事件和未处理的剩余 buffer(用于增量解析)。\n *\n * 关键行为:\n * - 只解析完整的 event(以空行结尾)\n * - 未完成的行保留在 rest 中,等待下次 chunk 补全\n * - 支持跨 chunk 的 event 分片\n */\nexport function parseSSEEvents(chunk: string): SSEParseResult {\n const events: SSEEvent[] = [];\n let eventType = \"\";\n let dataLines: string[] = [];\n let consumedUntil = 0;\n let cursor = 0;\n let malformedEvents = 0;\n\n while (cursor < chunk.length) {\n const lineEnd = chunk.indexOf(\"\\n\", cursor);\n if (lineEnd === -1) break;\n\n let line = chunk.slice(cursor, lineEnd);\n cursor = lineEnd + 1;\n\n if (line.endsWith(\"\\r\")) {\n line = line.slice(0, -1);\n }\n\n if (line.startsWith(\"event: \")) {\n eventType = line.slice(7).trim();\n } else if (line.startsWith(\"data: \")) {\n dataLines.push(line.slice(6));\n } else if (line === \"\" && eventType && dataLines.length > 0) {\n // 完整的 event(以空行结尾)\n const dataStr = dataLines.join(\"\\n\");\n if (dataStr === \"[DONE]\") {\n eventType = \"\";\n dataLines = [];\n consumedUntil = cursor;\n continue;\n }\n try {\n const data = JSON.parse(dataStr);\n events.push({ type: eventType, data });\n } catch {\n malformedEvents++;\n }\n eventType = \"\";\n dataLines = [];\n consumedUntil = cursor;\n } else if (line === \"\" && !eventType && dataLines.length === 0) {\n consumedUntil = cursor;\n }\n }\n\n return { events, rest: chunk.slice(consumedUntil), malformedEvents };\n}\n","/**\n * Responses Adapter\n *\n * 接入 OpenAI Responses API (responses 端点)。\n * 职责分层:\n * 1. buildRequest — 将 NormalizedRequest 转换为 Responses API 请求\n * 2. runStream — 调用 API、解析 SSE、发射 canonical 事件\n *\n * 支持消息流 / reasoning 流 / tool_call 流及高保真 replay。\n */\n\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { AIRequestError } from \"../core/errors.js\";\nimport {\n textBlock,\n messageItem,\n reasoningItem,\n toolCallItem,\n opaqueItem,\n replayFromOutput,\n blockToText,\n contentBlocksToText,\n} from \"../helpers/mapping.js\";\nimport { emitMalformedStreamWarning } from \"../helpers/adapter-auxiliary.js\";\nimport { usageFromOpenAIResponses } from \"../helpers/usage-mapping.js\";\n\nimport { parseSSEEvents } from \"../helpers/sse-parser.js\";\n\nimport type { NormalizedRequest, AIStreamEvent, EventFactory, OutputItem, FetchFn } from \"../index.js\";\n\n// ── 类型 ──────────────────────────────────────────────────────\n\nexport type ResponsesAdapterOptions = {\n apiKey: string;\n baseUrl?: string;\n /** 可注入自定义 fetch 实现(用于测试/代理) */\n fetch?: FetchFn;\n};\n\n// ── Responses API 请求类型 ────────────────────────────────────\n\ntype ResponsesAPIRequest = {\n model: string;\n input: ResponsesInputItem[];\n instructions?: string;\n tools?: ResponsesTool[];\n tool_choice?: \"auto\" | \"none\" | { type: \"function\"; name: string };\n metadata?: Record<string, string>;\n temperature?: number;\n max_output_tokens?: number;\n stream: true;\n};\n\ntype ResponsesInputItem =\n | { type: \"message\"; role: \"user\" | \"assistant\"; content: string }\n | { type: \"message\"; role: \"assistant\"; content: ResponsesContentBlock[] }\n | { type: \"function_call\"; id: string; name: string; arguments: string; call_id?: string }\n | { type: \"function_call_output\"; call_id: string; output: string }\n | { type: \"reasoning\"; content: ResponsesContentBlock[] }\n | { type: \"item_reference\"; id: string };\n\ntype ResponsesContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"reasoning\"; text: string }\n | { type: \"refusal\"; refusal: string };\n\ntype ResponsesTool = {\n type: \"function\";\n name: string;\n description?: string;\n input_schema: Record<string, unknown>;\n};\n\nfunction ensureResponsesTextBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): import(\"../index.js\").ContentBlock[] {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (!block) continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n throw new AIRequestError(\n `responses does not support ${field}[${i}] of type \"${block.type}\"; only text/json blocks are supported`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n }\n\n return blocks;\n}\n\nfunction ensureResponsesReasoningBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): Array<Extract<import(\"../index.js\").ContentBlock, { type: \"text\" }>> {\n return blocks.map((block, index) => {\n if (block.type !== \"text\") {\n throw new AIRequestError(\n `responses does not support ${field}[${index}] of type \"${block.type}\"; reasoning only supports text blocks`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n\n return block;\n });\n}\n\nfunction instructionsToResponsesText(instructions: string | import(\"../index.js\").InstructionBlock[]): string {\n return typeof instructions === \"string\"\n ? instructions\n : contentBlocksToText(ensureResponsesTextBlocks(instructions, \"instructions\"));\n}\n\nfunction assertResponsesToolResultOutcome(outcome: import(\"../index.js\").ToolResultItem[\"outcome\"]): void {\n if (outcome !== \"success\") {\n throw new AIRequestError(\n `responses does not preserve tool_result outcome \"${outcome}\"; only \"success\" is supported`,\n \"UNSUPPORTED_TOOL_RESULT_OUTCOME\",\n );\n }\n}\n\n// ── SSE 事件类型 ──────────────────────────────────────────────\n\ntype ResponsesSSEEvent =\n | { type: \"response.output_item.added\"; data: { item: { id: string; type: string; [key: string]: unknown } } }\n | { type: \"response.output_text.delta\"; data: { item_id: string; delta: string } }\n | { type: \"response.output_text.done\"; data: { item_id: string; text: string } }\n | { type: \"response.reasoning.delta\"; data: { item_id: string; delta: string } }\n | { type: \"response.reasoning.done\"; data: { item_id: string; text: string } }\n | { type: \"response.tool_call.delta\"; data: { item_id: string; delta: { arguments?: string } } }\n | { type: \"response.tool_call.done\"; data: { item_id: string; arguments?: string; name?: string } }\n | { type: \"response.completed\"; data: { response: ResponsesAPIResponse } }\n | { type: \"error\"; data: { message: string; code?: string } };\n\ntype ResponsesAPIResponse = {\n id: string;\n model: string;\n output: ResponsesAPIOutputItem[];\n usage?: {\n input_tokens: number;\n output_tokens: number;\n total_tokens: number;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n};\n\ntype ResponsesAPIOutputItem = {\n id: string;\n type: \"message\" | \"reasoning\" | \"function_call\";\n role?: string;\n content?: ResponsesContentBlock[];\n name?: string;\n arguments?: string;\n status?: string;\n};\n\n// ── SSE 解析 ──────────────────────────────────────────────────\n\nfunction parseSSE(chunk: string): { events: ResponsesSSEEvent[]; rest: string; malformedEvents: number } {\n const result = parseSSEEvents(chunk);\n return { events: result.events as ResponsesSSEEvent[], rest: result.rest, malformedEvents: result.malformedEvents };\n}\n\nfunction isReplayCanonicalInput(item: ResponsesInputItem): boolean {\n return (\n (item.type === \"message\" && item.role === \"assistant\") || item.type === \"reasoning\" || item.type === \"function_call\"\n );\n}\n\nfunction rollbackTrailingReplayCanonicalItems(input: ResponsesInputItem[]): void {\n while (input.length > 0) {\n const last = input[input.length - 1];\n if (!last || !isReplayCanonicalInput(last)) break;\n input.pop();\n }\n}\n\n// ── Content block 映射 ─────────────────────────────────────────\n\nfunction canonicalToResponsesBlock(b: import(\"../index.js\").ContentBlock): ResponsesContentBlock {\n if (b.type === \"text\") return { type: \"text\", text: b.text };\n if (b.type === \"json\") return { type: \"text\", text: JSON.stringify(b.json) };\n throw new AIRequestError(\n `responses does not support content block type \"${b.type}\" in canonical mapping`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n}\n\n// ── Adapter ───────────────────────────────────────────────────\n\nexport class ResponsesAdapter extends AdapterBase {\n readonly kind = \"responses\" as const;\n readonly nativeStreaming = true;\n\n private apiKey: string;\n private baseUrl: string;\n private fetchFn: FetchFn;\n\n constructor(options: ResponsesAdapterOptions) {\n super();\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://api.openai.com/v1\";\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n // ── buildRequest ──────────────────────────────────────────\n\n protected buildRequest(request: NormalizedRequest): ResponsesAPIRequest {\n const input: ResponsesInputItem[] = [];\n\n for (const item of request.input) {\n switch (item.type) {\n case \"message\": {\n // Responses API 中只有 assistant 角色支持 content blocks\n if (item.role === \"assistant\") {\n const blocks = ensureResponsesTextBlocks(item.content, `assistant message (${item.role}) content`).map(\n canonicalToResponsesBlock,\n );\n input.push({ type: \"message\", role: item.role, content: blocks });\n } else {\n input.push({\n type: \"message\",\n role: item.role,\n content: contentBlocksToText(\n ensureResponsesTextBlocks(item.content, `input message (${item.role}) content`),\n ),\n });\n }\n break;\n }\n case \"reasoning\": {\n const blocks = ensureResponsesReasoningBlocks(item.content, \"reasoning content\").map(\n (b): ResponsesContentBlock => ({ type: \"reasoning\", text: b.text }),\n );\n input.push({ type: \"reasoning\", content: blocks });\n break;\n }\n case \"tool_call\": {\n input.push({\n type: \"function_call\",\n id: item.id,\n name: item.name,\n arguments: item.argumentsText,\n });\n break;\n }\n case \"tool_result\": {\n assertResponsesToolResultOutcome(item.outcome);\n const output = ensureResponsesTextBlocks(item.content, `tool_result ${item.callId} content`)\n .map(blockToText)\n .join(\"\\n\");\n input.push({\n type: \"function_call_output\",\n call_id: item.callId,\n output,\n });\n break;\n }\n case \"opaque\": {\n // opaque items with item_reference purpose can be passed through\n if (\n item.source === \"responses\" &&\n item.purpose === \"replay\" &&\n typeof item.payload === \"object\" &&\n item.payload !== null &&\n \"id\" in (item.payload as Record<string, unknown>)\n ) {\n const { id } = item.payload as Record<string, unknown>;\n if (typeof id === \"string\") {\n rollbackTrailingReplayCanonicalItems(input);\n input.push({ type: \"item_reference\", id });\n }\n }\n break;\n }\n }\n }\n\n const body: ResponsesAPIRequest = {\n model: request.model,\n input,\n stream: true,\n };\n\n if (request.instructions) {\n body.instructions = instructionsToResponsesText(request.instructions);\n }\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map(\n (t): ResponsesTool => ({\n type: \"function\",\n name: t.name,\n description: t.description,\n input_schema: t.inputSchema,\n }),\n );\n }\n\n if (request.toolChoice) {\n if (request.toolChoice === \"auto\") body.tool_choice = \"auto\";\n else if (request.toolChoice === \"none\") body.tool_choice = \"none\";\n else if (request.toolChoice.type === \"tool\") {\n body.tool_choice = { type: \"function\", name: request.toolChoice.name };\n }\n }\n\n if (request.temperature !== undefined) body.temperature = request.temperature;\n if (request.maxOutputTokens !== undefined) body.max_output_tokens = request.maxOutputTokens;\n if (request.metadata) body.metadata = request.metadata;\n\n return body;\n }\n\n // ── runStream ─────────────────────────────────────────────\n\n protected async *runStream(\n providerRequest: ResponsesAPIRequest,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n const auxiliary = this.createAuxiliaryState(request);\n const response = await this.fetchFn(`${this.baseUrl}/responses`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(providerRequest),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"unknown error\");\n throw new Error(`Responses API error ${response.status}: ${errorText}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n // 流式累积状态\n const output: OutputItem[] = [];\n const decoder = new TextDecoder();\n let buffer = \"\";\n let completedResponse: ResponsesAPIResponse | undefined;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { events, rest, malformedEvents } = parseSSE(buffer);\n buffer = rest;\n\n const malformedWarning = emitMalformedStreamWarning(factory, {\n count: malformedEvents,\n providerLabel: \"Responses\",\n transportLabel: \"SSE event(s)\",\n });\n if (malformedWarning) {\n yield malformedWarning;\n }\n\n for (const sseEvent of events) {\n if (sseEvent.type === \"error\") {\n yield factory.responseWarning(sseEvent.data.message, sseEvent.data.code);\n continue;\n }\n\n // item 级事件\n if (sseEvent.type === \"response.output_item.added\") {\n const item = sseEvent.data.item;\n switch (item.type) {\n case \"message\":\n yield factory.messageStarted(item.id);\n break;\n case \"reasoning\":\n yield factory.reasoningStarted(item.id, \"full\");\n break;\n case \"function_call\":\n yield factory.toolCallStarted(item.id, ((item as Record<string, unknown>).name as string) ?? \"unknown\");\n break;\n }\n continue;\n }\n\n if (sseEvent.type === \"response.output_text.delta\") {\n yield factory.messageDelta(sseEvent.data.item_id, sseEvent.data.delta);\n continue;\n }\n\n if (sseEvent.type === \"response.output_text.done\") {\n yield factory.messageCompleted(messageItem([textBlock(sseEvent.data.text)], { id: sseEvent.data.item_id }));\n output.push(messageItem([textBlock(sseEvent.data.text)], { id: sseEvent.data.item_id }));\n continue;\n }\n\n if (sseEvent.type === \"response.reasoning.delta\") {\n yield factory.reasoningDelta(sseEvent.data.item_id, textBlock(sseEvent.data.delta));\n continue;\n }\n\n if (sseEvent.type === \"response.reasoning.done\") {\n yield factory.reasoningCompleted(\n reasoningItem([textBlock(sseEvent.data.text)], \"full\", sseEvent.data.item_id),\n );\n output.push(reasoningItem([textBlock(sseEvent.data.text)], \"full\", sseEvent.data.item_id));\n continue;\n }\n\n if (sseEvent.type === \"response.tool_call.delta\") {\n if (sseEvent.data.delta.arguments) {\n yield factory.toolCallDelta(sseEvent.data.item_id, { argumentsText: sseEvent.data.delta.arguments });\n }\n continue;\n }\n\n if (sseEvent.type === \"response.tool_call.done\") {\n const tcItem = toolCallItem(\n sseEvent.data.item_id,\n sseEvent.data.name ?? \"unknown\",\n sseEvent.data.arguments ?? \"\",\n );\n yield factory.toolCallCompleted(tcItem);\n output.push(tcItem);\n continue;\n }\n\n if (sseEvent.type === \"response.completed\") {\n completedResponse = sseEvent.data.response;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n if (buffer.trim().length > 0) {\n yield factory.responseWarning(\"Stream ended with an incomplete Responses SSE frame\", \"STREAM_ERROR\");\n }\n\n // 解析完成响应中的 usage 和 replay\n let rawResponseId: string | undefined;\n\n if (completedResponse) {\n rawResponseId = completedResponse.id;\n if (completedResponse.usage) {\n auxiliary.recordUsage(usageFromOpenAIResponses(completedResponse.usage), \"final\", completedResponse.usage);\n }\n }\n\n // 构造 replay:在 output 基础上追加 opaque continuation\n const replay = [...replayFromOutput(output)];\n\n // 如果有 provider continuation id,附加 opaque replay item\n if (completedResponse?.id) {\n replay.push(opaqueItem(\"responses\", \"replay\", { id: completedResponse.id }));\n }\n\n // 从 completedResponse 推断 stop reason\n const stopReason = completedResponse ? this.inferStopReason(completedResponse) : undefined;\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId,\n },\n factory,\n ),\n );\n }\n\n // ── 辅助方法 ──────────────────────────────────────────────\n\n private inferStopReason(response: ResponsesAPIResponse): import(\"../index.js\").StopReason {\n const output = response.output;\n if (!output || output.length === 0) return \"unknown\";\n\n // 检查是否有未完成的 function_call\n const hasFunctionCall = output.some((item) => item.type === \"function_call\");\n if (hasFunctionCall) return \"tool_call\";\n\n // 检查最后一条 message 的 status\n const lastMsg = output[output.length - 1];\n if (lastMsg?.status === \"incomplete\") return \"max_output_tokens\";\n\n return \"end_turn\";\n }\n}\n","/**\n * Messages Adapter\n *\n * 接入 Anthropic Messages API (messages 端点)。\n * 支持:\n * - 文本消息流 (text content block)\n * - 思维链流 (thinking content block)\n * - 工具调用流 (tool_use content block)\n * - 高保真 replay(含 opaque continuation)\n * - 能力降级 warning\n */\n\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { AIRequestError } from \"../core/errors.js\";\nimport {\n textBlock,\n messageItem,\n reasoningItem,\n toolCallItem,\n opaqueItem,\n replayFromOutput,\n mapStopReason,\n blockToText,\n contentBlocksToText,\n} from \"../helpers/mapping.js\";\nimport { emitMalformedStreamWarning } from \"../helpers/adapter-auxiliary.js\";\nimport { usageFromAnthropicMessages } from \"../helpers/usage-mapping.js\";\n\nimport { parseSSEEvents } from \"../helpers/sse-parser.js\";\n\nimport type { NormalizedRequest, AIStreamEvent, EventFactory, OutputItem, FetchFn } from \"../index.js\";\n\n// ── 类型 ──────────────────────────────────────────────────────\n\nexport type MessagesAdapterOptions = {\n apiKey: string;\n apiVersion?: string;\n baseUrl?: string;\n /** 可注入自定义 fetch 实现(用于测试/代理) */\n fetch?: FetchFn;\n};\n\n// ── Messages API 请求类型 ────────────────────────────────────\n\ntype MessagesAPIRequest = {\n model: string;\n max_tokens: number;\n messages: MessagesAPIMessage[];\n system?: string;\n tools?: MessagesAPITool[];\n tool_choice?: { type: \"auto\" | \"none\" } | { type: \"tool\"; name: string };\n temperature?: number;\n thinking?: { type: \"enabled\"; budget_tokens: number };\n stream: true;\n};\n\ntype MessagesAPIMessage = {\n role: \"user\" | \"assistant\";\n content: string | MessagesAPIContentBlock[];\n};\n\ntype MessagesAPIContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"thinking\"; thinking: string; signature?: string }\n | { type: \"redacted_thinking\"; data: string }\n | { type: \"tool_use\"; id: string; name: string; input: Record<string, unknown> }\n | { type: \"tool_result\"; tool_use_id: string; content: string | MessagesAPIContentBlock[]; is_error?: boolean };\n\ntype MessagesAPITool = {\n name: string;\n description?: string;\n input_schema: Record<string, unknown>;\n};\n\nfunction ensureMessagesTextBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): import(\"../index.js\").ContentBlock[] {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (!block) continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n throw new AIRequestError(\n `messages does not support ${field}[${i}] of type \"${block.type}\"; only text/json blocks are supported`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n }\n\n return blocks;\n}\n\nfunction ensureMessagesReasoningBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): Array<Extract<import(\"../index.js\").ContentBlock, { type: \"text\" }>> {\n return blocks.map((block, index) => {\n if (block.type !== \"text\") {\n throw new AIRequestError(\n `messages does not support ${field}[${index}] of type \"${block.type}\"; reasoning only supports text blocks`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n\n return block;\n });\n}\n\nfunction instructionsToMessagesText(instructions: string | import(\"../index.js\").InstructionBlock[]): string {\n return typeof instructions === \"string\"\n ? instructions\n : contentBlocksToText(ensureMessagesTextBlocks(instructions, \"instructions\"));\n}\n\nfunction assertMessagesToolResultOutcome(outcome: import(\"../index.js\").ToolResultItem[\"outcome\"]): void {\n if (outcome === \"rejected\") {\n throw new AIRequestError(\n 'messages does not preserve tool_result outcome \"rejected\"; only \"success\" and \"error\" are supported',\n \"UNSUPPORTED_TOOL_RESULT_OUTCOME\",\n );\n }\n}\n\n// ── SSE 事件类型 ──────────────────────────────────────────────\n\ntype MessagesSSEEvent =\n | { type: \"message_start\"; data: { message: MessagesAPIMessageResponse } }\n | { type: \"content_block_start\"; data: { index: number; content_block: { type: string; [key: string]: unknown } } }\n | { type: \"content_block_delta\"; data: { index: number; delta: { type: string; [key: string]: unknown } } }\n | { type: \"content_block_stop\"; data: { index: number } }\n | {\n type: \"message_delta\";\n data: {\n delta: { stop_reason?: string; stop_sequence?: string | null };\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n };\n };\n }\n | { type: \"message_stop\"; data: Record<string, never> }\n | { type: \"ping\"; data: Record<string, never> }\n | { type: \"error\"; data: { error: { type: string; message: string } } };\n\ntype MessagesAPIMessageResponse = {\n id: string;\n type: string;\n role: \"assistant\";\n model: string;\n content: MessagesAPIContentBlock[];\n stop_reason?: \"end_turn\" | \"max_tokens\" | \"tool_use\" | string;\n stop_sequence?: string | null;\n usage: { input_tokens: number; output_tokens: number };\n};\n\n// ── SSE 解析 ──────────────────────────────────────────────────\n\nfunction parseMessagesSSE(chunk: string): { events: MessagesSSEEvent[]; rest: string; malformedEvents: number } {\n const result = parseSSEEvents(chunk);\n return { events: result.events as MessagesSSEEvent[], rest: result.rest, malformedEvents: result.malformedEvents };\n}\n\nfunction rollbackTrailingAssistantMessages(messages: MessagesAPIMessage[]): void {\n while (messages.length > 0 && messages[messages.length - 1]?.role === \"assistant\") {\n messages.pop();\n }\n}\n\n/** 用 response 级别的命名空间合成 content block 的 item ID,避免多轮工具循环 ID 碰撞 */\nfunction synthesizeItemId(kind: \"msg\" | \"reason\" | \"reason-redacted\", blockIndex: number, responseId: string): string {\n return `${kind}-${blockIndex}-${responseId}`;\n}\n\nfunction parseToolUseInput(input: string): Record<string, unknown> {\n try {\n const parsed = JSON.parse(input);\n return parsed && typeof parsed === \"object\" ? (parsed as Record<string, unknown>) : {};\n } catch {\n return {};\n }\n}\n\n// ── Content block 映射 ─────────────────────────────────────────\n\nfunction canonicalToMessagesBlock(b: import(\"../index.js\").ContentBlock): MessagesAPIContentBlock {\n if (b.type === \"text\") return { type: \"text\", text: b.text };\n if (b.type === \"json\") return { type: \"text\", text: JSON.stringify(b.json) };\n throw new AIRequestError(\n `messages does not support content block type \"${b.type}\" in canonical mapping`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n}\n\nfunction pickProviderHeaders(headers: Headers): Record<string, string> {\n const metadata: Record<string, string> = {};\n\n headers.forEach((value, key) => {\n const normalizedKey = key.toLowerCase();\n if (\n normalizedKey === \"request-id\" ||\n normalizedKey === \"x-request-id\" ||\n normalizedKey === \"anthropic-organization-id\" ||\n normalizedKey === \"anthropic-beta\" ||\n normalizedKey === \"retry-after\" ||\n normalizedKey.startsWith(\"anthropic-ratelimit-\")\n ) {\n metadata[normalizedKey] = value;\n }\n });\n\n return metadata;\n}\n\nfunction buildStreamMetadata(options: {\n apiVersion: string;\n message?: MessagesAPIMessageResponse;\n stopReason?: string;\n stopSequence?: string | null;\n}): Record<string, unknown> {\n const { apiVersion, message, stopReason, stopSequence } = options;\n const metadata: Record<string, unknown> = {\n apiVersion,\n };\n\n if (message) {\n metadata.message = {\n id: message.id,\n type: message.type,\n role: message.role,\n model: message.model,\n };\n }\n\n if (stopReason !== undefined || stopSequence !== undefined) {\n metadata.stop = {\n reason: stopReason,\n sequence: stopSequence,\n };\n }\n\n return metadata;\n}\n\n// ── Adapter ───────────────────────────────────────────────────\n\nexport class MessagesAdapter extends AdapterBase {\n readonly kind = \"messages\" as const;\n readonly nativeStreaming = true;\n\n private apiKey: string;\n private apiVersion: string;\n private baseUrl: string;\n private fetchFn: FetchFn;\n private warningAccumulator: string[];\n\n constructor(options: MessagesAdapterOptions) {\n super();\n this.apiKey = options.apiKey;\n this.apiVersion = options.apiVersion ?? \"2023-06-01\";\n this.baseUrl = options.baseUrl ?? \"https://api.anthropic.com/v1\";\n this.fetchFn = options.fetch ?? globalThis.fetch;\n this.warningAccumulator = [];\n }\n\n protected warn(message: string, _code?: string): void {\n this.warningAccumulator.push(message);\n }\n\n // ── buildRequest ──────────────────────────────────────────\n\n protected buildRequest(request: NormalizedRequest): MessagesAPIRequest {\n const messages: MessagesAPIMessage[] = [];\n let systemPrompt: string | undefined;\n\n // 处理 instructions → system prompt\n if (request.instructions) {\n systemPrompt = instructionsToMessagesText(request.instructions);\n }\n\n // 处理 input items\n for (const item of request.input) {\n switch (item.type) {\n case \"message\": {\n const role = item.role === \"user\" ? \"user\" : \"assistant\";\n const supportedContent = ensureMessagesTextBlocks(item.content, `input message (${item.role}) content`);\n if (supportedContent.length === 1 && supportedContent[0]?.type === \"text\") {\n messages.push({ role, content: supportedContent[0].text });\n } else {\n messages.push({ role, content: supportedContent.map(canonicalToMessagesBlock) });\n }\n break;\n }\n case \"tool_call\": {\n // Anthropic 使用 tool_use block 在 assistant message 中\n const lastMsg = messages[messages.length - 1];\n const toolBlock: MessagesAPIContentBlock = {\n type: \"tool_use\",\n id: item.id,\n name: item.name,\n input: (item.argumentsJson as Record<string, unknown> | undefined) ?? parseToolUseInput(item.argumentsText),\n };\n\n if (lastMsg && lastMsg.role === \"assistant\" && typeof lastMsg.content !== \"string\") {\n lastMsg.content.push(toolBlock);\n } else {\n messages.push({ role: \"assistant\", content: [toolBlock] });\n }\n break;\n }\n case \"tool_result\": {\n assertMessagesToolResultOutcome(item.outcome);\n const content = ensureMessagesTextBlocks(item.content, `tool_result ${item.callId} content`)\n .map(blockToText)\n .join(\"\\n\");\n const block: MessagesAPIContentBlock = {\n type: \"tool_result\",\n tool_use_id: item.callId,\n content,\n is_error: item.outcome === \"error\",\n };\n messages.push({ role: \"user\", content: [block] });\n break;\n }\n case \"reasoning\": {\n // 将 reasoning item 转为 thinking block 在 assistant message 中\n const text = contentBlocksToText(ensureMessagesReasoningBlocks(item.content, \"reasoning content\"));\n const block: MessagesAPIContentBlock = { type: \"thinking\", thinking: text };\n const lastMsg = messages[messages.length - 1];\n if (lastMsg && lastMsg.role === \"assistant\" && typeof lastMsg.content !== \"string\") {\n lastMsg.content.push(block);\n } else {\n messages.push({ role: \"assistant\", content: [block] });\n }\n break;\n }\n case \"opaque\": {\n // 尝试从 opaque replay item 中提取 assistant message\n if (item.purpose === \"replay\" && typeof item.payload === \"object\" && item.payload !== null) {\n const payload = item.payload as Record<string, unknown>;\n if (payload.role === \"assistant\" && Array.isArray(payload.content)) {\n // 验证 content 是合法的 MessagesAPIContentBlock[]\n const isValidContent = payload.content.every(\n (b): b is MessagesAPIContentBlock =>\n typeof b === \"object\" &&\n b !== null &&\n \"type\" in b &&\n (b.type === \"text\" ||\n b.type === \"thinking\" ||\n b.type === \"redacted_thinking\" ||\n b.type === \"tool_use\" ||\n b.type === \"tool_result\"),\n );\n if (isValidContent) {\n rollbackTrailingAssistantMessages(messages);\n messages.push({\n role: \"assistant\",\n content: payload.content as MessagesAPIContentBlock[],\n });\n }\n }\n }\n break;\n }\n }\n }\n\n const body: MessagesAPIRequest = {\n model: request.model,\n max_tokens: request.maxOutputTokens ?? 4096,\n messages,\n stream: true,\n };\n\n if (systemPrompt) body.system = systemPrompt;\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map(\n (t): MessagesAPITool => ({\n name: t.name,\n description: t.description,\n input_schema: t.inputSchema,\n }),\n );\n }\n\n if (request.toolChoice) {\n if (request.toolChoice === \"auto\") body.tool_choice = { type: \"auto\" };\n else if (request.toolChoice === \"none\") body.tool_choice = { type: \"none\" };\n else if (request.toolChoice.type === \"tool\") {\n body.tool_choice = { type: \"tool\", name: request.toolChoice.name };\n }\n }\n\n if (request.temperature !== undefined) body.temperature = request.temperature;\n\n return body;\n }\n\n // ── runStream ─────────────────────────────────────────────\n\n protected async *runStream(\n providerRequest: MessagesAPIRequest,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n this.warningAccumulator = [];\n const auxiliary = this.createAuxiliaryState(request);\n\n if (request.metadata) {\n yield factory.responseWarning(\n \"Request metadata is not supported by the Messages adapter\",\n \"UNSUPPORTED_METADATA\",\n );\n }\n\n const response = await this.fetchFn(`${this.baseUrl}/messages`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": this.apiKey,\n \"anthropic-version\": this.apiVersion,\n },\n body: JSON.stringify(providerRequest),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"unknown error\");\n throw new Error(`Messages API error ${response.status}: ${errorText}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n // 流累积状态\n const output: OutputItem[] = [];\n const decoder = new TextDecoder();\n let buffer = \"\";\n let messageResponse: MessagesAPIMessageResponse | undefined;\n let currentContentBlockIndex = -1;\n let currentItemType: \"message\" | \"reasoning\" | \"tool_call\" | null = null;\n let currentItemId = \"\";\n let currentToolName = \"\";\n let currentArgsText = \"\";\n let currentThinkingVisibility: \"full\" | \"redacted\" = \"full\";\n let hasStreamedReasoning = false;\n const rawReplayContent: MessagesAPIContentBlock[] = [];\n\n // 内容块累积缓冲\n let textBuffer = \"\";\n let thinkingBuffer = \"\";\n let argsBuffer = \"\";\n\n // 完成响应数据\n let stopReason: string | undefined;\n let stopSequence: string | null | undefined;\n let rawResponseId = \"\";\n\n if (request.include?.providerMetadata !== \"off\") {\n const headerMetadata = pickProviderHeaders(response.headers);\n auxiliary.recordProviderMetadata(\n \"header\",\n Object.keys(headerMetadata).length > 0 ? { headers: headerMetadata } : undefined,\n );\n }\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { events, rest, malformedEvents } = parseMessagesSSE(buffer);\n buffer = rest;\n\n const malformedWarning = emitMalformedStreamWarning(factory, {\n count: malformedEvents,\n providerLabel: \"Messages\",\n transportLabel: \"SSE event(s)\",\n });\n if (malformedWarning) {\n yield malformedWarning;\n }\n\n for (const sseEvent of events) {\n switch (sseEvent.type) {\n case \"ping\":\n continue;\n\n case \"error\": {\n const err = sseEvent.data.error;\n yield factory.responseWarning(err.message, err.type);\n this.warn(err.message, err.type);\n continue;\n }\n\n case \"message_start\": {\n messageResponse = sseEvent.data.message;\n rawResponseId = messageResponse.id;\n // 检查是否有 thinking 能力\n if (messageResponse.content.some((b) => b.type === \"thinking\" || b.type === \"redacted_thinking\")) {\n hasStreamedReasoning = true;\n }\n continue;\n }\n\n case \"content_block_start\": {\n const block = sseEvent.data.content_block;\n currentContentBlockIndex = sseEvent.data.index;\n\n switch (block.type) {\n case \"text\": {\n currentItemType = \"message\";\n currentItemId = synthesizeItemId(\"msg\", currentContentBlockIndex, rawResponseId);\n textBuffer = \"\";\n yield factory.messageStarted(currentItemId);\n break;\n }\n case \"thinking\": {\n hasStreamedReasoning = true;\n currentItemType = \"reasoning\";\n currentItemId = synthesizeItemId(\"reason\", currentContentBlockIndex, rawResponseId);\n currentThinkingVisibility = \"full\";\n thinkingBuffer = \"\";\n yield factory.reasoningStarted(currentItemId, \"full\");\n break;\n }\n case \"redacted_thinking\": {\n hasStreamedReasoning = true;\n currentItemType = \"reasoning\";\n currentItemId = synthesizeItemId(\"reason-redacted\", currentContentBlockIndex, rawResponseId);\n currentThinkingVisibility = \"redacted\";\n const data = (block as unknown as { data: string }).data;\n yield factory.reasoningStarted(currentItemId, \"redacted\");\n yield factory.reasoningDelta(currentItemId, textBlock(data));\n const redactedItem = reasoningItem([textBlock(data)], \"redacted\", currentItemId);\n yield factory.reasoningCompleted(redactedItem);\n output.push(redactedItem);\n rawReplayContent.push({ type: \"redacted_thinking\", data });\n currentItemType = null;\n break;\n }\n case \"tool_use\": {\n const tuBlock = block as unknown as { id: string; name: string };\n currentItemType = \"tool_call\";\n currentItemId = tuBlock.id;\n currentToolName = tuBlock.name;\n currentArgsText = \"\";\n argsBuffer = \"\";\n yield factory.toolCallStarted(currentItemId, currentToolName);\n break;\n }\n }\n continue;\n }\n\n case \"content_block_delta\": {\n const delta = sseEvent.data.delta;\n\n switch (delta.type) {\n case \"text_delta\": {\n if (currentItemType === \"message\" && currentItemId) {\n const txt = (delta as unknown as { text: string }).text;\n textBuffer += txt;\n yield factory.messageDelta(currentItemId, txt);\n }\n break;\n }\n case \"thinking_delta\": {\n if (currentItemType === \"reasoning\" && currentItemId) {\n const txt = (delta as unknown as { thinking: string }).thinking;\n thinkingBuffer += txt;\n yield factory.reasoningDelta(currentItemId, textBlock(txt));\n }\n break;\n }\n case \"input_json_delta\": {\n if (currentItemType === \"tool_call\" && currentItemId) {\n const partial = (delta as unknown as { partial_json: string }).partial_json;\n argsBuffer += partial;\n yield factory.toolCallDelta(currentItemId, { argumentsText: partial });\n }\n break;\n }\n }\n continue;\n }\n\n case \"content_block_stop\": {\n if (currentItemType === \"message\" && currentItemId) {\n yield factory.messageCompleted(messageItem([textBlock(textBuffer)], { id: currentItemId }));\n output.push(messageItem([textBlock(textBuffer)], { id: currentItemId }));\n rawReplayContent.push({ type: \"text\", text: textBuffer });\n } else if (currentItemType === \"reasoning\" && currentItemId && currentThinkingVisibility !== \"redacted\") {\n yield factory.reasoningCompleted(\n reasoningItem([textBlock(thinkingBuffer)], currentThinkingVisibility, currentItemId),\n );\n output.push(reasoningItem([textBlock(thinkingBuffer)], currentThinkingVisibility, currentItemId));\n rawReplayContent.push({ type: \"thinking\", thinking: thinkingBuffer });\n } else if (currentItemType === \"tool_call\" && currentItemId) {\n const tcItem = toolCallItem(currentItemId, currentToolName, currentArgsText || argsBuffer);\n yield factory.toolCallCompleted(tcItem);\n output.push(tcItem);\n rawReplayContent.push({\n type: \"tool_use\",\n id: currentItemId,\n name: currentToolName,\n input: parseToolUseInput(currentArgsText || argsBuffer),\n });\n }\n\n currentItemType = null;\n currentItemId = \"\";\n continue;\n }\n\n case \"message_delta\": {\n stopReason = sseEvent.data.delta.stop_reason;\n stopSequence = sseEvent.data.delta.stop_sequence;\n const u = sseEvent.data.usage;\n if (u) {\n auxiliary.recordUsage(usageFromAnthropicMessages(u), \"stream\", u);\n }\n continue;\n }\n\n case \"message_stop\": {\n // 流结束,构造 final response\n break;\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n if (buffer.trim().length > 0) {\n yield factory.responseWarning(\"Stream ended with an incomplete Messages SSE frame\", \"STREAM_ERROR\");\n }\n\n // 构造 replay\n const replay = [...replayFromOutput(output)];\n\n // 附加 opaque replay item 用于续接\n // 保存 provider 原始 block 以实现高保真 replay\n if (messageResponse) {\n const replayContent = rawReplayContent.length > 0 ? rawReplayContent : messageResponse.content;\n replay.push(\n opaqueItem(\"messages\", \"replay\", {\n replaceCanonical: true,\n role: messageResponse.role,\n content: replayContent,\n messageId: messageResponse.id,\n stopReason: stopReason ?? messageResponse.stop_reason,\n }),\n );\n }\n\n if (request.include?.providerMetadata !== \"off\") {\n auxiliary.recordProviderMetadata(\n \"stream\",\n buildStreamMetadata({\n apiVersion: this.apiVersion,\n message: messageResponse,\n stopReason,\n stopSequence,\n }),\n );\n }\n\n // 警告低 replay fidelity\n if (!hasStreamedReasoning) {\n // 没有 reasoning,replay fidelity 较低\n }\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason: stopReason ? mapStopReason(stopReason) : undefined,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId,\n },\n factory,\n ),\n );\n }\n}\n","/**\n * Chat Completions Adapter\n *\n * 接入 OpenAI Chat Completions API (chat/completions 端点)。\n * 弱能力兼容层:\n * - third-party reasoning 字段仅做 best-effort 提取\n * - 工具调用通常整块到达(非逐 token 流)\n * - replay fidelity 依赖 provider 是否暴露可回放的 assistant turn 字段\n */\n\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { AIRequestError } from \"../core/errors.js\";\nimport {\n textBlock,\n messageItem,\n reasoningItem,\n toolCallItem,\n opaqueItem,\n replayFromOutput,\n mapStopReason,\n contentBlocksToText,\n} from \"../helpers/mapping.js\";\nimport { emitMalformedStreamWarning } from \"../helpers/adapter-auxiliary.js\";\nimport { usageFromChatCompletions } from \"../helpers/usage-mapping.js\";\n\nimport type { NormalizedRequest, AIStreamEvent, EventFactory, OutputItem, FetchFn } from \"../index.js\";\n\n// ── 类型 ──────────────────────────────────────────────────────\n\nexport type ChatCompletionsAdapterOptions = {\n apiKey: string;\n baseUrl?: string;\n fetch?: FetchFn;\n};\n\n// ── Chat API 请求类型 ─────────────────────────────────────────\n\ntype ChatRequest = {\n model: string;\n messages: ChatMessage[];\n tools?: ChatTool[];\n tool_choice?: \"auto\" | \"none\" | { type: \"function\"; function: { name: string } };\n metadata?: Record<string, string>;\n temperature?: number;\n max_tokens?: number;\n stream: true;\n};\n\ntype ChatMessage = {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string | null;\n tool_calls?: ChatToolCall[];\n tool_call_id?: string;\n name?: string;\n [key: string]: unknown;\n};\n\ntype ChatToolCall = {\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n};\n\ntype ChatTool = {\n type: \"function\";\n function: { name: string; description?: string; parameters: Record<string, unknown> };\n};\n\n// ── SSE chunk 类型 ────────────────────────────────────────────\n\ntype ChatChunk = {\n id: string;\n object: string;\n created: number;\n model: string;\n choices: ChatChunkChoice[];\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n prompt_tokens_details?: { cached_tokens?: number };\n completion_tokens_details?: { reasoning_tokens?: number };\n };\n};\n\ntype ChatChunkChoice = {\n index: number;\n delta: {\n role?: string;\n content?: string | null;\n reasoning?: unknown;\n reasoning_content?: unknown;\n tool_calls?: ChatChunkToolCall[];\n function_call?: { name?: string; arguments?: string };\n [key: string]: unknown;\n };\n finish_reason?: string | null;\n};\n\ntype ChatChunkToolCall = {\n index: number;\n id?: string;\n type?: string;\n function?: { name?: string; arguments?: string };\n};\n\ntype PendingToolCall = {\n id: string;\n name: string;\n args: string;\n};\n\ntype ReasoningFieldName = \"reasoning\" | \"reasoning_content\";\n\nconst REASONING_FIELDS: readonly ReasoningFieldName[] = [\"reasoning_content\", \"reasoning\"];\n\nfunction assertChatToolResultOutcome(outcome: import(\"../index.js\").ToolResultItem[\"outcome\"]): void {\n if (outcome !== \"success\") {\n throw new AIRequestError(\n `chat-completions does not preserve tool_result outcome \"${outcome}\"; only \"success\" is supported`,\n \"UNSUPPORTED_TOOL_RESULT_OUTCOME\",\n );\n }\n}\n\n// ── SSE 解析 ──────────────────────────────────────────────────\n\n/**\n * Chat Completions 的简化 SSE 解析器。\n *\n * 约束:\n * - 每条 `data:` 行必须已经是一个完整 JSON 对象\n * - 允许传输层把单行拆成多个 chunk,但不接受 provider 把一个 JSON event 改写成多条 `data:` 行\n */\nfunction parseChatSSE(buffer: string): { chunks: ChatChunk[]; rest: string; malformedEvents: number } {\n const chunks: ChatChunk[] = [];\n let rest = buffer;\n let malformedEvents = 0;\n\n while (true) {\n const lineEnd = rest.indexOf(\"\\n\");\n if (lineEnd === -1) {\n // 没有更多完整行,剩余部分保留到下次\n break;\n }\n\n const line = rest.slice(0, lineEnd).trim();\n rest = rest.slice(lineEnd + 1);\n\n if (!line.startsWith(\"data: \")) continue;\n\n const data = line.slice(6).trim();\n if (data === \"[DONE]\") continue;\n\n try {\n chunks.push(JSON.parse(data));\n } catch {\n malformedEvents++;\n }\n }\n\n return { chunks, rest, malformedEvents };\n}\n\nfunction ensureTextCompatibleBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): import(\"../index.js\").ContentBlock[] {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (!block) continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n throw new AIRequestError(\n `chat-completions does not support ${field}[${i}] of type \"${block.type}\"; only text/json blocks are supported`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n }\n\n return blocks;\n}\n\nfunction contentBlocksToChatText(blocks: import(\"../index.js\").ContentBlock[], field: string): string {\n return contentBlocksToText(ensureTextCompatibleBlocks(blocks, field));\n}\n\nfunction extractReasoningText(value: unknown): string {\n if (typeof value === \"string\") return value;\n\n if (Array.isArray(value)) {\n return value.map(extractReasoningText).join(\"\");\n }\n\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n for (const key of [\"text\", \"content\", \"reasoning\", \"reasoning_content\", \"thinking\", \"value\"]) {\n const nested = extractReasoningText(record[key]);\n if (nested) return nested;\n }\n }\n\n return \"\";\n}\n\nfunction extractReasoningDeltas(delta: ChatChunkChoice[\"delta\"]): Array<{ field: ReasoningFieldName; text: string }> {\n const deltas: Array<{ field: ReasoningFieldName; text: string }> = [];\n\n for (const field of REASONING_FIELDS) {\n const text = extractReasoningText(delta[field]);\n if (text) {\n deltas.push({ field, text });\n }\n }\n\n return deltas;\n}\n\nfunction rollbackTrailingAssistantMessages(messages: ChatMessage[]): void {\n while (messages.length > 0 && messages[messages.length - 1]?.role === \"assistant\") {\n messages.pop();\n }\n}\n\nfunction buildAssistantReplayMessage(params: {\n content: string;\n reasoningByField: ReadonlyMap<ReasoningFieldName, string>;\n toolCalls: readonly PendingToolCall[];\n}): ChatMessage | null {\n const { content, reasoningByField, toolCalls } = params;\n if (!content && reasoningByField.size === 0 && toolCalls.length === 0) return null;\n\n const replayMessage: ChatMessage = {\n role: \"assistant\",\n content: content || null,\n };\n\n for (const [field, text] of reasoningByField) {\n replayMessage[field] = text;\n }\n\n if (toolCalls.length > 0) {\n replayMessage.tool_calls = toolCalls.map((toolCall) => ({\n id: toolCall.id,\n type: \"function\",\n function: {\n name: toolCall.name,\n arguments: toolCall.args,\n },\n }));\n }\n\n return replayMessage;\n}\n\n// ── Adapter ───────────────────────────────────────────────────\n\nexport class ChatCompletionsAdapter extends AdapterBase {\n readonly kind = \"chat-completions\" as const;\n readonly nativeStreaming = true;\n\n private apiKey: string;\n private baseUrl: string;\n private fetchFn: FetchFn;\n\n constructor(options: ChatCompletionsAdapterOptions) {\n super();\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://api.openai.com/v1\";\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n // ── buildRequest ──────────────────────────────────────────\n\n protected buildRequest(request: NormalizedRequest): ChatRequest {\n const messages: ChatMessage[] = [];\n\n // handle instructions → system message\n if (request.instructions) {\n const content =\n typeof request.instructions === \"string\"\n ? request.instructions\n : contentBlocksToChatText(request.instructions, \"instructions\");\n messages.push({ role: \"system\", content });\n }\n\n for (const item of request.input) {\n switch (item.type) {\n case \"message\": {\n const role = item.role;\n const text = contentBlocksToChatText(item.content, `input message (${item.role}) content`);\n messages.push({ role, content: text || null });\n break;\n }\n case \"tool_call\": {\n // 只允许附着到尾部 assistant turn,否则新建一个\n const lastAssistant =\n messages.length > 0 && messages[messages.length - 1]?.role === \"assistant\"\n ? messages[messages.length - 1]\n : null;\n const tc: ChatToolCall = {\n id: item.id,\n type: \"function\",\n function: { name: item.name, arguments: item.argumentsText },\n };\n if (lastAssistant) {\n lastAssistant.tool_calls = [...(lastAssistant.tool_calls ?? []), tc];\n } else {\n messages.push({ role: \"assistant\", content: null, tool_calls: [tc] });\n }\n break;\n }\n case \"tool_result\": {\n assertChatToolResultOutcome(item.outcome);\n messages.push({\n role: \"tool\",\n tool_call_id: item.callId,\n name: item.toolName,\n content: contentBlocksToChatText(item.content, `tool_result ${item.callId} content`),\n });\n break;\n }\n case \"reasoning\": {\n // chat.completions doesn't support reasoning items in input\n // Convert to a text message for best-effort\n messages.push({\n role: \"assistant\",\n content: contentBlocksToChatText(item.content, \"reasoning content\"),\n });\n break;\n }\n case \"opaque\": {\n // Try to restore from opaque replay\n if (item.purpose === \"replay\" && typeof item.payload === \"object\" && item.payload !== null) {\n const payload = item.payload as Record<string, unknown>;\n if (payload.role === \"assistant\" && typeof payload.content === \"string\") {\n messages.push({ role: \"assistant\", content: payload.content as string });\n } else if (payload.replaceCanonical === true && Array.isArray(payload.messages)) {\n rollbackTrailingAssistantMessages(messages);\n for (const m of payload.messages as ChatMessage[]) {\n messages.push(m);\n }\n } else if (Array.isArray(payload.messages)) {\n for (const m of payload.messages as ChatMessage[]) {\n messages.push(m);\n }\n }\n }\n break;\n }\n }\n }\n\n const body: ChatRequest = {\n model: request.model,\n messages,\n stream: true,\n };\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map(\n (t): ChatTool => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.inputSchema as Record<string, unknown>,\n },\n }),\n );\n }\n\n if (request.toolChoice) {\n if (request.toolChoice === \"auto\") body.tool_choice = \"auto\";\n else if (request.toolChoice === \"none\") body.tool_choice = \"none\";\n else if (request.toolChoice.type === \"tool\") {\n body.tool_choice = { type: \"function\", function: { name: request.toolChoice.name } };\n }\n }\n\n if (request.temperature !== undefined) body.temperature = request.temperature;\n if (request.maxOutputTokens !== undefined) body.max_tokens = request.maxOutputTokens;\n if (request.metadata) body.metadata = request.metadata;\n\n return body;\n }\n\n // ── runStream ─────────────────────────────────────────────\n\n protected async *runStream(\n providerRequest: ChatRequest,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n const auxiliary = this.createAuxiliaryState(request);\n const response = await this.fetchFn(`${this.baseUrl}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(providerRequest),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"unknown error\");\n throw new Error(`Chat Completions API error ${response.status}: ${errorText}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n const output: OutputItem[] = [];\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n // 累积状态 — 支持多 choice,此处只取 index 0\n let responseId: string | undefined;\n let accumulatedContent = \"\";\n let accumulatedReasoning = \"\";\n let currentMessageId = \"\";\n let currentReasoningId = \"\";\n let hasMessageStarted = false;\n let hasReasoningStarted = false;\n\n // tool_calls 累积: tool call index → { id, name, args }\n const pendingToolCalls = new Map<number, PendingToolCall>();\n const reasoningByField = new Map<ReasoningFieldName, string>();\n\n const finalizePendingTurn = (): { events: AIStreamEvent[]; assistantReplayMessage: ChatMessage | null } => {\n const events: AIStreamEvent[] = [];\n const finalizedToolCalls = [...pendingToolCalls.values()];\n const finalizedReasoningByField = new Map(reasoningByField);\n\n if (hasReasoningStarted && accumulatedReasoning) {\n const reasoning = reasoningItem([textBlock(accumulatedReasoning)], \"full\", currentReasoningId);\n events.push(factory.reasoningCompleted(reasoning));\n output.push(reasoning);\n }\n\n if (hasMessageStarted && accumulatedContent) {\n const message = messageItem([textBlock(accumulatedContent)], { id: currentMessageId });\n events.push(factory.messageCompleted(message));\n output.push(message);\n }\n\n for (const pending of finalizedToolCalls) {\n const toolCall = toolCallItem(pending.id, pending.name, pending.args);\n events.push(factory.toolCallCompleted(toolCall));\n output.push(toolCall);\n }\n\n const assistantReplayMessage = buildAssistantReplayMessage({\n content: accumulatedContent,\n reasoningByField: finalizedReasoningByField,\n toolCalls: finalizedToolCalls,\n });\n\n accumulatedContent = \"\";\n accumulatedReasoning = \"\";\n currentMessageId = \"\";\n currentReasoningId = \"\";\n hasMessageStarted = false;\n hasReasoningStarted = false;\n pendingToolCalls.clear();\n reasoningByField.clear();\n\n return { events, assistantReplayMessage };\n };\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { chunks, rest, malformedEvents } = parseChatSSE(buffer);\n buffer = rest;\n\n const malformedWarning = emitMalformedStreamWarning(factory, {\n count: malformedEvents,\n providerLabel: \"Chat Completions\",\n transportLabel: \"SSE event(s)\",\n });\n if (malformedWarning) {\n yield malformedWarning;\n }\n\n for (const chunk of chunks) {\n responseId = chunk.id;\n\n // usage 可能在最终 chunk 中\n if (chunk.usage) {\n auxiliary.recordUsage(usageFromChatCompletions(chunk.usage), \"final\", chunk.usage);\n }\n\n for (const choice of chunk.choices) {\n if (choice.index !== 0) continue;\n\n const delta = choice.delta;\n const finishReason = choice.finish_reason;\n const reasoningDeltas = extractReasoningDeltas(delta);\n\n // 处理 role: assistant (首块标识)\n if (delta.role === \"assistant\" && typeof delta.content === \"string\" && !hasMessageStarted) {\n currentMessageId = `msg-${chunk.id}`;\n hasMessageStarted = true;\n accumulatedContent = \"\";\n yield factory.messageStarted(currentMessageId);\n }\n\n // 处理 third-party reasoning delta\n if (reasoningDeltas.length > 0) {\n if (!hasReasoningStarted) {\n currentReasoningId = `reason-${chunk.id}`;\n hasReasoningStarted = true;\n accumulatedReasoning = \"\";\n yield factory.reasoningStarted(currentReasoningId, \"full\");\n }\n\n for (const reasoningDelta of reasoningDeltas) {\n accumulatedReasoning += reasoningDelta.text;\n reasoningByField.set(\n reasoningDelta.field,\n (reasoningByField.get(reasoningDelta.field) ?? \"\") + reasoningDelta.text,\n );\n yield factory.reasoningDelta(currentReasoningId, textBlock(reasoningDelta.text));\n }\n }\n\n // 处理 content delta\n if (delta.content) {\n if (!hasMessageStarted) {\n currentMessageId = `msg-${chunk.id}`;\n hasMessageStarted = true;\n yield factory.messageStarted(currentMessageId);\n }\n accumulatedContent += delta.content;\n yield factory.messageDelta(currentMessageId, delta.content);\n }\n\n // 处理 tool_calls delta\n if (delta.tool_calls) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index;\n\n if (tc.id) {\n pendingToolCalls.set(idx, { id: tc.id, name: tc.function?.name ?? \"\", args: \"\" });\n yield factory.toolCallStarted(tc.id, tc.function?.name ?? \"\");\n }\n\n if (tc.function?.arguments) {\n const pending = pendingToolCalls.get(idx);\n if (pending) {\n pending.args += tc.function.arguments;\n yield factory.toolCallDelta(pending.id, { argumentsText: tc.function.arguments });\n }\n }\n }\n }\n\n // 处理 function_call delta (legacy format)\n if (delta.function_call) {\n if (delta.function_call.name) {\n const fcId = `fc-${chunk.id}-0`;\n pendingToolCalls.set(0, { id: fcId, name: delta.function_call.name, args: \"\" });\n yield factory.toolCallStarted(fcId, delta.function_call.name);\n }\n if (delta.function_call.arguments) {\n const pending = pendingToolCalls.get(0);\n if (pending) {\n pending.args += delta.function_call.arguments;\n yield factory.toolCallDelta(pending.id, { argumentsText: delta.function_call.arguments });\n }\n }\n }\n\n // 处理 finish_reason\n if (finishReason && finishReason !== null) {\n const { events, assistantReplayMessage } = finalizePendingTurn();\n for (const event of events) {\n yield event;\n }\n\n // 构建 stop reason\n const stopReason = mapStopReason(finishReason);\n\n // 构建 replay\n const replay = [...replayFromOutput(output)];\n\n // 附加 opaque replay\n if (assistantReplayMessage) {\n replay.push(\n opaqueItem(\"chat.completions\", \"replay\", {\n replaceCanonical: true,\n messages: [assistantReplayMessage],\n }),\n );\n }\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId: chunk.id,\n },\n factory,\n ),\n );\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n if (buffer.trim().length > 0) {\n yield factory.responseWarning(\"Stream ended with an incomplete Chat Completions SSE frame\", \"STREAM_ERROR\");\n }\n\n // 如果流结束时没有 finish_reason(断流),也尝试关闭\n if (hasMessageStarted || hasReasoningStarted || pendingToolCalls.size > 0) {\n yield factory.responseWarning(\"Stream ended without a finish_reason\", \"INCOMPLETE_STREAM\");\n\n const { events, assistantReplayMessage } = finalizePendingTurn();\n for (const event of events) {\n yield event;\n }\n\n const replay = [...replayFromOutput(output)];\n if (assistantReplayMessage) {\n replay.push(\n opaqueItem(\"chat.completions\", \"replay\", {\n replaceCanonical: true,\n messages: [assistantReplayMessage],\n }),\n );\n }\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId: responseId,\n },\n factory,\n ),\n );\n }\n }\n}\n","/**\n * Ollama Adapter\n *\n * 接入 Ollama 原生 Chat API (/api/chat)。\n * 与 Chat Completions 兼容层不同,此处直接使用 Ollama 的 NDJSON 流格式。\n *\n * 能力:\n * - 消息流(完整 content 逐块到达)\n * - 工具调用(整块到达,非逐 token)\n * - 用量信息(仅 prompt_eval_count / eval_count)\n *\n * 限制:\n * - 不流式输出 reasoning(Ollama 原生 API 无独立思考字段)\n * - tool_call 不支持逐 token 流式\n * - replay 保真度低(无 opaque continuation 机制)\n */\n\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { AIRequestError } from \"../core/errors.js\";\nimport {\n textBlock,\n messageItem,\n toolCallItem,\n opaqueItem,\n replayFromOutput,\n mapStopReason,\n contentBlocksToText,\n} from \"../helpers/mapping.js\";\nimport { emitMalformedStreamWarning } from \"../helpers/adapter-auxiliary.js\";\nimport { usageFromOllama } from \"../helpers/usage-mapping.js\";\n\nimport type { NormalizedRequest, AIStreamEvent, EventFactory, OutputItem, FetchFn } from \"../index.js\";\n\n// ── 选项类型 ──────────────────────────────────────────────────\n\nexport type OllamaAdapterOptions = {\n /** Ollama 服务地址,默认 http://localhost:11434 */\n baseUrl?: string;\n /** 可选 API key(用于需要认证的代理场景) */\n apiKey?: string;\n /** 可注入自定义 fetch 实现 */\n fetch?: FetchFn;\n};\n\n// ── Ollama Chat API 类型 ──────────────────────────────────────\n\ntype OllamaChatRequest = {\n model: string;\n messages: OllamaMessage[];\n stream: true;\n tools?: OllamaTool[];\n options?: {\n temperature?: number;\n num_predict?: number;\n [key: string]: unknown;\n };\n};\n\ntype OllamaMessage = {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string;\n images?: string[];\n tool_calls?: OllamaToolCall[];\n};\n\ntype OllamaToolCall = {\n function: {\n name: string;\n arguments: Record<string, unknown>;\n };\n};\n\ntype OllamaTool = {\n type: \"function\";\n function: {\n name: string;\n description?: string;\n parameters: Record<string, unknown>;\n };\n};\n\nfunction ensureOllamaTextBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): import(\"../index.js\").ContentBlock[] {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (!block) continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n throw new AIRequestError(\n `ollama does not support ${field}[${i}] of type \"${block.type}\"; only text/json blocks are supported`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n }\n\n return blocks;\n}\n\nfunction ensureOllamaReasoningBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): Array<Extract<import(\"../index.js\").ContentBlock, { type: \"text\" }>> {\n return blocks.map((block, index) => {\n if (block.type !== \"text\") {\n throw new AIRequestError(\n `ollama does not support ${field}[${index}] of type \"${block.type}\"; reasoning only supports text blocks`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n\n return block;\n });\n}\n\nfunction instructionsToOllamaText(instructions: string | import(\"../index.js\").InstructionBlock[]): string {\n return typeof instructions === \"string\"\n ? instructions\n : contentBlocksToText(ensureOllamaTextBlocks(instructions, \"instructions\"));\n}\n\nfunction parseOllamaToolArguments(item: import(\"../index.js\").ToolCallItem): Record<string, unknown> {\n if (item.argumentsJson && typeof item.argumentsJson === \"object\" && item.argumentsJson !== null) {\n return item.argumentsJson as Record<string, unknown>;\n }\n\n try {\n const parsed = JSON.parse(item.argumentsText);\n if (parsed && typeof parsed === \"object\") {\n return parsed as Record<string, unknown>;\n }\n } catch {\n // fall through\n }\n\n throw new AIRequestError(\n \"ollama tool_call argumentsText must be valid JSON object when argumentsJson is absent\",\n \"TOOL_CALL_ARGUMENTS_INVALID\",\n );\n}\n\nfunction assertOllamaToolResultOutcome(outcome: import(\"../index.js\").ToolResultItem[\"outcome\"]): void {\n if (outcome !== \"success\") {\n throw new AIRequestError(\n `ollama does not preserve tool_result outcome \"${outcome}\"; only \"success\" is supported`,\n \"UNSUPPORTED_TOOL_RESULT_OUTCOME\",\n );\n }\n}\n\n// ── Ollama 流式 chunk ─────────────────────────────────────────\n\ntype OllamaChatChunk = {\n model: string;\n created_at: string;\n message: {\n role: string;\n content: string;\n tool_calls?: OllamaToolCall[];\n };\n done: boolean;\n done_reason?: string;\n // 计时与用量(仅 final chunk 有值)\n total_duration?: number;\n load_duration?: number;\n prompt_eval_count?: number;\n prompt_eval_duration?: number;\n eval_count?: number;\n eval_duration?: number;\n};\n\n// ── NDJSON 解析 ───────────────────────────────────────────────\n\nfunction parseOllamaNDJSON(buffer: string): { chunks: OllamaChatChunk[]; rest: string; malformedLines: number } {\n const chunks: OllamaChatChunk[] = [];\n let rest = buffer;\n let malformedLines = 0;\n\n while (true) {\n const lineEnd = rest.indexOf(\"\\n\");\n if (lineEnd === -1) break;\n\n const line = rest.slice(0, lineEnd).trim();\n rest = rest.slice(lineEnd + 1);\n\n if (!line) continue;\n\n try {\n const parsed = JSON.parse(line);\n // Ollama chunks have a \"message\" field in streaming mode\n if (parsed && typeof parsed === \"object\" && \"message\" in parsed) {\n chunks.push(parsed as OllamaChatChunk);\n } else {\n malformedLines++;\n }\n } catch {\n malformedLines++;\n }\n }\n\n return { chunks, rest, malformedLines };\n}\n\nfunction rollbackTrailingAssistantMessages(messages: OllamaMessage[]): void {\n while (messages.length > 0 && messages[messages.length - 1]?.role === \"assistant\") {\n messages.pop();\n }\n}\n\nfunction isOllamaToolCalls(value: unknown): value is OllamaToolCall[] {\n return (\n Array.isArray(value) &&\n value.every((entry) => {\n if (!entry || typeof entry !== \"object\" || !(\"function\" in entry)) return false;\n const fn = (entry as { function?: unknown }).function;\n return (\n !!fn &&\n typeof fn === \"object\" &&\n \"name\" in fn &&\n typeof (fn as { name?: unknown }).name === \"string\" &&\n \"arguments\" in fn &&\n typeof (fn as { arguments?: unknown }).arguments === \"object\" &&\n (fn as { arguments?: unknown }).arguments !== null\n );\n })\n );\n}\n\n// ── Adapter ───────────────────────────────────────────────────\n\nexport class OllamaAdapter extends AdapterBase {\n readonly kind = \"ollama\" as const;\n readonly nativeStreaming = true;\n\n private baseUrl: string;\n private apiKey: string | undefined;\n private fetchFn: FetchFn;\n\n constructor(options: OllamaAdapterOptions = {}) {\n super();\n this.baseUrl = options.baseUrl ?? \"http://localhost:11434\";\n this.apiKey = options.apiKey;\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n // ── buildRequest ──────────────────────────────────────────\n\n protected buildRequest(request: NormalizedRequest): OllamaChatRequest {\n if (request.toolChoice && request.toolChoice !== \"auto\") {\n throw new AIRequestError(\"ollama does not support explicit toolChoice\", \"UNSUPPORTED_TOOL_CHOICE\");\n }\n\n const messages: OllamaMessage[] = [];\n\n // handle instructions → system message\n if (request.instructions) {\n messages.push({ role: \"system\", content: instructionsToOllamaText(request.instructions) });\n }\n\n for (const item of request.input) {\n switch (item.type) {\n case \"message\": {\n const role = item.role;\n messages.push({\n role,\n content: contentBlocksToText(ensureOllamaTextBlocks(item.content, `input message (${item.role}) content`)),\n });\n break;\n }\n case \"tool_call\": {\n // Ollama expects tool_calls on the last assistant message\n const lastAssistant = messages.findLast((m) => m.role === \"assistant\");\n const tc: OllamaToolCall = {\n function: {\n name: item.name,\n arguments: parseOllamaToolArguments(item),\n },\n };\n if (lastAssistant) {\n lastAssistant.tool_calls = [...(lastAssistant.tool_calls ?? []), tc];\n } else {\n messages.push({ role: \"assistant\", content: \"\", tool_calls: [tc] });\n }\n break;\n }\n case \"tool_result\": {\n assertOllamaToolResultOutcome(item.outcome);\n messages.push({\n role: \"tool\",\n content: contentBlocksToText(ensureOllamaTextBlocks(item.content, `tool_result ${item.callId} content`)),\n });\n break;\n }\n case \"reasoning\": {\n // Ollama doesn't support reasoning in input; convert to text message\n messages.push({\n role: \"assistant\",\n content: contentBlocksToText(ensureOllamaReasoningBlocks(item.content, \"reasoning content\")),\n });\n break;\n }\n case \"opaque\": {\n // Best-effort restore from opaque replay\n if (\n item.source === \"ollama\" &&\n item.purpose === \"replay\" &&\n typeof item.payload === \"object\" &&\n item.payload !== null\n ) {\n const payload = item.payload as Record<string, unknown>;\n if (payload.role === \"assistant\" && typeof payload.content === \"string\") {\n rollbackTrailingAssistantMessages(messages);\n messages.push({\n role: \"assistant\",\n content: payload.content,\n tool_calls: isOllamaToolCalls(payload.tool_calls) ? payload.tool_calls : undefined,\n });\n }\n }\n break;\n }\n }\n }\n\n const body: OllamaChatRequest = {\n model: request.model,\n messages,\n stream: true,\n };\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map(\n (t): OllamaTool => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.inputSchema as Record<string, unknown>,\n },\n }),\n );\n }\n\n if (request.temperature !== undefined || request.maxOutputTokens !== undefined) {\n body.options = {};\n if (request.temperature !== undefined) body.options.temperature = request.temperature;\n if (request.maxOutputTokens !== undefined) body.options.num_predict = request.maxOutputTokens;\n }\n\n return body;\n }\n\n // ── runStream ─────────────────────────────────────────────\n\n protected async *runStream(\n providerRequest: OllamaChatRequest,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n const auxiliary = this.createAuxiliaryState(request);\n if (request.metadata) {\n yield factory.responseWarning(\"Request metadata is not supported by the Ollama adapter\", \"UNSUPPORTED_METADATA\");\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (this.apiKey) {\n headers.Authorization = `Bearer ${this.apiKey}`;\n }\n\n const response = await this.fetchFn(`${this.baseUrl}/api/chat`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(providerRequest),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"unknown error\");\n throw new Error(`Ollama API error ${response.status}: ${errorText}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n const output: OutputItem[] = [];\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n // 累积状态\n let responseId: string | undefined;\n let accumulatedContent = \"\";\n let currentMessageId = \"\";\n let hasMessageStarted = false;\n\n // tool_calls 累积(于 final chunk 到达)\n let pendingToolCalls: Array<{ id: string; name: string; argumentsText: string; argumentsJson?: unknown }> = [];\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { chunks, rest, malformedLines } = parseOllamaNDJSON(buffer);\n buffer = rest;\n\n const malformedWarning = emitMalformedStreamWarning(factory, {\n count: malformedLines,\n providerLabel: \"Ollama\",\n transportLabel: \"NDJSON line(s)\",\n });\n if (malformedWarning) {\n yield malformedWarning;\n }\n\n for (const chunk of chunks) {\n responseId = chunk.created_at;\n\n const msg = chunk.message;\n\n // 处理 content delta\n if (msg.content) {\n if (!hasMessageStarted) {\n currentMessageId = `msg-${chunk.created_at}`;\n hasMessageStarted = true;\n yield factory.messageStarted(currentMessageId);\n }\n accumulatedContent += msg.content;\n yield factory.messageDelta(currentMessageId, msg.content);\n }\n\n // 处理 tool_calls (整块到达,在最终 chunk 中)\n if (msg.tool_calls && msg.tool_calls.length > 0) {\n for (const tc of msg.tool_calls) {\n const tcId = `tc-${chunk.created_at}-${tc.function.name}`;\n const argsText = JSON.stringify(tc.function.arguments);\n pendingToolCalls.push({\n id: tcId,\n name: tc.function.name,\n argumentsText: argsText,\n argumentsJson: tc.function.arguments,\n });\n }\n }\n\n // 处理 done_reason (final chunk)\n if (chunk.done) {\n // 如果有未开始的 message 但没内容,发一个空消息启动\n if (accumulatedContent === \"\" && pendingToolCalls.length > 0 && !hasMessageStarted) {\n currentMessageId = `msg-${chunk.created_at}`;\n hasMessageStarted = true;\n yield factory.messageStarted(currentMessageId);\n }\n\n // 完成消息(如果有累积的内容或正在进行的消息)\n if (hasMessageStarted) {\n const message = messageItem([textBlock(accumulatedContent)], { id: currentMessageId });\n yield factory.messageCompleted(message);\n if (accumulatedContent) {\n output.push(message);\n }\n }\n\n // 发出 tool_call 完成事件\n for (const pending of pendingToolCalls) {\n const toolCall = toolCallItem(pending.id, pending.name, pending.argumentsText, pending.argumentsJson);\n yield factory.toolCallStarted(pending.id, pending.name);\n yield factory.toolCallDelta(pending.id, { argumentsText: pending.argumentsText });\n yield factory.toolCallCompleted(toolCall);\n output.push(toolCall);\n }\n\n // 提取 usage\n if (\n request.include?.usage !== \"off\" &&\n (chunk.prompt_eval_count !== undefined || chunk.eval_count !== undefined)\n ) {\n auxiliary.recordUsage(\n usageFromOllama({\n prompt_eval_count: chunk.prompt_eval_count,\n eval_count: chunk.eval_count,\n }),\n \"final\",\n {\n prompt_eval_count: chunk.prompt_eval_count,\n eval_count: chunk.eval_count,\n },\n );\n }\n\n // 构建 stop reason\n const stopReason = chunk.done_reason ? mapStopReason(chunk.done_reason) : undefined;\n\n // 构建 replay\n const replay = replayFromOutput(output);\n\n // 附加 opaque replay(若有关联的 assistant 消息)\n if (accumulatedContent || pendingToolCalls.length > 0) {\n replay.push(\n opaqueItem(\"ollama\", \"replay\", {\n role: \"assistant\",\n content: accumulatedContent,\n tool_calls: pendingToolCalls.map((tc) => ({\n function: { name: tc.name, arguments: tc.argumentsJson },\n })),\n }),\n );\n }\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId: chunk.created_at,\n },\n factory,\n ),\n );\n\n // 重置累积状态\n accumulatedContent = \"\";\n currentMessageId = \"\";\n hasMessageStarted = false;\n pendingToolCalls = [];\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n if (buffer.trim().length > 0) {\n yield factory.responseWarning(\"Stream ended with an incomplete Ollama NDJSON line\", \"STREAM_ERROR\");\n }\n\n // 流结束但无 done=true(断流保护)\n if (hasMessageStarted || pendingToolCalls.length > 0) {\n yield factory.responseWarning(\"Stream ended without a done signal\", \"INCOMPLETE_STREAM\");\n\n if (hasMessageStarted) {\n const message = messageItem([textBlock(accumulatedContent)], { id: currentMessageId });\n yield factory.messageCompleted(message);\n if (accumulatedContent) {\n output.push(message);\n }\n }\n\n for (const pending of pendingToolCalls) {\n const toolCall = toolCallItem(pending.id, pending.name, pending.argumentsText, pending.argumentsJson);\n yield factory.toolCallStarted(pending.id, pending.name);\n yield factory.toolCallDelta(pending.id, { argumentsText: pending.argumentsText });\n yield factory.toolCallCompleted(toolCall);\n output.push(toolCall);\n }\n\n const replay = replayFromOutput(output);\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId: responseId,\n },\n factory,\n ),\n );\n }\n }\n}\n","/**\n * Mock Adapter\n *\n * 面向测试的回调驱动 adapter:\n * - 每次请求执行用户提供的 handler\n * - 验证调用方是否正确续接 replay / tool_result\n * - 发出可控的 message / reasoning / tool_call 流\n * - 注入 warning / auxiliary / content_filter / 中断 / provider error\n *\n * 这不是通用“假模型”,而是测试工具调用编排与错误路径的测试夹具。\n */\n\nimport { AIRequestError } from \"../core/errors.js\";\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { messageItem, reasoningItem, replayFromOutput, textBlock } from \"../helpers/mapping.js\";\n\nimport type {\n AIStreamEvent,\n AuxiliaryInfo,\n BillingInfo,\n ContentBlock,\n EventFactory,\n InputItem,\n MessageItem,\n NormalizedRequest,\n OutputItem,\n ReplayItem,\n StopReason,\n ToolCallItem,\n ToolResultItem,\n Usage,\n} from \"../index.js\";\n\nexport type MockInputExpectation = {\n type: InputItem[\"type\"];\n id?: string;\n role?: MessageItem[\"role\"];\n name?: string;\n toolName?: string;\n callId?: string;\n outcome?: ToolResultItem[\"outcome\"];\n visibility?: Extract<InputItem, { type: \"reasoning\" }>[\"visibility\"];\n source?: Extract<InputItem, { type: \"opaque\" }>[\"source\"];\n purpose?: Extract<InputItem, { type: \"opaque\" }>[\"purpose\"];\n textIncludes?: string;\n};\n\nexport type MockRequestExpectation = {\n minItems?: number;\n maxItems?: number;\n ordered?: boolean;\n requireReplayFromPreviousTurn?: boolean;\n requireToolResultsForPendingCalls?: boolean;\n tools?: \"ignore\" | \"present\" | \"absent\";\n toolChoice?: \"ignore\" | \"present\" | \"absent\";\n items?: MockInputExpectation[];\n};\n\nexport type MockHistoryRecord = {\n turnIndex: number;\n requestId: string;\n replay: ReplayItem[];\n toolCalls: ToolCallItem[];\n};\n\nexport type MockHandlerContext = {\n turnIndex: number;\n previousReplay: ReplayItem[];\n pendingToolCalls: readonly ToolCallItem[];\n history: readonly MockHistoryRecord[];\n};\n\nexport type MockWarningStep = {\n type: \"warning\";\n message: string;\n code?: string;\n};\n\nexport type MockAuxiliaryStep = {\n type: \"auxiliary\";\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: Partial<AuxiliaryInfo>;\n};\n\nexport type MockTextStreamOptions = {\n /**\n * 每秒吐出的字符数。未设置时仍会按 chunk 拆分,但不会额外等待。\n */\n charsPerSecond?: number;\n /**\n * 每个 delta 最多包含多少个字符,默认 1。\n */\n chunkSize?: number;\n /**\n * 首个 delta 发出前的延迟。\n */\n initialDelayMs?: number;\n};\n\nexport type MockMessageStep = {\n type: \"message\";\n id?: string;\n content: string | ContentBlock[];\n stream?: MockTextStreamOptions | false;\n};\n\nexport type MockReasoningStep = {\n type: \"reasoning\";\n id?: string;\n visibility?: Extract<OutputItem, { type: \"reasoning\" }>[\"visibility\"];\n content: string | ContentBlock[];\n stream?: MockTextStreamOptions | false;\n};\n\nexport type MockToolCallStep = {\n type: \"tool_call\";\n id: string;\n name: string;\n argumentsText: string;\n argumentsJson?: unknown;\n streamArguments?: boolean;\n stream?: MockTextStreamOptions | false;\n};\n\nexport type MockOutputStep = {\n type: \"output\";\n item: Extract<OutputItem, { type: \"message\" | \"reasoning\" | \"tool_call\" }>;\n stream?: MockTextStreamOptions | false;\n};\n\nexport type MockCompleteStep = {\n type: \"complete\";\n stopReason?: StopReason;\n replay?: ReplayItem[];\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: Partial<AuxiliaryInfo>;\n providerMetadata?: Record<string, unknown>;\n rawResponseId?: string;\n warnings?: string[];\n};\n\nexport type MockErrorStep = {\n type: \"error\";\n message: string;\n code?: string;\n stopReason?: StopReason;\n providerMetadata?: Record<string, unknown>;\n};\n\nexport type MockInterruptStep = {\n type: \"interrupt\";\n};\n\nexport type MockThrowStep = {\n type: \"throw\";\n error: string | Error;\n};\n\nexport type MockStep =\n | MockWarningStep\n | MockAuxiliaryStep\n | MockMessageStep\n | MockReasoningStep\n | MockToolCallStep\n | MockOutputStep\n | MockCompleteStep\n | MockErrorStep\n | MockInterruptStep\n | MockThrowStep;\n\nexport type MockHandler = (request: NormalizedRequest, context: MockHandlerContext) => AsyncIterable<MockStep>;\n\ntype MockHandlerSource = Iterable<MockStep> | AsyncIterable<MockStep>;\n\nexport type MockStaticHandler = (\n request: NormalizedRequest,\n context: MockHandlerContext,\n) => MockHandlerSource | Promise<MockHandlerSource>;\n\nexport type MockAdapterOptions = {\n handler: MockHandler;\n providerMetadata?: Record<string, unknown>;\n};\n\ntype MockProviderRequest = {\n request: NormalizedRequest;\n handlerResult: AsyncIterable<MockStep>;\n turnIndex: number;\n remainingPendingToolCalls: ToolCallItem[];\n};\n\ntype ResolvedMockTextStreamOptions = {\n charsPerSecond?: number;\n chunkSize: number;\n initialDelayMs: number;\n};\n\nexport function assertMockRequest(\n request: NormalizedRequest,\n expectation: MockRequestExpectation,\n context: MockHandlerContext,\n): void {\n const prefix = `MockAdapter turn ${context.turnIndex + 1} expectation failed`;\n\n if (expectation.minItems !== undefined && request.input.length < expectation.minItems) {\n throw new AIRequestError(\n `${prefix}: expected at least ${expectation.minItems} input item(s)`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n\n if (expectation.maxItems !== undefined && request.input.length > expectation.maxItems) {\n throw new AIRequestError(\n `${prefix}: expected at most ${expectation.maxItems} input item(s)`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n\n if (expectation.tools === \"present\" && (!request.tools || request.tools.length === 0)) {\n throw new AIRequestError(`${prefix}: expected tools to be present`, \"MOCK_EXPECTATION_FAILED\");\n }\n\n if (expectation.tools === \"absent\" && request.tools && request.tools.length > 0) {\n throw new AIRequestError(`${prefix}: expected tools to be absent`, \"MOCK_EXPECTATION_FAILED\");\n }\n\n if (expectation.toolChoice === \"present\" && request.toolChoice === undefined) {\n throw new AIRequestError(`${prefix}: expected toolChoice to be present`, \"MOCK_EXPECTATION_FAILED\");\n }\n\n if (expectation.toolChoice === \"absent\" && request.toolChoice !== undefined) {\n throw new AIRequestError(`${prefix}: expected toolChoice to be absent`, \"MOCK_EXPECTATION_FAILED\");\n }\n\n if (expectation.requireReplayFromPreviousTurn && context.previousReplay.length > 0) {\n assertReplayIncluded(request.input, context.previousReplay, prefix);\n }\n\n if (expectation.requireToolResultsForPendingCalls && context.pendingToolCalls.length > 0) {\n const toolResultIds = new Set(\n request.input.filter((item): item is ToolResultItem => item.type === \"tool_result\").map((item) => item.callId),\n );\n\n for (const call of context.pendingToolCalls) {\n if (!toolResultIds.has(call.id)) {\n throw new AIRequestError(\n `${prefix}: expected tool_result for pending tool call \"${call.id}\"`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n }\n }\n\n if (expectation.items && expectation.items.length > 0) {\n if (expectation.ordered) {\n assertOrderedItems(request.input, expectation.items, prefix);\n } else {\n assertUnorderedItems(request.input, expectation.items, prefix);\n }\n }\n}\n\nexport class MockAdapter extends AdapterBase {\n readonly kind = \"mock\" as const;\n readonly nativeStreaming = false;\n\n private readonly handler: MockHandler;\n private readonly providerMetadata?: Record<string, unknown>;\n\n private cursor = 0;\n private previousReplay: ReplayItem[] = [];\n private pendingToolCalls: ToolCallItem[] = [];\n private history: MockHistoryRecord[] = [];\n private activeStream = false;\n\n constructor(options: MockAdapterOptions) {\n super();\n this.handler = options.handler;\n this.providerMetadata = options.providerMetadata;\n }\n\n protected async buildRequest(request: NormalizedRequest): Promise<MockProviderRequest> {\n const turnIndex = this.cursor;\n const context = this.buildHandlerContext(turnIndex);\n const remainingPendingToolCalls = consumePendingToolCalls(this.pendingToolCalls, request.input);\n const handlerResult = this.handler(request, context);\n\n this.cursor += 1;\n\n return {\n request,\n handlerResult,\n turnIndex,\n remainingPendingToolCalls,\n };\n }\n\n protected async *runStream(\n providerRequest: unknown,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n if (this.activeStream) {\n throw new AIRequestError(\"MockAdapter does not support concurrent streams\", \"MOCK_CONCURRENT_STREAM\");\n }\n\n this.activeStream = true;\n\n try {\n const mockRequest = providerRequest as MockProviderRequest;\n const output: OutputItem[] = [];\n let stepCount = 0;\n\n for await (const step of mockRequest.handlerResult) {\n stepCount += 1;\n\n switch (step.type) {\n case \"warning\":\n yield factory.responseWarning(step.message, step.code);\n break;\n case \"auxiliary\":\n yield factory.responseAuxiliary({\n usage: step.usage,\n billing: step.billing,\n auxiliary: step.auxiliary,\n });\n break;\n case \"message\": {\n const item = createMessageFromStep(step, request, mockRequest.turnIndex, stepCount - 1);\n yield* emitMessage(factory, item, resolveStepStreamOptions(undefined, step.stream, \"message\"));\n output.push(item);\n break;\n }\n case \"reasoning\": {\n const item = createReasoningFromStep(step, request, mockRequest.turnIndex, stepCount - 1);\n yield* emitReasoning(factory, item, resolveStepStreamOptions(undefined, step.stream, \"reasoning\"));\n output.push(item);\n break;\n }\n case \"tool_call\": {\n const item = createToolCallFromStep(step);\n yield* emitToolCall(\n factory,\n item,\n step.streamArguments ?? true,\n resolveStepStreamOptions(undefined, step.stream, \"tool_call\"),\n );\n output.push(item);\n break;\n }\n case \"output\": {\n assertSupportedOutputItem(step.item);\n const item = attachSyntheticId(step.item, request, mockRequest.turnIndex, stepCount - 1);\n yield* emitOutputItem(factory, item, resolveStepStreamOptions(undefined, step.stream, \"output\"));\n output.push(item);\n break;\n }\n case \"complete\": {\n const response = this.finalizeTurn(request, factory, mockRequest, output, step, stepCount);\n yield factory.responseCompleted(response);\n return;\n }\n case \"error\": {\n yield factory.responseWarning(step.message, step.code);\n const response = this.finalizeTurn(\n request,\n factory,\n mockRequest,\n output,\n {\n type: \"complete\",\n stopReason: step.stopReason ?? \"error\",\n providerMetadata: step.providerMetadata,\n },\n stepCount,\n );\n yield factory.responseCompleted(response);\n return;\n }\n case \"interrupt\":\n this.pendingToolCalls = mockRequest.remainingPendingToolCalls;\n return;\n case \"throw\":\n throw typeof step.error === \"string\" ? new Error(step.error) : step.error;\n }\n }\n\n const response = this.finalizeTurn(\n request,\n factory,\n mockRequest,\n output,\n {\n type: \"complete\",\n },\n stepCount,\n );\n yield factory.responseCompleted(response);\n } finally {\n this.activeStream = false;\n }\n }\n\n private finalizeTurn(\n request: NormalizedRequest,\n factory: EventFactory,\n mockRequest: MockProviderRequest,\n output: OutputItem[],\n completion: MockCompleteStep,\n stepCount: number,\n ) {\n const replay = completion.replay ?? replayFromOutput(output);\n const toolCalls = output.filter((item): item is ToolCallItem => item.type === \"tool_call\");\n\n this.previousReplay = replay;\n this.pendingToolCalls = [...mockRequest.remainingPendingToolCalls, ...toolCalls];\n this.history.push({\n turnIndex: mockRequest.turnIndex,\n requestId: request.requestId,\n replay,\n toolCalls,\n });\n\n return this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason: completion.stopReason ?? resolveStopReason(output),\n usage: completion.usage,\n billing: completion.billing,\n auxiliary: completion.auxiliary,\n providerMetadata: {\n turnIndex: mockRequest.turnIndex,\n stepCount,\n pendingToolCallIds: this.pendingToolCalls.map((item) => item.id),\n historyLength: this.history.length,\n ...this.providerMetadata,\n ...completion.providerMetadata,\n },\n warnings: completion.warnings,\n metadataSources: [\"mock\"],\n rawResponseId: completion.rawResponseId,\n },\n factory,\n );\n }\n\n private buildHandlerContext(turnIndex: number): MockHandlerContext {\n return {\n turnIndex,\n previousReplay: this.previousReplay.map(cloneItem),\n pendingToolCalls: this.pendingToolCalls.map(cloneItem),\n history: this.history.map((record) => ({\n ...record,\n replay: record.replay.map(cloneItem),\n toolCalls: record.toolCalls.map(cloneItem),\n })),\n };\n }\n}\n\nexport function withMockStreaming(handler: MockStaticHandler, options: MockTextStreamOptions): MockHandler {\n const defaults = resolveMockTextStreamOptions(options, \"mock stream wrapper\");\n if (!defaults) {\n throw new AIRequestError(\"mock stream wrapper requires streaming options\", \"MOCK_STREAM_CONFIG_INVALID\");\n }\n\n return async function* streamWrappedHandler(\n request: NormalizedRequest,\n context: MockHandlerContext,\n ): AsyncIterable<MockStep> {\n const source = await handler(request, context);\n\n for await (const step of source) {\n yield applyDefaultStreaming(step, defaults);\n }\n };\n}\n\nfunction applyDefaultStreaming(step: MockStep, defaults: ResolvedMockTextStreamOptions): MockStep {\n switch (step.type) {\n case \"message\":\n case \"reasoning\":\n case \"tool_call\":\n case \"output\":\n if (step.stream !== undefined) {\n return step;\n }\n return {\n ...step,\n stream: {\n charsPerSecond: defaults.charsPerSecond,\n chunkSize: defaults.chunkSize,\n initialDelayMs: defaults.initialDelayMs,\n },\n };\n default:\n return step;\n }\n}\n\nfunction createMessageFromStep(\n step: MockMessageStep,\n request: NormalizedRequest,\n turnIndex: number,\n stepIndex: number,\n): MessageItem {\n return {\n ...messageItem(normalizeBlocks(step.content), {\n id: step.id ?? `mock-msg-${request.requestId}-${turnIndex}-${stepIndex}`,\n }),\n role: \"assistant\",\n };\n}\n\nfunction createReasoningFromStep(\n step: MockReasoningStep,\n request: NormalizedRequest,\n turnIndex: number,\n stepIndex: number,\n): Extract<OutputItem, { type: \"reasoning\" }> {\n return reasoningItem(\n normalizeBlocks(step.content),\n step.visibility ?? \"full\",\n step.id ?? `mock-reason-${request.requestId}-${turnIndex}-${stepIndex}`,\n );\n}\n\nfunction createToolCallFromStep(step: MockToolCallStep): ToolCallItem {\n return {\n type: \"tool_call\",\n id: step.id,\n name: step.name,\n argumentsText: step.argumentsText,\n argumentsJson: step.argumentsJson,\n };\n}\n\nfunction normalizeBlocks(content: string | ContentBlock[]): ContentBlock[] {\n return typeof content === \"string\" ? [textBlock(content)] : content;\n}\n\nfunction assertSupportedOutputItem(item: OutputItem): void {\n if (item.type === \"opaque\") {\n throw new AIRequestError(\n \"MockAdapter does not stream opaque output items; use complete.replay if needed\",\n \"MOCK_OPAQUE_OUTPUT\",\n );\n }\n}\n\nfunction attachSyntheticId(\n item: Extract<OutputItem, { type: \"message\" | \"reasoning\" | \"tool_call\" }>,\n request: NormalizedRequest,\n turnIndex: number,\n stepIndex: number,\n): Extract<OutputItem, { type: \"message\" | \"reasoning\" | \"tool_call\" }> {\n if (item.type === \"message\") {\n return {\n ...item,\n id: item.id ?? `mock-msg-${request.requestId}-${turnIndex}-${stepIndex}`,\n role: \"assistant\",\n };\n }\n\n if (item.type === \"reasoning\") {\n return {\n ...item,\n id: item.id ?? `mock-reason-${request.requestId}-${turnIndex}-${stepIndex}`,\n };\n }\n\n return item;\n}\n\nasync function* emitOutputItem(\n factory: EventFactory,\n item: Extract<OutputItem, { type: \"message\" | \"reasoning\" | \"tool_call\" }>,\n stream?: ResolvedMockTextStreamOptions,\n): AsyncIterable<AIStreamEvent> {\n if (item.type === \"message\") {\n yield* emitMessage(factory, item, stream);\n return;\n }\n\n if (item.type === \"reasoning\") {\n yield* emitReasoning(factory, item, stream);\n return;\n }\n\n yield* emitToolCall(factory, item, true, stream);\n}\n\nasync function* emitMessage(\n factory: EventFactory,\n item: MessageItem,\n stream?: ResolvedMockTextStreamOptions,\n): AsyncIterable<AIStreamEvent> {\n if (!item.id) {\n throw new AIRequestError(\"Mock message output requires an id after normalization\", \"MOCK_MESSAGE_ID_MISSING\");\n }\n\n yield factory.messageStarted(item.id);\n\n let chunkIndex = 0;\n for (const block of item.content) {\n if (block.type === \"text\") {\n for (const chunk of chunkText(block.text, stream)) {\n await delayForChunk(stream, chunkIndex, chunk.length);\n yield factory.messageDelta(item.id, chunk);\n chunkIndex += 1;\n }\n }\n }\n\n yield factory.messageCompleted(item);\n}\n\nasync function* emitReasoning(\n factory: EventFactory,\n item: Extract<OutputItem, { type: \"reasoning\" }>,\n stream?: ResolvedMockTextStreamOptions,\n): AsyncIterable<AIStreamEvent> {\n if (!item.id) {\n throw new AIRequestError(\"Mock reasoning output requires an id after normalization\", \"MOCK_REASONING_ID_MISSING\");\n }\n\n yield factory.reasoningStarted(item.id, item.visibility);\n\n let chunkIndex = 0;\n for (const block of item.content) {\n if (block.type !== \"text\") {\n yield factory.reasoningDelta(item.id, block);\n continue;\n }\n\n for (const chunk of chunkText(block.text, stream)) {\n await delayForChunk(stream, chunkIndex, chunk.length);\n yield factory.reasoningDelta(item.id, textBlock(chunk));\n chunkIndex += 1;\n }\n }\n\n yield factory.reasoningCompleted(item);\n}\n\nasync function* emitToolCall(\n factory: EventFactory,\n item: ToolCallItem,\n streamArguments: boolean,\n stream?: ResolvedMockTextStreamOptions,\n): AsyncIterable<AIStreamEvent> {\n yield factory.toolCallStarted(item.id, item.name);\n\n if (streamArguments && item.argumentsText) {\n let chunkIndex = 0;\n for (const chunk of chunkText(item.argumentsText, stream)) {\n await delayForChunk(stream, chunkIndex, chunk.length);\n yield factory.toolCallDelta(item.id, { argumentsText: chunk });\n chunkIndex += 1;\n }\n }\n\n yield factory.toolCallCompleted(item);\n}\n\nfunction resolveStepStreamOptions(\n defaults: ResolvedMockTextStreamOptions | undefined,\n override: MockTextStreamOptions | false | undefined,\n label: string,\n): ResolvedMockTextStreamOptions | undefined {\n if (override === false) {\n return undefined;\n }\n\n return resolveMockTextStreamOptions(override, `${label} stream`, defaults);\n}\n\nfunction resolveMockTextStreamOptions(\n options: MockTextStreamOptions | undefined,\n label: string,\n defaults?: ResolvedMockTextStreamOptions,\n): ResolvedMockTextStreamOptions | undefined {\n if (options === undefined) {\n return defaults;\n }\n\n const chunkSize = options.chunkSize ?? defaults?.chunkSize ?? 1;\n const initialDelayMs = options.initialDelayMs ?? defaults?.initialDelayMs ?? 0;\n const charsPerSecond = options.charsPerSecond ?? defaults?.charsPerSecond;\n\n if (!Number.isInteger(chunkSize) || chunkSize < 1) {\n throw new AIRequestError(`${label}: chunkSize must be a positive integer`, \"MOCK_STREAM_CONFIG_INVALID\");\n }\n\n if (!Number.isFinite(initialDelayMs) || initialDelayMs < 0) {\n throw new AIRequestError(`${label}: initialDelayMs must be a non-negative number`, \"MOCK_STREAM_CONFIG_INVALID\");\n }\n\n if (charsPerSecond !== undefined && (!Number.isFinite(charsPerSecond) || charsPerSecond <= 0)) {\n throw new AIRequestError(`${label}: charsPerSecond must be a positive number`, \"MOCK_STREAM_CONFIG_INVALID\");\n }\n\n return {\n chunkSize,\n initialDelayMs,\n charsPerSecond,\n };\n}\n\nfunction chunkText(text: string, stream?: ResolvedMockTextStreamOptions): string[] {\n if (!text) {\n return [];\n }\n\n if (!stream) {\n return [text];\n }\n\n const chars = Array.from(text);\n const chunks: string[] = [];\n\n for (let index = 0; index < chars.length; index += stream.chunkSize) {\n chunks.push(chars.slice(index, index + stream.chunkSize).join(\"\"));\n }\n\n return chunks;\n}\n\nasync function delayForChunk(\n stream: ResolvedMockTextStreamOptions | undefined,\n chunkIndex: number,\n chunkLength: number,\n): Promise<void> {\n if (!stream) {\n return;\n }\n\n if (chunkIndex === 0 && stream.initialDelayMs > 0) {\n await sleep(stream.initialDelayMs);\n return;\n }\n\n if (chunkIndex > 0 && stream.charsPerSecond !== undefined) {\n await sleep((chunkLength / stream.charsPerSecond) * 1000);\n }\n}\n\nasync function sleep(ms: number): Promise<void> {\n if (ms <= 0) {\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction resolveStopReason(output: OutputItem[]): StopReason {\n return output.some((item) => item.type === \"tool_call\") ? \"tool_call\" : \"end_turn\";\n}\n\nfunction consumePendingToolCalls(pending: readonly ToolCallItem[], input: readonly InputItem[]): ToolCallItem[] {\n const fulfilledIds = new Set(\n input.filter((item): item is ToolResultItem => item.type === \"tool_result\").map((item) => item.callId),\n );\n\n return pending.filter((item) => !fulfilledIds.has(item.id)).map(cloneItem);\n}\n\nfunction assertReplayIncluded(input: readonly InputItem[], replay: readonly ReplayItem[], prefix: string): void {\n const fingerprints = input.map(fingerprintItem);\n let cursor = 0;\n\n for (const replayItem of replay) {\n const target = fingerprintItem(replayItem);\n const foundIndex = fingerprints.indexOf(target, cursor);\n if (foundIndex === -1) {\n throw new AIRequestError(\n `${prefix}: previous replay item was not carried into the next request`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n cursor = foundIndex + 1;\n }\n}\n\nfunction assertOrderedItems(\n input: readonly InputItem[],\n expectations: readonly MockInputExpectation[],\n prefix: string,\n): void {\n let cursor = 0;\n\n for (const expected of expectations) {\n let matched = false;\n while (cursor < input.length) {\n const item = input[cursor];\n if (item !== undefined && matchesItemExpectation(item, expected)) {\n matched = true;\n cursor += 1;\n break;\n }\n cursor += 1;\n }\n\n if (!matched) {\n throw new AIRequestError(\n `${prefix}: missing ordered input item ${describeExpectation(expected)}`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n }\n}\n\nfunction assertUnorderedItems(\n input: readonly InputItem[],\n expectations: readonly MockInputExpectation[],\n prefix: string,\n): void {\n for (const expected of expectations) {\n const matched = input.some((item) => matchesItemExpectation(item, expected));\n if (!matched) {\n throw new AIRequestError(\n `${prefix}: missing input item ${describeExpectation(expected)}`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n }\n}\n\nfunction matchesItemExpectation(item: InputItem, expected: MockInputExpectation): boolean {\n if (item.type !== expected.type) {\n return false;\n }\n\n if (expected.id !== undefined && \"id\" in item && item.id !== expected.id) {\n return false;\n }\n\n switch (item.type) {\n case \"message\":\n return (\n (expected.role === undefined || item.role === expected.role) && matchesText(item.content, expected.textIncludes)\n );\n case \"reasoning\":\n return (\n (expected.visibility === undefined || item.visibility === expected.visibility) &&\n matchesText(item.content, expected.textIncludes)\n );\n case \"tool_call\":\n return (\n (expected.name === undefined || item.name === expected.name) &&\n (expected.textIncludes === undefined || item.argumentsText.includes(expected.textIncludes))\n );\n case \"tool_result\":\n return (\n (expected.toolName === undefined || item.toolName === expected.toolName) &&\n (expected.callId === undefined || item.callId === expected.callId) &&\n (expected.outcome === undefined || item.outcome === expected.outcome) &&\n matchesText(item.content, expected.textIncludes)\n );\n case \"opaque\":\n return (\n (expected.source === undefined || item.source === expected.source) &&\n (expected.purpose === undefined || item.purpose === expected.purpose)\n );\n }\n}\n\nfunction matchesText(blocks: readonly ContentBlock[], textIncludes: string | undefined): boolean {\n if (textIncludes === undefined) {\n return true;\n }\n\n return blocks.some((block) => {\n if (block.type === \"text\") return block.text.includes(textIncludes);\n if (block.type === \"json\") return JSON.stringify(block.json).includes(textIncludes);\n return false;\n });\n}\n\nfunction fingerprintItem(item: InputItem): string {\n return JSON.stringify(item);\n}\n\nfunction describeExpectation(expectation: MockInputExpectation): string {\n const parts = [`type=${expectation.type}`];\n if (expectation.role) parts.push(`role=${expectation.role}`);\n if (expectation.name) parts.push(`name=${expectation.name}`);\n if (expectation.toolName) parts.push(`toolName=${expectation.toolName}`);\n if (expectation.callId) parts.push(`callId=${expectation.callId}`);\n if (expectation.textIncludes) parts.push(`textIncludes=${JSON.stringify(expectation.textIncludes)}`);\n return `{ ${parts.join(\", \")} }`;\n}\n\nfunction cloneItem<T>(item: T): T {\n return structuredClone(item);\n}\n","/**\n * 模拟流式 (Synthetic Streaming)\n *\n * 将一组已解析的 canonical OutputItem 包装为规范事件流。\n * 适用于非原生流式后端:adapter 拿到完整响应后,调用此函数\n * 即可产出一致的事件序列,无需自己逐事件组装。\n *\n * 约束:\n * - 每个 item 只发一块完整 delta(不模拟逐 token)\n * - 保持 item 边界\n * - 保持后端原始顺序\n * - 不发明 reasoning\n * - 不改写工具参数\n */\n\nimport { createEventFactory } from \"../core/event-factory.js\";\nimport { replayFromOutput, extractText } from \"./mapping.js\";\n\nimport type {\n OutputItem,\n ReplayItem,\n StopReason,\n Usage,\n BillingInfo,\n AIStreamEvent,\n AIResponse,\n MessageItem,\n ReasoningItem,\n ToolCallItem,\n} from \"../types/index.js\";\n\n// ── 输入参数 ──────────────────────────────────────────────────\n\nexport type SyntheticStreamOptions = {\n model: string;\n responseId: string;\n backend: {\n kind: \"chat-completions\" | \"messages\" | \"responses\" | \"mock\";\n /** syntheticStream 强制设为 true */\n };\n output: OutputItem[];\n replay?: ReplayItem[];\n stopReason?: StopReason;\n usage?: Usage;\n billing?: BillingInfo;\n providerMetadata?: Record<string, unknown>;\n rawResponseId?: string;\n warnings?: string[];\n};\n\n// ── Synthetic Stream ──────────────────────────────────────────\n\n/**\n * 将已解析的 output items 包装为完整规范事件流。\n *\n * 用法示例(在 adapter 的 runStream 中):\n * ```ts\n * const result = parseNonStreamingResponse(data);\n * yield* syntheticStream({\n * model: request.model,\n * responseId: request.requestId,\n * backend: { kind: \"chat-completions\" },\n * output: result.output,\n * stopReason: result.stopReason,\n * usage: result.usage,\n * });\n * ```\n */\nexport async function* syntheticStream(options: SyntheticStreamOptions): AsyncIterable<AIStreamEvent> {\n const {\n model,\n responseId,\n backend,\n output,\n replay,\n stopReason,\n usage,\n billing,\n providerMetadata,\n rawResponseId,\n warnings: extraWarnings,\n } = options;\n\n const factory = createEventFactory({\n responseId,\n backend: { kind: backend.kind, isSynthetic: true },\n });\n\n // 1. 响应开始\n yield factory.responseStarted(model);\n\n // 2. item 级事件 — 每个 item 只发一块完整 delta\n for (const item of output) {\n yield* emitItemEvents(item, factory);\n }\n\n // 3. auxiliary 事件(如有)\n if (usage || billing) {\n yield factory.responseAuxiliary({ usage, billing });\n }\n\n // 4. 构建最终 response\n const finalReplay = replay ?? replayFromOutput(output);\n\n // 收集警告\n const allWarnings: string[] = [];\n allWarnings.push(\"Response is synthetically streamed; delta granularity may differ from native streaming\");\n if (extraWarnings) allWarnings.push(...extraWarnings);\n\n const response: AIResponse = {\n id: responseId,\n output,\n replay: finalReplay,\n text: extractText(output),\n toolCalls: output.filter((item): item is ToolCallItem => item.type === \"tool_call\"),\n stopReason,\n usage,\n billing,\n auxiliary: providerMetadata ? { providerMetadata } : undefined,\n warnings: allWarnings.length > 0 ? allWarnings : undefined,\n backend: {\n requestId: responseId,\n rawResponseId,\n adapter: backend.kind,\n isSyntheticStream: true,\n },\n };\n\n yield factory.responseCompleted(response);\n}\n\n// ── Item 事件发射 ─────────────────────────────────────────────\n\nfunction* emitItemEvents(item: OutputItem, factory: ReturnType<typeof createEventFactory>): Generator<AIStreamEvent> {\n switch (item.type) {\n case \"message\":\n yield* emitMessageEvents(item, factory);\n break;\n case \"reasoning\":\n yield* emitReasoningEvents(item, factory);\n break;\n case \"tool_call\":\n yield* emitToolCallEvents(item, factory);\n break;\n case \"opaque\":\n // Opaque items in output have no streaming events\n break;\n }\n}\n\nfunction* emitMessageEvents(\n item: MessageItem,\n factory: ReturnType<typeof createEventFactory>,\n): Generator<AIStreamEvent> {\n const id = item.id ?? `syn-msg-${crypto.randomUUID()}`;\n yield factory.messageStarted(id);\n\n for (const block of item.content) {\n if (block.type === \"text\") {\n yield factory.messageDelta(id, block.text);\n }\n }\n\n yield factory.messageCompleted(item);\n}\n\nfunction* emitReasoningEvents(\n item: ReasoningItem,\n factory: ReturnType<typeof createEventFactory>,\n): Generator<AIStreamEvent> {\n const id = item.id ?? `syn-reason-${crypto.randomUUID()}`;\n yield factory.reasoningStarted(id, item.visibility);\n\n for (const block of item.content) {\n if (block.type === \"text\") {\n yield factory.reasoningDelta(id, block);\n }\n }\n\n yield factory.reasoningCompleted(item);\n}\n\nfunction* emitToolCallEvents(\n item: ToolCallItem,\n factory: ReturnType<typeof createEventFactory>,\n): Generator<AIStreamEvent> {\n yield factory.toolCallStarted(item.id, item.name);\n\n if (item.argumentsText) {\n yield factory.toolCallDelta(item.id, { argumentsText: item.argumentsText });\n }\n\n yield factory.toolCallCompleted(item);\n}\n\n// ── Helper ────────────────────────────────────────────────────\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["mergeAuxiliary","rollbackTrailingAssistantMessages","rollbackTrailingAssistantMessages"],"sources":["../src/core/errors.ts","../src/core/validation.ts","../src/core/normalize.ts","../src/core/client.ts","../src/core/event-factory.ts","../src/core/aggregator.ts","../src/core/collect-stream.ts","../src/helpers/mapping.ts","../src/helpers/auxiliary-collector.ts","../src/helpers/adapter-auxiliary.ts","../src/helpers/adapter-base.ts","../src/helpers/usage-mapping.ts","../src/helpers/sse-parser.ts","../src/adapters/responses.ts","../src/adapters/messages.ts","../src/adapters/chat-completions.ts","../src/adapters/ollama.ts","../src/adapters/mock.ts","../src/helpers/synthetic-stream.ts"],"sourcesContent":["/**\n * 公共错误模型\n *\n * 把失败、降级、断流三类情况明确区分:\n * - 致命错误 → 同步抛错或迭代器抛错\n * - 非致命差异 → warning 通道\n * - 流中断 → 不伪造 response.completed\n */\n\n// ── 错误类型 ──────────────────────────────────────────────────\n\nexport type ErrorCode =\n | \"INPUT_EMPTY\"\n | \"TEMPERATURE_OUT_OF_RANGE\"\n | \"MAX_OUTPUT_TOKENS_INVALID\"\n | \"TOOL_CHOICE_NO_TOOLS\"\n | \"TOOL_CHOICE_UNKNOWN_TOOL\"\n | \"PROVIDER_ERROR\"\n | \"AUTH_ERROR\"\n | \"STREAM_ERROR\"\n | \"MAPPING_ERROR\"\n | \"STREAM_INCOMPLETE\"\n | \"LOOKUP_FAILED\"\n | \"LOOKUP_TIMEOUT\"\n | string;\n\nexport class AIError extends Error {\n override readonly name: string;\n\n constructor(\n message: string,\n public readonly code: ErrorCode,\n name?: string,\n ) {\n super(message);\n this.name = name ?? \"AIError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** 请求构造失败 — 参数校验不通过。在进入 adapter 前同步抛错。 */\nexport class AIRequestError extends AIError {\n constructor(message: string, code: ErrorCode) {\n super(message, code, \"AIRequestError\");\n }\n}\n\n/** Provider 调用失败 — HTTP 非 2xx、网络错误。由 AdapterBase 捕获转为 warning。 */\nexport class AIProviderError extends AIError {\n constructor(\n message: string,\n code: ErrorCode,\n public readonly statusCode?: number,\n public readonly responseBody?: string,\n ) {\n super(message, code, \"AIProviderError\");\n }\n}\n\n/** 流协议损坏 — SSE 解析失败、chunk 格式异常。 */\nexport class AIStreamError extends AIError {\n constructor(message: string, code: ErrorCode) {\n super(message, code, \"AIStreamError\");\n }\n}\n\n/** Canonical 映射失败 — 无法将 provider 响应映射到 canonical 类型。 */\nexport class AIMappingError extends AIError {\n constructor(message: string, code: ErrorCode) {\n super(message, code, \"AIMappingError\");\n }\n}\n\n// ── Warning 辅助 ──────────────────────────────────────────────\n\n/**\n * 标准 warning 代码列表。\n * 用于非致命差异的记录。\n */\nexport const WarningCode = {\n /** replay fidelity 低于预期 */\n REPLAY_FIDELITY_LOW: \"REPLAY_FIDELITY_LOW\",\n /** usage 字段缺失 */\n USAGE_MISSING: \"USAGE_MISSING\",\n /** billing 字段缺失 */\n BILLING_MISSING: \"BILLING_MISSING\",\n /** billing 只能给估算值 */\n BILLING_ESTIMATED: \"BILLING_ESTIMATED\",\n /** follow-up lookup 失败 */\n LOOKUP_FAILED: \"LOOKUP_FAILED\",\n /** lookup 超时 */\n LOOKUP_TIMEOUT: \"LOOKUP_TIMEOUT\",\n /** 流提前中断 */\n STREAM_INCOMPLETE: \"STREAM_INCOMPLETE\",\n /** 能力降级 */\n CAPABILITY_DOWNGRADE: \"CAPABILITY_DOWNGRADE\",\n /** 模拟流式 */\n SYNTHETIC_STREAM: \"SYNTHETIC_STREAM\",\n} as const;\n","/**\n * 请求校验\n *\n * 在请求进入 adapter 前对参数合法性做基础检查。\n * 校验失败时抛 AIRequestError。\n */\n\nimport type { AIRequest } from \"../types/index.js\";\nimport { AIRequestError } from \"./errors.js\";\n\nexport type ValidationIssue = {\n field: string;\n code: string;\n message: string;\n};\n\nconst MESSAGE_ROLES = new Set([\"user\", \"assistant\"]);\nconst REASONING_VISIBILITIES = new Set([\"full\", \"summary\", \"redacted\", \"opaque\"]);\nconst TOOL_RESULT_OUTCOMES = new Set([\"success\", \"error\", \"rejected\"]);\nconst INCLUDE_MODES = new Set([\"off\", \"best_effort\"]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction pushIssue(issues: ValidationIssue[], field: string, code: string, message: string): void {\n issues.push({ field, code, message });\n}\n\nfunction validateContentBlock(block: unknown, field: string, issues: ValidationIssue[]): void {\n if (!isRecord(block) || typeof block.type !== \"string\") {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field} must be a valid ContentBlock`);\n return;\n }\n\n switch (block.type) {\n case \"text\":\n if (typeof block.text !== \"string\") {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.text must be a string`);\n }\n return;\n case \"json\":\n if (!(\"json\" in block)) {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.json must be present`);\n }\n return;\n case \"image\":\n if (typeof block.imageUrl !== \"string\" || block.imageUrl.length === 0) {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.imageUrl must be a non-empty string`);\n }\n return;\n case \"binary_ref\":\n if (typeof block.ref !== \"string\" || block.ref.length === 0) {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.ref must be a non-empty string`);\n }\n return;\n case \"opaque\":\n if (!(\"payload\" in block)) {\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.payload must be present`);\n }\n return;\n default:\n pushIssue(issues, field, \"CONTENT_BLOCK_INVALID\", `${field}.type \"${block.type}\" is not supported`);\n }\n}\n\nfunction validateContentArray(content: unknown, field: string, issues: ValidationIssue[], code: string): void {\n if (!Array.isArray(content)) {\n pushIssue(issues, field, code, `${field} must be a ContentBlock[]`);\n return;\n }\n\n for (let i = 0; i < content.length; i++) {\n validateContentBlock(content[i], `${field}[${i}]`, issues);\n }\n}\n\nfunction validateInstructionArray(content: unknown, field: string, issues: ValidationIssue[]): void {\n if (!Array.isArray(content)) {\n pushIssue(issues, field, \"INSTRUCTIONS_INVALID\", `${field} must be an InstructionBlock[]`);\n return;\n }\n\n for (let i = 0; i < content.length; i++) {\n const block = content[i];\n const blockField = `${field}[${i}]`;\n validateContentBlock(block, blockField, issues);\n\n if (!isRecord(block) || typeof block.type !== \"string\") continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n pushIssue(issues, blockField, \"INSTRUCTIONS_INVALID\", `${blockField} only supports text/json blocks`);\n }\n }\n}\n\nfunction validateInputItem(item: unknown, field: string, issues: ValidationIssue[]): void {\n if (!isRecord(item)) {\n pushIssue(issues, field, \"INPUT_INVALID_ITEM\", `${field} must be a valid InputItem`);\n return;\n }\n\n if (typeof item.type !== \"string\") {\n pushIssue(issues, field, \"INPUT_ITEM_UNKNOWN_TYPE\", `${field}.type must be a supported InputItem type`);\n return;\n }\n\n switch (item.type) {\n case \"message\":\n if (typeof item.role !== \"string\" || !MESSAGE_ROLES.has(item.role)) {\n pushIssue(issues, `${field}.role`, \"MESSAGE_ROLE_INVALID\", `${field}.role must be a valid message role`);\n }\n validateContentArray(item.content, `${field}.content`, issues, \"MESSAGE_CONTENT_INVALID\");\n return;\n case \"reasoning\":\n if (typeof item.visibility !== \"string\" || !REASONING_VISIBILITIES.has(item.visibility)) {\n pushIssue(\n issues,\n `${field}.visibility`,\n \"REASONING_VISIBILITY_INVALID\",\n `${field}.visibility must be a valid reasoning visibility`,\n );\n }\n validateContentArray(item.content, `${field}.content`, issues, \"REASONING_CONTENT_INVALID\");\n return;\n case \"tool_call\":\n if (typeof item.id !== \"string\" || item.id.length === 0) {\n pushIssue(issues, `${field}.id`, \"TOOL_CALL_ID_INVALID\", `${field}.id must be a non-empty string`);\n }\n if (typeof item.name !== \"string\" || item.name.length === 0) {\n pushIssue(issues, `${field}.name`, \"TOOL_CALL_NAME_INVALID\", `${field}.name must be a non-empty string`);\n }\n if (typeof item.argumentsText !== \"string\") {\n pushIssue(\n issues,\n `${field}.argumentsText`,\n \"TOOL_CALL_ARGUMENTS_INVALID\",\n `${field}.argumentsText must be a string`,\n );\n }\n return;\n case \"tool_result\":\n if (typeof item.callId !== \"string\" || item.callId.length === 0) {\n pushIssue(\n issues,\n `${field}.callId`,\n \"TOOL_RESULT_CALL_ID_INVALID\",\n `${field}.callId must be a non-empty string`,\n );\n }\n if (typeof item.toolName !== \"string\" || item.toolName.length === 0) {\n pushIssue(\n issues,\n `${field}.toolName`,\n \"TOOL_RESULT_NAME_INVALID\",\n `${field}.toolName must be a non-empty string`,\n );\n }\n if (typeof item.outcome !== \"string\" || !TOOL_RESULT_OUTCOMES.has(item.outcome)) {\n pushIssue(\n issues,\n `${field}.outcome`,\n \"TOOL_RESULT_OUTCOME_INVALID\",\n `${field}.outcome must be success, error, or rejected`,\n );\n }\n validateContentArray(item.content, `${field}.content`, issues, \"TOOL_RESULT_CONTENT_INVALID\");\n return;\n case \"opaque\":\n if (typeof item.source !== \"string\" || item.source.length === 0) {\n pushIssue(issues, `${field}.source`, \"OPAQUE_SOURCE_INVALID\", `${field}.source must be a non-empty string`);\n }\n if (typeof item.purpose !== \"string\" || item.purpose.length === 0) {\n pushIssue(issues, `${field}.purpose`, \"OPAQUE_PURPOSE_INVALID\", `${field}.purpose must be a non-empty string`);\n }\n return;\n default:\n pushIssue(issues, `${field}.type`, \"INPUT_ITEM_UNKNOWN_TYPE\", `${field}.type \"${item.type}\" is not supported`);\n }\n}\n\nfunction validateTools(tools: unknown, issues: ValidationIssue[]): void {\n if (tools === undefined) return;\n if (!Array.isArray(tools)) {\n pushIssue(issues, \"tools\", \"TOOLS_INVALID\", \"tools must be an array\");\n return;\n }\n\n const seenNames = new Set<string>();\n for (let i = 0; i < tools.length; i++) {\n const tool = tools[i];\n const field = `tools[${i}]`;\n if (!isRecord(tool)) {\n pushIssue(issues, field, \"TOOL_INVALID\", `${field} must be a valid ToolDefinition`);\n continue;\n }\n\n if (typeof tool.name !== \"string\" || tool.name.length === 0) {\n pushIssue(issues, `${field}.name`, \"TOOL_NAME_INVALID\", `${field}.name must be a non-empty string`);\n } else {\n if (seenNames.has(tool.name)) {\n pushIssue(issues, `${field}.name`, \"TOOLS_DUPLICATE_NAME\", `tool name \"${tool.name}\" is duplicated`);\n }\n seenNames.add(tool.name);\n }\n\n if (tool.description !== undefined && typeof tool.description !== \"string\") {\n pushIssue(issues, `${field}.description`, \"TOOL_DESCRIPTION_INVALID\", `${field}.description must be a string`);\n }\n\n if (!isRecord(tool.inputSchema)) {\n pushIssue(issues, `${field}.inputSchema`, \"TOOL_INPUT_SCHEMA_INVALID\", `${field}.inputSchema must be an object`);\n }\n }\n}\n\nfunction validateToolChoice(toolChoice: unknown, issues: ValidationIssue[]): void {\n if (toolChoice === undefined) return;\n if (toolChoice === \"auto\" || toolChoice === \"none\") return;\n if (\n !isRecord(toolChoice) ||\n toolChoice.type !== \"tool\" ||\n typeof toolChoice.name !== \"string\" ||\n toolChoice.name.length === 0\n ) {\n pushIssue(issues, \"toolChoice\", \"TOOL_CHOICE_INVALID\", 'toolChoice must be auto, none, or { type: \"tool\", name }');\n }\n}\n\n/**\n * 校验 AIRequest,返回校验问题列表。\n * 空数组表示无问题。\n */\nexport function validateRequest(request: AIRequest): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n\n if (request.instructions !== undefined) {\n if (typeof request.instructions === \"string\") {\n // no-op\n } else if (Array.isArray(request.instructions)) {\n validateInstructionArray(request.instructions, \"instructions\", issues);\n } else {\n pushIssue(issues, \"instructions\", \"INSTRUCTIONS_INVALID\", \"instructions must be a string or InstructionBlock[]\");\n }\n }\n\n // input 非空约束\n if (!Array.isArray(request.input) || request.input.length === 0) {\n pushIssue(issues, \"input\", \"INPUT_EMPTY\", \"input must be a non-empty array\");\n }\n\n // input 元素类型检查\n if (Array.isArray(request.input)) {\n for (let i = 0; i < request.input.length; i++) {\n validateInputItem(request.input[i], `input[${i}]`, issues);\n }\n }\n\n // temperature 范围\n if (request.temperature !== undefined) {\n if (typeof request.temperature !== \"number\" || isNaN(request.temperature)) {\n issues.push({\n field: \"temperature\",\n code: \"TEMPERATURE_NOT_NUMBER\",\n message: \"temperature must be a number\",\n });\n } else if (request.temperature < 0 || request.temperature > 2) {\n issues.push({\n field: \"temperature\",\n code: \"TEMPERATURE_OUT_OF_RANGE\",\n message: \"temperature must be between 0 and 2\",\n });\n }\n }\n\n // maxOutputTokens 合法性\n if (request.maxOutputTokens !== undefined) {\n if (typeof request.maxOutputTokens !== \"number\" || isNaN(request.maxOutputTokens)) {\n issues.push({\n field: \"maxOutputTokens\",\n code: \"MAX_OUTPUT_TOKENS_NOT_NUMBER\",\n message: \"maxOutputTokens must be a number\",\n });\n } else if (!Number.isInteger(request.maxOutputTokens) || request.maxOutputTokens < 1) {\n issues.push({\n field: \"maxOutputTokens\",\n code: \"MAX_OUTPUT_TOKENS_INVALID\",\n message: \"maxOutputTokens must be a positive integer\",\n });\n }\n }\n\n if (request.include !== undefined) {\n if (!isRecord(request.include)) {\n pushIssue(issues, \"include\", \"INCLUDE_INVALID\", \"include must be an object\");\n } else {\n if (request.include.usage !== undefined && !INCLUDE_MODES.has(request.include.usage)) {\n pushIssue(issues, \"include.usage\", \"INCLUDE_USAGE_INVALID\", \"include.usage must be off or best_effort\");\n }\n if (request.include.billing !== undefined && !INCLUDE_MODES.has(request.include.billing)) {\n pushIssue(issues, \"include.billing\", \"INCLUDE_BILLING_INVALID\", \"include.billing must be off or best_effort\");\n }\n if (request.include.providerMetadata !== undefined && !INCLUDE_MODES.has(request.include.providerMetadata)) {\n pushIssue(\n issues,\n \"include.providerMetadata\",\n \"INCLUDE_PROVIDER_METADATA_INVALID\",\n \"include.providerMetadata must be off or best_effort\",\n );\n }\n }\n }\n\n if (request.metadata !== undefined) {\n if (!isRecord(request.metadata)) {\n pushIssue(issues, \"metadata\", \"METADATA_INVALID\", \"metadata must be an object\");\n } else {\n for (const [key, value] of Object.entries(request.metadata)) {\n if (typeof value !== \"string\") {\n pushIssue(issues, `metadata.${key}`, \"METADATA_VALUE_INVALID\", `metadata.${key} must be a string`);\n }\n }\n }\n }\n\n validateTools(request.tools, issues);\n validateToolChoice(request.toolChoice, issues);\n\n // toolChoice 与 tools 的一致性\n if (\n request.toolChoice &&\n typeof request.toolChoice === \"object\" &&\n \"type\" in request.toolChoice &&\n request.toolChoice.type === \"tool\"\n ) {\n const chosenName = request.toolChoice.name;\n if (!request.tools || request.tools.length === 0) {\n issues.push({\n field: \"toolChoice\",\n code: \"TOOL_CHOICE_NO_TOOLS\",\n message: `toolChoice specifies tool \"${chosenName}\" but no tools are defined`,\n });\n } else if (!request.tools.some((t) => t.name === chosenName)) {\n issues.push({\n field: \"toolChoice\",\n code: \"TOOL_CHOICE_UNKNOWN_TOOL\",\n message: `toolChoice specifies tool \"${chosenName}\" which is not in tools array`,\n });\n }\n }\n\n return issues;\n}\n\n/**\n * 校验请求并抛出首个问题。\n * 适用于客户端入口的快速失败检查。\n */\nexport function assertValidRequest(request: AIRequest): void {\n const issues = validateRequest(request);\n const first = issues[0];\n if (first) {\n throw new AIRequestError(first.message, first.code);\n }\n}\n","/**\n * 请求归一化\n *\n * 将 AIRequest + client 配置归一化为 NormalizedRequest,\n * 包括默认值合并、requestId 生成、include 默认值填充。\n */\n\nimport type { AIRequest, NormalizedRequest } from \"../types/index.js\";\nimport { assertValidRequest } from \"./validation.js\";\n\nexport type NormalizeOptions = {\n model: string;\n defaults?: Partial<AIRequest>;\n};\n\nconst DEFAULT_INCLUDE = {\n usage: \"best_effort\" as const,\n billing: \"best_effort\" as const,\n providerMetadata: \"best_effort\" as const,\n};\n\n/**\n * 归一化请求:\n * 1. 合并 defaults\n * 2. 填充 include 默认值\n * 3. 生成 requestId\n * 4. 校验请求合法性\n */\nexport function normalizeRequest(request: AIRequest, options: NormalizeOptions): NormalizedRequest {\n const { model, defaults } = options;\n\n // 合并 defaults(浅合并,input/tools 由 request 完全覆盖)\n const merged: AIRequest = {\n ...defaults,\n ...request,\n include: {\n ...DEFAULT_INCLUDE,\n ...defaults?.include,\n ...request.include,\n },\n };\n\n // 校验\n assertValidRequest(merged);\n\n return {\n ...merged,\n model,\n requestId: crypto.randomUUID(),\n };\n}\n","/**\n * AI 客户端入口\n *\n * 打通 createAIClient() 到 adapter 调用之间的公共入口。\n */\n\nimport type { AIRequest, AIStreamEvent, AIClient, CreateAIClientOptions } from \"../types/index.js\";\nimport { normalizeRequest } from \"./normalize.js\";\n\nexport function createAIClient(options: CreateAIClientOptions): AIClient {\n const { adapter, model, defaults } = options;\n\n const client: AIClient = {\n stream(request: AIRequest): AsyncIterable<AIStreamEvent> {\n const normalized = normalizeRequest(request, { model, defaults });\n return adapter.stream(normalized);\n },\n };\n\n return client;\n}\n\nexport type { AIClient, CreateAIClientOptions } from \"../types/index.js\";\n","/**\n * 共享事件工厂\n *\n * 负责创建带有统一 sequence / timestamp / responseId / backend 的事件对象。\n * 每个 factory 实例管理一个单调递增的 sequence 计数器。\n */\n\nimport type {\n ResponseStartedEvent,\n ResponseWarningEvent,\n ResponseAuxiliaryEvent,\n ResponseCompletedEvent,\n MessageStartedEvent,\n MessageDeltaEvent,\n MessageCompletedEvent,\n ReasoningStartedEvent,\n ReasoningDeltaEvent,\n ReasoningCompletedEvent,\n ToolCallStartedEvent,\n ToolCallDeltaEvent,\n ToolCallCompletedEvent,\n MessageItem,\n ReasoningItem,\n ToolCallItem,\n ContentBlock,\n Usage,\n BillingInfo,\n AuxiliaryInfo,\n AIResponse,\n} from \"../types/index.js\";\n\nexport type EventFactoryBackend = {\n kind: \"chat-completions\" | \"messages\" | \"responses\" | \"ollama\" | \"mock\";\n isSynthetic: boolean;\n};\n\nexport type EventFactoryState = {\n responseId: string;\n backend: EventFactoryBackend;\n};\n\nfunction timestamp(): string {\n return new Date().toISOString();\n}\n\nexport function createEventFactory(state: EventFactoryState) {\n let seq = 0;\n const warnings: string[] = [];\n\n function next(): number {\n return seq++;\n }\n\n function base(): Pick<ResponseStartedEvent, \"responseId\" | \"sequence\" | \"timestamp\" | \"backend\"> {\n return {\n responseId: state.responseId,\n sequence: next(),\n timestamp: timestamp(),\n backend: { ...state.backend },\n };\n }\n\n return {\n // ── 响应级事件 ──────────────────────────────────────────\n\n responseStarted(model: string): ResponseStartedEvent {\n return { ...base(), type: \"response.started\", model };\n },\n\n responseWarning(message: string, code?: string): ResponseWarningEvent {\n warnings.push(message);\n return { ...base(), type: \"response.warning\", message, code };\n },\n\n responseAuxiliary(data: {\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: Partial<AuxiliaryInfo>;\n }): ResponseAuxiliaryEvent {\n return { ...base(), type: \"response.auxiliary\", ...data };\n },\n\n responseCompleted(response: AIResponse): ResponseCompletedEvent {\n return { ...base(), type: \"response.completed\", response };\n },\n\n // ── 消息流事件 ──────────────────────────────────────────\n\n messageStarted(id: string): MessageStartedEvent {\n return { ...base(), type: \"message.started\", item: { id, role: \"assistant\" } };\n },\n\n messageDelta(itemId: string, text: string): MessageDeltaEvent {\n return { ...base(), type: \"message.delta\", itemId, delta: { type: \"text\", text } };\n },\n\n messageCompleted(item: MessageItem): MessageCompletedEvent {\n return { ...base(), type: \"message.completed\", item };\n },\n\n // ── 思维链流事件 ────────────────────────────────────────\n\n reasoningStarted(id: string, visibility: ReasoningItem[\"visibility\"]): ReasoningStartedEvent {\n return { ...base(), type: \"reasoning.started\", item: { id, visibility } };\n },\n\n reasoningDelta(itemId: string, delta: ContentBlock): ReasoningDeltaEvent {\n return { ...base(), type: \"reasoning.delta\", itemId, delta };\n },\n\n reasoningCompleted(item: ReasoningItem): ReasoningCompletedEvent {\n return { ...base(), type: \"reasoning.completed\", item };\n },\n\n // ── 工具调用流事件 ──────────────────────────────────────\n\n toolCallStarted(id: string, name: string): ToolCallStartedEvent {\n return { ...base(), type: \"tool_call.started\", item: { id, name } };\n },\n\n toolCallDelta(itemId: string, delta: { argumentsText?: string }): ToolCallDeltaEvent {\n return { ...base(), type: \"tool_call.delta\", itemId, delta };\n },\n\n toolCallCompleted(item: ToolCallItem): ToolCallCompletedEvent {\n return { ...base(), type: \"tool_call.completed\", item };\n },\n\n /** 返回当前已发出的 sequence 计数(用于断言) */\n get sequence(): number {\n return seq;\n },\n\n /** 返回当前已记录的 warning 副本。 */\n get warnings(): string[] {\n return [...warnings];\n },\n };\n}\n\nexport type EventFactory = ReturnType<typeof createEventFactory>;\n","/**\n * 流聚合器\n *\n * 将 AIStreamEvent 序列聚合为统一的 AIResponse。\n * 职责:\n * - 合并 message.delta / reasoning.delta / tool_call.delta\n * - 合并多次 response.auxiliary 补丁\n * - 生成 output / text / toolCalls\n * - 保持 output 顺序稳定\n *\n * 约束:\n * - replay 由 adapter 显式提供,聚合器不猜测\n * - 不伪造 reasoning\n * - 不解释 opaque payload\n */\n\nimport type {\n AIStreamEvent,\n AIResponse,\n MessageItem,\n ToolCallItem,\n OutputItem,\n Usage,\n BillingInfo,\n AuxiliaryInfo,\n BackendTrace,\n StopReason,\n} from \"../types/index.js\";\n\n// ── 聚合器状态 ────────────────────────────────────────────────\n\nexport interface AggregatorState {\n responseId?: string;\n model?: string;\n backendInfo?: { kind: BackendTrace[\"adapter\"]; isSynthetic: boolean };\n\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary: AuxiliaryInfo;\n warnings: string[];\n warningSet: Set<string>;\n output: OutputItem[];\n textParts: string[];\n toolCalls: ToolCallItem[];\n lastEventType?: AIStreamEvent[\"type\"];\n\n /** adapter 在 response.completed 中提供的 replay */\n replayFromAdapter?: import(\"../types/index.js\").ReplayItem[];\n responseIdFromAdapter?: string;\n stopReasonFromAdapter?: StopReason;\n backendFromAdapter?: BackendTrace;\n}\n\nexport function createAggregatorState(): AggregatorState {\n return {\n auxiliary: {},\n warnings: [],\n warningSet: new Set(),\n output: [],\n textParts: [],\n toolCalls: [],\n };\n}\n\n// ── Event handlers ────────────────────────────────────────────\n\nfunction handleResponseStarted(state: AggregatorState, event: AIStreamEvent & { type: \"response.started\" }): void {\n state.responseId = event.responseId;\n state.model = event.model;\n state.backendInfo = event.backend;\n}\n\nfunction handleResponseWarning(state: AggregatorState, event: AIStreamEvent & { type: \"response.warning\" }): void {\n pushWarnings(state, [event.message]);\n}\n\nfunction handleResponseAuxiliary(state: AggregatorState, event: AIStreamEvent & { type: \"response.auxiliary\" }): void {\n if (event.usage) {\n state.usage = { ...state.usage, ...event.usage };\n }\n if (event.billing) {\n state.billing = { ...state.billing, ...event.billing };\n }\n if (event.auxiliary) {\n state.auxiliary = mergeAuxiliary(state.auxiliary, event.auxiliary);\n }\n}\n\nfunction handleMessageCompleted(state: AggregatorState, event: AIStreamEvent & { type: \"message.completed\" }): void {\n state.output.push(event.item);\n pushMessageText(state, event.item);\n}\n\nfunction handleReasoningCompleted(\n state: AggregatorState,\n event: AIStreamEvent & { type: \"reasoning.completed\" },\n): void {\n state.output.push(event.item);\n}\n\nfunction handleToolCallCompleted(state: AggregatorState, event: AIStreamEvent & { type: \"tool_call.completed\" }): void {\n state.output.push(event.item);\n state.toolCalls.push(event.item);\n}\n\nfunction handleResponseCompleted(state: AggregatorState, event: AIStreamEvent & { type: \"response.completed\" }): void {\n state.replayFromAdapter = event.response.replay;\n state.responseIdFromAdapter = event.response.id;\n state.stopReasonFromAdapter = event.response.stopReason;\n state.backendFromAdapter = event.response.backend;\n\n // 从 response.completed 中提取 usage/billing(适配器可能未发 auxiliary 事件)\n if (event.response.usage) {\n state.usage = { ...state.usage, ...event.response.usage };\n }\n if (event.response.billing) {\n state.billing = { ...state.billing, ...event.response.billing };\n }\n if (event.response.auxiliary) {\n state.auxiliary = mergeAuxiliary(state.auxiliary, event.response.auxiliary);\n }\n if (event.response.warnings) {\n pushWarnings(state, event.response.warnings);\n }\n}\n\n// ── 从聚合状态构建最终 AIResponse ─────────────────────────────\n\nfunction buildResponse(state: AggregatorState): AIResponse {\n // 合并 backend trace\n const backendFromResponse = state.backendFromAdapter;\n const backend: BackendTrace = {\n adapter: backendFromResponse?.adapter ?? state.backendInfo?.kind ?? (\"unknown\" as BackendTrace[\"adapter\"]),\n isSyntheticStream: backendFromResponse?.isSyntheticStream ?? state.backendInfo?.isSynthetic ?? false,\n requestId: backendFromResponse?.requestId ?? state.responseId,\n rawResponseId: backendFromResponse?.rawResponseId,\n metadataSources: backendFromResponse?.metadataSources,\n warnings: backendFromResponse?.warnings,\n };\n\n return {\n id: state.responseIdFromAdapter ?? state.responseId,\n output: state.output,\n replay: state.replayFromAdapter ?? [],\n text: state.textParts.join(\"\"),\n toolCalls: state.toolCalls,\n stopReason: state.stopReasonFromAdapter,\n usage: state.usage,\n billing: state.billing,\n auxiliary: state.auxiliary,\n warnings: state.warnings.length > 0 ? state.warnings : undefined,\n backend,\n };\n}\n\n// ── 公开 API ──────────────────────────────────────────────────\n\n/**\n * 将事件数组聚合为 AIResponse。\n * 适用于测试和离线处理场景。\n */\nexport function aggregateEvents(events: AIStreamEvent[]): AIResponse {\n const state = createAggregatorState();\n for (const event of events) {\n aggregateEvent(state, event);\n }\n return finalizeAggregation(state);\n}\n\nexport function aggregateEvent(state: AggregatorState, event: AIStreamEvent): void {\n state.lastEventType = event.type;\n\n switch (event.type) {\n case \"response.started\":\n handleResponseStarted(state, event);\n break;\n case \"response.warning\":\n handleResponseWarning(state, event);\n break;\n case \"response.auxiliary\":\n handleResponseAuxiliary(state, event);\n break;\n case \"message.started\":\n case \"message.delta\":\n case \"reasoning.started\":\n case \"reasoning.delta\":\n case \"tool_call.started\":\n case \"tool_call.delta\":\n break;\n case \"message.completed\":\n handleMessageCompleted(state, event);\n break;\n case \"reasoning.completed\":\n handleReasoningCompleted(state, event);\n break;\n case \"tool_call.completed\":\n handleToolCallCompleted(state, event);\n break;\n case \"response.completed\":\n handleResponseCompleted(state, event);\n break;\n }\n}\n\nexport function finalizeAggregation(state: AggregatorState): AIResponse {\n if (state.lastEventType !== \"response.completed\") {\n throw new Error(\"Stream must end with response.completed event to produce a valid AIResponse\");\n }\n\n return buildResponse(state);\n}\n\nfunction mergeAuxiliary(base: AuxiliaryInfo, patch: Partial<AuxiliaryInfo>): AuxiliaryInfo {\n const merged: AuxiliaryInfo = {\n ...base,\n ...patch,\n };\n\n if (base.providerMetadata || patch.providerMetadata) {\n merged.providerMetadata = {\n ...base.providerMetadata,\n ...patch.providerMetadata,\n };\n }\n\n return merged;\n}\n\nfunction pushWarnings(state: AggregatorState, warnings: readonly string[]): void {\n for (const warning of warnings) {\n if (!state.warningSet.has(warning)) {\n state.warningSet.add(warning);\n state.warnings.push(warning);\n }\n }\n}\n\nfunction pushMessageText(state: AggregatorState, item: MessageItem): void {\n for (const block of item.content) {\n if (block.type === \"text\") {\n state.textParts.push(block.text);\n }\n }\n}\n","/**\n * collectStream — 流收集 helper\n *\n * 将 AsyncIterable<AIStreamEvent> 消费完毕并聚合力 AIResponse。\n * 适用于不需要逐事件处理的调用方。\n */\n\nimport type { AIStreamEvent, AIResponse } from \"../types/index.js\";\nimport { aggregateEvent, createAggregatorState, finalizeAggregation } from \"./aggregator.js\";\n\nexport async function collectStream(stream: AsyncIterable<AIStreamEvent>): Promise<AIResponse> {\n const state = createAggregatorState();\n\n for await (const event of stream) {\n aggregateEvent(state, event);\n }\n\n return finalizeAggregation(state);\n}\n","/**\n * Adapter 共享映射 helper\n *\n * 提供 adapter 间通用的类型映射函数:\n * - stop reason 映射\n * - content block 映射\n * - item 映射\n * - warning 记录\n * - replay 构造工具\n */\n\nimport type {\n StopReason,\n ContentBlock,\n InstructionBlock,\n MessageItem,\n ReasoningItem,\n ToolCallItem,\n ToolResultItem,\n OpaqueItem,\n InputItem,\n OutputItem,\n ReplayItem,\n} from \"../types/index.js\";\n\n// ── Stop reason 映射 ──────────────────────────────────────────\n\n/**\n * 常见 provider stop_reason / finish_reason 到 canonical StopReason 的映射表。\n * adapter 可先查此表,未覆盖时走 fallback 规则。\n */\nconst STOP_REASON_MAP: Record<string, StopReason> = {\n // OpenAI / Azure\n stop: \"end_turn\",\n length: \"max_output_tokens\",\n content_filter: \"content_filter\",\n tool_calls: \"tool_call\",\n // Anthropic\n end_turn: \"end_turn\",\n max_tokens: \"max_output_tokens\",\n tool_use: \"tool_call\",\n // Generic\n error: \"error\",\n};\n\nexport function mapStopReason(providerReason: string): StopReason {\n return STOP_REASON_MAP[providerReason] ?? \"unknown\";\n}\n\n// ── Reasoning visibility 映射 ──────────────────────────────────\n\nexport function mapReasoningVisibility(hasThinking: boolean, hasRedacted: boolean): ReasoningItem[\"visibility\"] {\n if (hasRedacted) return \"redacted\";\n if (hasThinking) return \"full\";\n return \"opaque\";\n}\n\n// ── Content block 构造 helper ─────────────────────────────────\n\nexport function textBlock(text: string): ContentBlock & { type: \"text\" } {\n return { type: \"text\", text };\n}\n\nexport function jsonBlock(json: unknown): ContentBlock & { type: \"json\" } {\n return { type: \"json\", json };\n}\n\nexport function imageBlock(imageUrl: string): ContentBlock & { type: \"image\" } {\n return { type: \"image\", imageUrl };\n}\n\nexport function opaqueBlock(payload: unknown): ContentBlock & { type: \"opaque\" } {\n return { type: \"opaque\", payload };\n}\n\n// ── Item 构造 helper ──────────────────────────────────────────\n\nexport function messageItem(\n content: ContentBlock[],\n overrides?: Partial<Omit<MessageItem, \"type\" | \"content\">>,\n): MessageItem {\n return {\n type: \"message\",\n role: \"assistant\",\n ...overrides,\n content,\n };\n}\n\nexport function reasoningItem(\n content: ContentBlock[],\n visibility: ReasoningItem[\"visibility\"] = \"full\",\n id?: string,\n): ReasoningItem {\n return {\n type: \"reasoning\",\n id,\n visibility,\n content,\n };\n}\n\nexport function toolCallItem(id: string, name: string, argumentsText: string, argumentsJson?: unknown): ToolCallItem {\n return {\n type: \"tool_call\",\n id,\n name,\n argumentsText,\n argumentsJson,\n };\n}\n\nexport function toolResultItem(\n callId: string,\n toolName: string,\n outcome: ToolResultItem[\"outcome\"],\n content: ContentBlock[],\n): ToolResultItem {\n return {\n type: \"tool_result\",\n callId,\n toolName,\n outcome,\n content,\n };\n}\n\nexport function opaqueItem(\n source: OpaqueItem[\"source\"],\n purpose: OpaqueItem[\"purpose\"],\n payload: unknown,\n id?: string,\n): OpaqueItem {\n return {\n type: \"opaque\",\n id,\n source,\n purpose,\n payload,\n };\n}\n\n// ── Replay 构造工具 ──────────────────────────────────────────\n\n/**\n * 从 output items 构建标准 replay items。\n * 简单场景下 replay 与 output 一致。\n * 复杂场景(需要 opaque continuation)由 adapter 自行扩展。\n */\nexport function replayFromOutput(output: readonly OutputItem[]): ReplayItem[] {\n return output.map((item): InputItem => {\n switch (item.type) {\n case \"message\":\n case \"reasoning\":\n case \"tool_call\":\n return item as InputItem;\n case \"opaque\":\n return item;\n }\n });\n}\n\n// ── Content block 提取 helper ──────────────────────────────────\n\n/**\n * 将单个 ContentBlock 转为纯文本。\n * text 块直接返回文本,json 块序列化,其余返回空串。\n */\nexport function blockToText(b: ContentBlock): string {\n if (b.type === \"text\") return b.text;\n if (b.type === \"json\") return JSON.stringify(b.json);\n return \"\";\n}\n\n/**\n * 将 ContentBlock 数组拼接为纯文本,块间以换行符分隔。\n */\nexport function contentBlocksToText(blocks: ContentBlock[]): string {\n return blocks.map(blockToText).join(\"\\n\");\n}\n\n/**\n * 将 instructions(string | InstructionBlock[])归一化为纯文本。\n */\nexport function instructionsToText(instructions: string | InstructionBlock[]): string {\n return typeof instructions === \"string\" ? instructions : contentBlocksToText(instructions);\n}\n\n// ── Output 文本提取 ───────────────────────────────────────────\n\n/**\n * 从 OutputItem 数组中提取所有 message 类型 item 的文本内容。\n */\nexport function extractText(output: OutputItem[]): string {\n return output\n .filter((item): item is MessageItem => item.type === \"message\")\n .flatMap((m) => m.content)\n .filter((b): b is ContentBlock & { type: \"text\" } => b.type === \"text\")\n .map((b) => b.text)\n .join(\"\");\n}\n","/**\n * 辅助信息采集器 (AuxiliaryCollector)\n *\n * 为 usage、billing、providerMetadata 提供统一的 best-effort 采集。\n *\n * 采集优先级(分层):\n * 1. 主响应 body / terminal event\n * 2. headers / trailers\n * 3. SDK metadata\n * 4. 一次 follow-up lookup\n * 5. derived estimate\n *\n * 约束:\n * - lookup 最多一次有界补查\n * - lookup 失败只记录 warning\n * - 不阻断主生成链路\n */\n\nimport type { Usage, BillingInfo, AuxiliaryInfo } from \"../types/index.js\";\n\n// ── 来源类型 ──────────────────────────────────────────────────\n\nexport type UsageSource = NonNullable<AuxiliaryInfo[\"usageSource\"]>;\nexport type BillingSource = NonNullable<AuxiliaryInfo[\"billingSource\"]>;\n\nexport type LookupResult = {\n usage?: Partial<Usage>;\n billing?: Partial<BillingInfo>;\n providerMetadata?: Record<string, unknown>;\n};\n\n// ── Collector ─────────────────────────────────────────────────\n\nexport class AuxiliaryCollector {\n private usage: Partial<Usage> = {};\n private usageSource: UsageSource | undefined;\n private billing: Partial<BillingInfo> | undefined;\n private billingSource: BillingSource | undefined;\n private providerMetadata: Record<string, unknown> = {};\n private providerUsage: unknown;\n private providerBilling: unknown;\n private warnings: string[] = [];\n private lookupAttempted = false;\n\n // ── 记录方法 ──────────────────────────────────────────────\n\n /**\n * 记录 usage 信息。\n * 后调用的覆盖先调用的(优先级由调用方控制)。\n */\n recordUsage(usage: Partial<Usage>, source: UsageSource, raw?: unknown): this {\n this.usage = { ...this.usage, ...usage };\n this.usageSource = source;\n if (raw !== undefined) this.providerUsage = raw;\n return this;\n }\n\n /**\n * 记录 billing 信息。\n * 后调用的覆盖先调用的。\n */\n recordBilling(billing: Partial<BillingInfo>, source: BillingSource, raw?: unknown): this {\n this.billing = { ...this.billing, ...billing };\n this.billingSource = source;\n if (raw !== undefined) this.providerBilling = raw;\n return this;\n }\n\n /**\n * 记录 provider 元数据(非 canonical 的 key-value 信息)。\n */\n recordMetadata(metadata: Record<string, unknown>): this {\n this.providerMetadata = { ...this.providerMetadata, ...metadata };\n return this;\n }\n\n /**\n * 记录一条 warning。\n */\n recordWarning(message: string): this {\n this.warnings.push(message);\n return this;\n }\n\n // ── 有界 Lookup ───────────────────────────────────────────\n\n /**\n * 执行一次有界 follow-up lookup。\n * 最多调用一次;后续调用被忽略。\n * lookup 失败(抛错)仅记录 warning,不传播异常。\n */\n async tryLookup(lookupFn: () => Promise<LookupResult>, timeoutMs = 5_000): Promise<void> {\n if (this.lookupAttempted) return;\n this.lookupAttempted = true;\n\n try {\n const result = await withTimeout(lookupFn(), timeoutMs);\n if (result.usage) {\n this.recordUsage(result.usage, \"lookup\", result.usage);\n }\n if (result.billing) {\n const bill: Partial<BillingInfo> = {\n ...result.billing,\n source: result.billing?.source ?? \"lookup\",\n };\n this.recordBilling(bill, \"lookup\", result.billing);\n }\n if (result.providerMetadata) {\n this.recordMetadata(result.providerMetadata);\n }\n } catch (err) {\n this.recordWarning(`Auxiliary lookup failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // ── 构建最终结果 ──────────────────────────────────────────\n\n /**\n * 构建最终的 usage / billing / auxiliary。\n * 所有字段均为可选的 — 拿不到就不给。\n */\n build(): { usage?: Usage; billing?: BillingInfo; auxiliary?: AuxiliaryInfo; warnings?: string[] } {\n const result: { usage?: Usage; billing?: BillingInfo; auxiliary?: AuxiliaryInfo; warnings?: string[] } = {};\n\n if (Object.keys(this.usage).length > 0) {\n result.usage = this.usage as Usage;\n }\n\n if (this.billing) {\n result.billing = this.billing as BillingInfo;\n }\n\n const aux: AuxiliaryInfo = {};\n if (this.usageSource) aux.usageSource = this.usageSource;\n if (this.billingSource) aux.billingSource = this.billingSource;\n if (this.providerUsage !== undefined) aux.providerUsage = this.providerUsage;\n if (this.providerBilling !== undefined) aux.providerBilling = this.providerBilling;\n if (Object.keys(this.providerMetadata).length > 0) aux.providerMetadata = this.providerMetadata;\n\n if (Object.keys(aux).length > 0) {\n result.auxiliary = aux;\n }\n\n if (this.warnings.length > 0) {\n result.warnings = [...this.warnings];\n }\n\n return result;\n }\n\n /**\n * 已使用的来源列表(用于 debugging)。\n */\n get sources(): { usage?: UsageSource; billing?: BillingSource } {\n return { usage: this.usageSource, billing: this.billingSource };\n }\n}\n\n// ── Helper ────────────────────────────────────────────────────\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return Promise.race([\n promise,\n new Promise<T>((_, reject) => setTimeout(() => reject(new Error(`Lookup timed out after ${ms}ms`)), ms)),\n ]);\n}\n","import { WarningCode } from \"../core/errors.js\";\nimport type { EventFactory } from \"../core/event-factory.js\";\nimport type {\n AIStreamEvent,\n BillingInfo,\n NormalizedRequest,\n Usage,\n AuxiliaryInfo,\n BackendTrace,\n} from \"../types/index.js\";\nimport { AuxiliaryCollector, type BillingSource, type LookupResult, type UsageSource } from \"./auxiliary-collector.js\";\n\ntype MaybePromise<T> = T | Promise<T>;\n\nexport type BillingPostprocessHook = (context: {\n request: NormalizedRequest;\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: AuxiliaryInfo;\n}) => MaybePromise<Partial<BillingInfo> | undefined>;\n\nexport type AuxiliaryFinalizeOptions = {\n lookup?: () => Promise<LookupResult>;\n lookupTimeoutMs?: number;\n postprocessBilling?: BillingPostprocessHook;\n postprocessBillingSource?: BillingSource;\n};\n\nexport type AuxiliaryFinalizeResult = {\n events: AIStreamEvent[];\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: AuxiliaryInfo;\n warnings?: string[];\n metadataSources?: string[];\n};\n\nexport class AdapterAuxiliaryState {\n private readonly collector = new AuxiliaryCollector();\n private readonly metadataSources = new Set<string>();\n\n constructor(private readonly request: NormalizedRequest) {}\n\n recordUsage(usage: Partial<Usage>, source: UsageSource, raw?: unknown): void {\n if (this.request.include?.usage === \"off\" || isEmptyRecord(usage)) return;\n this.collector.recordUsage(usage, source, raw);\n }\n\n recordBilling(billing: Partial<BillingInfo>, source: BillingSource, raw?: unknown): void {\n if (this.request.include?.billing === \"off\" || isEmptyRecord(billing)) return;\n this.collector.recordBilling(billing, source, raw);\n }\n\n recordProviderMetadata(source: string, metadata: Record<string, unknown> | undefined): void {\n if (this.request.include?.providerMetadata === \"off\" || !metadata || isEmptyRecord(metadata)) return;\n this.collector.recordMetadata(metadata);\n this.metadataSources.add(source);\n }\n\n async finalize(factory: EventFactory, options: AuxiliaryFinalizeOptions = {}): Promise<AuxiliaryFinalizeResult> {\n if (options.lookup && this.shouldAttemptLookup()) {\n await this.collector.tryLookup(options.lookup, options.lookupTimeoutMs);\n }\n\n if (this.request.include?.billing !== \"off\" && options.postprocessBilling) {\n const snapshot = this.collector.build();\n if (!snapshot.billing) {\n const derived = await options.postprocessBilling({\n request: this.request,\n usage: snapshot.usage,\n billing: snapshot.billing,\n auxiliary: snapshot.auxiliary,\n });\n if (derived && !isEmptyRecord(derived)) {\n this.collector.recordBilling(\n {\n ...derived,\n isEstimated: derived.isEstimated ?? true,\n source: derived.source ?? \"derived\",\n },\n options.postprocessBillingSource ?? \"derived\",\n derived,\n );\n }\n }\n }\n\n const built = this.collector.build();\n const events: AIStreamEvent[] = [];\n\n if (built.usage || built.billing || built.auxiliary) {\n events.push(\n factory.responseAuxiliary({\n usage: built.usage,\n billing: built.billing,\n auxiliary: built.auxiliary,\n }),\n );\n }\n\n if (this.request.include?.usage !== \"off\" && !built.usage) {\n events.push(\n factory.responseWarning(\"Usage information was not provided by the provider\", WarningCode.USAGE_MISSING),\n );\n }\n\n if (this.request.include?.billing !== \"off\") {\n if (!built.billing) {\n events.push(\n factory.responseWarning(\"Billing information was not provided by the provider\", WarningCode.BILLING_MISSING),\n );\n } else if (built.billing.isEstimated) {\n events.push(factory.responseWarning(\"Billing amount is an estimate\", WarningCode.BILLING_ESTIMATED));\n }\n }\n\n return {\n events,\n usage: built.usage,\n billing: built.billing,\n auxiliary: built.auxiliary,\n warnings: built.warnings,\n metadataSources: this.metadataSources.size > 0 ? [...this.metadataSources] : undefined,\n };\n }\n\n private shouldAttemptLookup(): boolean {\n if (\n this.request.include?.usage === \"off\" &&\n this.request.include?.billing === \"off\" &&\n this.request.include?.providerMetadata === \"off\"\n ) {\n return false;\n }\n\n const snapshot = this.collector.build();\n return (\n (this.request.include?.usage !== \"off\" && !snapshot.usage) ||\n (this.request.include?.billing !== \"off\" && !snapshot.billing) ||\n (this.request.include?.providerMetadata !== \"off\" && !snapshot.auxiliary?.providerMetadata)\n );\n }\n}\n\nexport function emitMalformedStreamWarning(\n factory: EventFactory,\n options: {\n count: number;\n providerLabel: string;\n transportLabel: string;\n },\n): AIStreamEvent | undefined {\n if (options.count < 1) return undefined;\n return factory.responseWarning(\n `Skipped ${options.count} malformed ${options.providerLabel} ${options.transportLabel}`,\n \"STREAM_ERROR\",\n );\n}\n\nexport function metadataSourceList(\n ...groups: Array<Array<NonNullable<BackendTrace[\"metadataSources\"]>[number]> | undefined>\n): string[] | undefined {\n const sources = new Set<string>();\n\n for (const group of groups) {\n if (!group) continue;\n for (const source of group) {\n sources.add(source);\n }\n }\n\n return sources.size > 0 ? [...sources] : undefined;\n}\n\nfunction isEmptyRecord(value: object): boolean {\n return Object.keys(value).length === 0;\n}\n","/**\n * Adapter 抽象基类\n *\n * 约定 adapter 的内部职责分层(build / invoke / parse / emit):\n * 1. buildRequest — 将 NormalizedRequest 转换为 provider 请求格式\n * 2. invokeProvider — 调用 provider API\n * 3. parseResponse — 解析 provider 响应为 canonical 中间态\n * 4. emitEvents — 产出 canonical 事件流\n *\n * 子类实现 buildRequest() 和 runStream(),\n * runStream 返回 AsyncIterable,事件实时发射给消费者。\n */\n\nimport type {\n NormalizedRequest,\n BackendAdapter,\n AIStreamEvent,\n AIResponse,\n AuxiliaryInfo,\n OutputItem,\n ReplayItem,\n StopReason,\n Usage,\n BillingInfo,\n ToolCallItem,\n} from \"../types/index.js\";\nimport { createEventFactory } from \"../core/event-factory.js\";\nimport { AIMappingError, AIRequestError, AIStreamError } from \"../core/errors.js\";\nimport type { EventFactory } from \"../core/event-factory.js\";\nimport { extractText } from \"./mapping.js\";\nimport { AdapterAuxiliaryState } from \"./adapter-auxiliary.js\";\n\n// ── Adapter 解析中间结果 ──────────────────────────────────────\n\nexport type ProviderResponse = unknown;\n\n/**\n * adapter 完成一轮处理后返回的最终结果。\n * 用于 buildResponse() 构建 AIResponse。\n */\nexport type StreamResult = {\n output: OutputItem[];\n replay: ReplayItem[];\n stopReason?: StopReason;\n usage?: Usage;\n billing?: BillingInfo;\n providerMetadata?: Record<string, unknown>;\n auxiliary?: Partial<AuxiliaryInfo>;\n warnings?: string[];\n metadataSources?: string[];\n rawResponseId?: string;\n};\n\n// ── 抽象基类 ──────────────────────────────────────────────────\n\nexport abstract class AdapterBase implements BackendAdapter {\n abstract readonly kind: \"chat-completions\" | \"messages\" | \"responses\" | \"ollama\" | \"mock\";\n abstract readonly nativeStreaming: boolean;\n\n /**\n * stream 模板方法:\n * 1. 创建事件工厂,发射 response.started\n * 2. 构建 provider 请求\n * 3. 委托 runStream 发射全部流事件(含 response.completed)\n */\n async *stream(request: NormalizedRequest): AsyncIterable<AIStreamEvent> {\n const factory = createEventFactory({\n responseId: request.requestId,\n backend: { kind: this.kind, isSynthetic: !this.nativeStreaming },\n });\n\n yield factory.responseStarted(request.model);\n\n try {\n const providerRequest = await this.buildRequest(request);\n yield* this.runStream(providerRequest, factory, request);\n } catch (err) {\n if (err instanceof AIRequestError || err instanceof AIStreamError || err instanceof AIMappingError) {\n throw err;\n }\n yield factory.responseWarning(err instanceof Error ? err.message : String(err), \"PROVIDER_ERROR\");\n yield factory.responseCompleted(this.buildResponse(request, { output: [], replay: [] }, factory));\n }\n }\n\n // ── 子类必须实现 ──────────────────────────────────────────\n\n /** 将 NormalizedRequest 转换为 provider 请求格式。 */\n protected abstract buildRequest(request: NormalizedRequest): ProviderResponse | Promise<ProviderResponse>;\n\n /**\n * 执行流式请求,发射全部事件(含 response.completed)。\n * 子类负责:\n * - 调用 provider\n * - 解析每个 chunk\n * - 通过 factory 发射 item 事件\n * - 构建 StreamResult\n * - 发射 factory.responseCompleted(buildResponse(…))\n */\n protected abstract runStream(\n providerRequest: ProviderResponse,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent>;\n\n // ── 共享构造方法 ──────────────────────────────────────────\n\n /**\n * 从 StreamResult 构建完整 AIResponse。\n * 子类可在返回前自定义覆盖。\n */\n protected buildResponse(request: NormalizedRequest, result: StreamResult, _factory: EventFactory): AIResponse {\n const text = this.extractText(result.output);\n const warnings = mergeWarnings(result.warnings, _factory.warnings);\n const auxiliary = mergeAuxiliary(\n result.auxiliary,\n result.providerMetadata ? { providerMetadata: result.providerMetadata } : undefined,\n );\n\n return {\n id: request.requestId,\n output: result.output,\n replay: result.replay,\n text,\n toolCalls: result.output.filter((item): item is ToolCallItem => item.type === \"tool_call\"),\n stopReason: result.stopReason,\n usage: result.usage,\n billing: result.billing,\n auxiliary,\n warnings,\n backend: {\n requestId: request.requestId,\n rawResponseId: result.rawResponseId,\n adapter: this.kind,\n isSyntheticStream: !this.nativeStreaming,\n metadataSources: result.metadataSources,\n warnings,\n },\n };\n }\n\n /** 从 output items 中提取文本内容。 */\n protected extractText(output: OutputItem[]): string {\n return extractText(output);\n }\n\n protected createAuxiliaryState(request: NormalizedRequest): AdapterAuxiliaryState {\n return new AdapterAuxiliaryState(request);\n }\n}\n\nfunction mergeAuxiliary(base?: Partial<AuxiliaryInfo>, patch?: Partial<AuxiliaryInfo>): AuxiliaryInfo | undefined {\n if (!base && !patch) return undefined;\n\n const merged: AuxiliaryInfo = {\n ...base,\n ...patch,\n };\n\n if (base?.providerMetadata || patch?.providerMetadata) {\n merged.providerMetadata = {\n ...base?.providerMetadata,\n ...patch?.providerMetadata,\n };\n }\n\n return merged;\n}\n\nfunction mergeWarnings(...groups: Array<string[] | undefined>): string[] | undefined {\n const merged: string[] = [];\n\n for (const group of groups) {\n if (!group) continue;\n for (const warning of group) {\n if (!merged.includes(warning)) {\n merged.push(warning);\n }\n }\n }\n\n return merged.length > 0 ? merged : undefined;\n}\n","/**\n * Provider usage → canonical Usage 映射\n *\n * best-effort 提取 reasoning / cache / billable 等扩展字段。\n */\n\nimport type { Usage } from \"../types/index.js\";\n\nfunction num(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction record(obj: Record<string, number | undefined>): Partial<Usage> {\n const out: Partial<Usage> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n (out as Record<string, number>)[key] = value;\n }\n }\n return out;\n}\n\nfunction billableFromOpenAIStyle(\n inputTokens: number | undefined,\n outputTokens: number | undefined,\n cachedInputTokens: number | undefined,\n reasoningTokens: number | undefined,\n): Pick<Usage, \"billableInputTokens\" | \"billableOutputTokens\"> {\n let billableInputTokens: number | undefined;\n if (inputTokens !== undefined) {\n billableInputTokens =\n cachedInputTokens !== undefined ? Math.max(0, inputTokens - cachedInputTokens) : inputTokens;\n }\n\n let billableOutputTokens: number | undefined;\n if (outputTokens !== undefined) {\n billableOutputTokens =\n reasoningTokens !== undefined ? Math.max(0, outputTokens - reasoningTokens) : outputTokens;\n }\n\n return record({ billableInputTokens, billableOutputTokens });\n}\n\n/** OpenAI Chat Completions `usage` */\nexport function usageFromChatCompletions(raw: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n prompt_tokens_details?: { cached_tokens?: number; [key: string]: unknown };\n completion_tokens_details?: { reasoning_tokens?: number; [key: string]: unknown };\n}): Partial<Usage> {\n const inputTokens = num(raw.prompt_tokens);\n const outputTokens = num(raw.completion_tokens);\n const cachedInputTokens = num(raw.prompt_tokens_details?.cached_tokens);\n const reasoningTokens = num(raw.completion_tokens_details?.reasoning_tokens);\n const totalTokens =\n num(raw.total_tokens) ??\n (inputTokens !== undefined && outputTokens !== undefined ? inputTokens + outputTokens : undefined);\n\n return record({\n inputTokens,\n outputTokens,\n totalTokens,\n cachedInputTokens,\n reasoningTokens,\n ...billableFromOpenAIStyle(inputTokens, outputTokens, cachedInputTokens, reasoningTokens),\n });\n}\n\n/** OpenAI Responses API `usage` */\nexport function usageFromOpenAIResponses(raw: {\n input_tokens?: number;\n output_tokens?: number;\n total_tokens?: number;\n input_tokens_details?: { cached_tokens?: number; [key: string]: unknown };\n output_tokens_details?: { reasoning_tokens?: number; [key: string]: unknown };\n [key: string]: unknown;\n}): Partial<Usage> {\n const inputTokens = num(raw.input_tokens);\n const outputTokens = num(raw.output_tokens);\n const cachedInputTokens = num(raw.input_tokens_details?.cached_tokens);\n const reasoningTokens = num(raw.output_tokens_details?.reasoning_tokens);\n const totalTokens =\n num(raw.total_tokens) ??\n (inputTokens !== undefined && outputTokens !== undefined ? inputTokens + outputTokens : undefined);\n\n return record({\n inputTokens,\n outputTokens,\n totalTokens,\n cachedInputTokens,\n reasoningTokens,\n ...billableFromOpenAIStyle(inputTokens, outputTokens, cachedInputTokens, reasoningTokens),\n });\n}\n\n/** Anthropic Messages `usage`(message_start / message_delta) */\nexport function usageFromAnthropicMessages(raw: {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n [key: string]: unknown;\n}): Partial<Usage> {\n const inputTokens = num(raw.input_tokens);\n const outputTokens = num(raw.output_tokens);\n const cacheWriteInputTokens = num(raw.cache_creation_input_tokens);\n const cachedInputTokens = num(raw.cache_read_input_tokens);\n\n const inputParts = [inputTokens, cacheWriteInputTokens, cachedInputTokens].filter(\n (n): n is number => n !== undefined,\n );\n const summedInput = inputParts.length > 0 ? inputParts.reduce((sum, n) => sum + n, 0) : undefined;\n const totalTokens =\n summedInput !== undefined && outputTokens !== undefined ? summedInput + outputTokens : undefined;\n\n let billableInputTokens: number | undefined;\n if (inputTokens !== undefined || cacheWriteInputTokens !== undefined) {\n billableInputTokens = (inputTokens ?? 0) + (cacheWriteInputTokens ?? 0);\n }\n\n return record({\n inputTokens,\n outputTokens,\n totalTokens,\n cachedInputTokens,\n cacheWriteInputTokens,\n billableInputTokens,\n billableOutputTokens: outputTokens,\n });\n}\n\n/** Ollama 流式 chunk(无 cache / reasoning 细分时仅填基础与 billable 镜像) */\nexport function usageFromOllama(raw: {\n prompt_eval_count?: number;\n eval_count?: number;\n}): Partial<Usage> {\n const inputTokens = num(raw.prompt_eval_count);\n const outputTokens = num(raw.eval_count);\n const totalTokens =\n inputTokens !== undefined && outputTokens !== undefined ? inputTokens + outputTokens : undefined;\n\n return record({\n inputTokens,\n outputTokens,\n totalTokens,\n billableInputTokens: inputTokens,\n billableOutputTokens: outputTokens,\n });\n}","/**\n * 通用 SSE (Server-Sent Events) 解析器\n *\n * 解析标准 SSE 格式(event: + data: 行),适用于:\n * - Anthropic Messages API (messages.ts)\n * - OpenAI Responses API (responses.ts)\n *\n * 注意:OpenAI Chat Completions API 使用简化 SSE(仅有 data: 行),\n * 由 chat-completions.ts 中的 parseChatSSE 处理。\n *\n * 用法:\n * ```ts\n * const { events, rest } = parseSSEEvents(buffer);\n * for (const ev of events) {\n * // ev.type — 事件类型字符串\n * // ev.data — 已解析的 JSON 数据\n * }\n * // rest 是未处理的剩余 buffer,需要累积到下次调用\n * ```\n */\n\nexport type SSEEvent = { type: string; data: unknown };\n\nexport type SSEParseResult = {\n events: SSEEvent[];\n rest: string;\n malformedEvents: number;\n};\n\n/**\n * 将 SSE 文本块解析为事件数组。\n * 累积事件行直到遇到空行,支持 [DONE] 标记。\n * 返回已解析的事件和未处理的剩余 buffer(用于增量解析)。\n *\n * 关键行为:\n * - 只解析完整的 event(以空行结尾)\n * - 未完成的行保留在 rest 中,等待下次 chunk 补全\n * - 支持跨 chunk 的 event 分片\n */\nexport function parseSSEEvents(chunk: string): SSEParseResult {\n const events: SSEEvent[] = [];\n let eventType = \"\";\n let dataLines: string[] = [];\n let consumedUntil = 0;\n let cursor = 0;\n let malformedEvents = 0;\n\n while (cursor < chunk.length) {\n const lineEnd = chunk.indexOf(\"\\n\", cursor);\n if (lineEnd === -1) break;\n\n let line = chunk.slice(cursor, lineEnd);\n cursor = lineEnd + 1;\n\n if (line.endsWith(\"\\r\")) {\n line = line.slice(0, -1);\n }\n\n if (line.startsWith(\"event: \")) {\n eventType = line.slice(7).trim();\n } else if (line.startsWith(\"data: \")) {\n dataLines.push(line.slice(6));\n } else if (line === \"\" && eventType && dataLines.length > 0) {\n // 完整的 event(以空行结尾)\n const dataStr = dataLines.join(\"\\n\");\n if (dataStr === \"[DONE]\") {\n eventType = \"\";\n dataLines = [];\n consumedUntil = cursor;\n continue;\n }\n try {\n const data = JSON.parse(dataStr);\n events.push({ type: eventType, data });\n } catch {\n malformedEvents++;\n }\n eventType = \"\";\n dataLines = [];\n consumedUntil = cursor;\n } else if (line === \"\" && !eventType && dataLines.length === 0) {\n consumedUntil = cursor;\n }\n }\n\n return { events, rest: chunk.slice(consumedUntil), malformedEvents };\n}\n","/**\n * Responses Adapter\n *\n * 接入 OpenAI Responses API (responses 端点)。\n * 职责分层:\n * 1. buildRequest — 将 NormalizedRequest 转换为 Responses API 请求\n * 2. runStream — 调用 API、解析 SSE、发射 canonical 事件\n *\n * 支持消息流 / reasoning 流 / tool_call 流及高保真 replay。\n */\n\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { AIRequestError } from \"../core/errors.js\";\nimport {\n textBlock,\n messageItem,\n reasoningItem,\n toolCallItem,\n opaqueItem,\n replayFromOutput,\n blockToText,\n contentBlocksToText,\n} from \"../helpers/mapping.js\";\nimport { emitMalformedStreamWarning } from \"../helpers/adapter-auxiliary.js\";\nimport { usageFromOpenAIResponses } from \"../helpers/usage-mapping.js\";\n\nimport { parseSSEEvents } from \"../helpers/sse-parser.js\";\n\nimport type { NormalizedRequest, AIStreamEvent, EventFactory, OutputItem, FetchFn } from \"../index.js\";\n\n// ── 类型 ──────────────────────────────────────────────────────\n\nexport type ResponsesAdapterOptions = {\n apiKey: string;\n baseUrl?: string;\n /** 可注入自定义 fetch 实现(用于测试/代理) */\n fetch?: FetchFn;\n};\n\n// ── Responses API 请求类型 ────────────────────────────────────\n\ntype ResponsesAPIRequest = {\n model: string;\n input: ResponsesInputItem[];\n instructions?: string;\n tools?: ResponsesTool[];\n tool_choice?: \"auto\" | \"none\" | { type: \"function\"; name: string };\n metadata?: Record<string, string>;\n temperature?: number;\n max_output_tokens?: number;\n stream: true;\n};\n\ntype ResponsesInputItem =\n | { type: \"message\"; role: \"user\" | \"assistant\"; content: string }\n | { type: \"message\"; role: \"assistant\"; content: ResponsesContentBlock[] }\n | { type: \"function_call\"; id: string; name: string; arguments: string; call_id?: string }\n | { type: \"function_call_output\"; call_id: string; output: string }\n | { type: \"reasoning\"; content: ResponsesContentBlock[] }\n | { type: \"item_reference\"; id: string };\n\ntype ResponsesContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"reasoning\"; text: string }\n | { type: \"refusal\"; refusal: string };\n\ntype ResponsesTool = {\n type: \"function\";\n name: string;\n description?: string;\n input_schema: Record<string, unknown>;\n};\n\nfunction ensureResponsesTextBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): import(\"../index.js\").ContentBlock[] {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (!block) continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n throw new AIRequestError(\n `responses does not support ${field}[${i}] of type \"${block.type}\"; only text/json blocks are supported`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n }\n\n return blocks;\n}\n\nfunction ensureResponsesReasoningBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): Array<Extract<import(\"../index.js\").ContentBlock, { type: \"text\" }>> {\n return blocks.map((block, index) => {\n if (block.type !== \"text\") {\n throw new AIRequestError(\n `responses does not support ${field}[${index}] of type \"${block.type}\"; reasoning only supports text blocks`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n\n return block;\n });\n}\n\nfunction instructionsToResponsesText(instructions: string | import(\"../index.js\").InstructionBlock[]): string {\n return typeof instructions === \"string\"\n ? instructions\n : contentBlocksToText(ensureResponsesTextBlocks(instructions, \"instructions\"));\n}\n\nfunction assertResponsesToolResultOutcome(outcome: import(\"../index.js\").ToolResultItem[\"outcome\"]): void {\n if (outcome !== \"success\") {\n throw new AIRequestError(\n `responses does not preserve tool_result outcome \"${outcome}\"; only \"success\" is supported`,\n \"UNSUPPORTED_TOOL_RESULT_OUTCOME\",\n );\n }\n}\n\n// ── SSE 事件类型 ──────────────────────────────────────────────\n\ntype ResponsesSSEEvent =\n | { type: \"response.output_item.added\"; data: { item: { id: string; type: string; [key: string]: unknown } } }\n | { type: \"response.output_text.delta\"; data: { item_id: string; delta: string } }\n | { type: \"response.output_text.done\"; data: { item_id: string; text: string } }\n | { type: \"response.reasoning.delta\"; data: { item_id: string; delta: string } }\n | { type: \"response.reasoning.done\"; data: { item_id: string; text: string } }\n | { type: \"response.tool_call.delta\"; data: { item_id: string; delta: { arguments?: string } } }\n | { type: \"response.tool_call.done\"; data: { item_id: string; arguments?: string; name?: string } }\n | { type: \"response.completed\"; data: { response: ResponsesAPIResponse } }\n | { type: \"error\"; data: { message: string; code?: string } };\n\ntype ResponsesAPIResponse = {\n id: string;\n model: string;\n output: ResponsesAPIOutputItem[];\n usage?: {\n input_tokens: number;\n output_tokens: number;\n total_tokens: number;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n};\n\ntype ResponsesAPIOutputItem = {\n id: string;\n type: \"message\" | \"reasoning\" | \"function_call\";\n role?: string;\n content?: ResponsesContentBlock[];\n name?: string;\n arguments?: string;\n status?: string;\n};\n\n// ── SSE 解析 ──────────────────────────────────────────────────\n\nfunction parseSSE(chunk: string): { events: ResponsesSSEEvent[]; rest: string; malformedEvents: number } {\n const result = parseSSEEvents(chunk);\n return { events: result.events as ResponsesSSEEvent[], rest: result.rest, malformedEvents: result.malformedEvents };\n}\n\nfunction isReplayCanonicalInput(item: ResponsesInputItem): boolean {\n return (\n (item.type === \"message\" && item.role === \"assistant\") || item.type === \"reasoning\" || item.type === \"function_call\"\n );\n}\n\nfunction rollbackTrailingReplayCanonicalItems(input: ResponsesInputItem[]): void {\n while (input.length > 0) {\n const last = input[input.length - 1];\n if (!last || !isReplayCanonicalInput(last)) break;\n input.pop();\n }\n}\n\n// ── Content block 映射 ─────────────────────────────────────────\n\nfunction canonicalToResponsesBlock(b: import(\"../index.js\").ContentBlock): ResponsesContentBlock {\n if (b.type === \"text\") return { type: \"text\", text: b.text };\n if (b.type === \"json\") return { type: \"text\", text: JSON.stringify(b.json) };\n throw new AIRequestError(\n `responses does not support content block type \"${b.type}\" in canonical mapping`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n}\n\n// ── Adapter ───────────────────────────────────────────────────\n\nexport class ResponsesAdapter extends AdapterBase {\n readonly kind = \"responses\" as const;\n readonly nativeStreaming = true;\n\n private apiKey: string;\n private baseUrl: string;\n private fetchFn: FetchFn;\n\n constructor(options: ResponsesAdapterOptions) {\n super();\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://api.openai.com/v1\";\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n // ── buildRequest ──────────────────────────────────────────\n\n protected buildRequest(request: NormalizedRequest): ResponsesAPIRequest {\n const input: ResponsesInputItem[] = [];\n\n for (const item of request.input) {\n switch (item.type) {\n case \"message\": {\n // Responses API 中只有 assistant 角色支持 content blocks\n if (item.role === \"assistant\") {\n const blocks = ensureResponsesTextBlocks(item.content, `assistant message (${item.role}) content`).map(\n canonicalToResponsesBlock,\n );\n input.push({ type: \"message\", role: item.role, content: blocks });\n } else {\n input.push({\n type: \"message\",\n role: item.role,\n content: contentBlocksToText(\n ensureResponsesTextBlocks(item.content, `input message (${item.role}) content`),\n ),\n });\n }\n break;\n }\n case \"reasoning\": {\n const blocks = ensureResponsesReasoningBlocks(item.content, \"reasoning content\").map(\n (b): ResponsesContentBlock => ({ type: \"reasoning\", text: b.text }),\n );\n input.push({ type: \"reasoning\", content: blocks });\n break;\n }\n case \"tool_call\": {\n input.push({\n type: \"function_call\",\n id: item.id,\n name: item.name,\n arguments: item.argumentsText,\n });\n break;\n }\n case \"tool_result\": {\n assertResponsesToolResultOutcome(item.outcome);\n const output = ensureResponsesTextBlocks(item.content, `tool_result ${item.callId} content`)\n .map(blockToText)\n .join(\"\\n\");\n input.push({\n type: \"function_call_output\",\n call_id: item.callId,\n output,\n });\n break;\n }\n case \"opaque\": {\n // opaque items with item_reference purpose can be passed through\n if (\n item.source === \"responses\" &&\n item.purpose === \"replay\" &&\n typeof item.payload === \"object\" &&\n item.payload !== null &&\n \"id\" in (item.payload as Record<string, unknown>)\n ) {\n const { id } = item.payload as Record<string, unknown>;\n if (typeof id === \"string\") {\n rollbackTrailingReplayCanonicalItems(input);\n input.push({ type: \"item_reference\", id });\n }\n }\n break;\n }\n }\n }\n\n const body: ResponsesAPIRequest = {\n model: request.model,\n input,\n stream: true,\n };\n\n if (request.instructions) {\n body.instructions = instructionsToResponsesText(request.instructions);\n }\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map(\n (t): ResponsesTool => ({\n type: \"function\",\n name: t.name,\n description: t.description,\n input_schema: t.inputSchema,\n }),\n );\n }\n\n if (request.toolChoice) {\n if (request.toolChoice === \"auto\") body.tool_choice = \"auto\";\n else if (request.toolChoice === \"none\") body.tool_choice = \"none\";\n else if (request.toolChoice.type === \"tool\") {\n body.tool_choice = { type: \"function\", name: request.toolChoice.name };\n }\n }\n\n if (request.temperature !== undefined) body.temperature = request.temperature;\n if (request.maxOutputTokens !== undefined) body.max_output_tokens = request.maxOutputTokens;\n if (request.metadata) body.metadata = request.metadata;\n\n return body;\n }\n\n // ── runStream ─────────────────────────────────────────────\n\n protected async *runStream(\n providerRequest: ResponsesAPIRequest,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n const auxiliary = this.createAuxiliaryState(request);\n const response = await this.fetchFn(`${this.baseUrl}/responses`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(providerRequest),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"unknown error\");\n throw new Error(`Responses API error ${response.status}: ${errorText}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n // 流式累积状态\n const output: OutputItem[] = [];\n const decoder = new TextDecoder();\n let buffer = \"\";\n let completedResponse: ResponsesAPIResponse | undefined;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { events, rest, malformedEvents } = parseSSE(buffer);\n buffer = rest;\n\n const malformedWarning = emitMalformedStreamWarning(factory, {\n count: malformedEvents,\n providerLabel: \"Responses\",\n transportLabel: \"SSE event(s)\",\n });\n if (malformedWarning) {\n yield malformedWarning;\n }\n\n for (const sseEvent of events) {\n if (sseEvent.type === \"error\") {\n yield factory.responseWarning(sseEvent.data.message, sseEvent.data.code);\n continue;\n }\n\n // item 级事件\n if (sseEvent.type === \"response.output_item.added\") {\n const item = sseEvent.data.item;\n switch (item.type) {\n case \"message\":\n yield factory.messageStarted(item.id);\n break;\n case \"reasoning\":\n yield factory.reasoningStarted(item.id, \"full\");\n break;\n case \"function_call\":\n yield factory.toolCallStarted(item.id, ((item as Record<string, unknown>).name as string) ?? \"unknown\");\n break;\n }\n continue;\n }\n\n if (sseEvent.type === \"response.output_text.delta\") {\n yield factory.messageDelta(sseEvent.data.item_id, sseEvent.data.delta);\n continue;\n }\n\n if (sseEvent.type === \"response.output_text.done\") {\n yield factory.messageCompleted(messageItem([textBlock(sseEvent.data.text)], { id: sseEvent.data.item_id }));\n output.push(messageItem([textBlock(sseEvent.data.text)], { id: sseEvent.data.item_id }));\n continue;\n }\n\n if (sseEvent.type === \"response.reasoning.delta\") {\n yield factory.reasoningDelta(sseEvent.data.item_id, textBlock(sseEvent.data.delta));\n continue;\n }\n\n if (sseEvent.type === \"response.reasoning.done\") {\n yield factory.reasoningCompleted(\n reasoningItem([textBlock(sseEvent.data.text)], \"full\", sseEvent.data.item_id),\n );\n output.push(reasoningItem([textBlock(sseEvent.data.text)], \"full\", sseEvent.data.item_id));\n continue;\n }\n\n if (sseEvent.type === \"response.tool_call.delta\") {\n if (sseEvent.data.delta.arguments) {\n yield factory.toolCallDelta(sseEvent.data.item_id, { argumentsText: sseEvent.data.delta.arguments });\n }\n continue;\n }\n\n if (sseEvent.type === \"response.tool_call.done\") {\n const tcItem = toolCallItem(\n sseEvent.data.item_id,\n sseEvent.data.name ?? \"unknown\",\n sseEvent.data.arguments ?? \"\",\n );\n yield factory.toolCallCompleted(tcItem);\n output.push(tcItem);\n continue;\n }\n\n if (sseEvent.type === \"response.completed\") {\n completedResponse = sseEvent.data.response;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n if (buffer.trim().length > 0) {\n yield factory.responseWarning(\"Stream ended with an incomplete Responses SSE frame\", \"STREAM_ERROR\");\n }\n\n // 解析完成响应中的 usage 和 replay\n let rawResponseId: string | undefined;\n\n if (completedResponse) {\n rawResponseId = completedResponse.id;\n if (completedResponse.usage) {\n auxiliary.recordUsage(usageFromOpenAIResponses(completedResponse.usage), \"final\", completedResponse.usage);\n }\n }\n\n // 构造 replay:在 output 基础上追加 opaque continuation\n const replay = [...replayFromOutput(output)];\n\n // 如果有 provider continuation id,附加 opaque replay item\n if (completedResponse?.id) {\n replay.push(opaqueItem(\"responses\", \"replay\", { id: completedResponse.id }));\n }\n\n // 从 completedResponse 推断 stop reason\n const stopReason = completedResponse ? this.inferStopReason(completedResponse) : undefined;\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId,\n },\n factory,\n ),\n );\n }\n\n // ── 辅助方法 ──────────────────────────────────────────────\n\n private inferStopReason(response: ResponsesAPIResponse): import(\"../index.js\").StopReason {\n const output = response.output;\n if (!output || output.length === 0) return \"unknown\";\n\n // 检查是否有未完成的 function_call\n const hasFunctionCall = output.some((item) => item.type === \"function_call\");\n if (hasFunctionCall) return \"tool_call\";\n\n // 检查最后一条 message 的 status\n const lastMsg = output[output.length - 1];\n if (lastMsg?.status === \"incomplete\") return \"max_output_tokens\";\n\n return \"end_turn\";\n }\n}\n","/**\n * Messages Adapter\n *\n * 接入 Anthropic Messages API (messages 端点)。\n * 支持:\n * - 文本消息流 (text content block)\n * - 思维链流 (thinking content block)\n * - 工具调用流 (tool_use content block)\n * - 高保真 replay(含 opaque continuation)\n * - 能力降级 warning\n */\n\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { AIRequestError } from \"../core/errors.js\";\nimport {\n textBlock,\n messageItem,\n reasoningItem,\n toolCallItem,\n opaqueItem,\n replayFromOutput,\n mapStopReason,\n blockToText,\n contentBlocksToText,\n} from \"../helpers/mapping.js\";\nimport { emitMalformedStreamWarning } from \"../helpers/adapter-auxiliary.js\";\nimport { usageFromAnthropicMessages } from \"../helpers/usage-mapping.js\";\n\nimport { parseSSEEvents } from \"../helpers/sse-parser.js\";\n\nimport type { NormalizedRequest, AIStreamEvent, EventFactory, OutputItem, FetchFn } from \"../index.js\";\n\n// ── 类型 ──────────────────────────────────────────────────────\n\nexport type MessagesAdapterOptions = {\n apiKey: string;\n apiVersion?: string;\n baseUrl?: string;\n /** 可注入自定义 fetch 实现(用于测试/代理) */\n fetch?: FetchFn;\n};\n\n// ── Messages API 请求类型 ────────────────────────────────────\n\ntype MessagesAPIRequest = {\n model: string;\n max_tokens: number;\n messages: MessagesAPIMessage[];\n system?: string;\n tools?: MessagesAPITool[];\n tool_choice?: { type: \"auto\" | \"none\" } | { type: \"tool\"; name: string };\n temperature?: number;\n thinking?: { type: \"enabled\"; budget_tokens: number };\n stream: true;\n};\n\ntype MessagesAPIMessage = {\n role: \"user\" | \"assistant\";\n content: string | MessagesAPIContentBlock[];\n};\n\ntype MessagesAPIContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"thinking\"; thinking: string; signature?: string }\n | { type: \"redacted_thinking\"; data: string }\n | { type: \"tool_use\"; id: string; name: string; input: Record<string, unknown> }\n | { type: \"tool_result\"; tool_use_id: string; content: string | MessagesAPIContentBlock[]; is_error?: boolean };\n\ntype MessagesAPITool = {\n name: string;\n description?: string;\n input_schema: Record<string, unknown>;\n};\n\nfunction ensureMessagesTextBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): import(\"../index.js\").ContentBlock[] {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (!block) continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n throw new AIRequestError(\n `messages does not support ${field}[${i}] of type \"${block.type}\"; only text/json blocks are supported`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n }\n\n return blocks;\n}\n\nfunction ensureMessagesReasoningBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): Array<Extract<import(\"../index.js\").ContentBlock, { type: \"text\" }>> {\n return blocks.map((block, index) => {\n if (block.type !== \"text\") {\n throw new AIRequestError(\n `messages does not support ${field}[${index}] of type \"${block.type}\"; reasoning only supports text blocks`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n\n return block;\n });\n}\n\nfunction instructionsToMessagesText(instructions: string | import(\"../index.js\").InstructionBlock[]): string {\n return typeof instructions === \"string\"\n ? instructions\n : contentBlocksToText(ensureMessagesTextBlocks(instructions, \"instructions\"));\n}\n\nfunction assertMessagesToolResultOutcome(outcome: import(\"../index.js\").ToolResultItem[\"outcome\"]): void {\n if (outcome === \"rejected\") {\n throw new AIRequestError(\n 'messages does not preserve tool_result outcome \"rejected\"; only \"success\" and \"error\" are supported',\n \"UNSUPPORTED_TOOL_RESULT_OUTCOME\",\n );\n }\n}\n\n// ── SSE 事件类型 ──────────────────────────────────────────────\n\ntype MessagesSSEEvent =\n | { type: \"message_start\"; data: { message: MessagesAPIMessageResponse } }\n | { type: \"content_block_start\"; data: { index: number; content_block: { type: string; [key: string]: unknown } } }\n | { type: \"content_block_delta\"; data: { index: number; delta: { type: string; [key: string]: unknown } } }\n | { type: \"content_block_stop\"; data: { index: number } }\n | {\n type: \"message_delta\";\n data: {\n delta: { stop_reason?: string; stop_sequence?: string | null };\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n };\n };\n }\n | { type: \"message_stop\"; data: Record<string, never> }\n | { type: \"ping\"; data: Record<string, never> }\n | { type: \"error\"; data: { error: { type: string; message: string } } };\n\ntype MessagesAPIMessageResponse = {\n id: string;\n type: string;\n role: \"assistant\";\n model: string;\n content: MessagesAPIContentBlock[];\n stop_reason?: \"end_turn\" | \"max_tokens\" | \"tool_use\" | string;\n stop_sequence?: string | null;\n usage: { input_tokens: number; output_tokens: number };\n};\n\n// ── SSE 解析 ──────────────────────────────────────────────────\n\nfunction parseMessagesSSE(chunk: string): { events: MessagesSSEEvent[]; rest: string; malformedEvents: number } {\n const result = parseSSEEvents(chunk);\n return { events: result.events as MessagesSSEEvent[], rest: result.rest, malformedEvents: result.malformedEvents };\n}\n\nfunction rollbackTrailingAssistantMessages(messages: MessagesAPIMessage[]): void {\n while (messages.length > 0 && messages[messages.length - 1]?.role === \"assistant\") {\n messages.pop();\n }\n}\n\n/** 用 response 级别的命名空间合成 content block 的 item ID,避免多轮工具循环 ID 碰撞 */\nfunction synthesizeItemId(kind: \"msg\" | \"reason\" | \"reason-redacted\", blockIndex: number, responseId: string): string {\n return `${kind}-${blockIndex}-${responseId}`;\n}\n\nfunction parseToolUseInput(input: string): Record<string, unknown> {\n try {\n const parsed = JSON.parse(input);\n return parsed && typeof parsed === \"object\" ? (parsed as Record<string, unknown>) : {};\n } catch {\n return {};\n }\n}\n\n// ── Content block 映射 ─────────────────────────────────────────\n\nfunction canonicalToMessagesBlock(b: import(\"../index.js\").ContentBlock): MessagesAPIContentBlock {\n if (b.type === \"text\") return { type: \"text\", text: b.text };\n if (b.type === \"json\") return { type: \"text\", text: JSON.stringify(b.json) };\n throw new AIRequestError(\n `messages does not support content block type \"${b.type}\" in canonical mapping`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n}\n\nfunction pickProviderHeaders(headers: Headers): Record<string, string> {\n const metadata: Record<string, string> = {};\n\n headers.forEach((value, key) => {\n const normalizedKey = key.toLowerCase();\n if (\n normalizedKey === \"request-id\" ||\n normalizedKey === \"x-request-id\" ||\n normalizedKey === \"anthropic-organization-id\" ||\n normalizedKey === \"anthropic-beta\" ||\n normalizedKey === \"retry-after\" ||\n normalizedKey.startsWith(\"anthropic-ratelimit-\")\n ) {\n metadata[normalizedKey] = value;\n }\n });\n\n return metadata;\n}\n\nfunction buildStreamMetadata(options: {\n apiVersion: string;\n message?: MessagesAPIMessageResponse;\n stopReason?: string;\n stopSequence?: string | null;\n}): Record<string, unknown> {\n const { apiVersion, message, stopReason, stopSequence } = options;\n const metadata: Record<string, unknown> = {\n apiVersion,\n };\n\n if (message) {\n metadata.message = {\n id: message.id,\n type: message.type,\n role: message.role,\n model: message.model,\n };\n }\n\n if (stopReason !== undefined || stopSequence !== undefined) {\n metadata.stop = {\n reason: stopReason,\n sequence: stopSequence,\n };\n }\n\n return metadata;\n}\n\n// ── Adapter ───────────────────────────────────────────────────\n\nexport class MessagesAdapter extends AdapterBase {\n readonly kind = \"messages\" as const;\n readonly nativeStreaming = true;\n\n private apiKey: string;\n private apiVersion: string;\n private baseUrl: string;\n private fetchFn: FetchFn;\n private warningAccumulator: string[];\n\n constructor(options: MessagesAdapterOptions) {\n super();\n this.apiKey = options.apiKey;\n this.apiVersion = options.apiVersion ?? \"2023-06-01\";\n this.baseUrl = options.baseUrl ?? \"https://api.anthropic.com/v1\";\n this.fetchFn = options.fetch ?? globalThis.fetch;\n this.warningAccumulator = [];\n }\n\n protected warn(message: string, _code?: string): void {\n this.warningAccumulator.push(message);\n }\n\n // ── buildRequest ──────────────────────────────────────────\n\n protected buildRequest(request: NormalizedRequest): MessagesAPIRequest {\n const messages: MessagesAPIMessage[] = [];\n let systemPrompt: string | undefined;\n let pendingToolResultMessage: MessagesAPIMessage | undefined;\n\n // 处理 instructions → system prompt\n if (request.instructions) {\n systemPrompt = instructionsToMessagesText(request.instructions);\n }\n\n // 处理 input items\n for (const item of request.input) {\n if (item.type !== \"tool_result\") {\n pendingToolResultMessage = undefined;\n }\n\n switch (item.type) {\n case \"message\": {\n const role = item.role === \"user\" ? \"user\" : \"assistant\";\n const supportedContent = ensureMessagesTextBlocks(item.content, `input message (${item.role}) content`);\n if (supportedContent.length === 1 && supportedContent[0]?.type === \"text\") {\n messages.push({ role, content: supportedContent[0].text });\n } else {\n messages.push({ role, content: supportedContent.map(canonicalToMessagesBlock) });\n }\n break;\n }\n case \"tool_call\": {\n // Anthropic 使用 tool_use block 在 assistant message 中\n const lastMsg = messages[messages.length - 1];\n const toolBlock: MessagesAPIContentBlock = {\n type: \"tool_use\",\n id: item.id,\n name: item.name,\n input: (item.argumentsJson as Record<string, unknown> | undefined) ?? parseToolUseInput(item.argumentsText),\n };\n\n if (lastMsg && lastMsg.role === \"assistant\" && typeof lastMsg.content !== \"string\") {\n lastMsg.content.push(toolBlock);\n } else {\n messages.push({ role: \"assistant\", content: [toolBlock] });\n }\n break;\n }\n case \"tool_result\": {\n assertMessagesToolResultOutcome(item.outcome);\n const content = ensureMessagesTextBlocks(item.content, `tool_result ${item.callId} content`)\n .map(blockToText)\n .join(\"\\n\");\n const block: MessagesAPIContentBlock = {\n type: \"tool_result\",\n tool_use_id: item.callId,\n content,\n is_error: item.outcome === \"error\",\n };\n if (pendingToolResultMessage && typeof pendingToolResultMessage.content !== \"string\") {\n pendingToolResultMessage.content.push(block);\n } else {\n pendingToolResultMessage = { role: \"user\", content: [block] };\n messages.push(pendingToolResultMessage);\n }\n break;\n }\n case \"reasoning\": {\n // 将 reasoning item 转为 thinking block 在 assistant message 中\n const text = contentBlocksToText(ensureMessagesReasoningBlocks(item.content, \"reasoning content\"));\n const block: MessagesAPIContentBlock = { type: \"thinking\", thinking: text };\n const lastMsg = messages[messages.length - 1];\n if (lastMsg && lastMsg.role === \"assistant\" && typeof lastMsg.content !== \"string\") {\n lastMsg.content.push(block);\n } else {\n messages.push({ role: \"assistant\", content: [block] });\n }\n break;\n }\n case \"opaque\": {\n // 尝试从 opaque replay item 中提取 assistant message\n if (item.purpose === \"replay\" && typeof item.payload === \"object\" && item.payload !== null) {\n const payload = item.payload as Record<string, unknown>;\n if (payload.role === \"assistant\" && Array.isArray(payload.content)) {\n // 验证 content 是合法的 MessagesAPIContentBlock[]\n const isValidContent = payload.content.every(\n (b): b is MessagesAPIContentBlock =>\n typeof b === \"object\" &&\n b !== null &&\n \"type\" in b &&\n (b.type === \"text\" ||\n b.type === \"thinking\" ||\n b.type === \"redacted_thinking\" ||\n b.type === \"tool_use\" ||\n b.type === \"tool_result\"),\n );\n if (isValidContent) {\n rollbackTrailingAssistantMessages(messages);\n messages.push({\n role: \"assistant\",\n content: payload.content as MessagesAPIContentBlock[],\n });\n }\n }\n }\n break;\n }\n }\n }\n\n const body: MessagesAPIRequest = {\n model: request.model,\n max_tokens: request.maxOutputTokens ?? 4096,\n messages,\n stream: true,\n };\n\n if (systemPrompt) body.system = systemPrompt;\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map(\n (t): MessagesAPITool => ({\n name: t.name,\n description: t.description,\n input_schema: t.inputSchema,\n }),\n );\n }\n\n if (request.toolChoice) {\n if (request.toolChoice === \"auto\") body.tool_choice = { type: \"auto\" };\n else if (request.toolChoice === \"none\") body.tool_choice = { type: \"none\" };\n else if (request.toolChoice.type === \"tool\") {\n body.tool_choice = { type: \"tool\", name: request.toolChoice.name };\n }\n }\n\n if (request.temperature !== undefined) body.temperature = request.temperature;\n\n return body;\n }\n\n // ── runStream ─────────────────────────────────────────────\n\n protected async *runStream(\n providerRequest: MessagesAPIRequest,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n this.warningAccumulator = [];\n const auxiliary = this.createAuxiliaryState(request);\n\n if (request.metadata) {\n yield factory.responseWarning(\n \"Request metadata is not supported by the Messages adapter\",\n \"UNSUPPORTED_METADATA\",\n );\n }\n\n const response = await this.fetchFn(`${this.baseUrl}/messages`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": this.apiKey,\n \"anthropic-version\": this.apiVersion,\n },\n body: JSON.stringify(providerRequest),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"unknown error\");\n throw new Error(`Messages API error ${response.status}: ${errorText}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n // 流累积状态\n const output: OutputItem[] = [];\n const decoder = new TextDecoder();\n let buffer = \"\";\n let messageResponse: MessagesAPIMessageResponse | undefined;\n let currentContentBlockIndex = -1;\n let currentItemType: \"message\" | \"reasoning\" | \"tool_call\" | null = null;\n let currentItemId = \"\";\n let currentToolName = \"\";\n let currentArgsText = \"\";\n let currentThinkingVisibility: \"full\" | \"redacted\" = \"full\";\n let hasStreamedReasoning = false;\n const rawReplayContent: MessagesAPIContentBlock[] = [];\n\n // 内容块累积缓冲\n let textBuffer = \"\";\n let thinkingBuffer = \"\";\n let argsBuffer = \"\";\n\n // 完成响应数据\n let stopReason: string | undefined;\n let stopSequence: string | null | undefined;\n let rawResponseId = \"\";\n\n if (request.include?.providerMetadata !== \"off\") {\n const headerMetadata = pickProviderHeaders(response.headers);\n auxiliary.recordProviderMetadata(\n \"header\",\n Object.keys(headerMetadata).length > 0 ? { headers: headerMetadata } : undefined,\n );\n }\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { events, rest, malformedEvents } = parseMessagesSSE(buffer);\n buffer = rest;\n\n const malformedWarning = emitMalformedStreamWarning(factory, {\n count: malformedEvents,\n providerLabel: \"Messages\",\n transportLabel: \"SSE event(s)\",\n });\n if (malformedWarning) {\n yield malformedWarning;\n }\n\n for (const sseEvent of events) {\n switch (sseEvent.type) {\n case \"ping\":\n continue;\n\n case \"error\": {\n const err = sseEvent.data.error;\n yield factory.responseWarning(err.message, err.type);\n this.warn(err.message, err.type);\n continue;\n }\n\n case \"message_start\": {\n messageResponse = sseEvent.data.message;\n rawResponseId = messageResponse.id;\n // 检查是否有 thinking 能力\n if (messageResponse.content.some((b) => b.type === \"thinking\" || b.type === \"redacted_thinking\")) {\n hasStreamedReasoning = true;\n }\n continue;\n }\n\n case \"content_block_start\": {\n const block = sseEvent.data.content_block;\n currentContentBlockIndex = sseEvent.data.index;\n\n switch (block.type) {\n case \"text\": {\n currentItemType = \"message\";\n currentItemId = synthesizeItemId(\"msg\", currentContentBlockIndex, rawResponseId);\n textBuffer = \"\";\n yield factory.messageStarted(currentItemId);\n break;\n }\n case \"thinking\": {\n hasStreamedReasoning = true;\n currentItemType = \"reasoning\";\n currentItemId = synthesizeItemId(\"reason\", currentContentBlockIndex, rawResponseId);\n currentThinkingVisibility = \"full\";\n thinkingBuffer = \"\";\n yield factory.reasoningStarted(currentItemId, \"full\");\n break;\n }\n case \"redacted_thinking\": {\n hasStreamedReasoning = true;\n currentItemType = \"reasoning\";\n currentItemId = synthesizeItemId(\"reason-redacted\", currentContentBlockIndex, rawResponseId);\n currentThinkingVisibility = \"redacted\";\n const data = (block as unknown as { data: string }).data;\n yield factory.reasoningStarted(currentItemId, \"redacted\");\n yield factory.reasoningDelta(currentItemId, textBlock(data));\n const redactedItem = reasoningItem([textBlock(data)], \"redacted\", currentItemId);\n yield factory.reasoningCompleted(redactedItem);\n output.push(redactedItem);\n rawReplayContent.push({ type: \"redacted_thinking\", data });\n currentItemType = null;\n break;\n }\n case \"tool_use\": {\n const tuBlock = block as unknown as { id: string; name: string };\n currentItemType = \"tool_call\";\n currentItemId = tuBlock.id;\n currentToolName = tuBlock.name;\n currentArgsText = \"\";\n argsBuffer = \"\";\n yield factory.toolCallStarted(currentItemId, currentToolName);\n break;\n }\n }\n continue;\n }\n\n case \"content_block_delta\": {\n const delta = sseEvent.data.delta;\n\n switch (delta.type) {\n case \"text_delta\": {\n if (currentItemType === \"message\" && currentItemId) {\n const txt = (delta as unknown as { text: string }).text;\n textBuffer += txt;\n yield factory.messageDelta(currentItemId, txt);\n }\n break;\n }\n case \"thinking_delta\": {\n if (currentItemType === \"reasoning\" && currentItemId) {\n const txt = (delta as unknown as { thinking: string }).thinking;\n thinkingBuffer += txt;\n yield factory.reasoningDelta(currentItemId, textBlock(txt));\n }\n break;\n }\n case \"input_json_delta\": {\n if (currentItemType === \"tool_call\" && currentItemId) {\n const partial = (delta as unknown as { partial_json: string }).partial_json;\n argsBuffer += partial;\n yield factory.toolCallDelta(currentItemId, { argumentsText: partial });\n }\n break;\n }\n }\n continue;\n }\n\n case \"content_block_stop\": {\n if (currentItemType === \"message\" && currentItemId) {\n yield factory.messageCompleted(messageItem([textBlock(textBuffer)], { id: currentItemId }));\n output.push(messageItem([textBlock(textBuffer)], { id: currentItemId }));\n rawReplayContent.push({ type: \"text\", text: textBuffer });\n } else if (currentItemType === \"reasoning\" && currentItemId && currentThinkingVisibility !== \"redacted\") {\n yield factory.reasoningCompleted(\n reasoningItem([textBlock(thinkingBuffer)], currentThinkingVisibility, currentItemId),\n );\n output.push(reasoningItem([textBlock(thinkingBuffer)], currentThinkingVisibility, currentItemId));\n rawReplayContent.push({ type: \"thinking\", thinking: thinkingBuffer });\n } else if (currentItemType === \"tool_call\" && currentItemId) {\n const tcItem = toolCallItem(currentItemId, currentToolName, currentArgsText || argsBuffer);\n yield factory.toolCallCompleted(tcItem);\n output.push(tcItem);\n rawReplayContent.push({\n type: \"tool_use\",\n id: currentItemId,\n name: currentToolName,\n input: parseToolUseInput(currentArgsText || argsBuffer),\n });\n }\n\n currentItemType = null;\n currentItemId = \"\";\n continue;\n }\n\n case \"message_delta\": {\n stopReason = sseEvent.data.delta.stop_reason;\n stopSequence = sseEvent.data.delta.stop_sequence;\n const u = sseEvent.data.usage;\n if (u) {\n auxiliary.recordUsage(usageFromAnthropicMessages(u), \"stream\", u);\n }\n continue;\n }\n\n case \"message_stop\": {\n // 流结束,构造 final response\n break;\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n if (buffer.trim().length > 0) {\n yield factory.responseWarning(\"Stream ended with an incomplete Messages SSE frame\", \"STREAM_ERROR\");\n }\n\n // 构造 replay\n const replay = [...replayFromOutput(output)];\n\n // 附加 opaque replay item 用于续接\n // 保存 provider 原始 block 以实现高保真 replay\n if (messageResponse) {\n const replayContent = rawReplayContent.length > 0 ? rawReplayContent : messageResponse.content;\n replay.push(\n opaqueItem(\"messages\", \"replay\", {\n replaceCanonical: true,\n role: messageResponse.role,\n content: replayContent,\n messageId: messageResponse.id,\n stopReason: stopReason ?? messageResponse.stop_reason,\n }),\n );\n }\n\n if (request.include?.providerMetadata !== \"off\") {\n auxiliary.recordProviderMetadata(\n \"stream\",\n buildStreamMetadata({\n apiVersion: this.apiVersion,\n message: messageResponse,\n stopReason,\n stopSequence,\n }),\n );\n }\n\n // 警告低 replay fidelity\n if (!hasStreamedReasoning) {\n // 没有 reasoning,replay fidelity 较低\n }\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason: stopReason ? mapStopReason(stopReason) : undefined,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId,\n },\n factory,\n ),\n );\n }\n}\n","/**\n * Chat Completions Adapter\n *\n * 接入 OpenAI Chat Completions API (chat/completions 端点)。\n * 弱能力兼容层:\n * - third-party reasoning 字段仅做 best-effort 提取\n * - 工具调用通常整块到达(非逐 token 流)\n * - replay fidelity 依赖 provider 是否暴露可回放的 assistant turn 字段\n */\n\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { AIRequestError } from \"../core/errors.js\";\nimport {\n textBlock,\n messageItem,\n reasoningItem,\n toolCallItem,\n opaqueItem,\n replayFromOutput,\n mapStopReason,\n contentBlocksToText,\n} from \"../helpers/mapping.js\";\nimport { emitMalformedStreamWarning } from \"../helpers/adapter-auxiliary.js\";\nimport { usageFromChatCompletions } from \"../helpers/usage-mapping.js\";\n\nimport type { NormalizedRequest, AIStreamEvent, EventFactory, OutputItem, FetchFn } from \"../index.js\";\n\n// ── 类型 ──────────────────────────────────────────────────────\n\nexport type ChatCompletionsAdapterOptions = {\n apiKey: string;\n baseUrl?: string;\n fetch?: FetchFn;\n};\n\n// ── Chat API 请求类型 ─────────────────────────────────────────\n\ntype ChatRequest = {\n model: string;\n messages: ChatMessage[];\n tools?: ChatTool[];\n tool_choice?: \"auto\" | \"none\" | { type: \"function\"; function: { name: string } };\n metadata?: Record<string, string>;\n temperature?: number;\n max_tokens?: number;\n stream: true;\n};\n\ntype ChatMessage = {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string | null;\n tool_calls?: ChatToolCall[];\n tool_call_id?: string;\n name?: string;\n [key: string]: unknown;\n};\n\ntype ChatToolCall = {\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n};\n\ntype ChatTool = {\n type: \"function\";\n function: { name: string; description?: string; parameters: Record<string, unknown> };\n};\n\n// ── SSE chunk 类型 ────────────────────────────────────────────\n\ntype ChatChunk = {\n id: string;\n object: string;\n created: number;\n model: string;\n choices: ChatChunkChoice[];\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n prompt_tokens_details?: { cached_tokens?: number };\n completion_tokens_details?: { reasoning_tokens?: number };\n };\n};\n\ntype ChatChunkChoice = {\n index: number;\n delta: {\n role?: string;\n content?: string | null;\n reasoning?: unknown;\n reasoning_content?: unknown;\n tool_calls?: ChatChunkToolCall[];\n function_call?: { name?: string; arguments?: string };\n [key: string]: unknown;\n };\n finish_reason?: string | null;\n};\n\ntype ChatChunkToolCall = {\n index: number;\n id?: string;\n type?: string;\n function?: { name?: string; arguments?: string };\n};\n\ntype PendingToolCall = {\n id: string;\n name: string;\n args: string;\n};\n\ntype ReasoningFieldName = \"reasoning\" | \"reasoning_content\";\n\nconst REASONING_FIELDS: readonly ReasoningFieldName[] = [\"reasoning_content\", \"reasoning\"];\n\nfunction assertChatToolResultOutcome(outcome: import(\"../index.js\").ToolResultItem[\"outcome\"]): void {\n if (outcome !== \"success\") {\n throw new AIRequestError(\n `chat-completions does not preserve tool_result outcome \"${outcome}\"; only \"success\" is supported`,\n \"UNSUPPORTED_TOOL_RESULT_OUTCOME\",\n );\n }\n}\n\n// ── SSE 解析 ──────────────────────────────────────────────────\n\n/**\n * Chat Completions 的简化 SSE 解析器。\n *\n * 约束:\n * - 每条 `data:` 行必须已经是一个完整 JSON 对象\n * - 允许传输层把单行拆成多个 chunk,但不接受 provider 把一个 JSON event 改写成多条 `data:` 行\n */\nfunction parseChatSSE(buffer: string): { chunks: ChatChunk[]; rest: string; malformedEvents: number } {\n const chunks: ChatChunk[] = [];\n let rest = buffer;\n let malformedEvents = 0;\n\n while (true) {\n const lineEnd = rest.indexOf(\"\\n\");\n if (lineEnd === -1) {\n // 没有更多完整行,剩余部分保留到下次\n break;\n }\n\n const line = rest.slice(0, lineEnd).trim();\n rest = rest.slice(lineEnd + 1);\n\n if (!line.startsWith(\"data: \")) continue;\n\n const data = line.slice(6).trim();\n if (data === \"[DONE]\") continue;\n\n try {\n chunks.push(JSON.parse(data));\n } catch {\n malformedEvents++;\n }\n }\n\n return { chunks, rest, malformedEvents };\n}\n\nfunction ensureTextCompatibleBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): import(\"../index.js\").ContentBlock[] {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (!block) continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n throw new AIRequestError(\n `chat-completions does not support ${field}[${i}] of type \"${block.type}\"; only text/json blocks are supported`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n }\n\n return blocks;\n}\n\nfunction contentBlocksToChatText(blocks: import(\"../index.js\").ContentBlock[], field: string): string {\n return contentBlocksToText(ensureTextCompatibleBlocks(blocks, field));\n}\n\nfunction extractReasoningText(value: unknown): string {\n if (typeof value === \"string\") return value;\n\n if (Array.isArray(value)) {\n return value.map(extractReasoningText).join(\"\");\n }\n\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n for (const key of [\"text\", \"content\", \"reasoning\", \"reasoning_content\", \"thinking\", \"value\"]) {\n const nested = extractReasoningText(record[key]);\n if (nested) return nested;\n }\n }\n\n return \"\";\n}\n\nfunction extractReasoningDeltas(delta: ChatChunkChoice[\"delta\"]): Array<{ field: ReasoningFieldName; text: string }> {\n const deltas: Array<{ field: ReasoningFieldName; text: string }> = [];\n\n for (const field of REASONING_FIELDS) {\n const text = extractReasoningText(delta[field]);\n if (text) {\n deltas.push({ field, text });\n }\n }\n\n return deltas;\n}\n\nfunction rollbackTrailingAssistantMessages(messages: ChatMessage[]): void {\n while (messages.length > 0 && messages[messages.length - 1]?.role === \"assistant\") {\n messages.pop();\n }\n}\n\nfunction buildAssistantReplayMessage(params: {\n content: string;\n reasoningByField: ReadonlyMap<ReasoningFieldName, string>;\n toolCalls: readonly PendingToolCall[];\n}): ChatMessage | null {\n const { content, reasoningByField, toolCalls } = params;\n if (!content && reasoningByField.size === 0 && toolCalls.length === 0) return null;\n\n const replayMessage: ChatMessage = {\n role: \"assistant\",\n content: content || null,\n };\n\n for (const [field, text] of reasoningByField) {\n replayMessage[field] = text;\n }\n\n if (toolCalls.length > 0) {\n replayMessage.tool_calls = toolCalls.map((toolCall) => ({\n id: toolCall.id,\n type: \"function\",\n function: {\n name: toolCall.name,\n arguments: toolCall.args,\n },\n }));\n }\n\n return replayMessage;\n}\n\n// ── Adapter ───────────────────────────────────────────────────\n\nexport class ChatCompletionsAdapter extends AdapterBase {\n readonly kind = \"chat-completions\" as const;\n readonly nativeStreaming = true;\n\n private apiKey: string;\n private baseUrl: string;\n private fetchFn: FetchFn;\n\n constructor(options: ChatCompletionsAdapterOptions) {\n super();\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://api.openai.com/v1\";\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n // ── buildRequest ──────────────────────────────────────────\n\n protected buildRequest(request: NormalizedRequest): ChatRequest {\n const messages: ChatMessage[] = [];\n\n // handle instructions → system message\n if (request.instructions) {\n const content =\n typeof request.instructions === \"string\"\n ? request.instructions\n : contentBlocksToChatText(request.instructions, \"instructions\");\n messages.push({ role: \"system\", content });\n }\n\n for (const item of request.input) {\n switch (item.type) {\n case \"message\": {\n const role = item.role;\n const text = contentBlocksToChatText(item.content, `input message (${item.role}) content`);\n messages.push({ role, content: text || null });\n break;\n }\n case \"tool_call\": {\n // 只允许附着到尾部 assistant turn,否则新建一个\n const lastAssistant =\n messages.length > 0 && messages[messages.length - 1]?.role === \"assistant\"\n ? messages[messages.length - 1]\n : null;\n const tc: ChatToolCall = {\n id: item.id,\n type: \"function\",\n function: { name: item.name, arguments: item.argumentsText },\n };\n if (lastAssistant) {\n lastAssistant.tool_calls = [...(lastAssistant.tool_calls ?? []), tc];\n } else {\n messages.push({ role: \"assistant\", content: null, tool_calls: [tc] });\n }\n break;\n }\n case \"tool_result\": {\n assertChatToolResultOutcome(item.outcome);\n messages.push({\n role: \"tool\",\n tool_call_id: item.callId,\n name: item.toolName,\n content: contentBlocksToChatText(item.content, `tool_result ${item.callId} content`),\n });\n break;\n }\n case \"reasoning\": {\n // chat.completions doesn't support reasoning items in input\n // Convert to a text message for best-effort\n messages.push({\n role: \"assistant\",\n content: contentBlocksToChatText(item.content, \"reasoning content\"),\n });\n break;\n }\n case \"opaque\": {\n // Try to restore from opaque replay\n if (item.purpose === \"replay\" && typeof item.payload === \"object\" && item.payload !== null) {\n const payload = item.payload as Record<string, unknown>;\n if (payload.role === \"assistant\" && typeof payload.content === \"string\") {\n messages.push({ role: \"assistant\", content: payload.content as string });\n } else if (payload.replaceCanonical === true && Array.isArray(payload.messages)) {\n rollbackTrailingAssistantMessages(messages);\n for (const m of payload.messages as ChatMessage[]) {\n messages.push(m);\n }\n } else if (Array.isArray(payload.messages)) {\n for (const m of payload.messages as ChatMessage[]) {\n messages.push(m);\n }\n }\n }\n break;\n }\n }\n }\n\n const body: ChatRequest = {\n model: request.model,\n messages,\n stream: true,\n };\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map(\n (t): ChatTool => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.inputSchema as Record<string, unknown>,\n },\n }),\n );\n }\n\n if (request.toolChoice) {\n if (request.toolChoice === \"auto\") body.tool_choice = \"auto\";\n else if (request.toolChoice === \"none\") body.tool_choice = \"none\";\n else if (request.toolChoice.type === \"tool\") {\n body.tool_choice = { type: \"function\", function: { name: request.toolChoice.name } };\n }\n }\n\n if (request.temperature !== undefined) body.temperature = request.temperature;\n if (request.maxOutputTokens !== undefined) body.max_tokens = request.maxOutputTokens;\n if (request.metadata) body.metadata = request.metadata;\n\n return body;\n }\n\n // ── runStream ─────────────────────────────────────────────\n\n protected async *runStream(\n providerRequest: ChatRequest,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n const auxiliary = this.createAuxiliaryState(request);\n const response = await this.fetchFn(`${this.baseUrl}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(providerRequest),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"unknown error\");\n throw new Error(`Chat Completions API error ${response.status}: ${errorText}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n const output: OutputItem[] = [];\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n // 累积状态 — 支持多 choice,此处只取 index 0\n let responseId: string | undefined;\n let accumulatedContent = \"\";\n let accumulatedReasoning = \"\";\n let currentMessageId = \"\";\n let currentReasoningId = \"\";\n let hasMessageStarted = false;\n let hasReasoningStarted = false;\n\n // tool_calls 累积: tool call index → { id, name, args }\n const pendingToolCalls = new Map<number, PendingToolCall>();\n const reasoningByField = new Map<ReasoningFieldName, string>();\n\n const finalizePendingTurn = (): { events: AIStreamEvent[]; assistantReplayMessage: ChatMessage | null } => {\n const events: AIStreamEvent[] = [];\n const finalizedToolCalls = [...pendingToolCalls.values()];\n const finalizedReasoningByField = new Map(reasoningByField);\n\n if (hasReasoningStarted && accumulatedReasoning) {\n const reasoning = reasoningItem([textBlock(accumulatedReasoning)], \"full\", currentReasoningId);\n events.push(factory.reasoningCompleted(reasoning));\n output.push(reasoning);\n }\n\n if (hasMessageStarted && accumulatedContent) {\n const message = messageItem([textBlock(accumulatedContent)], { id: currentMessageId });\n events.push(factory.messageCompleted(message));\n output.push(message);\n }\n\n for (const pending of finalizedToolCalls) {\n const toolCall = toolCallItem(pending.id, pending.name, pending.args);\n events.push(factory.toolCallCompleted(toolCall));\n output.push(toolCall);\n }\n\n const assistantReplayMessage = buildAssistantReplayMessage({\n content: accumulatedContent,\n reasoningByField: finalizedReasoningByField,\n toolCalls: finalizedToolCalls,\n });\n\n accumulatedContent = \"\";\n accumulatedReasoning = \"\";\n currentMessageId = \"\";\n currentReasoningId = \"\";\n hasMessageStarted = false;\n hasReasoningStarted = false;\n pendingToolCalls.clear();\n reasoningByField.clear();\n\n return { events, assistantReplayMessage };\n };\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { chunks, rest, malformedEvents } = parseChatSSE(buffer);\n buffer = rest;\n\n const malformedWarning = emitMalformedStreamWarning(factory, {\n count: malformedEvents,\n providerLabel: \"Chat Completions\",\n transportLabel: \"SSE event(s)\",\n });\n if (malformedWarning) {\n yield malformedWarning;\n }\n\n for (const chunk of chunks) {\n responseId = chunk.id;\n\n // usage 可能在最终 chunk 中\n if (chunk.usage) {\n auxiliary.recordUsage(usageFromChatCompletions(chunk.usage), \"final\", chunk.usage);\n }\n\n for (const choice of chunk.choices) {\n if (choice.index !== 0) continue;\n\n const delta = choice.delta;\n const finishReason = choice.finish_reason;\n const reasoningDeltas = extractReasoningDeltas(delta);\n\n // 处理 role: assistant (首块标识)\n if (delta.role === \"assistant\" && typeof delta.content === \"string\" && !hasMessageStarted) {\n currentMessageId = `msg-${chunk.id}`;\n hasMessageStarted = true;\n accumulatedContent = \"\";\n yield factory.messageStarted(currentMessageId);\n }\n\n // 处理 third-party reasoning delta\n if (reasoningDeltas.length > 0) {\n if (!hasReasoningStarted) {\n currentReasoningId = `reason-${chunk.id}`;\n hasReasoningStarted = true;\n accumulatedReasoning = \"\";\n yield factory.reasoningStarted(currentReasoningId, \"full\");\n }\n\n for (const reasoningDelta of reasoningDeltas) {\n accumulatedReasoning += reasoningDelta.text;\n reasoningByField.set(\n reasoningDelta.field,\n (reasoningByField.get(reasoningDelta.field) ?? \"\") + reasoningDelta.text,\n );\n yield factory.reasoningDelta(currentReasoningId, textBlock(reasoningDelta.text));\n }\n }\n\n // 处理 content delta\n if (delta.content) {\n if (!hasMessageStarted) {\n currentMessageId = `msg-${chunk.id}`;\n hasMessageStarted = true;\n yield factory.messageStarted(currentMessageId);\n }\n accumulatedContent += delta.content;\n yield factory.messageDelta(currentMessageId, delta.content);\n }\n\n // 处理 tool_calls delta\n if (delta.tool_calls) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index;\n\n if (tc.id) {\n pendingToolCalls.set(idx, { id: tc.id, name: tc.function?.name ?? \"\", args: \"\" });\n yield factory.toolCallStarted(tc.id, tc.function?.name ?? \"\");\n }\n\n if (tc.function?.arguments) {\n const pending = pendingToolCalls.get(idx);\n if (pending) {\n pending.args += tc.function.arguments;\n yield factory.toolCallDelta(pending.id, { argumentsText: tc.function.arguments });\n }\n }\n }\n }\n\n // 处理 function_call delta (legacy format)\n if (delta.function_call) {\n if (delta.function_call.name) {\n const fcId = `fc-${chunk.id}-0`;\n pendingToolCalls.set(0, { id: fcId, name: delta.function_call.name, args: \"\" });\n yield factory.toolCallStarted(fcId, delta.function_call.name);\n }\n if (delta.function_call.arguments) {\n const pending = pendingToolCalls.get(0);\n if (pending) {\n pending.args += delta.function_call.arguments;\n yield factory.toolCallDelta(pending.id, { argumentsText: delta.function_call.arguments });\n }\n }\n }\n\n // 处理 finish_reason\n if (finishReason && finishReason !== null) {\n const { events, assistantReplayMessage } = finalizePendingTurn();\n for (const event of events) {\n yield event;\n }\n\n // 构建 stop reason\n const stopReason = mapStopReason(finishReason);\n\n // 构建 replay\n const replay = [...replayFromOutput(output)];\n\n // 附加 opaque replay\n if (assistantReplayMessage) {\n replay.push(\n opaqueItem(\"chat.completions\", \"replay\", {\n replaceCanonical: true,\n messages: [assistantReplayMessage],\n }),\n );\n }\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId: chunk.id,\n },\n factory,\n ),\n );\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n if (buffer.trim().length > 0) {\n yield factory.responseWarning(\"Stream ended with an incomplete Chat Completions SSE frame\", \"STREAM_ERROR\");\n }\n\n // 如果流结束时没有 finish_reason(断流),也尝试关闭\n if (hasMessageStarted || hasReasoningStarted || pendingToolCalls.size > 0) {\n yield factory.responseWarning(\"Stream ended without a finish_reason\", \"INCOMPLETE_STREAM\");\n\n const { events, assistantReplayMessage } = finalizePendingTurn();\n for (const event of events) {\n yield event;\n }\n\n const replay = [...replayFromOutput(output)];\n if (assistantReplayMessage) {\n replay.push(\n opaqueItem(\"chat.completions\", \"replay\", {\n replaceCanonical: true,\n messages: [assistantReplayMessage],\n }),\n );\n }\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId: responseId,\n },\n factory,\n ),\n );\n }\n }\n}\n","/**\n * Ollama Adapter\n *\n * 接入 Ollama 原生 Chat API (/api/chat)。\n * 与 Chat Completions 兼容层不同,此处直接使用 Ollama 的 NDJSON 流格式。\n *\n * 能力:\n * - 消息流(完整 content 逐块到达)\n * - 工具调用(整块到达,非逐 token)\n * - 用量信息(仅 prompt_eval_count / eval_count)\n *\n * 限制:\n * - 不流式输出 reasoning(Ollama 原生 API 无独立思考字段)\n * - tool_call 不支持逐 token 流式\n * - replay 保真度低(无 opaque continuation 机制)\n */\n\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { AIRequestError } from \"../core/errors.js\";\nimport {\n textBlock,\n messageItem,\n toolCallItem,\n opaqueItem,\n replayFromOutput,\n mapStopReason,\n contentBlocksToText,\n} from \"../helpers/mapping.js\";\nimport { emitMalformedStreamWarning } from \"../helpers/adapter-auxiliary.js\";\nimport { usageFromOllama } from \"../helpers/usage-mapping.js\";\n\nimport type { NormalizedRequest, AIStreamEvent, EventFactory, OutputItem, FetchFn } from \"../index.js\";\n\n// ── 选项类型 ──────────────────────────────────────────────────\n\nexport type OllamaAdapterOptions = {\n /** Ollama 服务地址,默认 http://localhost:11434 */\n baseUrl?: string;\n /** 可选 API key(用于需要认证的代理场景) */\n apiKey?: string;\n /** 可注入自定义 fetch 实现 */\n fetch?: FetchFn;\n};\n\n// ── Ollama Chat API 类型 ──────────────────────────────────────\n\ntype OllamaChatRequest = {\n model: string;\n messages: OllamaMessage[];\n stream: true;\n tools?: OllamaTool[];\n options?: {\n temperature?: number;\n num_predict?: number;\n [key: string]: unknown;\n };\n};\n\ntype OllamaMessage = {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string;\n images?: string[];\n tool_calls?: OllamaToolCall[];\n};\n\ntype OllamaToolCall = {\n function: {\n name: string;\n arguments: Record<string, unknown>;\n };\n};\n\ntype OllamaTool = {\n type: \"function\";\n function: {\n name: string;\n description?: string;\n parameters: Record<string, unknown>;\n };\n};\n\nfunction ensureOllamaTextBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): import(\"../index.js\").ContentBlock[] {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (!block) continue;\n if (block.type !== \"text\" && block.type !== \"json\") {\n throw new AIRequestError(\n `ollama does not support ${field}[${i}] of type \"${block.type}\"; only text/json blocks are supported`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n }\n\n return blocks;\n}\n\nfunction ensureOllamaReasoningBlocks(\n blocks: import(\"../index.js\").ContentBlock[],\n field: string,\n): Array<Extract<import(\"../index.js\").ContentBlock, { type: \"text\" }>> {\n return blocks.map((block, index) => {\n if (block.type !== \"text\") {\n throw new AIRequestError(\n `ollama does not support ${field}[${index}] of type \"${block.type}\"; reasoning only supports text blocks`,\n \"UNSUPPORTED_CONTENT_BLOCK\",\n );\n }\n\n return block;\n });\n}\n\nfunction instructionsToOllamaText(instructions: string | import(\"../index.js\").InstructionBlock[]): string {\n return typeof instructions === \"string\"\n ? instructions\n : contentBlocksToText(ensureOllamaTextBlocks(instructions, \"instructions\"));\n}\n\nfunction parseOllamaToolArguments(item: import(\"../index.js\").ToolCallItem): Record<string, unknown> {\n if (item.argumentsJson && typeof item.argumentsJson === \"object\" && item.argumentsJson !== null) {\n return item.argumentsJson as Record<string, unknown>;\n }\n\n try {\n const parsed = JSON.parse(item.argumentsText);\n if (parsed && typeof parsed === \"object\") {\n return parsed as Record<string, unknown>;\n }\n } catch {\n // fall through\n }\n\n throw new AIRequestError(\n \"ollama tool_call argumentsText must be valid JSON object when argumentsJson is absent\",\n \"TOOL_CALL_ARGUMENTS_INVALID\",\n );\n}\n\nfunction assertOllamaToolResultOutcome(outcome: import(\"../index.js\").ToolResultItem[\"outcome\"]): void {\n if (outcome !== \"success\") {\n throw new AIRequestError(\n `ollama does not preserve tool_result outcome \"${outcome}\"; only \"success\" is supported`,\n \"UNSUPPORTED_TOOL_RESULT_OUTCOME\",\n );\n }\n}\n\n// ── Ollama 流式 chunk ─────────────────────────────────────────\n\ntype OllamaChatChunk = {\n model: string;\n created_at: string;\n message: {\n role: string;\n content: string;\n tool_calls?: OllamaToolCall[];\n };\n done: boolean;\n done_reason?: string;\n // 计时与用量(仅 final chunk 有值)\n total_duration?: number;\n load_duration?: number;\n prompt_eval_count?: number;\n prompt_eval_duration?: number;\n eval_count?: number;\n eval_duration?: number;\n};\n\n// ── NDJSON 解析 ───────────────────────────────────────────────\n\nfunction parseOllamaNDJSON(buffer: string): { chunks: OllamaChatChunk[]; rest: string; malformedLines: number } {\n const chunks: OllamaChatChunk[] = [];\n let rest = buffer;\n let malformedLines = 0;\n\n while (true) {\n const lineEnd = rest.indexOf(\"\\n\");\n if (lineEnd === -1) break;\n\n const line = rest.slice(0, lineEnd).trim();\n rest = rest.slice(lineEnd + 1);\n\n if (!line) continue;\n\n try {\n const parsed = JSON.parse(line);\n // Ollama chunks have a \"message\" field in streaming mode\n if (parsed && typeof parsed === \"object\" && \"message\" in parsed) {\n chunks.push(parsed as OllamaChatChunk);\n } else {\n malformedLines++;\n }\n } catch {\n malformedLines++;\n }\n }\n\n return { chunks, rest, malformedLines };\n}\n\nfunction rollbackTrailingAssistantMessages(messages: OllamaMessage[]): void {\n while (messages.length > 0 && messages[messages.length - 1]?.role === \"assistant\") {\n messages.pop();\n }\n}\n\nfunction isOllamaToolCalls(value: unknown): value is OllamaToolCall[] {\n return (\n Array.isArray(value) &&\n value.every((entry) => {\n if (!entry || typeof entry !== \"object\" || !(\"function\" in entry)) return false;\n const fn = (entry as { function?: unknown }).function;\n return (\n !!fn &&\n typeof fn === \"object\" &&\n \"name\" in fn &&\n typeof (fn as { name?: unknown }).name === \"string\" &&\n \"arguments\" in fn &&\n typeof (fn as { arguments?: unknown }).arguments === \"object\" &&\n (fn as { arguments?: unknown }).arguments !== null\n );\n })\n );\n}\n\n// ── Adapter ───────────────────────────────────────────────────\n\nexport class OllamaAdapter extends AdapterBase {\n readonly kind = \"ollama\" as const;\n readonly nativeStreaming = true;\n\n private baseUrl: string;\n private apiKey: string | undefined;\n private fetchFn: FetchFn;\n\n constructor(options: OllamaAdapterOptions = {}) {\n super();\n this.baseUrl = options.baseUrl ?? \"http://localhost:11434\";\n this.apiKey = options.apiKey;\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n // ── buildRequest ──────────────────────────────────────────\n\n protected buildRequest(request: NormalizedRequest): OllamaChatRequest {\n if (request.toolChoice && request.toolChoice !== \"auto\") {\n throw new AIRequestError(\"ollama does not support explicit toolChoice\", \"UNSUPPORTED_TOOL_CHOICE\");\n }\n\n const messages: OllamaMessage[] = [];\n\n // handle instructions → system message\n if (request.instructions) {\n messages.push({ role: \"system\", content: instructionsToOllamaText(request.instructions) });\n }\n\n for (const item of request.input) {\n switch (item.type) {\n case \"message\": {\n const role = item.role;\n messages.push({\n role,\n content: contentBlocksToText(ensureOllamaTextBlocks(item.content, `input message (${item.role}) content`)),\n });\n break;\n }\n case \"tool_call\": {\n // Ollama expects tool_calls on the last assistant message\n const lastAssistant = messages.findLast((m) => m.role === \"assistant\");\n const tc: OllamaToolCall = {\n function: {\n name: item.name,\n arguments: parseOllamaToolArguments(item),\n },\n };\n if (lastAssistant) {\n lastAssistant.tool_calls = [...(lastAssistant.tool_calls ?? []), tc];\n } else {\n messages.push({ role: \"assistant\", content: \"\", tool_calls: [tc] });\n }\n break;\n }\n case \"tool_result\": {\n assertOllamaToolResultOutcome(item.outcome);\n messages.push({\n role: \"tool\",\n content: contentBlocksToText(ensureOllamaTextBlocks(item.content, `tool_result ${item.callId} content`)),\n });\n break;\n }\n case \"reasoning\": {\n // Ollama doesn't support reasoning in input; convert to text message\n messages.push({\n role: \"assistant\",\n content: contentBlocksToText(ensureOllamaReasoningBlocks(item.content, \"reasoning content\")),\n });\n break;\n }\n case \"opaque\": {\n // Best-effort restore from opaque replay\n if (\n item.source === \"ollama\" &&\n item.purpose === \"replay\" &&\n typeof item.payload === \"object\" &&\n item.payload !== null\n ) {\n const payload = item.payload as Record<string, unknown>;\n if (payload.role === \"assistant\" && typeof payload.content === \"string\") {\n rollbackTrailingAssistantMessages(messages);\n messages.push({\n role: \"assistant\",\n content: payload.content,\n tool_calls: isOllamaToolCalls(payload.tool_calls) ? payload.tool_calls : undefined,\n });\n }\n }\n break;\n }\n }\n }\n\n const body: OllamaChatRequest = {\n model: request.model,\n messages,\n stream: true,\n };\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map(\n (t): OllamaTool => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.inputSchema as Record<string, unknown>,\n },\n }),\n );\n }\n\n if (request.temperature !== undefined || request.maxOutputTokens !== undefined) {\n body.options = {};\n if (request.temperature !== undefined) body.options.temperature = request.temperature;\n if (request.maxOutputTokens !== undefined) body.options.num_predict = request.maxOutputTokens;\n }\n\n return body;\n }\n\n // ── runStream ─────────────────────────────────────────────\n\n protected async *runStream(\n providerRequest: OllamaChatRequest,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n const auxiliary = this.createAuxiliaryState(request);\n if (request.metadata) {\n yield factory.responseWarning(\"Request metadata is not supported by the Ollama adapter\", \"UNSUPPORTED_METADATA\");\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (this.apiKey) {\n headers.Authorization = `Bearer ${this.apiKey}`;\n }\n\n const response = await this.fetchFn(`${this.baseUrl}/api/chat`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(providerRequest),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"unknown error\");\n throw new Error(`Ollama API error ${response.status}: ${errorText}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n const output: OutputItem[] = [];\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n // 累积状态\n let responseId: string | undefined;\n let accumulatedContent = \"\";\n let currentMessageId = \"\";\n let hasMessageStarted = false;\n\n // tool_calls 累积(于 final chunk 到达)\n let pendingToolCalls: Array<{ id: string; name: string; argumentsText: string; argumentsJson?: unknown }> = [];\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { chunks, rest, malformedLines } = parseOllamaNDJSON(buffer);\n buffer = rest;\n\n const malformedWarning = emitMalformedStreamWarning(factory, {\n count: malformedLines,\n providerLabel: \"Ollama\",\n transportLabel: \"NDJSON line(s)\",\n });\n if (malformedWarning) {\n yield malformedWarning;\n }\n\n for (const chunk of chunks) {\n responseId = chunk.created_at;\n\n const msg = chunk.message;\n\n // 处理 content delta\n if (msg.content) {\n if (!hasMessageStarted) {\n currentMessageId = `msg-${chunk.created_at}`;\n hasMessageStarted = true;\n yield factory.messageStarted(currentMessageId);\n }\n accumulatedContent += msg.content;\n yield factory.messageDelta(currentMessageId, msg.content);\n }\n\n // 处理 tool_calls (整块到达,在最终 chunk 中)\n if (msg.tool_calls && msg.tool_calls.length > 0) {\n for (const tc of msg.tool_calls) {\n const tcId = `tc-${chunk.created_at}-${tc.function.name}`;\n const argsText = JSON.stringify(tc.function.arguments);\n pendingToolCalls.push({\n id: tcId,\n name: tc.function.name,\n argumentsText: argsText,\n argumentsJson: tc.function.arguments,\n });\n }\n }\n\n // 处理 done_reason (final chunk)\n if (chunk.done) {\n // 如果有未开始的 message 但没内容,发一个空消息启动\n if (accumulatedContent === \"\" && pendingToolCalls.length > 0 && !hasMessageStarted) {\n currentMessageId = `msg-${chunk.created_at}`;\n hasMessageStarted = true;\n yield factory.messageStarted(currentMessageId);\n }\n\n // 完成消息(如果有累积的内容或正在进行的消息)\n if (hasMessageStarted) {\n const message = messageItem([textBlock(accumulatedContent)], { id: currentMessageId });\n yield factory.messageCompleted(message);\n if (accumulatedContent) {\n output.push(message);\n }\n }\n\n // 发出 tool_call 完成事件\n for (const pending of pendingToolCalls) {\n const toolCall = toolCallItem(pending.id, pending.name, pending.argumentsText, pending.argumentsJson);\n yield factory.toolCallStarted(pending.id, pending.name);\n yield factory.toolCallDelta(pending.id, { argumentsText: pending.argumentsText });\n yield factory.toolCallCompleted(toolCall);\n output.push(toolCall);\n }\n\n // 提取 usage\n if (\n request.include?.usage !== \"off\" &&\n (chunk.prompt_eval_count !== undefined || chunk.eval_count !== undefined)\n ) {\n auxiliary.recordUsage(\n usageFromOllama({\n prompt_eval_count: chunk.prompt_eval_count,\n eval_count: chunk.eval_count,\n }),\n \"final\",\n {\n prompt_eval_count: chunk.prompt_eval_count,\n eval_count: chunk.eval_count,\n },\n );\n }\n\n // 构建 stop reason\n const stopReason = chunk.done_reason ? mapStopReason(chunk.done_reason) : undefined;\n\n // 构建 replay\n const replay = replayFromOutput(output);\n\n // 附加 opaque replay(若有关联的 assistant 消息)\n if (accumulatedContent || pendingToolCalls.length > 0) {\n replay.push(\n opaqueItem(\"ollama\", \"replay\", {\n role: \"assistant\",\n content: accumulatedContent,\n tool_calls: pendingToolCalls.map((tc) => ({\n function: { name: tc.name, arguments: tc.argumentsJson },\n })),\n }),\n );\n }\n\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId: chunk.created_at,\n },\n factory,\n ),\n );\n\n // 重置累积状态\n accumulatedContent = \"\";\n currentMessageId = \"\";\n hasMessageStarted = false;\n pendingToolCalls = [];\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n if (buffer.trim().length > 0) {\n yield factory.responseWarning(\"Stream ended with an incomplete Ollama NDJSON line\", \"STREAM_ERROR\");\n }\n\n // 流结束但无 done=true(断流保护)\n if (hasMessageStarted || pendingToolCalls.length > 0) {\n yield factory.responseWarning(\"Stream ended without a done signal\", \"INCOMPLETE_STREAM\");\n\n if (hasMessageStarted) {\n const message = messageItem([textBlock(accumulatedContent)], { id: currentMessageId });\n yield factory.messageCompleted(message);\n if (accumulatedContent) {\n output.push(message);\n }\n }\n\n for (const pending of pendingToolCalls) {\n const toolCall = toolCallItem(pending.id, pending.name, pending.argumentsText, pending.argumentsJson);\n yield factory.toolCallStarted(pending.id, pending.name);\n yield factory.toolCallDelta(pending.id, { argumentsText: pending.argumentsText });\n yield factory.toolCallCompleted(toolCall);\n output.push(toolCall);\n }\n\n const replay = replayFromOutput(output);\n const auxiliaryResult = await auxiliary.finalize(factory);\n for (const event of auxiliaryResult.events) {\n yield event;\n }\n yield factory.responseCompleted(\n this.buildResponse(\n request,\n {\n output,\n replay,\n usage: auxiliaryResult.usage,\n billing: auxiliaryResult.billing,\n auxiliary: auxiliaryResult.auxiliary,\n warnings: auxiliaryResult.warnings,\n metadataSources: auxiliaryResult.metadataSources,\n rawResponseId: responseId,\n },\n factory,\n ),\n );\n }\n }\n}\n","/**\n * Mock Adapter\n *\n * 面向测试的回调驱动 adapter:\n * - 每次请求执行用户提供的 handler\n * - 验证调用方是否正确续接 replay / tool_result\n * - 发出可控的 message / reasoning / tool_call 流\n * - 注入 warning / auxiliary / content_filter / 中断 / provider error\n *\n * 这不是通用“假模型”,而是测试工具调用编排与错误路径的测试夹具。\n */\n\nimport { AIRequestError } from \"../core/errors.js\";\nimport { AdapterBase } from \"../helpers/adapter-base.js\";\nimport { messageItem, reasoningItem, replayFromOutput, textBlock } from \"../helpers/mapping.js\";\n\nimport type {\n AIStreamEvent,\n AuxiliaryInfo,\n BillingInfo,\n ContentBlock,\n EventFactory,\n InputItem,\n MessageItem,\n NormalizedRequest,\n OutputItem,\n ReplayItem,\n StopReason,\n ToolCallItem,\n ToolResultItem,\n Usage,\n} from \"../index.js\";\n\nexport type MockInputExpectation = {\n type: InputItem[\"type\"];\n id?: string;\n role?: MessageItem[\"role\"];\n name?: string;\n toolName?: string;\n callId?: string;\n outcome?: ToolResultItem[\"outcome\"];\n visibility?: Extract<InputItem, { type: \"reasoning\" }>[\"visibility\"];\n source?: Extract<InputItem, { type: \"opaque\" }>[\"source\"];\n purpose?: Extract<InputItem, { type: \"opaque\" }>[\"purpose\"];\n textIncludes?: string;\n};\n\nexport type MockRequestExpectation = {\n minItems?: number;\n maxItems?: number;\n ordered?: boolean;\n requireReplayFromPreviousTurn?: boolean;\n requireToolResultsForPendingCalls?: boolean;\n tools?: \"ignore\" | \"present\" | \"absent\";\n toolChoice?: \"ignore\" | \"present\" | \"absent\";\n items?: MockInputExpectation[];\n};\n\nexport type MockHistoryRecord = {\n turnIndex: number;\n requestId: string;\n replay: ReplayItem[];\n toolCalls: ToolCallItem[];\n};\n\nexport type MockHandlerContext = {\n turnIndex: number;\n previousReplay: ReplayItem[];\n pendingToolCalls: readonly ToolCallItem[];\n history: readonly MockHistoryRecord[];\n};\n\nexport type MockWarningStep = {\n type: \"warning\";\n message: string;\n code?: string;\n};\n\nexport type MockAuxiliaryStep = {\n type: \"auxiliary\";\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: Partial<AuxiliaryInfo>;\n};\n\nexport type MockTextStreamOptions = {\n /**\n * 每秒吐出的字符数。未设置时仍会按 chunk 拆分,但不会额外等待。\n */\n charsPerSecond?: number;\n /**\n * 每个 delta 最多包含多少个字符,默认 1。\n */\n chunkSize?: number;\n /**\n * 首个 delta 发出前的延迟。\n */\n initialDelayMs?: number;\n};\n\nexport type MockMessageStep = {\n type: \"message\";\n id?: string;\n content: string | ContentBlock[];\n stream?: MockTextStreamOptions | false;\n};\n\nexport type MockReasoningStep = {\n type: \"reasoning\";\n id?: string;\n visibility?: Extract<OutputItem, { type: \"reasoning\" }>[\"visibility\"];\n content: string | ContentBlock[];\n stream?: MockTextStreamOptions | false;\n};\n\nexport type MockToolCallStep = {\n type: \"tool_call\";\n id: string;\n name: string;\n argumentsText: string;\n argumentsJson?: unknown;\n streamArguments?: boolean;\n stream?: MockTextStreamOptions | false;\n};\n\nexport type MockOutputStep = {\n type: \"output\";\n item: Extract<OutputItem, { type: \"message\" | \"reasoning\" | \"tool_call\" }>;\n stream?: MockTextStreamOptions | false;\n};\n\nexport type MockCompleteStep = {\n type: \"complete\";\n stopReason?: StopReason;\n replay?: ReplayItem[];\n usage?: Usage;\n billing?: BillingInfo;\n auxiliary?: Partial<AuxiliaryInfo>;\n providerMetadata?: Record<string, unknown>;\n rawResponseId?: string;\n warnings?: string[];\n};\n\nexport type MockErrorStep = {\n type: \"error\";\n message: string;\n code?: string;\n stopReason?: StopReason;\n providerMetadata?: Record<string, unknown>;\n};\n\nexport type MockInterruptStep = {\n type: \"interrupt\";\n};\n\nexport type MockThrowStep = {\n type: \"throw\";\n error: string | Error;\n};\n\nexport type MockStep =\n | MockWarningStep\n | MockAuxiliaryStep\n | MockMessageStep\n | MockReasoningStep\n | MockToolCallStep\n | MockOutputStep\n | MockCompleteStep\n | MockErrorStep\n | MockInterruptStep\n | MockThrowStep;\n\nexport type MockHandler = (request: NormalizedRequest, context: MockHandlerContext) => AsyncIterable<MockStep>;\n\ntype MockHandlerSource = Iterable<MockStep> | AsyncIterable<MockStep>;\n\nexport type MockStaticHandler = (\n request: NormalizedRequest,\n context: MockHandlerContext,\n) => MockHandlerSource | Promise<MockHandlerSource>;\n\nexport type MockAdapterOptions = {\n handler: MockHandler;\n providerMetadata?: Record<string, unknown>;\n};\n\ntype MockProviderRequest = {\n request: NormalizedRequest;\n handlerResult: AsyncIterable<MockStep>;\n turnIndex: number;\n remainingPendingToolCalls: ToolCallItem[];\n};\n\ntype ResolvedMockTextStreamOptions = {\n charsPerSecond?: number;\n chunkSize: number;\n initialDelayMs: number;\n};\n\nexport function assertMockRequest(\n request: NormalizedRequest,\n expectation: MockRequestExpectation,\n context: MockHandlerContext,\n): void {\n const prefix = `MockAdapter turn ${context.turnIndex + 1} expectation failed`;\n\n if (expectation.minItems !== undefined && request.input.length < expectation.minItems) {\n throw new AIRequestError(\n `${prefix}: expected at least ${expectation.minItems} input item(s)`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n\n if (expectation.maxItems !== undefined && request.input.length > expectation.maxItems) {\n throw new AIRequestError(\n `${prefix}: expected at most ${expectation.maxItems} input item(s)`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n\n if (expectation.tools === \"present\" && (!request.tools || request.tools.length === 0)) {\n throw new AIRequestError(`${prefix}: expected tools to be present`, \"MOCK_EXPECTATION_FAILED\");\n }\n\n if (expectation.tools === \"absent\" && request.tools && request.tools.length > 0) {\n throw new AIRequestError(`${prefix}: expected tools to be absent`, \"MOCK_EXPECTATION_FAILED\");\n }\n\n if (expectation.toolChoice === \"present\" && request.toolChoice === undefined) {\n throw new AIRequestError(`${prefix}: expected toolChoice to be present`, \"MOCK_EXPECTATION_FAILED\");\n }\n\n if (expectation.toolChoice === \"absent\" && request.toolChoice !== undefined) {\n throw new AIRequestError(`${prefix}: expected toolChoice to be absent`, \"MOCK_EXPECTATION_FAILED\");\n }\n\n if (expectation.requireReplayFromPreviousTurn && context.previousReplay.length > 0) {\n assertReplayIncluded(request.input, context.previousReplay, prefix);\n }\n\n if (expectation.requireToolResultsForPendingCalls && context.pendingToolCalls.length > 0) {\n const toolResultIds = new Set(\n request.input.filter((item): item is ToolResultItem => item.type === \"tool_result\").map((item) => item.callId),\n );\n\n for (const call of context.pendingToolCalls) {\n if (!toolResultIds.has(call.id)) {\n throw new AIRequestError(\n `${prefix}: expected tool_result for pending tool call \"${call.id}\"`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n }\n }\n\n if (expectation.items && expectation.items.length > 0) {\n if (expectation.ordered) {\n assertOrderedItems(request.input, expectation.items, prefix);\n } else {\n assertUnorderedItems(request.input, expectation.items, prefix);\n }\n }\n}\n\nexport class MockAdapter extends AdapterBase {\n readonly kind = \"mock\" as const;\n readonly nativeStreaming = false;\n\n private readonly handler: MockHandler;\n private readonly providerMetadata?: Record<string, unknown>;\n\n private cursor = 0;\n private previousReplay: ReplayItem[] = [];\n private pendingToolCalls: ToolCallItem[] = [];\n private history: MockHistoryRecord[] = [];\n private activeStream = false;\n\n constructor(options: MockAdapterOptions) {\n super();\n this.handler = options.handler;\n this.providerMetadata = options.providerMetadata;\n }\n\n protected async buildRequest(request: NormalizedRequest): Promise<MockProviderRequest> {\n const turnIndex = this.cursor;\n const context = this.buildHandlerContext(turnIndex);\n const remainingPendingToolCalls = consumePendingToolCalls(this.pendingToolCalls, request.input);\n const handlerResult = this.handler(request, context);\n\n this.cursor += 1;\n\n return {\n request,\n handlerResult,\n turnIndex,\n remainingPendingToolCalls,\n };\n }\n\n protected async *runStream(\n providerRequest: unknown,\n factory: EventFactory,\n request: NormalizedRequest,\n ): AsyncIterable<AIStreamEvent> {\n if (this.activeStream) {\n throw new AIRequestError(\"MockAdapter does not support concurrent streams\", \"MOCK_CONCURRENT_STREAM\");\n }\n\n this.activeStream = true;\n\n try {\n const mockRequest = providerRequest as MockProviderRequest;\n const output: OutputItem[] = [];\n let stepCount = 0;\n\n for await (const step of mockRequest.handlerResult) {\n stepCount += 1;\n\n switch (step.type) {\n case \"warning\":\n yield factory.responseWarning(step.message, step.code);\n break;\n case \"auxiliary\":\n yield factory.responseAuxiliary({\n usage: step.usage,\n billing: step.billing,\n auxiliary: step.auxiliary,\n });\n break;\n case \"message\": {\n const item = createMessageFromStep(step, request, mockRequest.turnIndex, stepCount - 1);\n yield* emitMessage(factory, item, resolveStepStreamOptions(undefined, step.stream, \"message\"));\n output.push(item);\n break;\n }\n case \"reasoning\": {\n const item = createReasoningFromStep(step, request, mockRequest.turnIndex, stepCount - 1);\n yield* emitReasoning(factory, item, resolveStepStreamOptions(undefined, step.stream, \"reasoning\"));\n output.push(item);\n break;\n }\n case \"tool_call\": {\n const item = createToolCallFromStep(step);\n yield* emitToolCall(\n factory,\n item,\n step.streamArguments ?? true,\n resolveStepStreamOptions(undefined, step.stream, \"tool_call\"),\n );\n output.push(item);\n break;\n }\n case \"output\": {\n assertSupportedOutputItem(step.item);\n const item = attachSyntheticId(step.item, request, mockRequest.turnIndex, stepCount - 1);\n yield* emitOutputItem(factory, item, resolveStepStreamOptions(undefined, step.stream, \"output\"));\n output.push(item);\n break;\n }\n case \"complete\": {\n const response = this.finalizeTurn(request, factory, mockRequest, output, step, stepCount);\n yield factory.responseCompleted(response);\n return;\n }\n case \"error\": {\n yield factory.responseWarning(step.message, step.code);\n const response = this.finalizeTurn(\n request,\n factory,\n mockRequest,\n output,\n {\n type: \"complete\",\n stopReason: step.stopReason ?? \"error\",\n providerMetadata: step.providerMetadata,\n },\n stepCount,\n );\n yield factory.responseCompleted(response);\n return;\n }\n case \"interrupt\":\n this.pendingToolCalls = mockRequest.remainingPendingToolCalls;\n return;\n case \"throw\":\n throw typeof step.error === \"string\" ? new Error(step.error) : step.error;\n }\n }\n\n const response = this.finalizeTurn(\n request,\n factory,\n mockRequest,\n output,\n {\n type: \"complete\",\n },\n stepCount,\n );\n yield factory.responseCompleted(response);\n } finally {\n this.activeStream = false;\n }\n }\n\n private finalizeTurn(\n request: NormalizedRequest,\n factory: EventFactory,\n mockRequest: MockProviderRequest,\n output: OutputItem[],\n completion: MockCompleteStep,\n stepCount: number,\n ) {\n const replay = completion.replay ?? replayFromOutput(output);\n const toolCalls = output.filter((item): item is ToolCallItem => item.type === \"tool_call\");\n\n this.previousReplay = replay;\n this.pendingToolCalls = [...mockRequest.remainingPendingToolCalls, ...toolCalls];\n this.history.push({\n turnIndex: mockRequest.turnIndex,\n requestId: request.requestId,\n replay,\n toolCalls,\n });\n\n return this.buildResponse(\n request,\n {\n output,\n replay,\n stopReason: completion.stopReason ?? resolveStopReason(output),\n usage: completion.usage,\n billing: completion.billing,\n auxiliary: completion.auxiliary,\n providerMetadata: {\n turnIndex: mockRequest.turnIndex,\n stepCount,\n pendingToolCallIds: this.pendingToolCalls.map((item) => item.id),\n historyLength: this.history.length,\n ...this.providerMetadata,\n ...completion.providerMetadata,\n },\n warnings: completion.warnings,\n metadataSources: [\"mock\"],\n rawResponseId: completion.rawResponseId,\n },\n factory,\n );\n }\n\n private buildHandlerContext(turnIndex: number): MockHandlerContext {\n return {\n turnIndex,\n previousReplay: this.previousReplay.map(cloneItem),\n pendingToolCalls: this.pendingToolCalls.map(cloneItem),\n history: this.history.map((record) => ({\n ...record,\n replay: record.replay.map(cloneItem),\n toolCalls: record.toolCalls.map(cloneItem),\n })),\n };\n }\n}\n\nexport function withMockStreaming(handler: MockStaticHandler, options: MockTextStreamOptions): MockHandler {\n const defaults = resolveMockTextStreamOptions(options, \"mock stream wrapper\");\n if (!defaults) {\n throw new AIRequestError(\"mock stream wrapper requires streaming options\", \"MOCK_STREAM_CONFIG_INVALID\");\n }\n\n return async function* streamWrappedHandler(\n request: NormalizedRequest,\n context: MockHandlerContext,\n ): AsyncIterable<MockStep> {\n const source = await handler(request, context);\n\n for await (const step of source) {\n yield applyDefaultStreaming(step, defaults);\n }\n };\n}\n\nfunction applyDefaultStreaming(step: MockStep, defaults: ResolvedMockTextStreamOptions): MockStep {\n switch (step.type) {\n case \"message\":\n case \"reasoning\":\n case \"tool_call\":\n case \"output\":\n if (step.stream !== undefined) {\n return step;\n }\n return {\n ...step,\n stream: {\n charsPerSecond: defaults.charsPerSecond,\n chunkSize: defaults.chunkSize,\n initialDelayMs: defaults.initialDelayMs,\n },\n };\n default:\n return step;\n }\n}\n\nfunction createMessageFromStep(\n step: MockMessageStep,\n request: NormalizedRequest,\n turnIndex: number,\n stepIndex: number,\n): MessageItem {\n return {\n ...messageItem(normalizeBlocks(step.content), {\n id: step.id ?? `mock-msg-${request.requestId}-${turnIndex}-${stepIndex}`,\n }),\n role: \"assistant\",\n };\n}\n\nfunction createReasoningFromStep(\n step: MockReasoningStep,\n request: NormalizedRequest,\n turnIndex: number,\n stepIndex: number,\n): Extract<OutputItem, { type: \"reasoning\" }> {\n return reasoningItem(\n normalizeBlocks(step.content),\n step.visibility ?? \"full\",\n step.id ?? `mock-reason-${request.requestId}-${turnIndex}-${stepIndex}`,\n );\n}\n\nfunction createToolCallFromStep(step: MockToolCallStep): ToolCallItem {\n return {\n type: \"tool_call\",\n id: step.id,\n name: step.name,\n argumentsText: step.argumentsText,\n argumentsJson: step.argumentsJson,\n };\n}\n\nfunction normalizeBlocks(content: string | ContentBlock[]): ContentBlock[] {\n return typeof content === \"string\" ? [textBlock(content)] : content;\n}\n\nfunction assertSupportedOutputItem(item: OutputItem): void {\n if (item.type === \"opaque\") {\n throw new AIRequestError(\n \"MockAdapter does not stream opaque output items; use complete.replay if needed\",\n \"MOCK_OPAQUE_OUTPUT\",\n );\n }\n}\n\nfunction attachSyntheticId(\n item: Extract<OutputItem, { type: \"message\" | \"reasoning\" | \"tool_call\" }>,\n request: NormalizedRequest,\n turnIndex: number,\n stepIndex: number,\n): Extract<OutputItem, { type: \"message\" | \"reasoning\" | \"tool_call\" }> {\n if (item.type === \"message\") {\n return {\n ...item,\n id: item.id ?? `mock-msg-${request.requestId}-${turnIndex}-${stepIndex}`,\n role: \"assistant\",\n };\n }\n\n if (item.type === \"reasoning\") {\n return {\n ...item,\n id: item.id ?? `mock-reason-${request.requestId}-${turnIndex}-${stepIndex}`,\n };\n }\n\n return item;\n}\n\nasync function* emitOutputItem(\n factory: EventFactory,\n item: Extract<OutputItem, { type: \"message\" | \"reasoning\" | \"tool_call\" }>,\n stream?: ResolvedMockTextStreamOptions,\n): AsyncIterable<AIStreamEvent> {\n if (item.type === \"message\") {\n yield* emitMessage(factory, item, stream);\n return;\n }\n\n if (item.type === \"reasoning\") {\n yield* emitReasoning(factory, item, stream);\n return;\n }\n\n yield* emitToolCall(factory, item, true, stream);\n}\n\nasync function* emitMessage(\n factory: EventFactory,\n item: MessageItem,\n stream?: ResolvedMockTextStreamOptions,\n): AsyncIterable<AIStreamEvent> {\n if (!item.id) {\n throw new AIRequestError(\"Mock message output requires an id after normalization\", \"MOCK_MESSAGE_ID_MISSING\");\n }\n\n yield factory.messageStarted(item.id);\n\n let chunkIndex = 0;\n for (const block of item.content) {\n if (block.type === \"text\") {\n for (const chunk of chunkText(block.text, stream)) {\n await delayForChunk(stream, chunkIndex, chunk.length);\n yield factory.messageDelta(item.id, chunk);\n chunkIndex += 1;\n }\n }\n }\n\n yield factory.messageCompleted(item);\n}\n\nasync function* emitReasoning(\n factory: EventFactory,\n item: Extract<OutputItem, { type: \"reasoning\" }>,\n stream?: ResolvedMockTextStreamOptions,\n): AsyncIterable<AIStreamEvent> {\n if (!item.id) {\n throw new AIRequestError(\"Mock reasoning output requires an id after normalization\", \"MOCK_REASONING_ID_MISSING\");\n }\n\n yield factory.reasoningStarted(item.id, item.visibility);\n\n let chunkIndex = 0;\n for (const block of item.content) {\n if (block.type !== \"text\") {\n yield factory.reasoningDelta(item.id, block);\n continue;\n }\n\n for (const chunk of chunkText(block.text, stream)) {\n await delayForChunk(stream, chunkIndex, chunk.length);\n yield factory.reasoningDelta(item.id, textBlock(chunk));\n chunkIndex += 1;\n }\n }\n\n yield factory.reasoningCompleted(item);\n}\n\nasync function* emitToolCall(\n factory: EventFactory,\n item: ToolCallItem,\n streamArguments: boolean,\n stream?: ResolvedMockTextStreamOptions,\n): AsyncIterable<AIStreamEvent> {\n yield factory.toolCallStarted(item.id, item.name);\n\n if (streamArguments && item.argumentsText) {\n let chunkIndex = 0;\n for (const chunk of chunkText(item.argumentsText, stream)) {\n await delayForChunk(stream, chunkIndex, chunk.length);\n yield factory.toolCallDelta(item.id, { argumentsText: chunk });\n chunkIndex += 1;\n }\n }\n\n yield factory.toolCallCompleted(item);\n}\n\nfunction resolveStepStreamOptions(\n defaults: ResolvedMockTextStreamOptions | undefined,\n override: MockTextStreamOptions | false | undefined,\n label: string,\n): ResolvedMockTextStreamOptions | undefined {\n if (override === false) {\n return undefined;\n }\n\n return resolveMockTextStreamOptions(override, `${label} stream`, defaults);\n}\n\nfunction resolveMockTextStreamOptions(\n options: MockTextStreamOptions | undefined,\n label: string,\n defaults?: ResolvedMockTextStreamOptions,\n): ResolvedMockTextStreamOptions | undefined {\n if (options === undefined) {\n return defaults;\n }\n\n const chunkSize = options.chunkSize ?? defaults?.chunkSize ?? 1;\n const initialDelayMs = options.initialDelayMs ?? defaults?.initialDelayMs ?? 0;\n const charsPerSecond = options.charsPerSecond ?? defaults?.charsPerSecond;\n\n if (!Number.isInteger(chunkSize) || chunkSize < 1) {\n throw new AIRequestError(`${label}: chunkSize must be a positive integer`, \"MOCK_STREAM_CONFIG_INVALID\");\n }\n\n if (!Number.isFinite(initialDelayMs) || initialDelayMs < 0) {\n throw new AIRequestError(`${label}: initialDelayMs must be a non-negative number`, \"MOCK_STREAM_CONFIG_INVALID\");\n }\n\n if (charsPerSecond !== undefined && (!Number.isFinite(charsPerSecond) || charsPerSecond <= 0)) {\n throw new AIRequestError(`${label}: charsPerSecond must be a positive number`, \"MOCK_STREAM_CONFIG_INVALID\");\n }\n\n return {\n chunkSize,\n initialDelayMs,\n charsPerSecond,\n };\n}\n\nfunction chunkText(text: string, stream?: ResolvedMockTextStreamOptions): string[] {\n if (!text) {\n return [];\n }\n\n if (!stream) {\n return [text];\n }\n\n const chars = Array.from(text);\n const chunks: string[] = [];\n\n for (let index = 0; index < chars.length; index += stream.chunkSize) {\n chunks.push(chars.slice(index, index + stream.chunkSize).join(\"\"));\n }\n\n return chunks;\n}\n\nasync function delayForChunk(\n stream: ResolvedMockTextStreamOptions | undefined,\n chunkIndex: number,\n chunkLength: number,\n): Promise<void> {\n if (!stream) {\n return;\n }\n\n if (chunkIndex === 0 && stream.initialDelayMs > 0) {\n await sleep(stream.initialDelayMs);\n return;\n }\n\n if (chunkIndex > 0 && stream.charsPerSecond !== undefined) {\n await sleep((chunkLength / stream.charsPerSecond) * 1000);\n }\n}\n\nasync function sleep(ms: number): Promise<void> {\n if (ms <= 0) {\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction resolveStopReason(output: OutputItem[]): StopReason {\n return output.some((item) => item.type === \"tool_call\") ? \"tool_call\" : \"end_turn\";\n}\n\nfunction consumePendingToolCalls(pending: readonly ToolCallItem[], input: readonly InputItem[]): ToolCallItem[] {\n const fulfilledIds = new Set(\n input.filter((item): item is ToolResultItem => item.type === \"tool_result\").map((item) => item.callId),\n );\n\n return pending.filter((item) => !fulfilledIds.has(item.id)).map(cloneItem);\n}\n\nfunction assertReplayIncluded(input: readonly InputItem[], replay: readonly ReplayItem[], prefix: string): void {\n const fingerprints = input.map(fingerprintItem);\n let cursor = 0;\n\n for (const replayItem of replay) {\n const target = fingerprintItem(replayItem);\n const foundIndex = fingerprints.indexOf(target, cursor);\n if (foundIndex === -1) {\n throw new AIRequestError(\n `${prefix}: previous replay item was not carried into the next request`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n cursor = foundIndex + 1;\n }\n}\n\nfunction assertOrderedItems(\n input: readonly InputItem[],\n expectations: readonly MockInputExpectation[],\n prefix: string,\n): void {\n let cursor = 0;\n\n for (const expected of expectations) {\n let matched = false;\n while (cursor < input.length) {\n const item = input[cursor];\n if (item !== undefined && matchesItemExpectation(item, expected)) {\n matched = true;\n cursor += 1;\n break;\n }\n cursor += 1;\n }\n\n if (!matched) {\n throw new AIRequestError(\n `${prefix}: missing ordered input item ${describeExpectation(expected)}`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n }\n}\n\nfunction assertUnorderedItems(\n input: readonly InputItem[],\n expectations: readonly MockInputExpectation[],\n prefix: string,\n): void {\n for (const expected of expectations) {\n const matched = input.some((item) => matchesItemExpectation(item, expected));\n if (!matched) {\n throw new AIRequestError(\n `${prefix}: missing input item ${describeExpectation(expected)}`,\n \"MOCK_EXPECTATION_FAILED\",\n );\n }\n }\n}\n\nfunction matchesItemExpectation(item: InputItem, expected: MockInputExpectation): boolean {\n if (item.type !== expected.type) {\n return false;\n }\n\n if (expected.id !== undefined && \"id\" in item && item.id !== expected.id) {\n return false;\n }\n\n switch (item.type) {\n case \"message\":\n return (\n (expected.role === undefined || item.role === expected.role) && matchesText(item.content, expected.textIncludes)\n );\n case \"reasoning\":\n return (\n (expected.visibility === undefined || item.visibility === expected.visibility) &&\n matchesText(item.content, expected.textIncludes)\n );\n case \"tool_call\":\n return (\n (expected.name === undefined || item.name === expected.name) &&\n (expected.textIncludes === undefined || item.argumentsText.includes(expected.textIncludes))\n );\n case \"tool_result\":\n return (\n (expected.toolName === undefined || item.toolName === expected.toolName) &&\n (expected.callId === undefined || item.callId === expected.callId) &&\n (expected.outcome === undefined || item.outcome === expected.outcome) &&\n matchesText(item.content, expected.textIncludes)\n );\n case \"opaque\":\n return (\n (expected.source === undefined || item.source === expected.source) &&\n (expected.purpose === undefined || item.purpose === expected.purpose)\n );\n }\n}\n\nfunction matchesText(blocks: readonly ContentBlock[], textIncludes: string | undefined): boolean {\n if (textIncludes === undefined) {\n return true;\n }\n\n return blocks.some((block) => {\n if (block.type === \"text\") return block.text.includes(textIncludes);\n if (block.type === \"json\") return JSON.stringify(block.json).includes(textIncludes);\n return false;\n });\n}\n\nfunction fingerprintItem(item: InputItem): string {\n return JSON.stringify(item);\n}\n\nfunction describeExpectation(expectation: MockInputExpectation): string {\n const parts = [`type=${expectation.type}`];\n if (expectation.role) parts.push(`role=${expectation.role}`);\n if (expectation.name) parts.push(`name=${expectation.name}`);\n if (expectation.toolName) parts.push(`toolName=${expectation.toolName}`);\n if (expectation.callId) parts.push(`callId=${expectation.callId}`);\n if (expectation.textIncludes) parts.push(`textIncludes=${JSON.stringify(expectation.textIncludes)}`);\n return `{ ${parts.join(\", \")} }`;\n}\n\nfunction cloneItem<T>(item: T): T {\n return structuredClone(item);\n}\n","/**\n * 模拟流式 (Synthetic Streaming)\n *\n * 将一组已解析的 canonical OutputItem 包装为规范事件流。\n * 适用于非原生流式后端:adapter 拿到完整响应后,调用此函数\n * 即可产出一致的事件序列,无需自己逐事件组装。\n *\n * 约束:\n * - 每个 item 只发一块完整 delta(不模拟逐 token)\n * - 保持 item 边界\n * - 保持后端原始顺序\n * - 不发明 reasoning\n * - 不改写工具参数\n */\n\nimport { createEventFactory } from \"../core/event-factory.js\";\nimport { replayFromOutput, extractText } from \"./mapping.js\";\n\nimport type {\n OutputItem,\n ReplayItem,\n StopReason,\n Usage,\n BillingInfo,\n AIStreamEvent,\n AIResponse,\n MessageItem,\n ReasoningItem,\n ToolCallItem,\n} from \"../types/index.js\";\n\n// ── 输入参数 ──────────────────────────────────────────────────\n\nexport type SyntheticStreamOptions = {\n model: string;\n responseId: string;\n backend: {\n kind: \"chat-completions\" | \"messages\" | \"responses\" | \"mock\";\n /** syntheticStream 强制设为 true */\n };\n output: OutputItem[];\n replay?: ReplayItem[];\n stopReason?: StopReason;\n usage?: Usage;\n billing?: BillingInfo;\n providerMetadata?: Record<string, unknown>;\n rawResponseId?: string;\n warnings?: string[];\n};\n\n// ── Synthetic Stream ──────────────────────────────────────────\n\n/**\n * 将已解析的 output items 包装为完整规范事件流。\n *\n * 用法示例(在 adapter 的 runStream 中):\n * ```ts\n * const result = parseNonStreamingResponse(data);\n * yield* syntheticStream({\n * model: request.model,\n * responseId: request.requestId,\n * backend: { kind: \"chat-completions\" },\n * output: result.output,\n * stopReason: result.stopReason,\n * usage: result.usage,\n * });\n * ```\n */\nexport async function* syntheticStream(options: SyntheticStreamOptions): AsyncIterable<AIStreamEvent> {\n const {\n model,\n responseId,\n backend,\n output,\n replay,\n stopReason,\n usage,\n billing,\n providerMetadata,\n rawResponseId,\n warnings: extraWarnings,\n } = options;\n\n const factory = createEventFactory({\n responseId,\n backend: { kind: backend.kind, isSynthetic: true },\n });\n\n // 1. 响应开始\n yield factory.responseStarted(model);\n\n // 2. item 级事件 — 每个 item 只发一块完整 delta\n for (const item of output) {\n yield* emitItemEvents(item, factory);\n }\n\n // 3. auxiliary 事件(如有)\n if (usage || billing) {\n yield factory.responseAuxiliary({ usage, billing });\n }\n\n // 4. 构建最终 response\n const finalReplay = replay ?? replayFromOutput(output);\n\n // 收集警告\n const allWarnings: string[] = [];\n allWarnings.push(\"Response is synthetically streamed; delta granularity may differ from native streaming\");\n if (extraWarnings) allWarnings.push(...extraWarnings);\n\n const response: AIResponse = {\n id: responseId,\n output,\n replay: finalReplay,\n text: extractText(output),\n toolCalls: output.filter((item): item is ToolCallItem => item.type === \"tool_call\"),\n stopReason,\n usage,\n billing,\n auxiliary: providerMetadata ? { providerMetadata } : undefined,\n warnings: allWarnings.length > 0 ? allWarnings : undefined,\n backend: {\n requestId: responseId,\n rawResponseId,\n adapter: backend.kind,\n isSyntheticStream: true,\n },\n };\n\n yield factory.responseCompleted(response);\n}\n\n// ── Item 事件发射 ─────────────────────────────────────────────\n\nfunction* emitItemEvents(item: OutputItem, factory: ReturnType<typeof createEventFactory>): Generator<AIStreamEvent> {\n switch (item.type) {\n case \"message\":\n yield* emitMessageEvents(item, factory);\n break;\n case \"reasoning\":\n yield* emitReasoningEvents(item, factory);\n break;\n case \"tool_call\":\n yield* emitToolCallEvents(item, factory);\n break;\n case \"opaque\":\n // Opaque items in output have no streaming events\n break;\n }\n}\n\nfunction* emitMessageEvents(\n item: MessageItem,\n factory: ReturnType<typeof createEventFactory>,\n): Generator<AIStreamEvent> {\n const id = item.id ?? `syn-msg-${crypto.randomUUID()}`;\n yield factory.messageStarted(id);\n\n for (const block of item.content) {\n if (block.type === \"text\") {\n yield factory.messageDelta(id, block.text);\n }\n }\n\n yield factory.messageCompleted(item);\n}\n\nfunction* emitReasoningEvents(\n item: ReasoningItem,\n factory: ReturnType<typeof createEventFactory>,\n): Generator<AIStreamEvent> {\n const id = item.id ?? `syn-reason-${crypto.randomUUID()}`;\n yield factory.reasoningStarted(id, item.visibility);\n\n for (const block of item.content) {\n if (block.type === \"text\") {\n yield factory.reasoningDelta(id, block);\n }\n }\n\n yield factory.reasoningCompleted(item);\n}\n\nfunction* emitToolCallEvents(\n item: ToolCallItem,\n factory: ReturnType<typeof createEventFactory>,\n): Generator<AIStreamEvent> {\n yield factory.toolCallStarted(item.id, item.name);\n\n if (item.argumentsText) {\n yield factory.toolCallDelta(item.id, { argumentsText: item.argumentsText });\n }\n\n yield factory.toolCallCompleted(item);\n}\n\n// ── Helper ────────────────────────────────────────────────────\n"],"mappings":"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"}