@fleetagent/pi-ai 0.1.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +29 -24
  3. package/dist/cli.js.map +1 -1
  4. package/dist/env-api-keys.d.ts.map +1 -1
  5. package/dist/env-api-keys.js +1 -1
  6. package/dist/env-api-keys.js.map +1 -1
  7. package/dist/image-models.generated.d.ts +225 -0
  8. package/dist/image-models.generated.d.ts.map +1 -1
  9. package/dist/image-models.generated.js +227 -2
  10. package/dist/image-models.generated.js.map +1 -1
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/models.d.ts +37 -2
  15. package/dist/models.d.ts.map +1 -1
  16. package/dist/models.generated.d.ts +6120 -2593
  17. package/dist/models.generated.d.ts.map +1 -1
  18. package/dist/models.generated.js +5347 -2110
  19. package/dist/models.generated.js.map +1 -1
  20. package/dist/models.js +259 -9
  21. package/dist/models.js.map +1 -1
  22. package/dist/oauth.d.ts +6 -1
  23. package/dist/oauth.d.ts.map +1 -1
  24. package/dist/oauth.js +4 -1
  25. package/dist/oauth.js.map +1 -1
  26. package/dist/providers/amazon-bedrock.d.ts +5 -4
  27. package/dist/providers/amazon-bedrock.d.ts.map +1 -1
  28. package/dist/providers/amazon-bedrock.js +303 -330
  29. package/dist/providers/amazon-bedrock.js.map +1 -1
  30. package/dist/providers/anthropic.d.ts +5 -4
  31. package/dist/providers/anthropic.d.ts.map +1 -1
  32. package/dist/providers/anthropic.js +492 -499
  33. package/dist/providers/anthropic.js.map +1 -1
  34. package/dist/providers/azure-openai-responses.d.ts +4 -2
  35. package/dist/providers/azure-openai-responses.d.ts.map +1 -1
  36. package/dist/providers/azure-openai-responses.js +52 -35
  37. package/dist/providers/azure-openai-responses.js.map +1 -1
  38. package/dist/providers/faux.d.ts +19 -22
  39. package/dist/providers/faux.d.ts.map +1 -1
  40. package/dist/providers/faux.js +106 -70
  41. package/dist/providers/faux.js.map +1 -1
  42. package/dist/providers/github-copilot-headers.d.ts +7 -4
  43. package/dist/providers/github-copilot-headers.d.ts.map +1 -1
  44. package/dist/providers/github-copilot-headers.js.map +1 -1
  45. package/dist/providers/google-shared.d.ts +24 -5
  46. package/dist/providers/google-shared.d.ts.map +1 -1
  47. package/dist/providers/google-shared.js +139 -140
  48. package/dist/providers/google-shared.js.map +1 -1
  49. package/dist/providers/google-vertex.d.ts +3 -7
  50. package/dist/providers/google-vertex.d.ts.map +1 -1
  51. package/dist/providers/google-vertex.js +216 -219
  52. package/dist/providers/google-vertex.js.map +1 -1
  53. package/dist/providers/google.d.ts +4 -7
  54. package/dist/providers/google.d.ts.map +1 -1
  55. package/dist/providers/google.js +214 -218
  56. package/dist/providers/google.js.map +1 -1
  57. package/dist/providers/images/openrouter.d.ts.map +1 -1
  58. package/dist/providers/images/openrouter.js +37 -27
  59. package/dist/providers/images/openrouter.js.map +1 -1
  60. package/dist/providers/mistral.d.ts +7 -6
  61. package/dist/providers/mistral.d.ts.map +1 -1
  62. package/dist/providers/mistral.js +287 -265
  63. package/dist/providers/mistral.js.map +1 -1
  64. package/dist/providers/openai-codex-responses.d.ts +8 -5
  65. package/dist/providers/openai-codex-responses.d.ts.map +1 -1
  66. package/dist/providers/openai-codex-responses.js +493 -391
  67. package/dist/providers/openai-codex-responses.js.map +1 -1
  68. package/dist/providers/openai-completions.d.ts +7 -10
  69. package/dist/providers/openai-completions.d.ts.map +1 -1
  70. package/dist/providers/openai-completions.js +670 -664
  71. package/dist/providers/openai-completions.js.map +1 -1
  72. package/dist/providers/openai-responses-shared.d.ts +5 -4
  73. package/dist/providers/openai-responses-shared.d.ts.map +1 -1
  74. package/dist/providers/openai-responses-shared.js +390 -360
  75. package/dist/providers/openai-responses-shared.js.map +1 -1
  76. package/dist/providers/openai-responses.d.ts +5 -5
  77. package/dist/providers/openai-responses.d.ts.map +1 -1
  78. package/dist/providers/openai-responses.js +134 -109
  79. package/dist/providers/openai-responses.js.map +1 -1
  80. package/dist/providers/simple-options.d.ts +4 -2
  81. package/dist/providers/simple-options.d.ts.map +1 -1
  82. package/dist/providers/simple-options.js.map +1 -1
  83. package/dist/providers/transform-messages.d.ts.map +1 -1
  84. package/dist/providers/transform-messages.js +112 -137
  85. package/dist/providers/transform-messages.js.map +1 -1
  86. package/dist/stream.d.ts +0 -1
  87. package/dist/stream.d.ts.map +1 -1
  88. package/dist/stream.js +0 -1
  89. package/dist/stream.js.map +1 -1
  90. package/dist/types.d.ts +91 -63
  91. package/dist/types.d.ts.map +1 -1
  92. package/dist/types.js.map +1 -1
  93. package/dist/utils/error-body.d.ts.map +1 -1
  94. package/dist/utils/error-body.js +15 -4
  95. package/dist/utils/error-body.js.map +1 -1
  96. package/dist/utils/estimate.d.ts +4 -0
  97. package/dist/utils/estimate.d.ts.map +1 -1
  98. package/dist/utils/estimate.js +3 -1
  99. package/dist/utils/estimate.js.map +1 -1
  100. package/dist/utils/headers.d.ts +3 -0
  101. package/dist/utils/headers.d.ts.map +1 -1
  102. package/dist/utils/headers.js +21 -0
  103. package/dist/utils/headers.js.map +1 -1
  104. package/dist/utils/json-parse.d.ts.map +1 -1
  105. package/dist/utils/json-parse.js +17 -19
  106. package/dist/utils/json-parse.js.map +1 -1
  107. package/dist/utils/oauth/anthropic.d.ts +4 -11
  108. package/dist/utils/oauth/anthropic.d.ts.map +1 -1
  109. package/dist/utils/oauth/anthropic.js +100 -117
  110. package/dist/utils/oauth/anthropic.js.map +1 -1
  111. package/dist/utils/oauth/device-code.d.ts.map +1 -1
  112. package/dist/utils/oauth/device-code.js +51 -38
  113. package/dist/utils/oauth/device-code.js.map +1 -1
  114. package/dist/utils/oauth/github-copilot.d.ts +6 -9
  115. package/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  116. package/dist/utils/oauth/github-copilot.js +47 -42
  117. package/dist/utils/oauth/github-copilot.js.map +1 -1
  118. package/dist/utils/oauth/index.d.ts +8 -17
  119. package/dist/utils/oauth/index.d.ts.map +1 -1
  120. package/dist/utils/oauth/index.js +27 -23
  121. package/dist/utils/oauth/index.js.map +1 -1
  122. package/dist/utils/oauth/oauth-page.d.ts.map +1 -1
  123. package/dist/utils/oauth/oauth-page.js.map +1 -1
  124. package/dist/utils/oauth/openai-codex.d.ts +7 -12
  125. package/dist/utils/oauth/openai-codex.d.ts.map +1 -1
  126. package/dist/utils/oauth/openai-codex.js +72 -89
  127. package/dist/utils/oauth/openai-codex.js.map +1 -1
  128. package/dist/utils/oauth/pkce.d.ts +5 -4
  129. package/dist/utils/oauth/pkce.d.ts.map +1 -1
  130. package/dist/utils/oauth/pkce.js.map +1 -1
  131. package/dist/utils/oauth/types.d.ts +7 -2
  132. package/dist/utils/oauth/types.d.ts.map +1 -1
  133. package/dist/utils/oauth/types.js.map +1 -1
  134. package/dist/utils/provider-retry.d.ts +16 -0
  135. package/dist/utils/provider-retry.d.ts.map +1 -0
  136. package/dist/utils/provider-retry.js +94 -0
  137. package/dist/utils/provider-retry.js.map +1 -0
  138. package/dist/utils/retry.d.ts +14 -0
  139. package/dist/utils/retry.d.ts.map +1 -1
  140. package/dist/utils/retry.js +84 -0
  141. package/dist/utils/retry.js.map +1 -1
  142. package/dist/utils/typebox-helpers.d.ts +5 -4
  143. package/dist/utils/typebox-helpers.d.ts.map +1 -1
  144. package/dist/utils/typebox-helpers.js.map +1 -1
  145. package/dist/utils/validation.d.ts.map +1 -1
  146. package/dist/utils/validation.js +102 -99
  147. package/dist/utils/validation.js.map +1 -1
  148. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/providers/openai-responses.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { getEnvApiKey } from \"../env-api-keys.ts\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { isCloudflareProvider, resolveCloudflareBaseUrl } from \"./cloudflare.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16: https://github.com/earendil-works/pi/issues/6265\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (typeof process !== \"undefined\" && process.env.PI_CACHE_RETENTION === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsendSessionIdHeader: model.compat?.sendSessionIdHeader ?? true,\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention ? \"24h\" : undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\treturn formatProviderError(normalizeProviderError(error), \"OpenAI API error\");\n}\n\n// OpenAI Responses-specific options\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n}\n\n/**\n * Generate function for OpenAI Responses API\n */\nexport const streamOpenAIResponses: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t// Start async processing\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: model.api as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\t// Create OpenAI client\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider) || \"\";\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, cacheSessionId);\n\t\t\tlet params = buildParams(model, context, options);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as ResponseCreateParamsStreaming;\n\t\t\t}\n\t\t\tconst requestOptions = {\n\t\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\t\tmaxRetries: options?.maxRetries ?? 0,\n\t\t\t};\n\t\t\tconst { data: openaiStream, response } = await client.responses.create(params, requestOptions).withResponse();\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\t\t\tserviceTier: options?.serviceTier,\n\t\t\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\n\t\t\t});\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) {\n\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t// partialJson is only a streaming scratch buffer; never persist it.\n\t\t\t\tdelete (block as { partialJson?: string }).partialJson;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatOpenAIResponsesError(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nexport const streamSimpleOpenAIResponses: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst base = buildBaseOptions(model, context, options, apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn streamOpenAIResponses(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey?: string,\n\toptionsHeaders?: Record<string, string>,\n\tsessionId?: string,\n) {\n\tif (!apiKey) {\n\t\tif (!process.env.OPENAI_API_KEY) {\n\t\t\tthrow new Error(\n\t\t\t\t\"OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.\",\n\t\t\t);\n\t\t}\n\t\tapiKey = process.env.OPENAI_API_KEY;\n\t}\n\n\tconst compat = getCompat(model);\n\tconst headers = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tconst copilotHeaders = buildCopilotDynamicHeaders({\n\t\t\tmessages: context.messages,\n\t\t\thasImages,\n\t\t});\n\t\tObject.assign(headers, copilotHeaders);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sendSessionIdHeader) {\n\t\t\theaders.session_id = sessionId;\n\t\t}\n\t\theaders[\"x-client-request-id\"] = sessionId;\n\t}\n\n\t// Merge options headers last so they can override defaults\n\tif (optionsHeaders) {\n\t\tObject.assign(headers, optionsHeaders);\n\t}\n\n\tconst defaultHeaders =\n\t\tmodel.provider === \"cloudflare-ai-gateway\"\n\t\t\t? {\n\t\t\t\t\t...headers,\n\t\t\t\t\tAuthorization: headers.Authorization ?? null,\n\t\t\t\t\t\"cf-aig-authorization\": `Bearer ${apiKey}`,\n\t\t\t\t}\n\t\t\t: headers;\n\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: isCloudflareProvider(model.provider) ? resolveCloudflareBaseUrl(model) : model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders,\n\t});\n}\n\nfunction buildParams(model: Model<\"openai-responses\">, context: Context, options?: OpenAIResponsesOptions) {\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS);\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention);\n\tconst compat = getCompat(model);\n\tconst params: ResponseCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tstore: false,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (context.tools && context.tools.length > 0) {\n\t\tparams.tools = convertResponsesTools(context.tools);\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tconst effort = options?.reasoningEffort\n\t\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t\t: \"medium\";\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else if (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t};\n\t\t}\n\t}\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n"]}
