@jecruz/merc-ai 0.1.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.
- package/README.md +1453 -0
- package/dist/api-registry.d.ts +20 -0
- package/dist/api-registry.d.ts.map +1 -0
- package/dist/api-registry.js +44 -0
- package/dist/api-registry.js.map +1 -0
- package/dist/bedrock-provider.d.ts +5 -0
- package/dist/bedrock-provider.d.ts.map +1 -0
- package/dist/bedrock-provider.js +6 -0
- package/dist/bedrock-provider.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +116 -0
- package/dist/cli.js.map +1 -0
- package/dist/env-api-keys.d.ts +18 -0
- package/dist/env-api-keys.d.ts.map +1 -0
- package/dist/env-api-keys.js +134 -0
- package/dist/env-api-keys.js.map +1 -0
- package/dist/image-models.d.ts +10 -0
- package/dist/image-models.d.ts.map +1 -0
- package/dist/image-models.generated.d.ts +530 -0
- package/dist/image-models.generated.d.ts.map +1 -0
- package/dist/image-models.generated.js +532 -0
- package/dist/image-models.generated.js.map +1 -0
- package/dist/image-models.js +23 -0
- package/dist/image-models.js.map +1 -0
- package/dist/images-api-registry.d.ts +14 -0
- package/dist/images-api-registry.d.ts.map +1 -0
- package/dist/images-api-registry.js +22 -0
- package/dist/images-api-registry.js.map +1 -0
- package/dist/images.d.ts +5 -0
- package/dist/images.d.ts.map +1 -0
- package/dist/images.js +18 -0
- package/dist/images.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/models.d.ts +22 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.generated.d.ts +20591 -0
- package/dist/models.generated.d.ts.map +1 -0
- package/dist/models.generated.js +19123 -0
- package/dist/models.generated.js.map +1 -0
- package/dist/models.js +80 -0
- package/dist/models.js.map +1 -0
- package/dist/oauth.d.ts +2 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +2 -0
- package/dist/oauth.js.map +1 -0
- package/dist/providers/amazon-bedrock.d.ts +38 -0
- package/dist/providers/amazon-bedrock.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock.js +813 -0
- package/dist/providers/amazon-bedrock.js.map +1 -0
- package/dist/providers/anthropic.d.ts +54 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +1035 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/azure-openai-responses.d.ts +15 -0
- package/dist/providers/azure-openai-responses.d.ts.map +1 -0
- package/dist/providers/azure-openai-responses.js +219 -0
- package/dist/providers/azure-openai-responses.js.map +1 -0
- package/dist/providers/claude-cli.d.ts +4 -0
- package/dist/providers/claude-cli.d.ts.map +1 -0
- package/dist/providers/claude-cli.js +224 -0
- package/dist/providers/claude-cli.js.map +1 -0
- package/dist/providers/cloudflare.d.ts +13 -0
- package/dist/providers/cloudflare.d.ts.map +1 -0
- package/dist/providers/cloudflare.js +26 -0
- package/dist/providers/cloudflare.js.map +1 -0
- package/dist/providers/faux.d.ts +56 -0
- package/dist/providers/faux.d.ts.map +1 -0
- package/dist/providers/faux.js +377 -0
- package/dist/providers/faux.js.map +1 -0
- package/dist/providers/github-copilot-headers.d.ts +8 -0
- package/dist/providers/github-copilot-headers.d.ts.map +1 -0
- package/dist/providers/github-copilot-headers.js +29 -0
- package/dist/providers/github-copilot-headers.js.map +1 -0
- package/dist/providers/google-shared.d.ts +70 -0
- package/dist/providers/google-shared.d.ts.map +1 -0
- package/dist/providers/google-shared.js +329 -0
- package/dist/providers/google-shared.js.map +1 -0
- package/dist/providers/google-vertex.d.ts +15 -0
- package/dist/providers/google-vertex.d.ts.map +1 -0
- package/dist/providers/google-vertex.js +446 -0
- package/dist/providers/google-vertex.js.map +1 -0
- package/dist/providers/google.d.ts +13 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +437 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/mistral.d.ts +25 -0
- package/dist/providers/mistral.d.ts.map +1 -0
- package/dist/providers/mistral.js +538 -0
- package/dist/providers/mistral.js.map +1 -0
- package/dist/providers/openai-codex-responses.d.ts +33 -0
- package/dist/providers/openai-codex-responses.d.ts.map +1 -0
- package/dist/providers/openai-codex-responses.js +1190 -0
- package/dist/providers/openai-codex-responses.js.map +1 -0
- package/dist/providers/openai-completions.d.ts +19 -0
- package/dist/providers/openai-completions.d.ts.map +1 -0
- package/dist/providers/openai-completions.js +1126 -0
- package/dist/providers/openai-completions.js.map +1 -0
- package/dist/providers/openai-responses-shared.d.ts +20 -0
- package/dist/providers/openai-responses-shared.d.ts.map +1 -0
- package/dist/providers/openai-responses-shared.js +543 -0
- package/dist/providers/openai-responses-shared.js.map +1 -0
- package/dist/providers/openai-responses.d.ts +14 -0
- package/dist/providers/openai-responses.d.ts.map +1 -0
- package/dist/providers/openai-responses.js +253 -0
- package/dist/providers/openai-responses.js.map +1 -0
- package/dist/providers/openrouter-images.d.ts +3 -0
- package/dist/providers/openrouter-images.d.ts.map +1 -0
- package/dist/providers/openrouter-images.js +139 -0
- package/dist/providers/openrouter-images.js.map +1 -0
- package/dist/providers/register-builtins.d.ts +37 -0
- package/dist/providers/register-builtins.d.ts.map +1 -0
- package/dist/providers/register-builtins.js +261 -0
- package/dist/providers/register-builtins.js.map +1 -0
- package/dist/providers/register-images-builtins.d.ts +4 -0
- package/dist/providers/register-images-builtins.d.ts.map +1 -0
- package/dist/providers/register-images-builtins.js +48 -0
- package/dist/providers/register-images-builtins.js.map +1 -0
- package/dist/providers/simple-options.d.ts +8 -0
- package/dist/providers/simple-options.d.ts.map +1 -0
- package/dist/providers/simple-options.js +47 -0
- package/dist/providers/simple-options.js.map +1 -0
- package/dist/providers/transform-messages.d.ts +8 -0
- package/dist/providers/transform-messages.d.ts.map +1 -0
- package/dist/providers/transform-messages.js +193 -0
- package/dist/providers/transform-messages.js.map +1 -0
- package/dist/session-resources.d.ts +4 -0
- package/dist/session-resources.d.ts.map +1 -0
- package/dist/session-resources.js +22 -0
- package/dist/session-resources.js.map +1 -0
- package/dist/stream.d.ts +8 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +27 -0
- package/dist/stream.js.map +1 -0
- package/dist/types.d.ts +556 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/deferred-tools.d.ts +15 -0
- package/dist/utils/deferred-tools.d.ts.map +1 -0
- package/dist/utils/deferred-tools.js +48 -0
- package/dist/utils/deferred-tools.js.map +1 -0
- package/dist/utils/diagnostics.d.ts +19 -0
- package/dist/utils/diagnostics.d.ts.map +1 -0
- package/dist/utils/diagnostics.js +25 -0
- package/dist/utils/diagnostics.js.map +1 -0
- package/dist/utils/error-body.d.ts +20 -0
- package/dist/utils/error-body.d.ts.map +1 -0
- package/dist/utils/error-body.js +71 -0
- package/dist/utils/error-body.js.map +1 -0
- package/dist/utils/event-stream.d.ts +26 -0
- package/dist/utils/event-stream.d.ts.map +1 -0
- package/dist/utils/event-stream.js +98 -0
- package/dist/utils/event-stream.js.map +1 -0
- package/dist/utils/hash.d.ts +3 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +14 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/headers.d.ts +2 -0
- package/dist/utils/headers.d.ts.map +1 -0
- package/dist/utils/headers.js +8 -0
- package/dist/utils/headers.js.map +1 -0
- package/dist/utils/json-parse.d.ts +16 -0
- package/dist/utils/json-parse.d.ts.map +1 -0
- package/dist/utils/json-parse.js +113 -0
- package/dist/utils/json-parse.js.map +1 -0
- package/dist/utils/oauth/anthropic.d.ts +25 -0
- package/dist/utils/oauth/anthropic.d.ts.map +1 -0
- package/dist/utils/oauth/anthropic.js +335 -0
- package/dist/utils/oauth/anthropic.js.map +1 -0
- package/dist/utils/oauth/github-copilot.d.ts +30 -0
- package/dist/utils/oauth/github-copilot.d.ts.map +1 -0
- package/dist/utils/oauth/github-copilot.js +351 -0
- package/dist/utils/oauth/github-copilot.js.map +1 -0
- package/dist/utils/oauth/index.d.ts +57 -0
- package/dist/utils/oauth/index.d.ts.map +1 -0
- package/dist/utils/oauth/index.js +121 -0
- package/dist/utils/oauth/index.js.map +1 -0
- package/dist/utils/oauth/oauth-page.d.ts +3 -0
- package/dist/utils/oauth/oauth-page.d.ts.map +1 -0
- package/dist/utils/oauth/oauth-page.js +105 -0
- package/dist/utils/oauth/oauth-page.js.map +1 -0
- package/dist/utils/oauth/openai-codex.d.ts +34 -0
- package/dist/utils/oauth/openai-codex.d.ts.map +1 -0
- package/dist/utils/oauth/openai-codex.js +374 -0
- package/dist/utils/oauth/openai-codex.js.map +1 -0
- package/dist/utils/oauth/pkce.d.ts +13 -0
- package/dist/utils/oauth/pkce.d.ts.map +1 -0
- package/dist/utils/oauth/pkce.js +31 -0
- package/dist/utils/oauth/pkce.js.map +1 -0
- package/dist/utils/oauth/types.d.ts +57 -0
- package/dist/utils/oauth/types.d.ts.map +1 -0
- package/dist/utils/oauth/types.js +2 -0
- package/dist/utils/oauth/types.js.map +1 -0
- package/dist/utils/overflow.d.ts +56 -0
- package/dist/utils/overflow.d.ts.map +1 -0
- package/dist/utils/overflow.js +152 -0
- package/dist/utils/overflow.js.map +1 -0
- package/dist/utils/provider-env.d.ts +9 -0
- package/dist/utils/provider-env.d.ts.map +1 -0
- package/dist/utils/provider-env.js +82 -0
- package/dist/utils/provider-env.js.map +1 -0
- package/dist/utils/sanitize-unicode.d.ts +22 -0
- package/dist/utils/sanitize-unicode.d.ts.map +1 -0
- package/dist/utils/sanitize-unicode.js +26 -0
- package/dist/utils/sanitize-unicode.js.map +1 -0
- package/dist/utils/typebox-helpers.d.ts +17 -0
- package/dist/utils/typebox-helpers.d.ts.map +1 -0
- package/dist/utils/typebox-helpers.js +21 -0
- package/dist/utils/typebox-helpers.js.map +1 -0
- package/dist/utils/validation.d.ts +18 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +281 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +113 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../src/providers/openai-responses.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAC;AAG7F,OAAO,KAAK,EAQX,mBAAmB,EACnB,cAAc,EACd,aAAa,EAEb,MAAM,aAAa,CAAC;AAyDrB,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC5D,eAAe,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAC1E,gBAAgB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1D,WAAW,CAAC,EAAE,6BAA6B,CAAC,cAAc,CAAC,CAAC;IAC5D,UAAU,CAAC,EAAE,6BAA6B,CAAC,aAAa,CAAC,CAAC;CAC1D;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,kBAAkB,EAAE,sBAAsB,CA4E5F,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,cAAc,CAAC,kBAAkB,EAAE,mBAAmB,CAkB/F,CAAC","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { getEnvApiKey } from \"../env-api-keys.js\";\nimport { clampThinkingLevel } from \"../models.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.js\";\nimport { splitDeferredTools } from \"../utils/deferred-tools.js\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { headersToRecord } from \"../utils/headers.js\";\nimport { getProviderEnvValue } from \"../utils/provider-env.js\";\nimport { isCloudflareProvider, resolveCloudflareBaseUrl } from \"./cloudflare.js\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.js\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.js\";\nimport { buildBaseOptions } from \"./simple-options.js\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16.\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses MERC_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"MERC_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsessionAffinityFormat:\n\t\t\tmodel.compat?.sessionAffinityFormat ??\n\t\t\t(model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\") ? \"openrouter\" : \"openai\"),\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t\tsupportsToolSearch: model.compat?.supportsToolSearch ?? defaultSupportsToolSearch(model),\n\t};\n}\n\nfunction defaultSupportsToolSearch(model: Model<\"openai-responses\">): boolean {\n\tif (model.provider !== \"openai\") return false;\n\treturn /gpt-5\\.(4|5|6)/.test(model.id);\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\" | \"max\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n\ttoolChoice?: ResponseCreateParamsStreaming[\"tool_choice\"];\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, options?.env) || \"\";\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, cacheSessionId, options?.env);\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\t...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),\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, options?.env);\n\tif (!apiKey && model.authHeader !== false) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst base = buildBaseOptions(model, 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\tenv?: ProviderEnv,\n) {\n\tconst noAuth = model.authHeader === false;\n\tif (!apiKey && !noAuth) {\n\t\tconst configuredApiKey = getProviderEnvValue(\"OPENAI_API_KEY\", env);\n\t\tif (!configuredApiKey) {\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 = configuredApiKey;\n\t}\n\tif (!apiKey) apiKey = \"merc-no-auth\";\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.sessionAffinityFormat === \"openrouter\") {\n\t\t\theaders[\"x-session-id\"] = sessionId;\n\t\t} else {\n\t\t\tif (compat.sessionAffinityFormat === \"openai\") {\n\t\t\t\theaders.session_id = sessionId;\n\t\t\t}\n\t\t\theaders[\"x-client-request-id\"] = sessionId;\n\t\t}\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 = noAuth\n\t\t? { ...headers, Authorization: null }\n\t\t: model.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, env) : 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 compat = getCompat(model);\n\tconst toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {\n\t\tdeferredTools: toolPlacement.deferred,\n\t});\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\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 : 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 (toolPlacement.immediate.length > 0) {\n\t\tparams.tools = convertResponsesTools(toolPlacement.immediate);\n\t}\n\n\tif (options?.toolChoice !== undefined) {\n\t\tparams.tool_choice = options.toolChoice;\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"]}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import OpenAI from "openai";
|
|
2
|
+
import { getEnvApiKey } from "../env-api-keys.js";
|
|
3
|
+
import { clampThinkingLevel } from "../models.js";
|
|
4
|
+
import { splitDeferredTools } from "../utils/deferred-tools.js";
|
|
5
|
+
import { formatProviderError, normalizeProviderError } from "../utils/error-body.js";
|
|
6
|
+
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
7
|
+
import { headersToRecord } from "../utils/headers.js";
|
|
8
|
+
import { getProviderEnvValue } from "../utils/provider-env.js";
|
|
9
|
+
import { isCloudflareProvider, resolveCloudflareBaseUrl } from "./cloudflare.js";
|
|
10
|
+
import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
|
|
11
|
+
import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
|
|
12
|
+
import { buildBaseOptions } from "./simple-options.js";
|
|
13
|
+
const OPENAI_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode"]);
|
|
14
|
+
// OpenAI Responses rejects max_output_tokens below 16.
|
|
15
|
+
const OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve cache retention preference.
|
|
18
|
+
* Defaults to "short" and uses MERC_CACHE_RETENTION for backward compatibility.
|
|
19
|
+
*/
|
|
20
|
+
function resolveCacheRetention(cacheRetention, env) {
|
|
21
|
+
if (cacheRetention) {
|
|
22
|
+
return cacheRetention;
|
|
23
|
+
}
|
|
24
|
+
if (getProviderEnvValue("MERC_CACHE_RETENTION", env) === "long") {
|
|
25
|
+
return "long";
|
|
26
|
+
}
|
|
27
|
+
return "short";
|
|
28
|
+
}
|
|
29
|
+
function getCompat(model) {
|
|
30
|
+
return {
|
|
31
|
+
supportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,
|
|
32
|
+
sessionAffinityFormat: model.compat?.sessionAffinityFormat ??
|
|
33
|
+
(model.provider === "openrouter" || model.baseUrl.includes("openrouter.ai") ? "openrouter" : "openai"),
|
|
34
|
+
supportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,
|
|
35
|
+
supportsToolSearch: model.compat?.supportsToolSearch ?? defaultSupportsToolSearch(model),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function defaultSupportsToolSearch(model) {
|
|
39
|
+
if (model.provider !== "openai")
|
|
40
|
+
return false;
|
|
41
|
+
return /gpt-5\.(4|5|6)/.test(model.id);
|
|
42
|
+
}
|
|
43
|
+
function getPromptCacheRetention(compat, cacheRetention) {
|
|
44
|
+
return cacheRetention === "long" && compat.supportsLongCacheRetention ? "24h" : undefined;
|
|
45
|
+
}
|
|
46
|
+
function formatOpenAIResponsesError(error) {
|
|
47
|
+
return formatProviderError(normalizeProviderError(error), "OpenAI API error");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Generate function for OpenAI Responses API
|
|
51
|
+
*/
|
|
52
|
+
export const streamOpenAIResponses = (model, context, options) => {
|
|
53
|
+
const stream = new AssistantMessageEventStream();
|
|
54
|
+
// Start async processing
|
|
55
|
+
(async () => {
|
|
56
|
+
const output = {
|
|
57
|
+
role: "assistant",
|
|
58
|
+
content: [],
|
|
59
|
+
api: model.api,
|
|
60
|
+
provider: model.provider,
|
|
61
|
+
model: model.id,
|
|
62
|
+
usage: {
|
|
63
|
+
input: 0,
|
|
64
|
+
output: 0,
|
|
65
|
+
cacheRead: 0,
|
|
66
|
+
cacheWrite: 0,
|
|
67
|
+
totalTokens: 0,
|
|
68
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
69
|
+
},
|
|
70
|
+
stopReason: "stop",
|
|
71
|
+
timestamp: Date.now(),
|
|
72
|
+
};
|
|
73
|
+
try {
|
|
74
|
+
// Create OpenAI client
|
|
75
|
+
const apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env) || "";
|
|
76
|
+
const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
|
|
77
|
+
const cacheSessionId = cacheRetention === "none" ? undefined : options?.sessionId;
|
|
78
|
+
const client = createClient(model, context, apiKey, options?.headers, cacheSessionId, options?.env);
|
|
79
|
+
let params = buildParams(model, context, options);
|
|
80
|
+
const nextParams = await options?.onPayload?.(params, model);
|
|
81
|
+
if (nextParams !== undefined) {
|
|
82
|
+
params = nextParams;
|
|
83
|
+
}
|
|
84
|
+
const requestOptions = {
|
|
85
|
+
...(options?.signal ? { signal: options.signal } : {}),
|
|
86
|
+
...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
|
|
87
|
+
...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),
|
|
88
|
+
};
|
|
89
|
+
const { data: openaiStream, response } = await client.responses.create(params, requestOptions).withResponse();
|
|
90
|
+
await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
|
|
91
|
+
stream.push({ type: "start", partial: output });
|
|
92
|
+
await processResponsesStream(openaiStream, output, stream, model, {
|
|
93
|
+
serviceTier: options?.serviceTier,
|
|
94
|
+
applyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),
|
|
95
|
+
});
|
|
96
|
+
if (options?.signal?.aborted) {
|
|
97
|
+
throw new Error("Request was aborted");
|
|
98
|
+
}
|
|
99
|
+
if (output.stopReason === "aborted" || output.stopReason === "error") {
|
|
100
|
+
throw new Error("An unknown error occurred");
|
|
101
|
+
}
|
|
102
|
+
stream.push({ type: "done", reason: output.stopReason, message: output });
|
|
103
|
+
stream.end();
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
for (const block of output.content) {
|
|
107
|
+
delete block.index;
|
|
108
|
+
// partialJson is only a streaming scratch buffer; never persist it.
|
|
109
|
+
delete block.partialJson;
|
|
110
|
+
}
|
|
111
|
+
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
112
|
+
output.errorMessage = formatOpenAIResponsesError(error);
|
|
113
|
+
stream.push({ type: "error", reason: output.stopReason, error: output });
|
|
114
|
+
stream.end();
|
|
115
|
+
}
|
|
116
|
+
})();
|
|
117
|
+
return stream;
|
|
118
|
+
};
|
|
119
|
+
export const streamSimpleOpenAIResponses = (model, context, options) => {
|
|
120
|
+
const apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env);
|
|
121
|
+
if (!apiKey && model.authHeader !== false) {
|
|
122
|
+
throw new Error(`No API key for provider: ${model.provider}`);
|
|
123
|
+
}
|
|
124
|
+
const base = buildBaseOptions(model, options, apiKey ?? "");
|
|
125
|
+
const clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;
|
|
126
|
+
const reasoningEffort = clampedReasoning === "off" ? undefined : clampedReasoning;
|
|
127
|
+
return streamOpenAIResponses(model, context, {
|
|
128
|
+
...base,
|
|
129
|
+
reasoningEffort,
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
function createClient(model, context, apiKey, optionsHeaders, sessionId, env) {
|
|
133
|
+
const noAuth = model.authHeader === false;
|
|
134
|
+
if (!apiKey && !noAuth) {
|
|
135
|
+
const configuredApiKey = getProviderEnvValue("OPENAI_API_KEY", env);
|
|
136
|
+
if (!configuredApiKey) {
|
|
137
|
+
throw new Error("OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.");
|
|
138
|
+
}
|
|
139
|
+
apiKey = configuredApiKey;
|
|
140
|
+
}
|
|
141
|
+
if (!apiKey)
|
|
142
|
+
apiKey = "merc-no-auth";
|
|
143
|
+
const compat = getCompat(model);
|
|
144
|
+
const headers = { ...model.headers };
|
|
145
|
+
if (model.provider === "github-copilot") {
|
|
146
|
+
const hasImages = hasCopilotVisionInput(context.messages);
|
|
147
|
+
const copilotHeaders = buildCopilotDynamicHeaders({
|
|
148
|
+
messages: context.messages,
|
|
149
|
+
hasImages,
|
|
150
|
+
});
|
|
151
|
+
Object.assign(headers, copilotHeaders);
|
|
152
|
+
}
|
|
153
|
+
if (sessionId) {
|
|
154
|
+
if (compat.sessionAffinityFormat === "openrouter") {
|
|
155
|
+
headers["x-session-id"] = sessionId;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
if (compat.sessionAffinityFormat === "openai") {
|
|
159
|
+
headers.session_id = sessionId;
|
|
160
|
+
}
|
|
161
|
+
headers["x-client-request-id"] = sessionId;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Merge options headers last so they can override defaults
|
|
165
|
+
if (optionsHeaders) {
|
|
166
|
+
Object.assign(headers, optionsHeaders);
|
|
167
|
+
}
|
|
168
|
+
const defaultHeaders = noAuth
|
|
169
|
+
? { ...headers, Authorization: null }
|
|
170
|
+
: model.provider === "cloudflare-ai-gateway"
|
|
171
|
+
? {
|
|
172
|
+
...headers,
|
|
173
|
+
Authorization: headers.Authorization ?? null,
|
|
174
|
+
"cf-aig-authorization": `Bearer ${apiKey}`,
|
|
175
|
+
}
|
|
176
|
+
: headers;
|
|
177
|
+
return new OpenAI({
|
|
178
|
+
apiKey,
|
|
179
|
+
baseURL: isCloudflareProvider(model.provider) ? resolveCloudflareBaseUrl(model, env) : model.baseUrl,
|
|
180
|
+
dangerouslyAllowBrowser: true,
|
|
181
|
+
defaultHeaders,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
function buildParams(model, context, options) {
|
|
185
|
+
const compat = getCompat(model);
|
|
186
|
+
const toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);
|
|
187
|
+
const messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {
|
|
188
|
+
deferredTools: toolPlacement.deferred,
|
|
189
|
+
});
|
|
190
|
+
const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
|
|
191
|
+
const params = {
|
|
192
|
+
model: model.id,
|
|
193
|
+
input: messages,
|
|
194
|
+
stream: true,
|
|
195
|
+
prompt_cache_key: cacheRetention === "none" ? undefined : options?.sessionId,
|
|
196
|
+
prompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),
|
|
197
|
+
store: false,
|
|
198
|
+
};
|
|
199
|
+
if (options?.maxTokens) {
|
|
200
|
+
params.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);
|
|
201
|
+
}
|
|
202
|
+
if (options?.temperature !== undefined) {
|
|
203
|
+
params.temperature = options?.temperature;
|
|
204
|
+
}
|
|
205
|
+
if (options?.serviceTier !== undefined) {
|
|
206
|
+
params.service_tier = options.serviceTier;
|
|
207
|
+
}
|
|
208
|
+
if (toolPlacement.immediate.length > 0) {
|
|
209
|
+
params.tools = convertResponsesTools(toolPlacement.immediate);
|
|
210
|
+
}
|
|
211
|
+
if (options?.toolChoice !== undefined) {
|
|
212
|
+
params.tool_choice = options.toolChoice;
|
|
213
|
+
}
|
|
214
|
+
if (model.reasoning) {
|
|
215
|
+
if (options?.reasoningEffort || options?.reasoningSummary) {
|
|
216
|
+
const effort = options?.reasoningEffort
|
|
217
|
+
? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)
|
|
218
|
+
: "medium";
|
|
219
|
+
params.reasoning = {
|
|
220
|
+
effort: effort,
|
|
221
|
+
summary: options?.reasoningSummary || "auto",
|
|
222
|
+
};
|
|
223
|
+
params.include = ["reasoning.encrypted_content"];
|
|
224
|
+
}
|
|
225
|
+
else if (model.provider !== "github-copilot" && model.thinkingLevelMap?.off !== null) {
|
|
226
|
+
params.reasoning = {
|
|
227
|
+
effort: (model.thinkingLevelMap?.off ?? "none"),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return params;
|
|
232
|
+
}
|
|
233
|
+
function getServiceTierCostMultiplier(model, serviceTier) {
|
|
234
|
+
switch (serviceTier) {
|
|
235
|
+
case "flex":
|
|
236
|
+
return 0.5;
|
|
237
|
+
case "priority":
|
|
238
|
+
return model.id === "gpt-5.5" ? 2.5 : 2;
|
|
239
|
+
default:
|
|
240
|
+
return 1;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function applyServiceTierPricing(usage, serviceTier, model) {
|
|
244
|
+
const multiplier = getServiceTierCostMultiplier(model, serviceTier);
|
|
245
|
+
if (multiplier === 1)
|
|
246
|
+
return;
|
|
247
|
+
usage.cost.input *= multiplier;
|
|
248
|
+
usage.cost.output *= multiplier;
|
|
249
|
+
usage.cost.cacheRead *= multiplier;
|
|
250
|
+
usage.cost.cacheWrite *= multiplier;
|
|
251
|
+
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=openai-responses.js.map
|
|
@@ -0,0 +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.js\";\nimport { clampThinkingLevel } from \"../models.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.js\";\nimport { splitDeferredTools } from \"../utils/deferred-tools.js\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { headersToRecord } from \"../utils/headers.js\";\nimport { getProviderEnvValue } from \"../utils/provider-env.js\";\nimport { isCloudflareProvider, resolveCloudflareBaseUrl } from \"./cloudflare.js\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.js\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.js\";\nimport { buildBaseOptions } from \"./simple-options.js\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16.\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses MERC_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"MERC_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsessionAffinityFormat:\n\t\t\tmodel.compat?.sessionAffinityFormat ??\n\t\t\t(model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\") ? \"openrouter\" : \"openai\"),\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t\tsupportsToolSearch: model.compat?.supportsToolSearch ?? defaultSupportsToolSearch(model),\n\t};\n}\n\nfunction defaultSupportsToolSearch(model: Model<\"openai-responses\">): boolean {\n\tif (model.provider !== \"openai\") return false;\n\treturn /gpt-5\\.(4|5|6)/.test(model.id);\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\" | \"max\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n\ttoolChoice?: ResponseCreateParamsStreaming[\"tool_choice\"];\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, options?.env) || \"\";\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, cacheSessionId, options?.env);\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\t...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),\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, options?.env);\n\tif (!apiKey && model.authHeader !== false) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst base = buildBaseOptions(model, 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\tenv?: ProviderEnv,\n) {\n\tconst noAuth = model.authHeader === false;\n\tif (!apiKey && !noAuth) {\n\t\tconst configuredApiKey = getProviderEnvValue(\"OPENAI_API_KEY\", env);\n\t\tif (!configuredApiKey) {\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 = configuredApiKey;\n\t}\n\tif (!apiKey) apiKey = \"merc-no-auth\";\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.sessionAffinityFormat === \"openrouter\") {\n\t\t\theaders[\"x-session-id\"] = sessionId;\n\t\t} else {\n\t\t\tif (compat.sessionAffinityFormat === \"openai\") {\n\t\t\t\theaders.session_id = sessionId;\n\t\t\t}\n\t\t\theaders[\"x-client-request-id\"] = sessionId;\n\t\t}\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 = noAuth\n\t\t? { ...headers, Authorization: null }\n\t\t: model.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, env) : 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 compat = getCompat(model);\n\tconst toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {\n\t\tdeferredTools: toolPlacement.deferred,\n\t});\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\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 : 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 (toolPlacement.immediate.length > 0) {\n\t\tparams.tools = convertResponsesTools(toolPlacement.immediate);\n\t}\n\n\tif (options?.toolChoice !== undefined) {\n\t\tparams.tool_choice = options.toolChoice;\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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter-images.d.ts","sourceRoot":"","sources":["../../src/providers/openrouter-images.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAIX,cAAc,EAEd,aAAa,EAEb,MAAM,aAAa,CAAC;AAsBrB,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,mBAAmB,EAAE,aAAa,CAiF/E,CAAC","sourcesContent":["import OpenAI from \"openai\";\nimport type {\n\tChatCompletion,\n\tChatCompletionContentPart,\n\tChatCompletionContentPartImage,\n\tChatCompletionContentPartText,\n\tChatCompletionCreateParamsNonStreaming,\n} from \"openai/resources/chat/completions.js\";\nimport { getEnvApiKey } from \"../env-api-keys.js\";\nimport type {\n\tAssistantImages,\n\tImageContent,\n\tImagesContext,\n\tImagesFunction,\n\tImagesModel,\n\tImagesOptions,\n\tTextContent,\n} from \"../types.js\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.js\";\nimport { AssistantImagesEventStream } from \"../utils/event-stream.js\";\nimport { headersToRecord } from \"../utils/headers.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\n\ninterface OpenRouterGeneratedImage {\n\timage_url?: string | { url?: string };\n}\n\ntype OpenRouterImageGenerationMessage = ChatCompletion[\"choices\"][number][\"message\"] & {\n\timages?: OpenRouterGeneratedImage[];\n};\n\ntype OpenRouterImageGenerationChoice = ChatCompletion[\"choices\"][number] & {\n\tmessage: OpenRouterImageGenerationMessage;\n};\n\ntype OpenRouterImageGenerationResponse = ChatCompletion & {\n\tchoices: OpenRouterImageGenerationChoice[];\n};\n\nexport const imagesOpenRouter: ImagesFunction<\"openrouter-images\", ImagesOptions> = (\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tcontext: ImagesContext,\n\toptions?: ImagesOptions,\n) => {\n\tconst stream = new AssistantImagesEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantImages = {\n\t\t\tapi: model.api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\toutput: [],\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env) || \"\";\n\t\t\tconst client = createClient(model, apiKey, options?.headers);\n\t\t\tlet params = buildParams(model, context);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as typeof params;\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\t...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),\n\t\t\t};\n\t\t\tconst { data: response, response: rawResponse } = await client.chat.completions\n\t\t\t\t.create(params as unknown as ChatCompletionCreateParamsNonStreaming, requestOptions)\n\t\t\t\t.withResponse();\n\t\t\tawait options?.onResponse?.(\n\t\t\t\t{ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) },\n\t\t\t\tmodel,\n\t\t\t);\n\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tconst imageResponse = response as OpenRouterImageGenerationResponse;\n\t\t\toutput.responseId = imageResponse.id;\n\t\t\tif (imageResponse.usage) {\n\t\t\t\toutput.usage = parseUsage(imageResponse.usage, model);\n\t\t\t}\n\n\t\t\tconst choice = imageResponse.choices[0];\n\t\t\tif (choice) {\n\t\t\t\tconst content = choice.message.content;\n\t\t\t\tif (typeof content === \"string\" && content.length > 0) {\n\t\t\t\t\toutput.output.push({ type: \"text\", text: content } satisfies TextContent);\n\t\t\t\t}\n\n\t\t\t\tfor (const image of choice.message.images ?? []) {\n\t\t\t\t\tconst imageUrl = typeof image.image_url === \"string\" ? image.image_url : image.image_url?.url;\n\t\t\t\t\tif (!imageUrl?.startsWith(\"data:\")) continue;\n\t\t\t\t\tconst matches = imageUrl.match(/^data:([^;]+);base64,(.+)$/);\n\t\t\t\t\tif (!matches) continue;\n\t\t\t\t\tconst imageBlock: ImageContent = {\n\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\tmimeType: matches[1],\n\t\t\t\t\t\tdata: matches[2],\n\t\t\t\t\t};\n\t\t\t\t\toutput.output.push(imageBlock);\n\t\t\t\t\tconst contentIndex = output.output.length - 1;\n\t\t\t\t\tstream.push({ type: \"image_start\", contentIndex, partial: output });\n\t\t\t\t\tstream.push({ type: \"image_end\", contentIndex, image: imageBlock, partial: output });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: \"stop\", images: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatProviderError(normalizeProviderError(error));\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end(output);\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction createClient(\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tapiKey: string,\n\toptionsHeaders?: Record<string, string>,\n): OpenAI {\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: {\n\t\t\t...model.headers,\n\t\t\t...optionsHeaders,\n\t\t},\n\t});\n}\n\ntype OpenRouterImagesCreateParams = Omit<ChatCompletionCreateParamsNonStreaming, \"modalities\"> & {\n\tmodalities: Array<\"image\" | \"text\">;\n};\n\nfunction buildParams(model: ImagesModel<\"openrouter-images\">, context: ImagesContext): OpenRouterImagesCreateParams {\n\tconst content: ChatCompletionContentPart[] = context.input.map((item): ChatCompletionContentPart => {\n\t\tif (item.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t} satisfies ChatCompletionContentPartText;\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image_url\",\n\t\t\timage_url: {\n\t\t\t\turl: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t},\n\t\t} satisfies ChatCompletionContentPartImage;\n\t});\n\n\treturn {\n\t\tmodel: model.id,\n\t\tmessages: [\n\t\t\t{\n\t\t\t\trole: \"user\" as const,\n\t\t\t\tcontent,\n\t\t\t},\n\t\t],\n\t\tstream: false,\n\t\tmodalities: model.output.includes(\"text\") ? [\"image\", \"text\"] : [\"image\"],\n\t};\n}\n\nfunction parseUsage(\n\trawUsage: {\n\t\tprompt_tokens?: number;\n\t\tcompletion_tokens?: number;\n\t\tprompt_tokens_details?: { cached_tokens?: number; cache_write_tokens?: number };\n\t},\n\tmodel: ImagesModel<\"openrouter-images\">,\n) {\n\tconst promptTokens = rawUsage.prompt_tokens || 0;\n\tconst reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;\n\tconst cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;\n\tconst cacheReadTokens =\n\t\tcacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;\n\tconst input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);\n\tconst output = rawUsage.completion_tokens || 0;\n\tconst usage = {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: cacheReadTokens,\n\t\tcacheWrite: cacheWriteTokens,\n\t\ttotalTokens: input + output + cacheReadTokens + cacheWriteTokens,\n\t\tcost: {\n\t\t\tinput: (model.cost.input / 1000000) * input,\n\t\t\toutput: (model.cost.output / 1000000) * output,\n\t\t\tcacheRead: (model.cost.cacheRead / 1000000) * cacheReadTokens,\n\t\t\tcacheWrite: (model.cost.cacheWrite / 1000000) * cacheWriteTokens,\n\t\t\ttotal: 0,\n\t\t},\n\t};\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage;\n}\n"]}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import OpenAI from "openai";
|
|
2
|
+
import { getEnvApiKey } from "../env-api-keys.js";
|
|
3
|
+
import { formatProviderError, normalizeProviderError } from "../utils/error-body.js";
|
|
4
|
+
import { AssistantImagesEventStream } from "../utils/event-stream.js";
|
|
5
|
+
import { headersToRecord } from "../utils/headers.js";
|
|
6
|
+
import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
|
|
7
|
+
export const imagesOpenRouter = (model, context, options) => {
|
|
8
|
+
const stream = new AssistantImagesEventStream();
|
|
9
|
+
(async () => {
|
|
10
|
+
const output = {
|
|
11
|
+
api: model.api,
|
|
12
|
+
provider: model.provider,
|
|
13
|
+
model: model.id,
|
|
14
|
+
output: [],
|
|
15
|
+
stopReason: "stop",
|
|
16
|
+
timestamp: Date.now(),
|
|
17
|
+
};
|
|
18
|
+
try {
|
|
19
|
+
const apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env) || "";
|
|
20
|
+
const client = createClient(model, apiKey, options?.headers);
|
|
21
|
+
let params = buildParams(model, context);
|
|
22
|
+
const nextParams = await options?.onPayload?.(params, model);
|
|
23
|
+
if (nextParams !== undefined) {
|
|
24
|
+
params = nextParams;
|
|
25
|
+
}
|
|
26
|
+
const requestOptions = {
|
|
27
|
+
...(options?.signal ? { signal: options.signal } : {}),
|
|
28
|
+
...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
|
|
29
|
+
...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),
|
|
30
|
+
};
|
|
31
|
+
const { data: response, response: rawResponse } = await client.chat.completions
|
|
32
|
+
.create(params, requestOptions)
|
|
33
|
+
.withResponse();
|
|
34
|
+
await options?.onResponse?.({ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) }, model);
|
|
35
|
+
stream.push({ type: "start", partial: output });
|
|
36
|
+
const imageResponse = response;
|
|
37
|
+
output.responseId = imageResponse.id;
|
|
38
|
+
if (imageResponse.usage) {
|
|
39
|
+
output.usage = parseUsage(imageResponse.usage, model);
|
|
40
|
+
}
|
|
41
|
+
const choice = imageResponse.choices[0];
|
|
42
|
+
if (choice) {
|
|
43
|
+
const content = choice.message.content;
|
|
44
|
+
if (typeof content === "string" && content.length > 0) {
|
|
45
|
+
output.output.push({ type: "text", text: content });
|
|
46
|
+
}
|
|
47
|
+
for (const image of choice.message.images ?? []) {
|
|
48
|
+
const imageUrl = typeof image.image_url === "string" ? image.image_url : image.image_url?.url;
|
|
49
|
+
if (!imageUrl?.startsWith("data:"))
|
|
50
|
+
continue;
|
|
51
|
+
const matches = imageUrl.match(/^data:([^;]+);base64,(.+)$/);
|
|
52
|
+
if (!matches)
|
|
53
|
+
continue;
|
|
54
|
+
const imageBlock = {
|
|
55
|
+
type: "image",
|
|
56
|
+
mimeType: matches[1],
|
|
57
|
+
data: matches[2],
|
|
58
|
+
};
|
|
59
|
+
output.output.push(imageBlock);
|
|
60
|
+
const contentIndex = output.output.length - 1;
|
|
61
|
+
stream.push({ type: "image_start", contentIndex, partial: output });
|
|
62
|
+
stream.push({ type: "image_end", contentIndex, image: imageBlock, partial: output });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
stream.push({ type: "done", reason: "stop", images: output });
|
|
66
|
+
stream.end();
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
70
|
+
output.errorMessage = formatProviderError(normalizeProviderError(error));
|
|
71
|
+
stream.push({ type: "error", reason: output.stopReason, error: output });
|
|
72
|
+
stream.end(output);
|
|
73
|
+
}
|
|
74
|
+
})();
|
|
75
|
+
return stream;
|
|
76
|
+
};
|
|
77
|
+
function createClient(model, apiKey, optionsHeaders) {
|
|
78
|
+
return new OpenAI({
|
|
79
|
+
apiKey,
|
|
80
|
+
baseURL: model.baseUrl,
|
|
81
|
+
dangerouslyAllowBrowser: true,
|
|
82
|
+
defaultHeaders: {
|
|
83
|
+
...model.headers,
|
|
84
|
+
...optionsHeaders,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function buildParams(model, context) {
|
|
89
|
+
const content = context.input.map((item) => {
|
|
90
|
+
if (item.type === "text") {
|
|
91
|
+
return {
|
|
92
|
+
type: "text",
|
|
93
|
+
text: sanitizeSurrogates(item.text),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
type: "image_url",
|
|
98
|
+
image_url: {
|
|
99
|
+
url: `data:${item.mimeType};base64,${item.data}`,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
model: model.id,
|
|
105
|
+
messages: [
|
|
106
|
+
{
|
|
107
|
+
role: "user",
|
|
108
|
+
content,
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
stream: false,
|
|
112
|
+
modalities: model.output.includes("text") ? ["image", "text"] : ["image"],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function parseUsage(rawUsage, model) {
|
|
116
|
+
const promptTokens = rawUsage.prompt_tokens || 0;
|
|
117
|
+
const reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;
|
|
118
|
+
const cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;
|
|
119
|
+
const cacheReadTokens = cacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;
|
|
120
|
+
const input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);
|
|
121
|
+
const output = rawUsage.completion_tokens || 0;
|
|
122
|
+
const usage = {
|
|
123
|
+
input,
|
|
124
|
+
output,
|
|
125
|
+
cacheRead: cacheReadTokens,
|
|
126
|
+
cacheWrite: cacheWriteTokens,
|
|
127
|
+
totalTokens: input + output + cacheReadTokens + cacheWriteTokens,
|
|
128
|
+
cost: {
|
|
129
|
+
input: (model.cost.input / 1000000) * input,
|
|
130
|
+
output: (model.cost.output / 1000000) * output,
|
|
131
|
+
cacheRead: (model.cost.cacheRead / 1000000) * cacheReadTokens,
|
|
132
|
+
cacheWrite: (model.cost.cacheWrite / 1000000) * cacheWriteTokens,
|
|
133
|
+
total: 0,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
137
|
+
return usage;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=openrouter-images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter-images.js","sourceRoot":"","sources":["../../src/providers/openrouter-images.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type {\n\tChatCompletion,\n\tChatCompletionContentPart,\n\tChatCompletionContentPartImage,\n\tChatCompletionContentPartText,\n\tChatCompletionCreateParamsNonStreaming,\n} from \"openai/resources/chat/completions.js\";\nimport { getEnvApiKey } from \"../env-api-keys.js\";\nimport type {\n\tAssistantImages,\n\tImageContent,\n\tImagesContext,\n\tImagesFunction,\n\tImagesModel,\n\tImagesOptions,\n\tTextContent,\n} from \"../types.js\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.js\";\nimport { AssistantImagesEventStream } from \"../utils/event-stream.js\";\nimport { headersToRecord } from \"../utils/headers.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\n\ninterface OpenRouterGeneratedImage {\n\timage_url?: string | { url?: string };\n}\n\ntype OpenRouterImageGenerationMessage = ChatCompletion[\"choices\"][number][\"message\"] & {\n\timages?: OpenRouterGeneratedImage[];\n};\n\ntype OpenRouterImageGenerationChoice = ChatCompletion[\"choices\"][number] & {\n\tmessage: OpenRouterImageGenerationMessage;\n};\n\ntype OpenRouterImageGenerationResponse = ChatCompletion & {\n\tchoices: OpenRouterImageGenerationChoice[];\n};\n\nexport const imagesOpenRouter: ImagesFunction<\"openrouter-images\", ImagesOptions> = (\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tcontext: ImagesContext,\n\toptions?: ImagesOptions,\n) => {\n\tconst stream = new AssistantImagesEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantImages = {\n\t\t\tapi: model.api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\toutput: [],\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env) || \"\";\n\t\t\tconst client = createClient(model, apiKey, options?.headers);\n\t\t\tlet params = buildParams(model, context);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as typeof params;\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\t...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),\n\t\t\t};\n\t\t\tconst { data: response, response: rawResponse } = await client.chat.completions\n\t\t\t\t.create(params as unknown as ChatCompletionCreateParamsNonStreaming, requestOptions)\n\t\t\t\t.withResponse();\n\t\t\tawait options?.onResponse?.(\n\t\t\t\t{ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) },\n\t\t\t\tmodel,\n\t\t\t);\n\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tconst imageResponse = response as OpenRouterImageGenerationResponse;\n\t\t\toutput.responseId = imageResponse.id;\n\t\t\tif (imageResponse.usage) {\n\t\t\t\toutput.usage = parseUsage(imageResponse.usage, model);\n\t\t\t}\n\n\t\t\tconst choice = imageResponse.choices[0];\n\t\t\tif (choice) {\n\t\t\t\tconst content = choice.message.content;\n\t\t\t\tif (typeof content === \"string\" && content.length > 0) {\n\t\t\t\t\toutput.output.push({ type: \"text\", text: content } satisfies TextContent);\n\t\t\t\t}\n\n\t\t\t\tfor (const image of choice.message.images ?? []) {\n\t\t\t\t\tconst imageUrl = typeof image.image_url === \"string\" ? image.image_url : image.image_url?.url;\n\t\t\t\t\tif (!imageUrl?.startsWith(\"data:\")) continue;\n\t\t\t\t\tconst matches = imageUrl.match(/^data:([^;]+);base64,(.+)$/);\n\t\t\t\t\tif (!matches) continue;\n\t\t\t\t\tconst imageBlock: ImageContent = {\n\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\tmimeType: matches[1],\n\t\t\t\t\t\tdata: matches[2],\n\t\t\t\t\t};\n\t\t\t\t\toutput.output.push(imageBlock);\n\t\t\t\t\tconst contentIndex = output.output.length - 1;\n\t\t\t\t\tstream.push({ type: \"image_start\", contentIndex, partial: output });\n\t\t\t\t\tstream.push({ type: \"image_end\", contentIndex, image: imageBlock, partial: output });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: \"stop\", images: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatProviderError(normalizeProviderError(error));\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end(output);\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction createClient(\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tapiKey: string,\n\toptionsHeaders?: Record<string, string>,\n): OpenAI {\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: {\n\t\t\t...model.headers,\n\t\t\t...optionsHeaders,\n\t\t},\n\t});\n}\n\ntype OpenRouterImagesCreateParams = Omit<ChatCompletionCreateParamsNonStreaming, \"modalities\"> & {\n\tmodalities: Array<\"image\" | \"text\">;\n};\n\nfunction buildParams(model: ImagesModel<\"openrouter-images\">, context: ImagesContext): OpenRouterImagesCreateParams {\n\tconst content: ChatCompletionContentPart[] = context.input.map((item): ChatCompletionContentPart => {\n\t\tif (item.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t} satisfies ChatCompletionContentPartText;\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image_url\",\n\t\t\timage_url: {\n\t\t\t\turl: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t},\n\t\t} satisfies ChatCompletionContentPartImage;\n\t});\n\n\treturn {\n\t\tmodel: model.id,\n\t\tmessages: [\n\t\t\t{\n\t\t\t\trole: \"user\" as const,\n\t\t\t\tcontent,\n\t\t\t},\n\t\t],\n\t\tstream: false,\n\t\tmodalities: model.output.includes(\"text\") ? [\"image\", \"text\"] : [\"image\"],\n\t};\n}\n\nfunction parseUsage(\n\trawUsage: {\n\t\tprompt_tokens?: number;\n\t\tcompletion_tokens?: number;\n\t\tprompt_tokens_details?: { cached_tokens?: number; cache_write_tokens?: number };\n\t},\n\tmodel: ImagesModel<\"openrouter-images\">,\n) {\n\tconst promptTokens = rawUsage.prompt_tokens || 0;\n\tconst reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;\n\tconst cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;\n\tconst cacheReadTokens =\n\t\tcacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;\n\tconst input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);\n\tconst output = rawUsage.completion_tokens || 0;\n\tconst usage = {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: cacheReadTokens,\n\t\tcacheWrite: cacheWriteTokens,\n\t\ttotalTokens: input + output + cacheReadTokens + cacheWriteTokens,\n\t\tcost: {\n\t\t\tinput: (model.cost.input / 1000000) * input,\n\t\t\toutput: (model.cost.output / 1000000) * output,\n\t\t\tcacheRead: (model.cost.cacheRead / 1000000) * cacheReadTokens,\n\t\t\tcacheWrite: (model.cost.cacheWrite / 1000000) * cacheWriteTokens,\n\t\t\ttotal: 0,\n\t\t},\n\t};\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage;\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AssistantMessageEvent, Context, Model, SimpleStreamOptions, StreamFunction, StreamOptions } from "../types.js";
|
|
2
|
+
import type { BedrockOptions } from "./amazon-bedrock.js";
|
|
3
|
+
import type { AnthropicOptions } from "./anthropic.js";
|
|
4
|
+
import type { AzureOpenAIResponsesOptions } from "./azure-openai-responses.js";
|
|
5
|
+
import type { GoogleOptions } from "./google.js";
|
|
6
|
+
import type { GoogleVertexOptions } from "./google-vertex.js";
|
|
7
|
+
import type { MistralOptions } from "./mistral.js";
|
|
8
|
+
import type { OpenAICodexResponsesOptions } from "./openai-codex-responses.js";
|
|
9
|
+
import type { OpenAICompletionsOptions } from "./openai-completions.js";
|
|
10
|
+
import type { OpenAIResponsesOptions } from "./openai-responses.js";
|
|
11
|
+
interface BedrockProviderModule {
|
|
12
|
+
streamBedrock: (model: Model<"bedrock-converse-stream">, context: Context, options?: BedrockOptions) => AsyncIterable<AssistantMessageEvent>;
|
|
13
|
+
streamSimpleBedrock: (model: Model<"bedrock-converse-stream">, context: Context, options?: SimpleStreamOptions) => AsyncIterable<AssistantMessageEvent>;
|
|
14
|
+
}
|
|
15
|
+
export declare function setBedrockProviderModule(module: BedrockProviderModule): void;
|
|
16
|
+
export declare const streamAnthropic: StreamFunction<"anthropic-messages", AnthropicOptions>;
|
|
17
|
+
export declare const streamSimpleAnthropic: StreamFunction<"anthropic-messages", SimpleStreamOptions>;
|
|
18
|
+
export declare const streamAzureOpenAIResponses: StreamFunction<"azure-openai-responses", AzureOpenAIResponsesOptions>;
|
|
19
|
+
export declare const streamSimpleAzureOpenAIResponses: StreamFunction<"azure-openai-responses", SimpleStreamOptions>;
|
|
20
|
+
export declare const streamGoogle: StreamFunction<"google-generative-ai", GoogleOptions>;
|
|
21
|
+
export declare const streamSimpleGoogle: StreamFunction<"google-generative-ai", SimpleStreamOptions>;
|
|
22
|
+
export declare const streamGoogleVertex: StreamFunction<"google-vertex", GoogleVertexOptions>;
|
|
23
|
+
export declare const streamSimpleGoogleVertex: StreamFunction<"google-vertex", SimpleStreamOptions>;
|
|
24
|
+
export declare const streamMistral: StreamFunction<"mistral-conversations", MistralOptions>;
|
|
25
|
+
export declare const streamSimpleMistral: StreamFunction<"mistral-conversations", SimpleStreamOptions>;
|
|
26
|
+
export declare const streamOpenAICodexResponses: StreamFunction<"openai-codex-responses", OpenAICodexResponsesOptions>;
|
|
27
|
+
export declare const streamSimpleOpenAICodexResponses: StreamFunction<"openai-codex-responses", SimpleStreamOptions>;
|
|
28
|
+
export declare const streamOpenAICompletions: StreamFunction<"openai-completions", OpenAICompletionsOptions>;
|
|
29
|
+
export declare const streamSimpleOpenAICompletions: StreamFunction<"openai-completions", SimpleStreamOptions>;
|
|
30
|
+
export declare const streamOpenAIResponses: StreamFunction<"openai-responses", OpenAIResponsesOptions>;
|
|
31
|
+
export declare const streamSimpleOpenAIResponses: StreamFunction<"openai-responses", SimpleStreamOptions>;
|
|
32
|
+
export declare const streamClaudeCli: StreamFunction<"claude-cli", StreamOptions>;
|
|
33
|
+
export declare const streamSimpleClaudeCli: StreamFunction<"claude-cli", SimpleStreamOptions>;
|
|
34
|
+
export declare function registerBuiltInApiProviders(): void;
|
|
35
|
+
export declare function resetApiProviders(): void;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=register-builtins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-builtins.d.ts","sourceRoot":"","sources":["../../src/providers/register-builtins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGX,qBAAqB,EACrB,OAAO,EACP,KAAK,EACL,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC/E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAuDpE,UAAU,qBAAqB;IAC9B,aAAa,EAAE,CACd,KAAK,EAAE,KAAK,CAAC,yBAAyB,CAAC,EACvC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,cAAc,KACpB,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC1C,mBAAmB,EAAE,CACpB,KAAK,EAAE,KAAK,CAAC,yBAAyB,CAAC,EACvC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,KACzB,aAAa,CAAC,qBAAqB,CAAC,CAAC;CAC1C;AA2CD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAK5E;AA+MD,eAAO,MAAM,eAAe,wDAAgD,CAAC;AAC7E,eAAO,MAAM,qBAAqB,2DAAsD,CAAC;AACzF,eAAO,MAAM,0BAA0B,uEAA2D,CAAC;AACnG,eAAO,MAAM,gCAAgC,+DAAiE,CAAC;AAC/G,eAAO,MAAM,YAAY,uDAA6C,CAAC;AACvE,eAAO,MAAM,kBAAkB,6DAAmD,CAAC;AACnF,eAAO,MAAM,kBAAkB,sDAAmD,CAAC;AACnF,eAAO,MAAM,wBAAwB,sDAAyD,CAAC;AAC/F,eAAO,MAAM,aAAa,yDAA8C,CAAC;AACzE,eAAO,MAAM,mBAAmB,8DAAoD,CAAC;AACrF,eAAO,MAAM,0BAA0B,uEAA2D,CAAC;AACnG,eAAO,MAAM,gCAAgC,+DAAiE,CAAC;AAC/G,eAAO,MAAM,uBAAuB,gEAAwD,CAAC;AAC7F,eAAO,MAAM,6BAA6B,2DAA8D,CAAC;AACzG,eAAO,MAAM,qBAAqB,4DAAsD,CAAC;AACzF,eAAO,MAAM,2BAA2B,yDAA4D,CAAC;AAGrG,eAAO,MAAM,eAAe,6CAAgD,CAAC;AAC7E,eAAO,MAAM,qBAAqB,mDAAsD,CAAC;AAEzF,wBAAgB,2BAA2B,IAAI,IAAI,CA4DlD;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC","sourcesContent":["import { clearApiProviders, registerApiProvider } from \"../api-registry.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tContext,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport type { BedrockOptions } from \"./amazon-bedrock.js\";\nimport type { AnthropicOptions } from \"./anthropic.js\";\nimport type { AzureOpenAIResponsesOptions } from \"./azure-openai-responses.js\";\nimport type { GoogleOptions } from \"./google.js\";\nimport type { GoogleVertexOptions } from \"./google-vertex.js\";\nimport type { MistralOptions } from \"./mistral.js\";\nimport type { OpenAICodexResponsesOptions } from \"./openai-codex-responses.js\";\nimport type { OpenAICompletionsOptions } from \"./openai-completions.js\";\nimport type { OpenAIResponsesOptions } from \"./openai-responses.js\";\n\ninterface LazyProviderModule<\n\tTApi extends Api,\n\tTOptions extends StreamOptions,\n\tTSimpleOptions extends SimpleStreamOptions,\n> {\n\tstream: (model: Model<TApi>, context: Context, options?: TOptions) => AsyncIterable<AssistantMessageEvent>;\n\tstreamSimple: (\n\t\tmodel: Model<TApi>,\n\t\tcontext: Context,\n\t\toptions?: TSimpleOptions,\n\t) => AsyncIterable<AssistantMessageEvent>;\n}\n\ninterface AnthropicProviderModule {\n\tstreamAnthropic: StreamFunction<\"anthropic-messages\", AnthropicOptions>;\n\tstreamSimpleAnthropic: StreamFunction<\"anthropic-messages\", SimpleStreamOptions>;\n}\n\ninterface AzureOpenAIResponsesProviderModule {\n\tstreamAzureOpenAIResponses: StreamFunction<\"azure-openai-responses\", AzureOpenAIResponsesOptions>;\n\tstreamSimpleAzureOpenAIResponses: StreamFunction<\"azure-openai-responses\", SimpleStreamOptions>;\n}\n\ninterface GoogleProviderModule {\n\tstreamGoogle: StreamFunction<\"google-generative-ai\", GoogleOptions>;\n\tstreamSimpleGoogle: StreamFunction<\"google-generative-ai\", SimpleStreamOptions>;\n}\n\ninterface GoogleVertexProviderModule {\n\tstreamGoogleVertex: StreamFunction<\"google-vertex\", GoogleVertexOptions>;\n\tstreamSimpleGoogleVertex: StreamFunction<\"google-vertex\", SimpleStreamOptions>;\n}\n\ninterface MistralProviderModule {\n\tstreamMistral: StreamFunction<\"mistral-conversations\", MistralOptions>;\n\tstreamSimpleMistral: StreamFunction<\"mistral-conversations\", SimpleStreamOptions>;\n}\n\ninterface OpenAICodexResponsesProviderModule {\n\tstreamOpenAICodexResponses: StreamFunction<\"openai-codex-responses\", OpenAICodexResponsesOptions>;\n\tstreamSimpleOpenAICodexResponses: StreamFunction<\"openai-codex-responses\", SimpleStreamOptions>;\n}\n\ninterface OpenAICompletionsProviderModule {\n\tstreamOpenAICompletions: StreamFunction<\"openai-completions\", OpenAICompletionsOptions>;\n\tstreamSimpleOpenAICompletions: StreamFunction<\"openai-completions\", SimpleStreamOptions>;\n}\n\ninterface OpenAIResponsesProviderModule {\n\tstreamOpenAIResponses: StreamFunction<\"openai-responses\", OpenAIResponsesOptions>;\n\tstreamSimpleOpenAIResponses: StreamFunction<\"openai-responses\", SimpleStreamOptions>;\n}\n\ninterface BedrockProviderModule {\n\tstreamBedrock: (\n\t\tmodel: Model<\"bedrock-converse-stream\">,\n\t\tcontext: Context,\n\t\toptions?: BedrockOptions,\n\t) => AsyncIterable<AssistantMessageEvent>;\n\tstreamSimpleBedrock: (\n\t\tmodel: Model<\"bedrock-converse-stream\">,\n\t\tcontext: Context,\n\t\toptions?: SimpleStreamOptions,\n\t) => AsyncIterable<AssistantMessageEvent>;\n}\n\ninterface ClaudeCliProviderModule {\n\tstreamClaudeCli: StreamFunction<\"claude-cli\", StreamOptions>;\n\tstreamSimpleClaudeCli: StreamFunction<\"claude-cli\", SimpleStreamOptions>;\n}\n\nconst importNodeOnlyProvider = (specifier: string): Promise<unknown> => import(specifier);\n\nlet anthropicProviderModulePromise:\n\t| Promise<LazyProviderModule<\"anthropic-messages\", AnthropicOptions, SimpleStreamOptions>>\n\t| undefined;\nlet azureOpenAIResponsesProviderModulePromise:\n\t| Promise<LazyProviderModule<\"azure-openai-responses\", AzureOpenAIResponsesOptions, SimpleStreamOptions>>\n\t| undefined;\nlet googleProviderModulePromise:\n\t| Promise<LazyProviderModule<\"google-generative-ai\", GoogleOptions, SimpleStreamOptions>>\n\t| undefined;\nlet googleVertexProviderModulePromise:\n\t| Promise<LazyProviderModule<\"google-vertex\", GoogleVertexOptions, SimpleStreamOptions>>\n\t| undefined;\nlet mistralProviderModulePromise:\n\t| Promise<LazyProviderModule<\"mistral-conversations\", MistralOptions, SimpleStreamOptions>>\n\t| undefined;\nlet openAICodexResponsesProviderModulePromise:\n\t| Promise<LazyProviderModule<\"openai-codex-responses\", OpenAICodexResponsesOptions, SimpleStreamOptions>>\n\t| undefined;\nlet openAICompletionsProviderModulePromise:\n\t| Promise<LazyProviderModule<\"openai-completions\", OpenAICompletionsOptions, SimpleStreamOptions>>\n\t| undefined;\nlet openAIResponsesProviderModulePromise:\n\t| Promise<LazyProviderModule<\"openai-responses\", OpenAIResponsesOptions, SimpleStreamOptions>>\n\t| undefined;\nlet bedrockProviderModuleOverride:\n\t| LazyProviderModule<\"bedrock-converse-stream\", BedrockOptions, SimpleStreamOptions>\n\t| undefined;\nlet bedrockProviderModulePromise:\n\t| Promise<LazyProviderModule<\"bedrock-converse-stream\", BedrockOptions, SimpleStreamOptions>>\n\t| undefined;\nlet claudeCliProviderModulePromise:\n\t| Promise<LazyProviderModule<\"claude-cli\", StreamOptions, SimpleStreamOptions>>\n\t| undefined;\n\nexport function setBedrockProviderModule(module: BedrockProviderModule): void {\n\tbedrockProviderModuleOverride = {\n\t\tstream: module.streamBedrock,\n\t\tstreamSimple: module.streamSimpleBedrock,\n\t};\n}\n\nfunction forwardStream(target: AssistantMessageEventStream, source: AsyncIterable<AssistantMessageEvent>): void {\n\t(async () => {\n\t\tfor await (const event of source) {\n\t\t\ttarget.push(event);\n\t\t}\n\t\ttarget.end();\n\t})();\n}\n\nfunction createLazyLoadErrorMessage<TApi extends Api>(model: Model<TApi>, error: unknown): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.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: \"error\",\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction createLazyStream<TApi extends Api, TOptions extends StreamOptions, TSimpleOptions extends SimpleStreamOptions>(\n\tloadModule: () => Promise<LazyProviderModule<TApi, TOptions, TSimpleOptions>>,\n): StreamFunction<TApi, TOptions> {\n\treturn (model, context, options) => {\n\t\tconst outer = new AssistantMessageEventStream();\n\n\t\tloadModule()\n\t\t\t.then((module) => {\n\t\t\t\tconst inner = module.stream(model, context, options);\n\t\t\t\tforwardStream(outer, inner);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconst message = createLazyLoadErrorMessage(model, error);\n\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\touter.end(message);\n\t\t\t});\n\n\t\treturn outer;\n\t};\n}\n\nfunction createLazySimpleStream<\n\tTApi extends Api,\n\tTOptions extends StreamOptions,\n\tTSimpleOptions extends SimpleStreamOptions,\n>(loadModule: () => Promise<LazyProviderModule<TApi, TOptions, TSimpleOptions>>): StreamFunction<TApi, TSimpleOptions> {\n\treturn (model, context, options) => {\n\t\tconst outer = new AssistantMessageEventStream();\n\n\t\tloadModule()\n\t\t\t.then((module) => {\n\t\t\t\tconst inner = module.streamSimple(model, context, options);\n\t\t\t\tforwardStream(outer, inner);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconst message = createLazyLoadErrorMessage(model, error);\n\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\touter.end(message);\n\t\t\t});\n\n\t\treturn outer;\n\t};\n}\n\nfunction loadAnthropicProviderModule(): Promise<\n\tLazyProviderModule<\"anthropic-messages\", AnthropicOptions, SimpleStreamOptions>\n> {\n\tanthropicProviderModulePromise ||= import(\"./anthropic.js\").then((module) => {\n\t\tconst provider = module as AnthropicProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamAnthropic,\n\t\t\tstreamSimple: provider.streamSimpleAnthropic,\n\t\t};\n\t});\n\treturn anthropicProviderModulePromise;\n}\n\nfunction loadAzureOpenAIResponsesProviderModule(): Promise<\n\tLazyProviderModule<\"azure-openai-responses\", AzureOpenAIResponsesOptions, SimpleStreamOptions>\n> {\n\tazureOpenAIResponsesProviderModulePromise ||= import(\"./azure-openai-responses.js\").then((module) => {\n\t\tconst provider = module as AzureOpenAIResponsesProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamAzureOpenAIResponses,\n\t\t\tstreamSimple: provider.streamSimpleAzureOpenAIResponses,\n\t\t};\n\t});\n\treturn azureOpenAIResponsesProviderModulePromise;\n}\n\nfunction loadGoogleProviderModule(): Promise<\n\tLazyProviderModule<\"google-generative-ai\", GoogleOptions, SimpleStreamOptions>\n> {\n\tgoogleProviderModulePromise ||= import(\"./google.js\").then((module) => {\n\t\tconst provider = module as GoogleProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamGoogle,\n\t\t\tstreamSimple: provider.streamSimpleGoogle,\n\t\t};\n\t});\n\treturn googleProviderModulePromise;\n}\n\nfunction loadGoogleVertexProviderModule(): Promise<\n\tLazyProviderModule<\"google-vertex\", GoogleVertexOptions, SimpleStreamOptions>\n> {\n\tgoogleVertexProviderModulePromise ||= import(\"./google-vertex.js\").then((module) => {\n\t\tconst provider = module as GoogleVertexProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamGoogleVertex,\n\t\t\tstreamSimple: provider.streamSimpleGoogleVertex,\n\t\t};\n\t});\n\treturn googleVertexProviderModulePromise;\n}\n\nfunction loadMistralProviderModule(): Promise<\n\tLazyProviderModule<\"mistral-conversations\", MistralOptions, SimpleStreamOptions>\n> {\n\tmistralProviderModulePromise ||= import(\"./mistral.js\").then((module) => {\n\t\tconst provider = module as MistralProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamMistral,\n\t\t\tstreamSimple: provider.streamSimpleMistral,\n\t\t};\n\t});\n\treturn mistralProviderModulePromise;\n}\n\nfunction loadOpenAICodexResponsesProviderModule(): Promise<\n\tLazyProviderModule<\"openai-codex-responses\", OpenAICodexResponsesOptions, SimpleStreamOptions>\n> {\n\topenAICodexResponsesProviderModulePromise ||= import(\"./openai-codex-responses.js\").then((module) => {\n\t\tconst provider = module as OpenAICodexResponsesProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamOpenAICodexResponses,\n\t\t\tstreamSimple: provider.streamSimpleOpenAICodexResponses,\n\t\t};\n\t});\n\treturn openAICodexResponsesProviderModulePromise;\n}\n\nfunction loadOpenAICompletionsProviderModule(): Promise<\n\tLazyProviderModule<\"openai-completions\", OpenAICompletionsOptions, SimpleStreamOptions>\n> {\n\topenAICompletionsProviderModulePromise ||= import(\"./openai-completions.js\").then((module) => {\n\t\tconst provider = module as OpenAICompletionsProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamOpenAICompletions,\n\t\t\tstreamSimple: provider.streamSimpleOpenAICompletions,\n\t\t};\n\t});\n\treturn openAICompletionsProviderModulePromise;\n}\n\nfunction loadOpenAIResponsesProviderModule(): Promise<\n\tLazyProviderModule<\"openai-responses\", OpenAIResponsesOptions, SimpleStreamOptions>\n> {\n\topenAIResponsesProviderModulePromise ||= import(\"./openai-responses.js\").then((module) => {\n\t\tconst provider = module as OpenAIResponsesProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamOpenAIResponses,\n\t\t\tstreamSimple: provider.streamSimpleOpenAIResponses,\n\t\t};\n\t});\n\treturn openAIResponsesProviderModulePromise;\n}\n\nfunction loadBedrockProviderModule(): Promise<\n\tLazyProviderModule<\"bedrock-converse-stream\", BedrockOptions, SimpleStreamOptions>\n> {\n\tif (bedrockProviderModuleOverride) {\n\t\treturn Promise.resolve(bedrockProviderModuleOverride);\n\t}\n\tbedrockProviderModulePromise ||= importNodeOnlyProvider(\"./amazon-bedrock.js\").then((module) => {\n\t\tconst provider = module as BedrockProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamBedrock,\n\t\t\tstreamSimple: provider.streamSimpleBedrock,\n\t\t};\n\t});\n\treturn bedrockProviderModulePromise;\n}\n\nfunction loadClaudeCliProviderModule(): Promise<LazyProviderModule<\"claude-cli\", StreamOptions, SimpleStreamOptions>> {\n\tclaudeCliProviderModulePromise ||= importNodeOnlyProvider(\"./claude-cli.js\").then((module) => {\n\t\tconst provider = module as ClaudeCliProviderModule;\n\t\treturn {\n\t\t\tstream: provider.streamClaudeCli,\n\t\t\tstreamSimple: provider.streamSimpleClaudeCli,\n\t\t};\n\t});\n\treturn claudeCliProviderModulePromise;\n}\n\nexport const streamAnthropic = createLazyStream(loadAnthropicProviderModule);\nexport const streamSimpleAnthropic = createLazySimpleStream(loadAnthropicProviderModule);\nexport const streamAzureOpenAIResponses = createLazyStream(loadAzureOpenAIResponsesProviderModule);\nexport const streamSimpleAzureOpenAIResponses = createLazySimpleStream(loadAzureOpenAIResponsesProviderModule);\nexport const streamGoogle = createLazyStream(loadGoogleProviderModule);\nexport const streamSimpleGoogle = createLazySimpleStream(loadGoogleProviderModule);\nexport const streamGoogleVertex = createLazyStream(loadGoogleVertexProviderModule);\nexport const streamSimpleGoogleVertex = createLazySimpleStream(loadGoogleVertexProviderModule);\nexport const streamMistral = createLazyStream(loadMistralProviderModule);\nexport const streamSimpleMistral = createLazySimpleStream(loadMistralProviderModule);\nexport const streamOpenAICodexResponses = createLazyStream(loadOpenAICodexResponsesProviderModule);\nexport const streamSimpleOpenAICodexResponses = createLazySimpleStream(loadOpenAICodexResponsesProviderModule);\nexport const streamOpenAICompletions = createLazyStream(loadOpenAICompletionsProviderModule);\nexport const streamSimpleOpenAICompletions = createLazySimpleStream(loadOpenAICompletionsProviderModule);\nexport const streamOpenAIResponses = createLazyStream(loadOpenAIResponsesProviderModule);\nexport const streamSimpleOpenAIResponses = createLazySimpleStream(loadOpenAIResponsesProviderModule);\nconst streamBedrockLazy = createLazyStream(loadBedrockProviderModule);\nconst streamSimpleBedrockLazy = createLazySimpleStream(loadBedrockProviderModule);\nexport const streamClaudeCli = createLazyStream(loadClaudeCliProviderModule);\nexport const streamSimpleClaudeCli = createLazySimpleStream(loadClaudeCliProviderModule);\n\nexport function registerBuiltInApiProviders(): void {\n\tregisterApiProvider({\n\t\tapi: \"anthropic-messages\",\n\t\tstream: streamAnthropic,\n\t\tstreamSimple: streamSimpleAnthropic,\n\t});\n\n\tregisterApiProvider({\n\t\tapi: \"openai-completions\",\n\t\tstream: streamOpenAICompletions,\n\t\tstreamSimple: streamSimpleOpenAICompletions,\n\t});\n\n\tregisterApiProvider({\n\t\tapi: \"mistral-conversations\",\n\t\tstream: streamMistral,\n\t\tstreamSimple: streamSimpleMistral,\n\t});\n\n\tregisterApiProvider({\n\t\tapi: \"openai-responses\",\n\t\tstream: streamOpenAIResponses,\n\t\tstreamSimple: streamSimpleOpenAIResponses,\n\t});\n\n\tregisterApiProvider({\n\t\tapi: \"azure-openai-responses\",\n\t\tstream: streamAzureOpenAIResponses,\n\t\tstreamSimple: streamSimpleAzureOpenAIResponses,\n\t});\n\n\tregisterApiProvider({\n\t\tapi: \"openai-codex-responses\",\n\t\tstream: streamOpenAICodexResponses,\n\t\tstreamSimple: streamSimpleOpenAICodexResponses,\n\t});\n\n\tregisterApiProvider({\n\t\tapi: \"google-generative-ai\",\n\t\tstream: streamGoogle,\n\t\tstreamSimple: streamSimpleGoogle,\n\t});\n\n\tregisterApiProvider({\n\t\tapi: \"google-vertex\",\n\t\tstream: streamGoogleVertex,\n\t\tstreamSimple: streamSimpleGoogleVertex,\n\t});\n\n\tregisterApiProvider({\n\t\tapi: \"bedrock-converse-stream\",\n\t\tstream: streamBedrockLazy,\n\t\tstreamSimple: streamSimpleBedrockLazy,\n\t});\n\n\tregisterApiProvider({\n\t\tapi: \"claude-cli\",\n\t\tstream: streamClaudeCli,\n\t\tstreamSimple: streamSimpleClaudeCli,\n\t});\n}\n\nexport function resetApiProviders(): void {\n\tclearApiProviders();\n\tregisterBuiltInApiProviders();\n}\n\nregisterBuiltInApiProviders();\n"]}
|