1
+ {"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/providers/openai-responses.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming, ResponseStreamEvent } from \"openai/resources/responses/responses.js\";\nimport { getEnvApiKey } from \"../env-api-keys.ts\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderHeaders,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { retryProviderRequest } from \"../utils/provider-retry.ts\";\nimport { isCloudflareProvider, resolveCloudflareBaseUrl } from \"./cloudflare.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport {\n\tconvertResponsesMessages,\n\tconvertResponsesTools,\n\ttype OpenAIResponseServiceTier,\n\tprocessResponsesStream,\n} from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16: https://github.com/fleetagent/pi/issues/6265\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (typeof process !== \"undefined\" && process.env.PI_CACHE_RETENTION === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsReasoningEffort: model.compat?.supportsReasoningEffort ?? true,\n\t\tsendSessionIdHeader: model.compat?.sendSessionIdHeader ?? true,\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention ? \"24h\" : undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\treturn formatProviderError(normalizeProviderError(error), \"OpenAI API error\");\n}\n\n// OpenAI Responses-specific options\nexport type OpenAIResponsesReasoningEffort = \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\nexport type OpenAIResponsesReasoningSummary = \"auto\" | \"detailed\" | \"concise\";\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: OpenAIResponsesReasoningEffort;\n\treasoningSummary?: OpenAIResponsesReasoningSummary | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n}\n\ntype CompletedOpenAIResponsesMessage = AssistantMessage & { stopReason: \"stop\" | \"length\" | \"toolUse\" };\n\nfunction createOpenAIResponsesOutput(model: Model<\"openai-responses\">): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api as Api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotalTokens: 0,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t\tstopReason: \"pending\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nasync function startOpenAIResponsesRequest(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions: OpenAIResponsesOptions | undefined,\n): Promise<AsyncIterable<ResponseStreamEvent>> {\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider) || \"\";\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention);\n\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\tconst client = createClient(model, context, apiKey, options?.headers, cacheSessionId);\n\tlet params = buildParams(model, context, options);\n\tconst nextParams = await options?.onPayload?.(params, model);\n\tif (nextParams !== undefined) params = nextParams as ResponseCreateParamsStreaming;\n\tconst requestOptions = {\n\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\tmaxRetries: 0,\n\t};\n\tconst { data, response } = await retryProviderRequest(\n\t\t() => client.responses.create(params, requestOptions).withResponse(),\n\t\t{\n\t\t\tmaxRetries: options?.maxRetries,\n\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\t\tsignal: options?.signal,\n\t\t},\n\t);\n\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\treturn data;\n}\n\nfunction validateOpenAIResponsesCompletion(\n\toutput: AssistantMessage,\n\tsignal?: AbortSignal,\n): asserts output is CompletedOpenAIResponsesMessage {\n\tif (signal?.aborted) throw new Error(\"Request was aborted\");\n\tif (output.stopReason === \"pending\") throw new Error(\"OpenAI Responses stream ended without a stop reason\");\n\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") throw new Error(\"An unknown error occurred\");\n}\n\nasync function executeOpenAIResponsesStream(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions: OpenAIResponsesOptions | undefined,\n\tstream: AssistantMessageEventStream,\n\toutput: AssistantMessage,\n): Promise<void> {\n\tconst openaiStream = await startOpenAIResponsesRequest(model, context, options);\n\tstream.push({ type: \"start\", partial: output });\n\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\tserviceTier: options?.serviceTier,\n\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\n\t});\n\tvalidateOpenAIResponsesCompletion(output, options?.signal);\n\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\tstream.end();\n}\n\nfunction failOpenAIResponsesStream(\n\toutput: AssistantMessage,\n\tstream: AssistantMessageEventStream,\n\terror: unknown,\n\toptions: OpenAIResponsesOptions | undefined,\n): void {\n\tfor (const block of output.content) {\n\t\tdelete (block as { index?: number }).index;\n\t\t// partialJson is only a streaming scratch buffer; never persist it.\n\t\tdelete (block as { partialJson?: string }).partialJson;\n\t}\n\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\toutput.errorMessage = formatOpenAIResponsesError(error);\n\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\tstream.end();\n}\n\nasync function runOpenAIResponsesStream(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions: OpenAIResponsesOptions | undefined,\n\tstream: AssistantMessageEventStream,\n): Promise<void> {\n\tconst output = createOpenAIResponsesOutput(model);\n\ttry {\n\t\tawait executeOpenAIResponsesStream(model, context, options, stream, output);\n\t} catch (error) {\n\t\tfailOpenAIResponsesStream(output, stream, error, options);\n\t}\n}\n\n/** Generate a stream using the OpenAI Responses API. */\nexport const streamOpenAIResponses: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\tvoid runOpenAIResponsesStream(model, context, options, stream);\n\treturn stream;\n};\n\nexport const streamSimpleOpenAIResponses: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst base = buildBaseOptions(model, context, options, apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn streamOpenAIResponses(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction resolveOpenAIResponsesApiKey(apiKey?: string): string {\n\tif (apiKey) return apiKey;\n\tconst environmentApiKey = process.env.OPENAI_API_KEY;\n\tif (environmentApiKey) return environmentApiKey;\n\tthrow new Error(\"OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.\");\n}\n\nfunction buildOpenAIResponsesHeaders(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n\tsessionId?: string,\n): ProviderHeaders {\n\tconst compat = getCompat(model);\n\tconst headers: ProviderHeaders = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tObject.assign(\n\t\t\theaders,\n\t\t\tbuildCopilotDynamicHeaders({\n\t\t\t\tmessages: context.messages,\n\t\t\t\thasImages,\n\t\t\t}),\n\t\t);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sendSessionIdHeader) headers.session_id = sessionId;\n\t\theaders[\"x-client-request-id\"] = sessionId;\n\t}\n\n\tif (model.provider === \"cloudflare-ai-gateway\") {\n\t\tif (!(\"Authorization\" in headers)) headers.Authorization = null;\n\t\tif (!(\"cf-aig-authorization\" in headers)) headers[\"cf-aig-authorization\"] = `Bearer ${apiKey}`;\n\t}\n\n\t// Merge options headers last so they can override or suppress defaults.\n\tif (optionsHeaders) Object.assign(headers, optionsHeaders);\n\treturn headers;\n}\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey?: string,\n\toptionsHeaders?: ProviderHeaders,\n\tsessionId?: string,\n) {\n\tconst resolvedApiKey = resolveOpenAIResponsesApiKey(apiKey);\n\tconst headers = buildOpenAIResponsesHeaders(model, context, resolvedApiKey, optionsHeaders, sessionId);\n\treturn new OpenAI({\n\t\tapiKey: resolvedApiKey,\n\t\tbaseURL: isCloudflareProvider(model.provider) ? resolveCloudflareBaseUrl(model) : model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: headers,\n\t});\n}\n\nfunction applyOpenAIResponsesReasoning(\n\tparams: ResponseCreateParamsStreaming,\n\tmodel: Model<\"openai-responses\">,\n\tcompat: Required<OpenAIResponsesCompat>,\n\toptions?: OpenAIResponsesOptions,\n): void {\n\tif (!model.reasoning || !compat.supportsReasoningEffort) return;\n\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\tconst effort = options.reasoningEffort\n\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t: \"medium\";\n\t\tparams.reasoning = {\n\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\tsummary: options.reasoningSummary || \"auto\",\n\t\t};\n\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\treturn;\n\t}\n\tif (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\tparams.reasoning = {\n\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t};\n\t}\n}\n\nfunction buildParams(model: Model<\"openai-responses\">, context: Context, options?: OpenAIResponsesOptions) {\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS);\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention);\n\tconst compat = getCompat(model);\n\tconst params: ResponseCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tstore: false,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (context.tools && context.tools.length > 0) {\n\t\tparams.tools = convertResponsesTools(context.tools);\n\t}\n\tapplyOpenAIResponsesReasoning(params, model, compat, options);\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: OpenAIResponseServiceTier | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: OpenAIResponseServiceTier | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n"]}
@@ -2,8 +2,10 @@ import type { Api, Context, Model, SimpleStreamOptions, StreamOptions, ThinkingB
2
2
  export declare function clampMaxTokensToContext(model: Model<Api>, context: Context, maxTokens: number): number;
3
3
  export declare function buildBaseOptions(model: Model<Api>, context: Context, options?: SimpleStreamOptions, apiKey?: string): StreamOptions;
4
4
  export declare function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, "xhigh"> | undefined;
5
- export declare function adjustMaxTokensForThinking(baseMaxTokens: number | undefined, modelMaxTokens: number, reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): {
5
+ interface ThinkingTokenAllocation {
6
6
  maxTokens: number;
7
7
  thinkingBudget: number;
8
- };
8
+ }
9
+ export declare function adjustMaxTokensForThinking(baseMaxTokens: number | undefined, modelMaxTokens: number, reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): ThinkingTokenAllocation;
10
+ export {};
9
11
  //# sourceMappingURL=simple-options.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"simple-options.d.ts","sourceRoot":"","sources":["../../src/providers/simple-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,OAAO,EACP,KAAK,EACL,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,aAAa,EACb,MAAM,aAAa,CAAC;AAMrB,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAItG;AAED,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,EAC7B,MAAM,CAAC,EAAE,MAAM,GACb,aAAa,CAiBf;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,SAAS,CAE7G;AAED,wBAAgB,0BAA0B,CAEzC,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,aAAa,EAC7B,aAAa,CAAC,EAAE,eAAe,GAC7B;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAoB/C","sourcesContent":["import type {\n\tApi,\n\tContext,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamOptions,\n\tThinkingBudgets,\n\tThinkingLevel,\n} from \"../types.ts\";\nimport { estimateContextTokens } from \"../utils/estimate.ts\";\n\nconst CONTEXT_SAFETY_TOKENS = 4096;\nconst MIN_MAX_TOKENS = 1;\n\nexport function clampMaxTokensToContext(model: Model<Api>, context: Context, maxTokens: number): number {\n\tif (model.contextWindow <= 0) return Math.max(MIN_MAX_TOKENS, maxTokens);\n\tconst available = model.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;\n\treturn Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));\n}\n\nexport function buildBaseOptions(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n\tapiKey?: string,\n): StreamOptions {\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: clampMaxTokensToContext(model, context, options?.maxTokens ?? model.maxTokens),\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\ttransport: options?.transport,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t};\n}\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\"> | undefined {\n\treturn effort === \"xhigh\" ? \"high\" : effort;\n}\n\nexport function adjustMaxTokensForThinking(\n\t// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.\n\tbaseMaxTokens: number | undefined,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): { maxTokens: number; thinkingBudget: number } {\n\tconst defaultBudgets: ThinkingBudgets = {\n\t\tminimal: 1024,\n\t\tlow: 2048,\n\t\tmedium: 8192,\n\t\thigh: 16384,\n\t};\n\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\tconst minOutputTokens = 1024;\n\tconst level = clampReasoning(reasoningLevel)!;\n\tlet thinkingBudget = budgets[level]!;\n\tconst maxTokens =\n\t\tbaseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
1
+ {"version":3,"file":"simple-options.d.ts","sourceRoot":"","sources":["../../src/providers/simple-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,OAAO,EACP,KAAK,EACL,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,aAAa,EACb,MAAM,aAAa,CAAC;AAMrB,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAItG;AAED,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,EAC7B,MAAM,CAAC,EAAE,MAAM,GACb,aAAa,CAiBf;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,SAAS,CAE7G;AAED,UAAU,uBAAuB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,0BAA0B,CAEzC,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,aAAa,EAC7B,aAAa,CAAC,EAAE,eAAe,GAC7B,uBAAuB,CAoBzB","sourcesContent":["import type {\n\tApi,\n\tContext,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamOptions,\n\tThinkingBudgets,\n\tThinkingLevel,\n} from \"../types.ts\";\nimport { estimateContextTokens } from \"../utils/estimate.ts\";\n\nconst CONTEXT_SAFETY_TOKENS = 4096;\nconst MIN_MAX_TOKENS = 1;\n\nexport function clampMaxTokensToContext(model: Model<Api>, context: Context, maxTokens: number): number {\n\tif (model.contextWindow <= 0) return Math.max(MIN_MAX_TOKENS, maxTokens);\n\tconst available = model.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;\n\treturn Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));\n}\n\nexport function buildBaseOptions(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n\tapiKey?: string,\n): StreamOptions {\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: clampMaxTokensToContext(model, context, options?.maxTokens ?? model.maxTokens),\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\ttransport: options?.transport,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t};\n}\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\"> | undefined {\n\treturn effort === \"xhigh\" ? \"high\" : effort;\n}\n\ninterface ThinkingTokenAllocation {\n\tmaxTokens: number;\n\tthinkingBudget: number;\n}\n\nexport function adjustMaxTokensForThinking(\n\t// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.\n\tbaseMaxTokens: number | undefined,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): ThinkingTokenAllocation {\n\tconst defaultBudgets: ThinkingBudgets = {\n\t\tminimal: 1024,\n\t\tlow: 2048,\n\t\tmedium: 8192,\n\t\thigh: 16384,\n\t};\n\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\tconst minOutputTokens = 1024;\n\tconst level = clampReasoning(reasoningLevel)!;\n\tlet thinkingBudget = budgets[level]!;\n\tconst maxTokens =\n\t\tbaseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"simple-options.js","sourceRoot":"","sources":["../../src/providers/simple-options.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,qBAAqB,GAAG,IAAI,CAAC;AACnC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,MAAM,UAAU,uBAAuB,CAAC,KAAiB,EAAE,OAAgB,EAAE,SAAiB,EAAU;IACvG,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,KAAK,CAAC,aAAa,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,qBAAqB,CAAC;IACtG,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,CAAC;AAAA,CAChE;AAED,MAAM,UAAU,gBAAgB,CAC/B,KAAiB,EACjB,OAAgB,EAChB,OAA6B,EAC7B,MAAe,EACC;IAChB,OAAO;QACN,WAAW,EAAE,OAAO,EAAE,WAAW;QACjC,SAAS,EAAE,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;QACzF,MAAM,EAAE,OAAO,EAAE,MAAM;QACvB,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM;QACjC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,cAAc,EAAE,OAAO,EAAE,cAAc;QACvC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,OAAO,EAAE,OAAO,EAAE,OAAO;QACzB,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,eAAe,EAAE,OAAO,EAAE,eAAe;QACzC,QAAQ,EAAE,OAAO,EAAE,QAAQ;KAC3B,CAAC;AAAA,CACF;AAED,MAAM,UAAU,cAAc,CAAC,MAAiC,EAA+C;IAC9G,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAAA,CAC5C;AAED,MAAM,UAAU,0BAA0B;AACzC,wFAAwF;AACxF,aAAiC,EACjC,cAAsB,EACtB,cAA6B,EAC7B,aAA+B,EACiB;IAChD,MAAM,cAAc,GAAoB;QACvC,OAAO,EAAE,IAAI;QACb,GAAG,EAAE,IAAI;QACT,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,KAAK;KACX,CAAC;IACF,MAAM,OAAO,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,aAAa,EAAE,CAAC;IAExD,MAAM,eAAe,GAAG,IAAI,CAAC;IAC7B,MAAM,KAAK,GAAG,cAAc,CAAC,cAAc,CAAE,CAAC;IAC9C,IAAI,cAAc,GAAG,OAAO,CAAC,KAAK,CAAE,CAAC;IACrC,MAAM,SAAS,GACd,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,cAAc,EAAE,cAAc,CAAC,CAAC;IAEzG,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;QACjC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,eAAe,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AAAA,CACrC","sourcesContent":["import type {\n\tApi,\n\tContext,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamOptions,\n\tThinkingBudgets,\n\tThinkingLevel,\n} from \"../types.ts\";\nimport { estimateContextTokens } from \"../utils/estimate.ts\";\n\nconst CONTEXT_SAFETY_TOKENS = 4096;\nconst MIN_MAX_TOKENS = 1;\n\nexport function clampMaxTokensToContext(model: Model<Api>, context: Context, maxTokens: number): number {\n\tif (model.contextWindow <= 0) return Math.max(MIN_MAX_TOKENS, maxTokens);\n\tconst available = model.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;\n\treturn Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));\n}\n\nexport function buildBaseOptions(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n\tapiKey?: string,\n): StreamOptions {\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: clampMaxTokensToContext(model, context, options?.maxTokens ?? model.maxTokens),\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\ttransport: options?.transport,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t};\n}\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\"> | undefined {\n\treturn effort === \"xhigh\" ? \"high\" : effort;\n}\n\nexport function adjustMaxTokensForThinking(\n\t// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.\n\tbaseMaxTokens: number | undefined,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): { maxTokens: number; thinkingBudget: number } {\n\tconst defaultBudgets: ThinkingBudgets = {\n\t\tminimal: 1024,\n\t\tlow: 2048,\n\t\tmedium: 8192,\n\t\thigh: 16384,\n\t};\n\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\tconst minOutputTokens = 1024;\n\tconst level = clampReasoning(reasoningLevel)!;\n\tlet thinkingBudget = budgets[level]!;\n\tconst maxTokens =\n\t\tbaseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
1
+ {"version":3,"file":"simple-options.js","sourceRoot":"","sources":["../../src/providers/simple-options.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,qBAAqB,GAAG,IAAI,CAAC;AACnC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,MAAM,UAAU,uBAAuB,CAAC,KAAiB,EAAE,OAAgB,EAAE,SAAiB,EAAU;IACvG,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,KAAK,CAAC,aAAa,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,qBAAqB,CAAC;IACtG,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,CAAC;AAAA,CAChE;AAED,MAAM,UAAU,gBAAgB,CAC/B,KAAiB,EACjB,OAAgB,EAChB,OAA6B,EAC7B,MAAe,EACC;IAChB,OAAO;QACN,WAAW,EAAE,OAAO,EAAE,WAAW;QACjC,SAAS,EAAE,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;QACzF,MAAM,EAAE,OAAO,EAAE,MAAM;QACvB,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM;QACjC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,cAAc,EAAE,OAAO,EAAE,cAAc;QACvC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,OAAO,EAAE,OAAO,EAAE,OAAO;QACzB,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,eAAe,EAAE,OAAO,EAAE,eAAe;QACzC,QAAQ,EAAE,OAAO,EAAE,QAAQ;KAC3B,CAAC;AAAA,CACF;AAED,MAAM,UAAU,cAAc,CAAC,MAAiC,EAA+C;IAC9G,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAAA,CAC5C;AAOD,MAAM,UAAU,0BAA0B;AACzC,wFAAwF;AACxF,aAAiC,EACjC,cAAsB,EACtB,cAA6B,EAC7B,aAA+B,EACL;IAC1B,MAAM,cAAc,GAAoB;QACvC,OAAO,EAAE,IAAI;QACb,GAAG,EAAE,IAAI;QACT,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,KAAK;KACX,CAAC;IACF,MAAM,OAAO,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,aAAa,EAAE,CAAC;IAExD,MAAM,eAAe,GAAG,IAAI,CAAC;IAC7B,MAAM,KAAK,GAAG,cAAc,CAAC,cAAc,CAAE,CAAC;IAC9C,IAAI,cAAc,GAAG,OAAO,CAAC,KAAK,CAAE,CAAC;IACrC,MAAM,SAAS,GACd,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,cAAc,EAAE,cAAc,CAAC,CAAC;IAEzG,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;QACjC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,eAAe,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AAAA,CACrC","sourcesContent":["import type {\n\tApi,\n\tContext,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamOptions,\n\tThinkingBudgets,\n\tThinkingLevel,\n} from \"../types.ts\";\nimport { estimateContextTokens } from \"../utils/estimate.ts\";\n\nconst CONTEXT_SAFETY_TOKENS = 4096;\nconst MIN_MAX_TOKENS = 1;\n\nexport function clampMaxTokensToContext(model: Model<Api>, context: Context, maxTokens: number): number {\n\tif (model.contextWindow <= 0) return Math.max(MIN_MAX_TOKENS, maxTokens);\n\tconst available = model.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;\n\treturn Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));\n}\n\nexport function buildBaseOptions(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n\tapiKey?: string,\n): StreamOptions {\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: clampMaxTokensToContext(model, context, options?.maxTokens ?? model.maxTokens),\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\ttransport: options?.transport,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t};\n}\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\"> | undefined {\n\treturn effort === \"xhigh\" ? \"high\" : effort;\n}\n\ninterface ThinkingTokenAllocation {\n\tmaxTokens: number;\n\tthinkingBudget: number;\n}\n\nexport function adjustMaxTokensForThinking(\n\t// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.\n\tbaseMaxTokens: number | undefined,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): ThinkingTokenAllocation {\n\tconst defaultBudgets: ThinkingBudgets = {\n\t\tminimal: 1024,\n\t\tlow: 2048,\n\t\tmedium: 8192,\n\t\thigh: 16384,\n\t};\n\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\tconst minOutputTokens = 1024;\n\tconst level = clampReasoning(reasoningLevel)!;\n\tlet thinkingBudget = budgets[level]!;\n\tconst maxTokens =\n\t\tbaseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"transform-messages.d.ts","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAEhB,OAAO,EACP,KAAK,EAIL,MAAM,aAAa,CAAC;AAiDrB;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,SAAS,GAAG,EACjD,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,gBAAgB,KAAK,MAAM,GACxF,OAAO,EAAE,CAwJX","sourcesContent":["import type {\n\tApi,\n\tAssistantMessage,\n\tImageContent,\n\tMessage,\n\tModel,\n\tTextContent,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.ts\";\n\nconst NON_VISION_USER_IMAGE_PLACEHOLDER = \"(image omitted: model does not support images)\";\nconst NON_VISION_TOOL_IMAGE_PLACEHOLDER = \"(tool image omitted: model does not support images)\";\n\nfunction replaceImagesWithPlaceholder(content: (TextContent | ImageContent)[], placeholder: string): TextContent[] {\n\tconst result: TextContent[] = [];\n\tlet previousWasPlaceholder = false;\n\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") {\n\t\t\tif (!previousWasPlaceholder) {\n\t\t\t\tresult.push({ type: \"text\", text: placeholder });\n\t\t\t}\n\t\t\tpreviousWasPlaceholder = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(block);\n\t\tpreviousWasPlaceholder = block.text === placeholder;\n\t}\n\n\treturn result;\n}\n\nfunction downgradeUnsupportedImages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\tif (model.input.includes(\"image\")) {\n\t\treturn messages;\n\t}\n\n\treturn messages.map((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\tif (msg.role === \"toolResult\") {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\treturn msg;\n\t});\n}\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nexport function transformMessages<TApi extends Api>(\n\tmessages: Message[],\n\tmodel: Model<TApi>,\n\tnormalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string,\n): Message[] {\n\t// Build a map of original tool call IDs to normalized IDs\n\tconst toolCallIdMap = new Map<string, string>();\n\tconst imageAwareMessages = downgradeUnsupportedImages(messages, model);\n\n\t// First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)\n\tconst transformed = imageAwareMessages.map((msg) => {\n\t\t// User messages pass through unchanged\n\t\tif (msg.role === \"user\") {\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Handle toolResult messages - normalize toolCallId if we have a mapping\n\t\tif (msg.role === \"toolResult\") {\n\t\t\tconst normalizedId = toolCallIdMap.get(msg.toolCallId);\n\t\t\tif (normalizedId && normalizedId !== msg.toolCallId) {\n\t\t\t\treturn { ...msg, toolCallId: normalizedId };\n\t\t\t}\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Assistant messages need transformation check\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst isSameModel =\n\t\t\t\tassistantMsg.provider === model.provider &&\n\t\t\t\tassistantMsg.api === model.api &&\n\t\t\t\tassistantMsg.model === model.id;\n\n\t\t\tconst transformedContent = assistantMsg.content.flatMap((block) => {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\t// Redacted thinking is opaque encrypted content, only valid for the same model.\n\t\t\t\t\t// Drop it for cross-model to avoid API errors.\n\t\t\t\t\tif (block.redacted) {\n\t\t\t\t\t\treturn isSameModel ? block : [];\n\t\t\t\t\t}\n\t\t\t\t\t// For same model: keep thinking blocks with signatures (needed for replay)\n\t\t\t\t\t// even if the thinking text is empty (OpenAI encrypted reasoning)\n\t\t\t\t\tif (isSameModel && block.thinkingSignature) return block;\n\t\t\t\t\t// Skip empty thinking blocks, convert others to plain text\n\t\t\t\t\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.thinking,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"toolCall\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tlet normalizedToolCall: ToolCall = toolCall;\n\n\t\t\t\t\tif (!isSameModel && toolCall.thoughtSignature) {\n\t\t\t\t\t\tnormalizedToolCall = { ...toolCall };\n\t\t\t\t\t\tdelete (normalizedToolCall as { thoughtSignature?: string }).thoughtSignature;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isSameModel && normalizeToolCallId) {\n\t\t\t\t\t\tconst normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);\n\t\t\t\t\t\tif (normalizedId !== toolCall.id) {\n\t\t\t\t\t\t\ttoolCallIdMap.set(toolCall.id, normalizedId);\n\t\t\t\t\t\t\tnormalizedToolCall = { ...normalizedToolCall, id: normalizedId };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn normalizedToolCall;\n\t\t\t\t}\n\n\t\t\t\treturn block;\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t...assistantMsg,\n\t\t\t\tcontent: transformedContent,\n\t\t\t};\n\t\t}\n\t\treturn msg;\n\t});\n\n\t// Second pass: insert synthetic empty tool results for orphaned tool calls\n\t// This preserves thinking signatures and satisfies API requirements\n\tconst result: Message[] = [];\n\tlet pendingToolCalls: ToolCall[] = [];\n\tlet existingToolResultIds = new Set<string>();\n\tconst insertSyntheticToolResults = () => {\n\t\tif (pendingToolCalls.length > 0) {\n\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpendingToolCalls = [];\n\t\t\texistingToolResultIds = new Set();\n\t\t}\n\t};\n\n\tfor (let i = 0; i < transformed.length; i++) {\n\t\tconst msg = transformed[i];\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\t// If we have pending orphaned tool calls from a previous assistant, insert synthetic results now\n\t\t\tinsertSyntheticToolResults();\n\n\t\t\t// Skip errored/aborted assistant messages entirely.\n\t\t\t// These are incomplete turns that shouldn't be replayed:\n\t\t\t// - May have partial content (reasoning without message, incomplete tool calls)\n\t\t\t// - Replaying them can cause API errors (e.g., OpenAI \"reasoning without following item\")\n\t\t\t// - The model should retry from the last valid state\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\n\t\t\tconst toolCalls = assistantMsg.content.filter((b) => b.type === \"toolCall\") as ToolCall[];\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = toolCalls;\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\texistingToolResultIds.add(msg.toolCallId);\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"user\") {\n\t\t\t// User message interrupts tool flow - insert synthetic results for orphaned calls\n\t\t\tinsertSyntheticToolResults();\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\t// If the conversation ends with unresolved tool calls, synthesize results now.\n\tinsertSyntheticToolResults();\n\n\treturn result;\n}\n"]}
1
+ {"version":3,"file":"transform-messages.d.ts","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EAEH,gBAAgB,EAEhB,OAAO,EACP,KAAK,EAKL,MAAM,aAAa,CAAC;AAiLrB;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,SAAS,GAAG,EACjD,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,gBAAgB,KAAK,MAAM,GACxF,OAAO,EAAE,CAYX","sourcesContent":["import type {\n\tApi,\n\tAssistantContent,\n\tAssistantMessage,\n\tImageContent,\n\tMessage,\n\tModel,\n\tTextContent,\n\tThinkingContent,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.ts\";\n\nconst NON_VISION_USER_IMAGE_PLACEHOLDER = \"(image omitted: model does not support images)\";\nconst NON_VISION_TOOL_IMAGE_PLACEHOLDER = \"(tool image omitted: model does not support images)\";\n\nfunction replaceImagesWithPlaceholder(content: (TextContent | ImageContent)[], placeholder: string): TextContent[] {\n\tconst result: TextContent[] = [];\n\tlet previousWasPlaceholder = false;\n\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") {\n\t\t\tif (!previousWasPlaceholder) {\n\t\t\t\tresult.push({ type: \"text\", text: placeholder });\n\t\t\t}\n\t\t\tpreviousWasPlaceholder = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(block);\n\t\tpreviousWasPlaceholder = block.text === placeholder;\n\t}\n\n\treturn result;\n}\n\nfunction downgradeUnsupportedImages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\tif (model.input.includes(\"image\")) {\n\t\treturn messages;\n\t}\n\n\treturn messages.map((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\tif (msg.role === \"toolResult\") {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\treturn msg;\n\t});\n}\n\ninterface MessageTransformationContext<TApi extends Api> {\n\tmodel: Model<TApi>;\n\tnormalizeToolCallId: ((id: string, model: Model<TApi>, source: AssistantMessage) => string) | undefined;\n\ttoolCallIdMap: Map<string, string>;\n}\n\ninterface ToolFlowRepairState {\n\tresult: Message[];\n\tpendingToolCalls: ToolCall[];\n\texistingToolResultIds: Set<string>;\n}\n\nfunction isSameAssistantModel<TApi extends Api>(message: AssistantMessage, model: Model<TApi>): boolean {\n\treturn message.provider === model.provider && message.api === model.api && message.model === model.id;\n}\n\nfunction transformThinkingForModel(\n\tblock: ThinkingContent,\n\tisSameModel: boolean,\n): AssistantContent | AssistantContent[] {\n\tif (block.redacted) return isSameModel ? block : [];\n\tif (isSameModel && block.thinkingSignature) return block;\n\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\treturn isSameModel ? block : { type: \"text\", text: block.thinking };\n}\n\nfunction transformToolCallForModel<TApi extends Api>(\n\ttoolCall: ToolCall,\n\tmessage: AssistantMessage,\n\tisSameModel: boolean,\n\tcontext: MessageTransformationContext<TApi>,\n): ToolCall {\n\tlet transformed = toolCall;\n\tif (!isSameModel && toolCall.thoughtSignature) {\n\t\ttransformed = { ...toolCall };\n\t\tdelete (transformed as { thoughtSignature?: string }).thoughtSignature;\n\t}\n\tif (isSameModel || !context.normalizeToolCallId) return transformed;\n\n\tconst normalizedId = context.normalizeToolCallId(toolCall.id, context.model, message);\n\tif (normalizedId === toolCall.id) return transformed;\n\tcontext.toolCallIdMap.set(toolCall.id, normalizedId);\n\treturn { ...transformed, id: normalizedId };\n}\n\nfunction transformAssistantContentForModel<TApi extends Api>(\n\tmessage: AssistantMessage,\n\tcontext: MessageTransformationContext<TApi>,\n): AssistantContent[] {\n\tconst isSameModel = isSameAssistantModel(message, context.model);\n\treturn message.content.flatMap((block) => {\n\t\tswitch (block.type) {\n\t\t\tcase \"thinking\":\n\t\t\t\treturn transformThinkingForModel(block, isSameModel);\n\t\t\tcase \"text\":\n\t\t\t\treturn isSameModel ? block : { type: \"text\", text: block.text };\n\t\t\tcase \"toolCall\":\n\t\t\t\treturn transformToolCallForModel(block, message, isSameModel, context);\n\t\t\tdefault:\n\t\t\t\treturn block;\n\t\t}\n\t});\n}\n\nfunction transformMessageForModel<TApi extends Api>(\n\tmessage: Message,\n\tcontext: MessageTransformationContext<TApi>,\n): Message {\n\tif (message.role === \"user\") return message;\n\tif (message.role === \"toolResult\") {\n\t\tconst normalizedId = context.toolCallIdMap.get(message.toolCallId);\n\t\treturn normalizedId && normalizedId !== message.toolCallId ? { ...message, toolCallId: normalizedId } : message;\n\t}\n\treturn {\n\t\t...message,\n\t\tcontent: transformAssistantContentForModel(message, context),\n\t};\n}\n\nfunction insertSyntheticToolResults(state: ToolFlowRepairState): void {\n\tif (state.pendingToolCalls.length === 0) return;\n\tfor (const toolCall of state.pendingToolCalls) {\n\t\tif (state.existingToolResultIds.has(toolCall.id)) continue;\n\t\tstate.result.push({\n\t\t\trole: \"toolResult\",\n\t\t\ttoolCallId: toolCall.id,\n\t\t\ttoolName: toolCall.name,\n\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\tisError: true,\n\t\t\ttimestamp: Date.now(),\n\t\t} as ToolResultMessage);\n\t}\n\tstate.pendingToolCalls = [];\n\tstate.existingToolResultIds = new Set();\n}\n\nfunction appendRepairedMessage(state: ToolFlowRepairState, message: Message): void {\n\tif (message.role === \"assistant\") {\n\t\tinsertSyntheticToolResults(state);\n\t\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") return;\n\t\tconst toolCalls = message.content.filter((block): block is ToolCall => block.type === \"toolCall\");\n\t\tif (toolCalls.length > 0) {\n\t\t\tstate.pendingToolCalls = toolCalls;\n\t\t\tstate.existingToolResultIds = new Set();\n\t\t}\n\t\tstate.result.push(message);\n\t\treturn;\n\t}\n\tif (message.role === \"toolResult\") {\n\t\tstate.existingToolResultIds.add(message.toolCallId);\n\t\tstate.result.push(message);\n\t\treturn;\n\t}\n\tif (message.role === \"user\") insertSyntheticToolResults(state);\n\tstate.result.push(message);\n}\n\nfunction repairOrphanedToolCalls(messages: Message[]): Message[] {\n\tconst state: ToolFlowRepairState = {\n\t\tresult: [],\n\t\tpendingToolCalls: [],\n\t\texistingToolResultIds: new Set(),\n\t};\n\tfor (const message of messages) appendRepairedMessage(state, message);\n\tinsertSyntheticToolResults(state);\n\treturn state.result;\n}\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nexport function transformMessages<TApi extends Api>(\n\tmessages: Message[],\n\tmodel: Model<TApi>,\n\tnormalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string,\n): Message[] {\n\tconst normalizedMessages = messages.map((message) =>\n\t\tmessage.content == null ? { ...message, content: [] } : message,\n\t);\n\tconst imageAwareMessages = downgradeUnsupportedImages(normalizedMessages, model);\n\tconst context: MessageTransformationContext<TApi> = {\n\t\tmodel,\n\t\tnormalizeToolCallId,\n\t\ttoolCallIdMap: new Map(),\n\t};\n\tconst transformedMessages = imageAwareMessages.map((message) => transformMessageForModel(message, context));\n\treturn repairOrphanedToolCalls(transformedMessages);\n}\n"]}
@@ -36,149 +36,124 @@ function downgradeUnsupportedImages(messages, model) {
36
36
  return msg;
37
37
  });
38
38
  }
39
+ function isSameAssistantModel(message, model) {
40
+ return message.provider === model.provider && message.api === model.api && message.model === model.id;
41
+ }
42
+ function transformThinkingForModel(block, isSameModel) {
43
+ if (block.redacted)
44
+ return isSameModel ? block : [];
45
+ if (isSameModel && block.thinkingSignature)
46
+ return block;
47
+ if (!block.thinking || block.thinking.trim() === "")
48
+ return [];
49
+ return isSameModel ? block : { type: "text", text: block.thinking };
50
+ }
51
+ function transformToolCallForModel(toolCall, message, isSameModel, context) {
52
+ let transformed = toolCall;
53
+ if (!isSameModel && toolCall.thoughtSignature) {
54
+ transformed = { ...toolCall };
55
+ delete transformed.thoughtSignature;
56
+ }
57
+ if (isSameModel || !context.normalizeToolCallId)
58
+ return transformed;
59
+ const normalizedId = context.normalizeToolCallId(toolCall.id, context.model, message);
60
+ if (normalizedId === toolCall.id)
61
+ return transformed;
62
+ context.toolCallIdMap.set(toolCall.id, normalizedId);
63
+ return { ...transformed, id: normalizedId };
64
+ }
65
+ function transformAssistantContentForModel(message, context) {
66
+ const isSameModel = isSameAssistantModel(message, context.model);
67
+ return message.content.flatMap((block) => {
68
+ switch (block.type) {
69
+ case "thinking":
70
+ return transformThinkingForModel(block, isSameModel);
71
+ case "text":
72
+ return isSameModel ? block : { type: "text", text: block.text };
73
+ case "toolCall":
74
+ return transformToolCallForModel(block, message, isSameModel, context);
75
+ default:
76
+ return block;
77
+ }
78
+ });
79
+ }
80
+ function transformMessageForModel(message, context) {
81
+ if (message.role === "user")
82
+ return message;
83
+ if (message.role === "toolResult") {
84
+ const normalizedId = context.toolCallIdMap.get(message.toolCallId);
85
+ return normalizedId && normalizedId !== message.toolCallId ? { ...message, toolCallId: normalizedId } : message;
86
+ }
87
+ return {
88
+ ...message,
89
+ content: transformAssistantContentForModel(message, context),
90
+ };
91
+ }
92
+ function insertSyntheticToolResults(state) {
93
+ if (state.pendingToolCalls.length === 0)
94
+ return;
95
+ for (const toolCall of state.pendingToolCalls) {
96
+ if (state.existingToolResultIds.has(toolCall.id))
97
+ continue;
98
+ state.result.push({
99
+ role: "toolResult",
100
+ toolCallId: toolCall.id,
101
+ toolName: toolCall.name,
102
+ content: [{ type: "text", text: "No result provided" }],
103
+ isError: true,
104
+ timestamp: Date.now(),
105
+ });
106
+ }
107
+ state.pendingToolCalls = [];
108
+ state.existingToolResultIds = new Set();
109
+ }
110
+ function appendRepairedMessage(state, message) {
111
+ if (message.role === "assistant") {
112
+ insertSyntheticToolResults(state);
113
+ if (message.stopReason === "error" || message.stopReason === "aborted")
114
+ return;
115
+ const toolCalls = message.content.filter((block) => block.type === "toolCall");
116
+ if (toolCalls.length > 0) {
117
+ state.pendingToolCalls = toolCalls;
118
+ state.existingToolResultIds = new Set();
119
+ }
120
+ state.result.push(message);
121
+ return;
122
+ }
123
+ if (message.role === "toolResult") {
124
+ state.existingToolResultIds.add(message.toolCallId);
125
+ state.result.push(message);
126
+ return;
127
+ }
128
+ if (message.role === "user")
129
+ insertSyntheticToolResults(state);
130
+ state.result.push(message);
131
+ }
132
+ function repairOrphanedToolCalls(messages) {
133
+ const state = {
134
+ result: [],
135
+ pendingToolCalls: [],
136
+ existingToolResultIds: new Set(),
137
+ };
138
+ for (const message of messages)
139
+ appendRepairedMessage(state, message);
140
+ insertSyntheticToolResults(state);
141
+ return state.result;
142
+ }
39
143
  /**
40
144
  * Normalize tool call ID for cross-provider compatibility.
41
145
  * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
42
146
  * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
43
147
  */
44
148
  export function transformMessages(messages, model, normalizeToolCallId) {
45
- // Build a map of original tool call IDs to normalized IDs
46
- const toolCallIdMap = new Map();
47
- const imageAwareMessages = downgradeUnsupportedImages(messages, model);
48
- // First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)
49
- const transformed = imageAwareMessages.map((msg) => {
50
- // User messages pass through unchanged
51
- if (msg.role === "user") {
52
- return msg;
53
- }
54
- // Handle toolResult messages - normalize toolCallId if we have a mapping
55
- if (msg.role === "toolResult") {
56
- const normalizedId = toolCallIdMap.get(msg.toolCallId);
57
- if (normalizedId && normalizedId !== msg.toolCallId) {
58
- return { ...msg, toolCallId: normalizedId };
59
- }
60
- return msg;
61
- }
62
- // Assistant messages need transformation check
63
- if (msg.role === "assistant") {
64
- const assistantMsg = msg;
65
- const isSameModel = assistantMsg.provider === model.provider &&
66
- assistantMsg.api === model.api &&
67
- assistantMsg.model === model.id;
68
- const transformedContent = assistantMsg.content.flatMap((block) => {
69
- if (block.type === "thinking") {
70
- // Redacted thinking is opaque encrypted content, only valid for the same model.
71
- // Drop it for cross-model to avoid API errors.
72
- if (block.redacted) {
73
- return isSameModel ? block : [];
74
- }
75
- // For same model: keep thinking blocks with signatures (needed for replay)
76
- // even if the thinking text is empty (OpenAI encrypted reasoning)
77
- if (isSameModel && block.thinkingSignature)
78
- return block;
79
- // Skip empty thinking blocks, convert others to plain text
80
- if (!block.thinking || block.thinking.trim() === "")
81
- return [];
82
- if (isSameModel)
83
- return block;
84
- return {
85
- type: "text",
86
- text: block.thinking,
87
- };
88
- }
89
- if (block.type === "text") {
90
- if (isSameModel)
91
- return block;
92
- return {
93
- type: "text",
94
- text: block.text,
95
- };
96
- }
97
- if (block.type === "toolCall") {
98
- const toolCall = block;
99
- let normalizedToolCall = toolCall;
100
- if (!isSameModel && toolCall.thoughtSignature) {
101
- normalizedToolCall = { ...toolCall };
102
- delete normalizedToolCall.thoughtSignature;
103
- }
104
- if (!isSameModel && normalizeToolCallId) {
105
- const normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);
106
- if (normalizedId !== toolCall.id) {
107
- toolCallIdMap.set(toolCall.id, normalizedId);
108
- normalizedToolCall = { ...normalizedToolCall, id: normalizedId };
109
- }
110
- }
111
- return normalizedToolCall;
112
- }
113
- return block;
114
- });
115
- return {
116
- ...assistantMsg,
117
- content: transformedContent,
118
- };
119
- }
120
- return msg;
121
- });
122
- // Second pass: insert synthetic empty tool results for orphaned tool calls
123
- // This preserves thinking signatures and satisfies API requirements
124
- const result = [];
125
- let pendingToolCalls = [];
126
- let existingToolResultIds = new Set();
127
- const insertSyntheticToolResults = () => {
128
- if (pendingToolCalls.length > 0) {
129
- for (const tc of pendingToolCalls) {
130
- if (!existingToolResultIds.has(tc.id)) {
131
- result.push({
132
- role: "toolResult",
133
- toolCallId: tc.id,
134
- toolName: tc.name,
135
- content: [{ type: "text", text: "No result provided" }],
136
- isError: true,
137
- timestamp: Date.now(),
138
- });
139
- }
140
- }
141
- pendingToolCalls = [];
142
- existingToolResultIds = new Set();
143
- }
149
+ const normalizedMessages = messages.map((message) => message.content == null ? { ...message, content: [] } : message);
150
+ const imageAwareMessages = downgradeUnsupportedImages(normalizedMessages, model);
151
+ const context = {
152
+ model,
153
+ normalizeToolCallId,
154
+ toolCallIdMap: new Map(),
144
155
  };
145
- for (let i = 0; i < transformed.length; i++) {
146
- const msg = transformed[i];
147
- if (msg.role === "assistant") {
148
- // If we have pending orphaned tool calls from a previous assistant, insert synthetic results now
149
- insertSyntheticToolResults();
150
- // Skip errored/aborted assistant messages entirely.
151
- // These are incomplete turns that shouldn't be replayed:
152
- // - May have partial content (reasoning without message, incomplete tool calls)
153
- // - Replaying them can cause API errors (e.g., OpenAI "reasoning without following item")
154
- // - The model should retry from the last valid state
155
- const assistantMsg = msg;
156
- if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") {
157
- continue;
158
- }
159
- // Track tool calls from this assistant message
160
- const toolCalls = assistantMsg.content.filter((b) => b.type === "toolCall");
161
- if (toolCalls.length > 0) {
162
- pendingToolCalls = toolCalls;
163
- existingToolResultIds = new Set();
164
- }
165
- result.push(msg);
166
- }
167
- else if (msg.role === "toolResult") {
168
- existingToolResultIds.add(msg.toolCallId);
169
- result.push(msg);
170
- }
171
- else if (msg.role === "user") {
172
- // User message interrupts tool flow - insert synthetic results for orphaned calls
173
- insertSyntheticToolResults();
174
- result.push(msg);
175
- }
176
- else {
177
- result.push(msg);
178
- }
179
- }
180
- // If the conversation ends with unresolved tool calls, synthesize results now.
181
- insertSyntheticToolResults();
182
- return result;
156
+ const transformedMessages = imageAwareMessages.map((message) => transformMessageForModel(message, context));
157
+ return repairOrphanedToolCalls(transformedMessages);
183
158
  }
184
159
  //# sourceMappingURL=transform-messages.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform-messages.js","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tApi,\n\tAssistantMessage,\n\tImageContent,\n\tMessage,\n\tModel,\n\tTextContent,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.ts\";\n\nconst NON_VISION_USER_IMAGE_PLACEHOLDER = \"(image omitted: model does not support images)\";\nconst NON_VISION_TOOL_IMAGE_PLACEHOLDER = \"(tool image omitted: model does not support images)\";\n\nfunction replaceImagesWithPlaceholder(content: (TextContent | ImageContent)[], placeholder: string): TextContent[] {\n\tconst result: TextContent[] = [];\n\tlet previousWasPlaceholder = false;\n\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") {\n\t\t\tif (!previousWasPlaceholder) {\n\t\t\t\tresult.push({ type: \"text\", text: placeholder });\n\t\t\t}\n\t\t\tpreviousWasPlaceholder = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(block);\n\t\tpreviousWasPlaceholder = block.text === placeholder;\n\t}\n\n\treturn result;\n}\n\nfunction downgradeUnsupportedImages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\tif (model.input.includes(\"image\")) {\n\t\treturn messages;\n\t}\n\n\treturn messages.map((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\tif (msg.role === \"toolResult\") {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\treturn msg;\n\t});\n}\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nexport function transformMessages<TApi extends Api>(\n\tmessages: Message[],\n\tmodel: Model<TApi>,\n\tnormalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string,\n): Message[] {\n\t// Build a map of original tool call IDs to normalized IDs\n\tconst toolCallIdMap = new Map<string, string>();\n\tconst imageAwareMessages = downgradeUnsupportedImages(messages, model);\n\n\t// First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)\n\tconst transformed = imageAwareMessages.map((msg) => {\n\t\t// User messages pass through unchanged\n\t\tif (msg.role === \"user\") {\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Handle toolResult messages - normalize toolCallId if we have a mapping\n\t\tif (msg.role === \"toolResult\") {\n\t\t\tconst normalizedId = toolCallIdMap.get(msg.toolCallId);\n\t\t\tif (normalizedId && normalizedId !== msg.toolCallId) {\n\t\t\t\treturn { ...msg, toolCallId: normalizedId };\n\t\t\t}\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Assistant messages need transformation check\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst isSameModel =\n\t\t\t\tassistantMsg.provider === model.provider &&\n\t\t\t\tassistantMsg.api === model.api &&\n\t\t\t\tassistantMsg.model === model.id;\n\n\t\t\tconst transformedContent = assistantMsg.content.flatMap((block) => {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\t// Redacted thinking is opaque encrypted content, only valid for the same model.\n\t\t\t\t\t// Drop it for cross-model to avoid API errors.\n\t\t\t\t\tif (block.redacted) {\n\t\t\t\t\t\treturn isSameModel ? block : [];\n\t\t\t\t\t}\n\t\t\t\t\t// For same model: keep thinking blocks with signatures (needed for replay)\n\t\t\t\t\t// even if the thinking text is empty (OpenAI encrypted reasoning)\n\t\t\t\t\tif (isSameModel && block.thinkingSignature) return block;\n\t\t\t\t\t// Skip empty thinking blocks, convert others to plain text\n\t\t\t\t\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.thinking,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"toolCall\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tlet normalizedToolCall: ToolCall = toolCall;\n\n\t\t\t\t\tif (!isSameModel && toolCall.thoughtSignature) {\n\t\t\t\t\t\tnormalizedToolCall = { ...toolCall };\n\t\t\t\t\t\tdelete (normalizedToolCall as { thoughtSignature?: string }).thoughtSignature;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isSameModel && normalizeToolCallId) {\n\t\t\t\t\t\tconst normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);\n\t\t\t\t\t\tif (normalizedId !== toolCall.id) {\n\t\t\t\t\t\t\ttoolCallIdMap.set(toolCall.id, normalizedId);\n\t\t\t\t\t\t\tnormalizedToolCall = { ...normalizedToolCall, id: normalizedId };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn normalizedToolCall;\n\t\t\t\t}\n\n\t\t\t\treturn block;\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t...assistantMsg,\n\t\t\t\tcontent: transformedContent,\n\t\t\t};\n\t\t}\n\t\treturn msg;\n\t});\n\n\t// Second pass: insert synthetic empty tool results for orphaned tool calls\n\t// This preserves thinking signatures and satisfies API requirements\n\tconst result: Message[] = [];\n\tlet pendingToolCalls: ToolCall[] = [];\n\tlet existingToolResultIds = new Set<string>();\n\tconst insertSyntheticToolResults = () => {\n\t\tif (pendingToolCalls.length > 0) {\n\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpendingToolCalls = [];\n\t\t\texistingToolResultIds = new Set();\n\t\t}\n\t};\n\n\tfor (let i = 0; i < transformed.length; i++) {\n\t\tconst msg = transformed[i];\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\t// If we have pending orphaned tool calls from a previous assistant, insert synthetic results now\n\t\t\tinsertSyntheticToolResults();\n\n\t\t\t// Skip errored/aborted assistant messages entirely.\n\t\t\t// These are incomplete turns that shouldn't be replayed:\n\t\t\t// - May have partial content (reasoning without message, incomplete tool calls)\n\t\t\t// - Replaying them can cause API errors (e.g., OpenAI \"reasoning without following item\")\n\t\t\t// - The model should retry from the last valid state\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\n\t\t\tconst toolCalls = assistantMsg.content.filter((b) => b.type === \"toolCall\") as ToolCall[];\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = toolCalls;\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\texistingToolResultIds.add(msg.toolCallId);\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"user\") {\n\t\t\t// User message interrupts tool flow - insert synthetic results for orphaned calls\n\t\t\tinsertSyntheticToolResults();\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\t// If the conversation ends with unresolved tool calls, synthesize results now.\n\tinsertSyntheticToolResults();\n\n\treturn result;\n}\n"]}
1
+ {"version":3,"file":"transform-messages.js","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tApi,\n\tAssistantContent,\n\tAssistantMessage,\n\tImageContent,\n\tMessage,\n\tModel,\n\tTextContent,\n\tThinkingContent,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.ts\";\n\nconst NON_VISION_USER_IMAGE_PLACEHOLDER = \"(image omitted: model does not support images)\";\nconst NON_VISION_TOOL_IMAGE_PLACEHOLDER = \"(tool image omitted: model does not support images)\";\n\nfunction replaceImagesWithPlaceholder(content: (TextContent | ImageContent)[], placeholder: string): TextContent[] {\n\tconst result: TextContent[] = [];\n\tlet previousWasPlaceholder = false;\n\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") {\n\t\t\tif (!previousWasPlaceholder) {\n\t\t\t\tresult.push({ type: \"text\", text: placeholder });\n\t\t\t}\n\t\t\tpreviousWasPlaceholder = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(block);\n\t\tpreviousWasPlaceholder = block.text === placeholder;\n\t}\n\n\treturn result;\n}\n\nfunction downgradeUnsupportedImages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\tif (model.input.includes(\"image\")) {\n\t\treturn messages;\n\t}\n\n\treturn messages.map((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\tif (msg.role === \"toolResult\") {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\treturn msg;\n\t});\n}\n\ninterface MessageTransformationContext<TApi extends Api> {\n\tmodel: Model<TApi>;\n\tnormalizeToolCallId: ((id: string, model: Model<TApi>, source: AssistantMessage) => string) | undefined;\n\ttoolCallIdMap: Map<string, string>;\n}\n\ninterface ToolFlowRepairState {\n\tresult: Message[];\n\tpendingToolCalls: ToolCall[];\n\texistingToolResultIds: Set<string>;\n}\n\nfunction isSameAssistantModel<TApi extends Api>(message: AssistantMessage, model: Model<TApi>): boolean {\n\treturn message.provider === model.provider && message.api === model.api && message.model === model.id;\n}\n\nfunction transformThinkingForModel(\n\tblock: ThinkingContent,\n\tisSameModel: boolean,\n): AssistantContent | AssistantContent[] {\n\tif (block.redacted) return isSameModel ? block : [];\n\tif (isSameModel && block.thinkingSignature) return block;\n\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\treturn isSameModel ? block : { type: \"text\", text: block.thinking };\n}\n\nfunction transformToolCallForModel<TApi extends Api>(\n\ttoolCall: ToolCall,\n\tmessage: AssistantMessage,\n\tisSameModel: boolean,\n\tcontext: MessageTransformationContext<TApi>,\n): ToolCall {\n\tlet transformed = toolCall;\n\tif (!isSameModel && toolCall.thoughtSignature) {\n\t\ttransformed = { ...toolCall };\n\t\tdelete (transformed as { thoughtSignature?: string }).thoughtSignature;\n\t}\n\tif (isSameModel || !context.normalizeToolCallId) return transformed;\n\n\tconst normalizedId = context.normalizeToolCallId(toolCall.id, context.model, message);\n\tif (normalizedId === toolCall.id) return transformed;\n\tcontext.toolCallIdMap.set(toolCall.id, normalizedId);\n\treturn { ...transformed, id: normalizedId };\n}\n\nfunction transformAssistantContentForModel<TApi extends Api>(\n\tmessage: AssistantMessage,\n\tcontext: MessageTransformationContext<TApi>,\n): AssistantContent[] {\n\tconst isSameModel = isSameAssistantModel(message, context.model);\n\treturn message.content.flatMap((block) => {\n\t\tswitch (block.type) {\n\t\t\tcase \"thinking\":\n\t\t\t\treturn transformThinkingForModel(block, isSameModel);\n\t\t\tcase \"text\":\n\t\t\t\treturn isSameModel ? block : { type: \"text\", text: block.text };\n\t\t\tcase \"toolCall\":\n\t\t\t\treturn transformToolCallForModel(block, message, isSameModel, context);\n\t\t\tdefault:\n\t\t\t\treturn block;\n\t\t}\n\t});\n}\n\nfunction transformMessageForModel<TApi extends Api>(\n\tmessage: Message,\n\tcontext: MessageTransformationContext<TApi>,\n): Message {\n\tif (message.role === \"user\") return message;\n\tif (message.role === \"toolResult\") {\n\t\tconst normalizedId = context.toolCallIdMap.get(message.toolCallId);\n\t\treturn normalizedId && normalizedId !== message.toolCallId ? { ...message, toolCallId: normalizedId } : message;\n\t}\n\treturn {\n\t\t...message,\n\t\tcontent: transformAssistantContentForModel(message, context),\n\t};\n}\n\nfunction insertSyntheticToolResults(state: ToolFlowRepairState): void {\n\tif (state.pendingToolCalls.length === 0) return;\n\tfor (const toolCall of state.pendingToolCalls) {\n\t\tif (state.existingToolResultIds.has(toolCall.id)) continue;\n\t\tstate.result.push({\n\t\t\trole: \"toolResult\",\n\t\t\ttoolCallId: toolCall.id,\n\t\t\ttoolName: toolCall.name,\n\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\tisError: true,\n\t\t\ttimestamp: Date.now(),\n\t\t} as ToolResultMessage);\n\t}\n\tstate.pendingToolCalls = [];\n\tstate.existingToolResultIds = new Set();\n}\n\nfunction appendRepairedMessage(state: ToolFlowRepairState, message: Message): void {\n\tif (message.role === \"assistant\") {\n\t\tinsertSyntheticToolResults(state);\n\t\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") return;\n\t\tconst toolCalls = message.content.filter((block): block is ToolCall => block.type === \"toolCall\");\n\t\tif (toolCalls.length > 0) {\n\t\t\tstate.pendingToolCalls = toolCalls;\n\t\t\tstate.existingToolResultIds = new Set();\n\t\t}\n\t\tstate.result.push(message);\n\t\treturn;\n\t}\n\tif (message.role === \"toolResult\") {\n\t\tstate.existingToolResultIds.add(message.toolCallId);\n\t\tstate.result.push(message);\n\t\treturn;\n\t}\n\tif (message.role === \"user\") insertSyntheticToolResults(state);\n\tstate.result.push(message);\n}\n\nfunction repairOrphanedToolCalls(messages: Message[]): Message[] {\n\tconst state: ToolFlowRepairState = {\n\t\tresult: [],\n\t\tpendingToolCalls: [],\n\t\texistingToolResultIds: new Set(),\n\t};\n\tfor (const message of messages) appendRepairedMessage(state, message);\n\tinsertSyntheticToolResults(state);\n\treturn state.result;\n}\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nexport function transformMessages<TApi extends Api>(\n\tmessages: Message[],\n\tmodel: Model<TApi>,\n\tnormalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string,\n): Message[] {\n\tconst normalizedMessages = messages.map((message) =>\n\t\tmessage.content == null ? { ...message, content: [] } : message,\n\t);\n\tconst imageAwareMessages = downgradeUnsupportedImages(normalizedMessages, model);\n\tconst context: MessageTransformationContext<TApi> = {\n\t\tmodel,\n\t\tnormalizeToolCallId,\n\t\ttoolCallIdMap: new Map(),\n\t};\n\tconst transformedMessages = imageAwareMessages.map((message) => transformMessageForModel(message, context));\n\treturn repairOrphanedToolCalls(transformedMessages);\n}\n"]}
package/dist/stream.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import "./providers/register-builtins.ts";
2
2
  import type { Api, AssistantMessage, AssistantMessageEventStream, Context, Model, ProviderStreamOptions, SimpleStreamOptions } from "./types.ts";
3
- export { getEnvApiKey } from "./env-api-keys.ts";
4
3
  export declare function stream<TApi extends Api>(model: Model<TApi>, context: Context, options?: ProviderStreamOptions): AssistantMessageEventStream;
5
4
  export declare function complete<TApi extends Api>(model: Model<TApi>, context: Context, options?: ProviderStreamOptions): Promise<AssistantMessage>;
6
5
  export declare function streamSimple<TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAG1C,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAChB,2BAA2B,EAC3B,OAAO,EACP,KAAK,EACL,qBAAqB,EACrB,mBAAmB,EAEnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAUjD,wBAAgB,MAAM,CAAC,IAAI,SAAS,GAAG,EACtC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,2BAA2B,CAG7B;AAED,wBAAsB,QAAQ,CAAC,IAAI,SAAS,GAAG,EAC9C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAS,GAAG,EAC5C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,2BAA2B,CAG7B;AAED,wBAAsB,cAAc,CAAC,IAAI,SAAS,GAAG,EACpD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAG3B","sourcesContent":["import \"./providers/register-builtins.ts\";\n\nimport { getApiProvider } from \"./api-registry.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tModel,\n\tProviderStreamOptions,\n\tSimpleStreamOptions,\n\tStreamOptions,\n} from \"./types.ts\";\n\nexport { getEnvApiKey } from \"./env-api-keys.ts\";\n\nfunction resolveApiProvider(api: Api) {\n\tconst provider = getApiProvider(api);\n\tif (!provider) {\n\t\tthrow new Error(`No API provider registered for api: ${api}`);\n\t}\n\treturn provider;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.stream(model, context, options as StreamOptions);\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.streamSimple(model, context, options);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n"]}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAG1C,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAChB,2BAA2B,EAC3B,OAAO,EACP,KAAK,EACL,qBAAqB,EACrB,mBAAmB,EAEnB,MAAM,YAAY,CAAC;AAUpB,wBAAgB,MAAM,CAAC,IAAI,SAAS,GAAG,EACtC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,2BAA2B,CAG7B;AAED,wBAAsB,QAAQ,CAAC,IAAI,SAAS,GAAG,EAC9C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAS,GAAG,EAC5C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,2BAA2B,CAG7B;AAED,wBAAsB,cAAc,CAAC,IAAI,SAAS,GAAG,EACpD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAG3B","sourcesContent":["import \"./providers/register-builtins.ts\";\n\nimport { getApiProvider } from \"./api-registry.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tModel,\n\tProviderStreamOptions,\n\tSimpleStreamOptions,\n\tStreamOptions,\n} from \"./types.ts\";\n\nfunction resolveApiProvider(api: Api) {\n\tconst provider = getApiProvider(api);\n\tif (!provider) {\n\t\tthrow new Error(`No API provider registered for api: ${api}`);\n\t}\n\treturn provider;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.stream(model, context, options as StreamOptions);\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.streamSimple(model, context, options);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n"]}
package/dist/stream.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import "./providers/register-builtins.js";
2
2
  import { getApiProvider } from "./api-registry.js";
3
- export { getEnvApiKey } from "./env-api-keys.js";
4
3
  function resolveApiProvider(api) {
5
4
  const provider = getApiProvider(api);
6
5
  if (!provider) {
@@ -1 +1 @@
1
- {"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAYnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,SAAS,kBAAkB,CAAC,GAAQ,EAAE;IACrC,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,QAAQ,CAAC;AAAA,CAChB;AAED,MAAM,UAAU,MAAM,CACrB,KAAkB,EAClB,OAAgB,EAChB,OAA+B,EACD;IAC9B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAwB,CAAC,CAAC;AAAA,CACjE;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC7B,KAAkB,EAClB,OAAgB,EAChB,OAA+B,EACH;IAC5B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AAAA,CAClB;AAED,MAAM,UAAU,YAAY,CAC3B,KAAkB,EAClB,OAAgB,EAChB,OAA6B,EACC;IAC9B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAAA,CACtD;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,KAAkB,EAClB,OAAgB,EAChB,OAA6B,EACD;IAC5B,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AAAA,CAClB","sourcesContent":["import \"./providers/register-builtins.ts\";\n\nimport { getApiProvider } from \"./api-registry.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tModel,\n\tProviderStreamOptions,\n\tSimpleStreamOptions,\n\tStreamOptions,\n} from \"./types.ts\";\n\nexport { getEnvApiKey } from \"./env-api-keys.ts\";\n\nfunction resolveApiProvider(api: Api) {\n\tconst provider = getApiProvider(api);\n\tif (!provider) {\n\t\tthrow new Error(`No API provider registered for api: ${api}`);\n\t}\n\treturn provider;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.stream(model, context, options as StreamOptions);\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.streamSimple(model, context, options);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n"]}
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAYnD,SAAS,kBAAkB,CAAC,GAAQ,EAAE;IACrC,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,QAAQ,CAAC;AAAA,CAChB;AAED,MAAM,UAAU,MAAM,CACrB,KAAkB,EAClB,OAAgB,EAChB,OAA+B,EACD;IAC9B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAwB,CAAC,CAAC;AAAA,CACjE;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC7B,KAAkB,EAClB,OAAgB,EAChB,OAA+B,EACH;IAC5B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AAAA,CAClB;AAED,MAAM,UAAU,YAAY,CAC3B,KAAkB,EAClB,OAAgB,EAChB,OAA6B,EACC;IAC9B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAAA,CACtD;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,KAAkB,EAClB,OAAgB,EAChB,OAA6B,EACD;IAC5B,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AAAA,CAClB","sourcesContent":["import \"./providers/register-builtins.ts\";\n\nimport { getApiProvider } from \"./api-registry.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tModel,\n\tProviderStreamOptions,\n\tSimpleStreamOptions,\n\tStreamOptions,\n} from \"./types.ts\";\n\nfunction resolveApiProvider(api: Api) {\n\tconst provider = getApiProvider(api);\n\tif (!provider) {\n\t\tthrow new Error(`No API provider registered for api: ${api}`);\n\t}\n\treturn provider;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.stream(model, context, options as StreamOptions);\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.streamSimple(model, context, options);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n"]}