@cloudflare/tanstack-ai 0.1.5 → 0.1.6
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/dist/adapters/anthropic.cjs +3 -3
- package/dist/adapters/anthropic.js +2 -2
- package/dist/adapters/grok.cjs +3 -3
- package/dist/adapters/grok.js +2 -2
- package/dist/adapters/openai.cjs +3 -3
- package/dist/adapters/openai.js +2 -2
- package/dist/adapters/openrouter.cjs +3 -3
- package/dist/adapters/openrouter.js +2 -2
- package/dist/adapters/workers-ai-image.cjs +3 -3
- package/dist/adapters/workers-ai-image.js +2 -2
- package/dist/adapters/workers-ai-summarize.cjs +3 -3
- package/dist/adapters/workers-ai-summarize.js +2 -2
- package/dist/adapters/workers-ai-transcription.cjs +3 -3
- package/dist/adapters/workers-ai-transcription.js +2 -2
- package/dist/adapters/workers-ai-tts.cjs +3 -3
- package/dist/adapters/workers-ai-tts.js +2 -2
- package/dist/adapters/workers-ai.cjs +3 -3
- package/dist/adapters/workers-ai.js +2 -2
- package/dist/{chunk-JDDH3EZD.js → chunk-3WK5ZD57.js} +2 -2
- package/dist/{chunk-OU57O7JK.js → chunk-53A2QIXV.js} +2 -2
- package/dist/{chunk-CEQA4ZVD.cjs → chunk-6MEX2ZSM.cjs} +5 -5
- package/dist/{chunk-CEQA4ZVD.cjs.map → chunk-6MEX2ZSM.cjs.map} +1 -1
- package/dist/{chunk-NGOJB274.js → chunk-AIAJANLC.js} +2 -2
- package/dist/chunk-AIAJANLC.js.map +1 -0
- package/dist/{chunk-72MGG2FX.cjs → chunk-CB3PSZY2.cjs} +6 -6
- package/dist/{chunk-72MGG2FX.cjs.map → chunk-CB3PSZY2.cjs.map} +1 -1
- package/dist/{chunk-GT3TZXZX.cjs → chunk-FQE2UKUU.cjs} +3 -3
- package/dist/{chunk-GT3TZXZX.cjs.map → chunk-FQE2UKUU.cjs.map} +1 -1
- package/dist/{chunk-KQ3JSPII.js → chunk-GL3HHR4M.js} +6 -4
- package/dist/chunk-GL3HHR4M.js.map +1 -0
- package/dist/{chunk-W24YURD6.js → chunk-JRFPCMSE.js} +2 -2
- package/dist/{chunk-MBDHL2I4.js → chunk-KWYOUT2Y.js} +2 -2
- package/dist/{chunk-JHZAPIW5.cjs → chunk-MJ45L566.cjs} +5 -5
- package/dist/{chunk-JHZAPIW5.cjs.map → chunk-MJ45L566.cjs.map} +1 -1
- package/dist/{chunk-2YEF5YWC.cjs → chunk-N6U27RQW.cjs} +6 -6
- package/dist/{chunk-2YEF5YWC.cjs.map → chunk-N6U27RQW.cjs.map} +1 -1
- package/dist/{chunk-RQLWAWHC.js → chunk-NH3FF5JC.js} +2 -2
- package/dist/{chunk-ZLPTIWRB.cjs → chunk-OFUYHQZE.cjs} +3 -3
- package/dist/{chunk-ZLPTIWRB.cjs.map → chunk-OFUYHQZE.cjs.map} +1 -1
- package/dist/{chunk-IQAGFHRT.cjs → chunk-OUEAAP25.cjs} +11 -9
- package/dist/chunk-OUEAAP25.cjs.map +1 -0
- package/dist/{chunk-JK4WXQVL.js → chunk-Q33U5I5S.js} +2 -2
- package/dist/{chunk-3L6IRVAV.cjs → chunk-WBTQKWFN.cjs} +2 -2
- package/dist/{chunk-3L6IRVAV.cjs.map → chunk-WBTQKWFN.cjs.map} +1 -1
- package/dist/{chunk-MM5TKP3U.js → chunk-YCGNMVQZ.js} +2 -2
- package/dist/{chunk-73UI5P36.js → chunk-Z5ZC5ZOQ.js} +2 -2
- package/dist/{chunk-HPMTYA35.cjs → chunk-ZFB72L57.cjs} +6 -6
- package/dist/{chunk-HPMTYA35.cjs.map → chunk-ZFB72L57.cjs.map} +1 -1
- package/dist/{chunk-5WAK4STT.cjs → chunk-ZGLSJM26.cjs} +6 -6
- package/dist/{chunk-5WAK4STT.cjs.map → chunk-ZGLSJM26.cjs.map} +1 -1
- package/dist/index.cjs +11 -11
- package/dist/index.js +10 -10
- package/package.json +1 -1
- package/dist/chunk-IQAGFHRT.cjs.map +0 -1
- package/dist/chunk-KQ3JSPII.js.map +0 -1
- package/dist/chunk-NGOJB274.js.map +0 -1
- /package/dist/{chunk-JDDH3EZD.js.map → chunk-3WK5ZD57.js.map} +0 -0
- /package/dist/{chunk-OU57O7JK.js.map → chunk-53A2QIXV.js.map} +0 -0
- /package/dist/{chunk-W24YURD6.js.map → chunk-JRFPCMSE.js.map} +0 -0
- /package/dist/{chunk-MBDHL2I4.js.map → chunk-KWYOUT2Y.js.map} +0 -0
- /package/dist/{chunk-RQLWAWHC.js.map → chunk-NH3FF5JC.js.map} +0 -0
- /package/dist/{chunk-JK4WXQVL.js.map → chunk-Q33U5I5S.js.map} +0 -0
- /package/dist/{chunk-MM5TKP3U.js.map → chunk-YCGNMVQZ.js.map} +0 -0
- /package/dist/{chunk-73UI5P36.js.map → chunk-Z5ZC5ZOQ.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkWBTQKWFNcjs = require('./chunk-WBTQKWFN.cjs');
|
|
4
4
|
|
|
5
5
|
// src/adapters/openai.ts
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ var _aiopenai = require('@tanstack/ai-openai');
|
|
|
19
19
|
function buildOpenAiConfig(provider, config) {
|
|
20
20
|
return {
|
|
21
21
|
apiKey: _nullishCoalesce(config.apiKey, () => ( "unused")),
|
|
22
|
-
fetch:
|
|
22
|
+
fetch: _chunkWBTQKWFNcjs.createGatewayFetch.call(void 0, provider, config)
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
function createOpenAiChat(model, config) {
|
|
@@ -54,4 +54,4 @@ function createOpenAiVideo(model, config) {
|
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
exports.OPENAI_CHAT_MODELS = _aiopenai.OPENAI_CHAT_MODELS; exports.OPENAI_IMAGE_MODELS = _aiopenai.OPENAI_IMAGE_MODELS; exports.OPENAI_TRANSCRIPTION_MODELS = _aiopenai.OPENAI_TRANSCRIPTION_MODELS; exports.OPENAI_TTS_MODELS = _aiopenai.OPENAI_TTS_MODELS; exports.OPENAI_VIDEO_MODELS = _aiopenai.OPENAI_VIDEO_MODELS; exports.createOpenAiChat = createOpenAiChat; exports.createOpenAiSummarize = createOpenAiSummarize; exports.createOpenAiImage = createOpenAiImage; exports.createOpenAiTranscription = createOpenAiTranscription; exports.createOpenAiTts = createOpenAiTts; exports.createOpenAiVideo = createOpenAiVideo;
|
|
57
|
-
//# sourceMappingURL=chunk-
|
|
57
|
+
//# sourceMappingURL=chunk-FQE2UKUU.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-FQE2UKUU.cjs","../src/adapters/openai.ts"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACA;ACJA;AACC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA,+CAMM;AASP,SAAS,iBAAA,CAAkB,QAAA,EAAkB,MAAA,EAA6B;AACzE,EAAA,OAAO;AAAA,IACN,MAAA,mBAAQ,MAAA,CAAO,MAAA,UAAU,UAAA;AAAA,IACzB,KAAA,EAAO,kDAAA,QAAmB,EAAU,MAAM;AAAA,EAC3C,CAAA;AACD;AAQO,SAAS,gBAAA,CAAiB,KAAA,EAAwB,MAAA,EAA6B;AACrF,EAAA,OAAO,IAAI,gCAAA,CAAkB,iBAAA,CAAkB,QAAA,EAAU,MAAM,CAAA,EAAG,KAAK,CAAA;AACxE;AAOO,SAAS,qBAAA,CAAsB,KAAA,EAAwB,MAAA,EAA6B;AAC1F,EAAA,OAAO,IAAI,qCAAA,CAAuB,iBAAA,CAAkB,QAAA,EAAU,MAAM,CAAA,EAAG,KAAK,CAAA;AAC7E;AAOO,SAAS,iBAAA,CAAkB,KAAA,EAAyB,MAAA,EAA6B;AACvF,EAAA,OAAO,IAAI,iCAAA,CAAmB,iBAAA,CAAkB,QAAA,EAAU,MAAM,CAAA,EAAG,KAAK,CAAA;AACzE;AAOO,SAAS,yBAAA,CACf,KAAA,EACA,MAAA,EACC;AACD,EAAA,OAAO,IAAI,yCAAA,CAA2B,iBAAA,CAAkB,QAAA,EAAU,MAAM,CAAA,EAAG,KAAK,CAAA;AACjF;AAOO,SAAS,eAAA,CAAgB,KAAA,EAAuB,MAAA,EAA6B;AACnF,EAAA,OAAO,IAAI,+BAAA,CAAiB,iBAAA,CAAkB,QAAA,EAAU,MAAM,CAAA,EAAG,KAAK,CAAA;AACvE;AAOO,SAAS,iBAAA,CAAkB,KAAA,EAAyB,MAAA,EAA6B;AACvF,EAAA,OAAO,IAAI,iCAAA,CAAmB,iBAAA,CAAkB,QAAA,EAAU,MAAM,CAAA,EAAG,KAAK,CAAA;AACzE;AD/CA;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,smBAAC","file":"/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-FQE2UKUU.cjs","sourcesContent":[null,"import {\n\tOpenAIImageAdapter,\n\tOpenAISummarizeAdapter,\n\tOpenAITextAdapter,\n\tOpenAITranscriptionAdapter,\n\tOpenAITTSAdapter,\n\tOpenAIVideoAdapter,\n\tOPENAI_CHAT_MODELS,\n\tOPENAI_IMAGE_MODELS,\n\tOPENAI_TRANSCRIPTION_MODELS,\n\tOPENAI_TTS_MODELS,\n\tOPENAI_VIDEO_MODELS,\n\ttype OpenAIChatModel,\n\ttype OpenAIImageModel,\n\ttype OpenAITranscriptionModel,\n\ttype OpenAITTSModel,\n\ttype OpenAIVideoModel,\n} from \"@tanstack/ai-openai\";\nimport { createGatewayFetch, type AiGatewayAdapterConfig } from \"../utils/create-fetcher\";\n\nexport type OpenAiGatewayConfig = AiGatewayAdapterConfig;\n\n/**\n * Builds an OpenAI-compatible config that injects the gateway fetch.\n * OpenAITextConfig extends OpenAI SDK's ClientOptions, which supports a `fetch` parameter.\n */\nfunction buildOpenAiConfig(provider: string, config: OpenAiGatewayConfig) {\n\treturn {\n\t\tapiKey: config.apiKey ?? \"unused\",\n\t\tfetch: createGatewayFetch(provider, config),\n\t};\n}\n\n/**\n * Creates an OpenAI chat adapter which uses Cloudflare AI Gateway.\n * Supports both binding and credential-based configurations.\n * @param model The OpenAI model to use\n * @param config Configuration options\n */\nexport function createOpenAiChat(model: OpenAIChatModel, config: OpenAiGatewayConfig) {\n\treturn new OpenAITextAdapter(buildOpenAiConfig(\"openai\", config), model);\n}\n\n/**\n * Creates an OpenAI summarize adapter which uses Cloudflare AI Gateway.\n * @param model The OpenAI model to use\n * @param config Configuration options\n */\nexport function createOpenAiSummarize(model: OpenAIChatModel, config: OpenAiGatewayConfig) {\n\treturn new OpenAISummarizeAdapter(buildOpenAiConfig(\"openai\", config), model);\n}\n\n/**\n * Creates an OpenAI image adapter which uses Cloudflare AI Gateway.\n * @param model The OpenAI image model to use\n * @param config Configuration options\n */\nexport function createOpenAiImage(model: OpenAIImageModel, config: OpenAiGatewayConfig) {\n\treturn new OpenAIImageAdapter(buildOpenAiConfig(\"openai\", config), model);\n}\n\n/**\n * Creates an OpenAI transcription adapter which uses Cloudflare AI Gateway.\n * @param model The OpenAI transcription model to use\n * @param config Configuration options\n */\nexport function createOpenAiTranscription(\n\tmodel: OpenAITranscriptionModel,\n\tconfig: OpenAiGatewayConfig,\n) {\n\treturn new OpenAITranscriptionAdapter(buildOpenAiConfig(\"openai\", config), model);\n}\n\n/**\n * Creates an OpenAI TTS adapter which uses Cloudflare AI Gateway.\n * @param model The OpenAI TTS model to use\n * @param config Configuration options\n */\nexport function createOpenAiTts(model: OpenAITTSModel, config: OpenAiGatewayConfig) {\n\treturn new OpenAITTSAdapter(buildOpenAiConfig(\"openai\", config), model);\n}\n\n/**\n * Creates an OpenAI video adapter which uses Cloudflare AI Gateway.\n * @param model The OpenAI video model to use\n * @param config Configuration options\n */\nexport function createOpenAiVideo(model: OpenAIVideoModel, config: OpenAiGatewayConfig) {\n\treturn new OpenAIVideoAdapter(buildOpenAiConfig(\"openai\", config), model);\n}\n\nexport {\n\tOPENAI_CHAT_MODELS,\n\tOPENAI_IMAGE_MODELS,\n\tOPENAI_TRANSCRIPTION_MODELS,\n\tOPENAI_TTS_MODELS,\n\tOPENAI_VIDEO_MODELS,\n\ttype OpenAIChatModel,\n\ttype OpenAIImageModel,\n\ttype OpenAITranscriptionModel,\n\ttype OpenAITTSModel,\n\ttype OpenAIVideoModel,\n};\n"]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
isDirectBindingConfig,
|
|
5
5
|
isDirectCredentialsConfig,
|
|
6
6
|
validateWorkersAiConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-AIAJANLC.js";
|
|
8
8
|
import {
|
|
9
9
|
__publicField
|
|
10
10
|
} from "./chunk-V6TY7KAL.js";
|
|
@@ -157,7 +157,7 @@ var WorkersAiTextAdapter = class extends BaseTextAdapter {
|
|
|
157
157
|
this.client = buildWorkersAiClient(config);
|
|
158
158
|
}
|
|
159
159
|
async *chatStream(options) {
|
|
160
|
-
const { systemPrompts, messages, tools, temperature, model } = options;
|
|
160
|
+
const { systemPrompts, messages, tools, temperature, maxTokens, model } = options;
|
|
161
161
|
const openAIMessages = buildOpenAIMessages(systemPrompts, messages);
|
|
162
162
|
const openAITools = buildOpenAITools(tools);
|
|
163
163
|
const timestamp = Date.now();
|
|
@@ -179,6 +179,7 @@ var WorkersAiTextAdapter = class extends BaseTextAdapter {
|
|
|
179
179
|
messages: openAIMessages,
|
|
180
180
|
tools: openAITools,
|
|
181
181
|
temperature,
|
|
182
|
+
max_tokens: maxTokens,
|
|
182
183
|
stream: true,
|
|
183
184
|
stream_options: { include_usage: true }
|
|
184
185
|
});
|
|
@@ -191,7 +192,8 @@ var WorkersAiTextAdapter = class extends BaseTextAdapter {
|
|
|
191
192
|
model: model ?? this.model,
|
|
192
193
|
messages: openAIMessages,
|
|
193
194
|
tools: openAITools,
|
|
194
|
-
temperature
|
|
195
|
+
temperature,
|
|
196
|
+
max_tokens: maxTokens
|
|
195
197
|
});
|
|
196
198
|
yield {
|
|
197
199
|
type: "RUN_STARTED",
|
|
@@ -518,4 +520,4 @@ export {
|
|
|
518
520
|
WorkersAiTextAdapter,
|
|
519
521
|
createWorkersAiChat
|
|
520
522
|
};
|
|
521
|
-
//# sourceMappingURL=chunk-
|
|
523
|
+
//# sourceMappingURL=chunk-GL3HHR4M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/workers-ai.ts"],"sourcesContent":["import type { AiModels, BaseAiTextGeneration } from \"@cloudflare/workers-types\";\nimport type { ContentPart, ModelMessage, StreamChunk, TextOptions } from \"@tanstack/ai\";\nimport {\n\tBaseTextAdapter,\n\ttype StructuredOutputOptions,\n\ttype StructuredOutputResult,\n} from \"@tanstack/ai/adapters\";\nimport OpenAI from \"openai\";\nimport {\n\ttype WorkersAiAdapterConfig,\n\ttype AiGatewayAdapterConfig,\n\tcreateGatewayFetch,\n\tcreateWorkersAiBindingFetch,\n\tisDirectBindingConfig,\n\tisDirectCredentialsConfig,\n\tvalidateWorkersAiConfig,\n} from \"../utils/create-fetcher\";\n\n// ---------------------------------------------------------------------------\n// Model types derived from @cloudflare/workers-types\n// ---------------------------------------------------------------------------\n\nexport type WorkersAiTextModel =\n\t| {\n\t\t\t[K in keyof AiModels]: AiModels[K] extends BaseAiTextGeneration ? K : never;\n\t }[keyof AiModels]\n\t| (string & {});\n\n// ---------------------------------------------------------------------------\n// Helpers: build the right OpenAI client depending on config mode\n// ---------------------------------------------------------------------------\n\nfunction buildWorkersAiClient(config: WorkersAiAdapterConfig): OpenAI {\n\tvalidateWorkersAiConfig(config);\n\n\tconst sessionHeaders: Record<string, string> | undefined = config.sessionAffinity\n\t\t? { \"x-session-affinity\": config.sessionAffinity }\n\t\t: undefined;\n\n\tif (isDirectBindingConfig(config)) {\n\t\t// Plain binding mode: shim translates OpenAI fetch calls to env.AI.run()\n\t\treturn new OpenAI({\n\t\t\tapiKey: \"unused\",\n\t\t\tfetch: createWorkersAiBindingFetch(\n\t\t\t\tconfig.binding,\n\t\t\t\tsessionHeaders ? { extraHeaders: sessionHeaders } : undefined,\n\t\t\t),\n\t\t});\n\t}\n\n\tif (isDirectCredentialsConfig(config)) {\n\t\t// Plain REST mode: point OpenAI SDK at Workers AI's OpenAI-compatible endpoint\n\t\treturn new OpenAI({\n\t\t\tbaseURL: `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/ai/v1`,\n\t\t\tapiKey: config.apiKey,\n\t\t\tdefaultHeaders: sessionHeaders,\n\t\t});\n\t}\n\n\t// Gateway mode (existing): use createGatewayFetch\n\tconst gatewayConfig = config as AiGatewayAdapterConfig;\n\treturn new OpenAI({\n\t\tfetch: createGatewayFetch(\"workers-ai\", gatewayConfig, sessionHeaders),\n\t\tapiKey: gatewayConfig.apiKey ?? \"unused\",\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Shared message-building helpers\n// ---------------------------------------------------------------------------\n\nfunction extractTextContent(content: ModelMessage[\"content\"]): string {\n\tif (content === null) return \"\";\n\tif (typeof content === \"string\") return content;\n\treturn content.flatMap((p) => (p.type === \"text\" ? [p.content] : [])).join(\"\");\n}\n\n/**\n * Convert a single TanStack AI {@link ContentPart} to the OpenAI Chat\n * Completions multi-modal format.\n *\n * TODO: handle other content types (audio, video, document)\n */\nfunction convertContentPart(part: ContentPart): OpenAI.Chat.ChatCompletionContentPart | undefined {\n\tswitch (part.type) {\n\t\tcase \"text\":\n\t\t\tif (part.content) {\n\t\t\t\treturn { type: \"text\", text: part.content };\n\t\t\t}\n\t\t\treturn undefined;\n\t\tcase \"image\": {\n\t\t\tlet url: string;\n\t\t\tif (part.source.type === \"data\") {\n\t\t\t\turl = part.source.value.startsWith(\"data:\")\n\t\t\t\t\t? part.source.value\n\t\t\t\t\t: `data:${part.source.mimeType};base64,${part.source.value}`;\n\t\t\t} else {\n\t\t\t\turl = part.source.value;\n\t\t\t}\n\t\t\treturn { type: \"image_url\", image_url: { url } };\n\t\t}\n\t\tdefault:\n\t\t\t// audio, video, document — not supported for now\n\t\t\tconsole.warn(\n\t\t\t\t`[@cloudflare/tanstack-ai] Unsupported content part type \"${part.type}\" — skipping`,\n\t\t\t);\n\t\t\treturn undefined;\n\t}\n}\n\n/**\n * Build OpenAI-compatible user message content from TanStack AI content.\n *\n * If the content has only text parts, returns a plain string.\n * If it includes image parts, returns an array of content parts in\n * OpenAI's multi-modal format (text + image_url).\n */\nfunction buildUserContent(\n\tcontent: ModelMessage[\"content\"],\n): string | OpenAI.Chat.ChatCompletionContentPart[] {\n\tif (content === null) return \"\";\n\tif (typeof content === \"string\") return content;\n\n\tconst hasImages = content.some((p) => p.type === \"image\");\n\tif (!hasImages) {\n\t\treturn content.flatMap((p) => (p.type === \"text\" ? [p.content] : [])).join(\"\");\n\t}\n\n\tconst parts: OpenAI.Chat.ChatCompletionContentPart[] = [];\n\tfor (const part of content) {\n\t\tconst converted = convertContentPart(part);\n\t\tif (converted) {\n\t\t\tparts.push(converted);\n\t\t}\n\t}\n\treturn parts;\n}\n\nfunction buildOpenAIMessages(\n\tsystemPrompts: string[] | undefined,\n\tmessages: ModelMessage[],\n\toptions?: { includeToolMessages?: boolean },\n): OpenAI.Chat.ChatCompletionMessageParam[] {\n\tconst includeTools = options?.includeToolMessages ?? true;\n\tconst openAIMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [];\n\n\tif (systemPrompts && systemPrompts.length > 0) {\n\t\topenAIMessages.push({\n\t\t\trole: \"system\",\n\t\t\tcontent: systemPrompts.join(\"\\n\"),\n\t\t});\n\t}\n\n\tfor (const message of messages) {\n\t\tif (message.role === \"user\") {\n\t\t\topenAIMessages.push({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: buildUserContent(message.content),\n\t\t\t});\n\t\t} else if (message.role === \"assistant\") {\n\t\t\tconst assistantMessage: OpenAI.Chat.ChatCompletionAssistantMessageParam = {\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: extractTextContent(message.content),\n\t\t\t};\n\t\t\tif (includeTools && message.toolCalls && message.toolCalls.length > 0) {\n\t\t\t\tassistantMessage.tool_calls = message.toolCalls.map((tc) => ({\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\ttype: \"function\" as const,\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\t\targuments: tc.function.arguments,\n\t\t\t\t\t},\n\t\t\t\t}));\n\t\t\t}\n\t\t\topenAIMessages.push(assistantMessage);\n\t\t} else if (includeTools && message.role === \"tool\") {\n\t\t\tlet toolContent: string;\n\t\t\tif (typeof message.content === \"string\") {\n\t\t\t\ttry {\n\t\t\t\t\tJSON.parse(message.content);\n\t\t\t\t\ttoolContent = message.content;\n\t\t\t\t} catch {\n\t\t\t\t\ttoolContent = JSON.stringify(message.content);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttoolContent = JSON.stringify(message.content);\n\t\t\t}\n\t\t\topenAIMessages.push({\n\t\t\t\trole: \"tool\",\n\t\t\t\ttool_call_id: message.toolCallId || `tool_${crypto.randomUUID().slice(0, 8)}`,\n\t\t\t\tcontent: toolContent,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn openAIMessages;\n}\n\nfunction buildOpenAITools(\n\ttools: Array<{ name: string; description: string; inputSchema?: unknown }> | undefined,\n): OpenAI.Chat.ChatCompletionTool[] | undefined {\n\tif (!tools) return undefined;\n\treturn tools.map((tool) => ({\n\t\ttype: \"function\" as const,\n\t\tfunction: {\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: tool.inputSchema as Record<string, unknown>,\n\t\t},\n\t}));\n}\n\n// ---------------------------------------------------------------------------\n// ID generation\n// ---------------------------------------------------------------------------\n\nfunction generateId(prefix = \"chatcmpl\"): string {\n\treturn `${prefix}-${crypto.randomUUID().replace(/-/g, \"\").slice(0, 16)}`;\n}\n\n// ---------------------------------------------------------------------------\n// WorkersAiTextAdapter: chat / structured output via OpenAI Chat Completions\n// ---------------------------------------------------------------------------\n\n// TODO: Replace `any` generic params with proper types once BaseTextAdapter's\n// provider-options generics stabilize. Workers AI doesn't have provider-specific\n// options in the TanStack sense, so `any` is pragmatic for now.\nexport class WorkersAiTextAdapter<TModel extends WorkersAiTextModel> extends BaseTextAdapter<\n\tTModel,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any -- BaseTextAdapter generic params are opaque\n\tany,\n\tany,\n\tany\n> {\n\tname = \"workers-ai\" as const;\n\n\tprivate client: OpenAI;\n\n\tconstructor(model: TModel, config: WorkersAiAdapterConfig) {\n\t\tsuper({ apiKey: \"unused\" }, model);\n\t\tthis.client = buildWorkersAiClient(config);\n\t}\n\n\tasync *chatStream(options: TextOptions<any>): AsyncIterable<StreamChunk> {\n\t\tconst { systemPrompts, messages, tools, temperature, maxTokens, model } = options;\n\n\t\tconst openAIMessages = buildOpenAIMessages(systemPrompts, messages);\n\t\tconst openAITools = buildOpenAITools(tools);\n\n\t\tconst timestamp = Date.now();\n\t\tconst runId = generateId();\n\t\tconst messageId = generateId();\n\t\tlet hasEmittedRunStarted = false;\n\t\tlet hasEmittedTextMessageStart = false;\n\t\tlet accumulatedContent = \"\";\n\t\tlet hasEmittedStepStarted = false;\n\t\tlet accumulatedReasoning = \"\";\n\t\tconst stepId = generateId();\n\t\tlet hasReceivedFinishReason = false;\n\t\tconst toolCallsInProgress = new Map<\n\t\t\tnumber,\n\t\t\t{ id: string; name: string; arguments: string; started: boolean }\n\t\t>();\n\n\t\ttry {\n\t\t\tlet stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>;\n\t\t\ttry {\n\t\t\t\tstream = await this.client.chat.completions.create({\n\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\tmessages: openAIMessages,\n\t\t\t\t\ttools: openAITools,\n\t\t\t\t\ttemperature,\n\t\t\t\t\tmax_tokens: maxTokens,\n\t\t\t\t\tstream: true,\n\t\t\t\t\tstream_options: { include_usage: true },\n\t\t\t\t});\n\t\t\t} catch (streamError: unknown) {\n\t\t\t\t// Some models (e.g. GPT-OSS) don't support streaming via the REST API.\n\t\t\t\t// Fall back to a non-streaming call and yield the result as a single chunk.\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"[tanstack-ai] Streaming failed, falling back to non-streaming:\",\n\t\t\t\t\tstreamError instanceof Error ? streamError.message : streamError,\n\t\t\t\t);\n\t\t\t\tconst nonStreamResult = await this.client.chat.completions.create({\n\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\tmessages: openAIMessages,\n\t\t\t\t\ttools: openAITools,\n\t\t\t\t\ttemperature,\n\t\t\t\t\tmax_tokens: maxTokens,\n\t\t\t\t});\n\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"RUN_STARTED\",\n\t\t\t\t\trunId,\n\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\ttimestamp,\n\t\t\t\t} satisfies StreamChunk;\n\n\t\t\t\tconst msg = nonStreamResult.choices[0]?.message;\n\t\t\t\tif (msg?.content) {\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_START\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_CONTENT\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\tdelta: msg.content,\n\t\t\t\t\t\tcontent: msg.content,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_END\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\tif (msg?.tool_calls) {\n\t\t\t\t\tfor (const tc of msg.tool_calls) {\n\t\t\t\t\t\tif (tc.type !== \"function\") continue;\n\t\t\t\t\t\tconst fn = tc.function;\n\t\t\t\t\t\tlet parsedInput: unknown = {};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tparsedInput = fn.arguments ? JSON.parse(fn.arguments) : {};\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tparsedInput = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TOOL_CALL_START\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: fn.name,\n\t\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\tindex: 0,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TOOL_CALL_END\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: fn.name,\n\t\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\tinput: parsedInput,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst finishReason = nonStreamResult.choices[0]?.finish_reason;\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"RUN_FINISHED\",\n\t\t\t\t\trunId,\n\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\ttimestamp,\n\t\t\t\t\tusage: nonStreamResult.usage\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tpromptTokens: nonStreamResult.usage.prompt_tokens,\n\t\t\t\t\t\t\t\tcompletionTokens: nonStreamResult.usage.completion_tokens,\n\t\t\t\t\t\t\t\ttotalTokens: nonStreamResult.usage.total_tokens,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t\tfinishReason:\n\t\t\t\t\t\tfinishReason === \"tool_calls\" || finishReason === \"function_call\"\n\t\t\t\t\t\t\t? \"tool_calls\"\n\t\t\t\t\t\t\t: ((finishReason as \"stop\" | \"length\" | \"content_filter\") ?? \"stop\"),\n\t\t\t\t} satisfies StreamChunk;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor await (const chunk of stream) {\n\t\t\t\tif (!chunk.choices || chunk.choices.length === 0) continue;\n\t\t\t\tconst choice = chunk.choices[0];\n\t\t\t\tif (!choice) continue;\n\n\t\t\t\t// Emit RUN_STARTED on first chunk\n\t\t\t\tif (!hasEmittedRunStarted) {\n\t\t\t\t\thasEmittedRunStarted = true;\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"RUN_STARTED\",\n\t\t\t\t\t\trunId,\n\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\tconst delta = choice.delta;\n\n\t\t\t\t// Reasoning content (used by models like QwQ, DeepSeek R1, Kimi K2.5)\n\t\t\t\t// The OpenAI SDK doesn't type this field, but models send it as an extension.\n\t\t\t\tconst reasoningContent = ((delta as Record<string, unknown>).reasoning_content ??\n\t\t\t\t\t(delta as Record<string, unknown>).reasoning) as string | undefined;\n\t\t\t\tif (reasoningContent) {\n\t\t\t\t\t// RUN_STARTED is already guaranteed by the guard above\n\t\t\t\t\tif (!hasEmittedStepStarted) {\n\t\t\t\t\t\thasEmittedStepStarted = true;\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"STEP_STARTED\",\n\t\t\t\t\t\t\tstepId,\n\t\t\t\t\t\t\tstepType: \"thinking\",\n\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\t\t\t\t\taccumulatedReasoning += reasoningContent;\n\t\t\t\t\t// TODO: TanStack AI's StreamProcessor currently treats STEP_FINISHED as an\n\t\t\t\t\t// incremental reasoning event (with `delta` + accumulated `content`), so we\n\t\t\t\t\t// emit one per token. If TanStack AI adds a dedicated STEP_CONTENT event\n\t\t\t\t\t// type, this should be updated to emit STEP_CONTENT per token and a single\n\t\t\t\t\t// STEP_FINISHED when reasoning ends (i.e. when the first non-reasoning\n\t\t\t\t\t// content or finish_reason arrives).\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"STEP_FINISHED\",\n\t\t\t\t\t\tstepId,\n\t\t\t\t\t\tdelta: reasoningContent,\n\t\t\t\t\t\tcontent: accumulatedReasoning,\n\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\t// Text content\n\t\t\t\tif (delta.content) {\n\t\t\t\t\tif (!hasEmittedTextMessageStart) {\n\t\t\t\t\t\thasEmittedTextMessageStart = true;\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TEXT_MESSAGE_START\",\n\t\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\n\t\t\t\t\taccumulatedContent += delta.content;\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_CONTENT\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\tdelta: delta.content,\n\t\t\t\t\t\tcontent: accumulatedContent,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\t// Tool calls\n\t\t\t\tif (delta.tool_calls) {\n\t\t\t\t\tfor (const toolCallDelta of delta.tool_calls) {\n\t\t\t\t\t\tconst index = toolCallDelta.index;\n\n\t\t\t\t\t\tif (!toolCallsInProgress.has(index)) {\n\t\t\t\t\t\t\t// Always generate a unique ID per tool call index.\n\t\t\t\t\t\t\t// The backend may send the same ID for multiple tool calls,\n\t\t\t\t\t\t\t// so we cannot trust toolCallDelta.id to be unique.\n\t\t\t\t\t\t\ttoolCallsInProgress.set(index, {\n\t\t\t\t\t\t\t\tid: generateId(\"chatcmpl-tool\"),\n\t\t\t\t\t\t\t\tname: toolCallDelta.function?.name || \"\",\n\t\t\t\t\t\t\t\targuments: \"\",\n\t\t\t\t\t\t\t\tstarted: false,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst toolCall = toolCallsInProgress.get(index)!;\n\n\t\t\t\t\t\t// Only update name if provided (ID is already set at creation time\n\t\t\t\t\t\t// and should not be overwritten by subsequent chunks that may have\n\t\t\t\t\t\t// duplicate/shared IDs from the backend)\n\t\t\t\t\t\tif (toolCallDelta.function?.name) {\n\t\t\t\t\t\t\ttoolCall.name = toolCallDelta.function.name;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (toolCallDelta.function?.arguments) {\n\t\t\t\t\t\t\ttoolCall.arguments += toolCallDelta.function.arguments;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Emit TOOL_CALL_START once we have id and name\n\t\t\t\t\t\tif (toolCall.id && toolCall.name && !toolCall.started) {\n\t\t\t\t\t\t\ttoolCall.started = true;\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"TOOL_CALL_START\",\n\t\t\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Stream tool call arguments\n\t\t\t\t\t\tif (toolCallDelta.function?.arguments && toolCall.started) {\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"TOOL_CALL_ARGS\",\n\t\t\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\t\tdelta: toolCallDelta.function.arguments,\n\t\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Finish\n\t\t\t\tif (choice.finish_reason) {\n\t\t\t\t\thasReceivedFinishReason = true;\n\n\t\t\t\t\t// End tool calls\n\t\t\t\t\tif (choice.finish_reason === \"tool_calls\" || toolCallsInProgress.size > 0) {\n\t\t\t\t\t\tfor (const [, toolCall] of toolCallsInProgress) {\n\t\t\t\t\t\t\tlet parsedInput: unknown = {};\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tparsedInput = toolCall.arguments\n\t\t\t\t\t\t\t\t\t? JSON.parse(toolCall.arguments)\n\t\t\t\t\t\t\t\t\t: {};\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tparsedInput = {};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"TOOL_CALL_END\",\n\t\t\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\t\tinput: parsedInput,\n\t\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst computedFinishReason =\n\t\t\t\t\t\tchoice.finish_reason === \"tool_calls\" ||\n\t\t\t\t\t\tchoice.finish_reason === \"function_call\" ||\n\t\t\t\t\t\ttoolCallsInProgress.size > 0\n\t\t\t\t\t\t\t? \"tool_calls\"\n\t\t\t\t\t\t\t: (choice.finish_reason as \"stop\" | \"length\" | \"content_filter\");\n\n\t\t\t\t\t// End text message if started\n\t\t\t\t\tif (hasEmittedTextMessageStart) {\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TEXT_MESSAGE_END\",\n\t\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Emit RUN_FINISHED\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"RUN_FINISHED\",\n\t\t\t\t\t\trunId,\n\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\tusage: chunk.usage\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tpromptTokens: chunk.usage.prompt_tokens,\n\t\t\t\t\t\t\t\t\tcompletionTokens: chunk.usage.completion_tokens,\n\t\t\t\t\t\t\t\t\ttotalTokens: chunk.usage.total_tokens,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tfinishReason: computedFinishReason,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Premature stream termination: the stream ended without a finish_reason.\n\t\t\t// This can happen when Workers AI truncates a response or the connection drops.\n\t\t\t// Emit proper closing events so the consumer doesn't hang.\n\t\t\tif (hasEmittedRunStarted && !hasReceivedFinishReason) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"[tanstack-ai] Stream ended without finish_reason — possible truncation or connection drop\",\n\t\t\t\t);\n\n\t\t\t\t// Close any open tool calls\n\t\t\t\tfor (const [, toolCall] of toolCallsInProgress) {\n\t\t\t\t\tif (toolCall.started) {\n\t\t\t\t\t\tlet parsedInput: unknown = {};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tparsedInput = toolCall.arguments ? JSON.parse(toolCall.arguments) : {};\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tparsedInput = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TOOL_CALL_END\",\n\t\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\tinput: parsedInput,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Close text message if open\n\t\t\t\tif (hasEmittedTextMessageStart) {\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_END\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"RUN_FINISHED\",\n\t\t\t\t\trunId,\n\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\ttimestamp,\n\t\t\t\t\tfinishReason: \"stop\",\n\t\t\t\t} satisfies StreamChunk;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconst code =\n\t\t\t\terror instanceof Error ? (error as Error & { code?: string }).code : undefined;\n\t\t\tif (!hasEmittedRunStarted) {\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"RUN_STARTED\",\n\t\t\t\t\trunId,\n\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\ttimestamp,\n\t\t\t\t} satisfies StreamChunk;\n\t\t\t}\n\t\t\tyield {\n\t\t\t\ttype: \"RUN_ERROR\",\n\t\t\t\trunId,\n\t\t\t\tmodel: model ?? this.model,\n\t\t\t\ttimestamp,\n\t\t\t\terror: {\n\t\t\t\t\tmessage: message || \"Unknown error\",\n\t\t\t\t\tcode,\n\t\t\t\t},\n\t\t\t} satisfies StreamChunk;\n\t\t}\n\t}\n\n\tasync structuredOutput(\n\t\toptions: StructuredOutputOptions<any>,\n\t): Promise<StructuredOutputResult<unknown>> {\n\t\tconst { outputSchema, chatOptions } = options;\n\t\tconst { systemPrompts, messages, temperature, model } = chatOptions;\n\n\t\tconst openAIMessages = buildOpenAIMessages(systemPrompts, messages, {\n\t\t\tincludeToolMessages: false,\n\t\t});\n\n\t\tconst response = await this.client.chat.completions.create({\n\t\t\tmodel: model ?? this.model,\n\t\t\tmessages: openAIMessages,\n\t\t\ttemperature,\n\t\t\tstream: false,\n\t\t\tresponse_format: {\n\t\t\t\ttype: \"json_schema\",\n\t\t\t\tjson_schema: {\n\t\t\t\t\tname: \"structured_output\",\n\t\t\t\t\tstrict: true,\n\t\t\t\t\tschema: outputSchema,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\tconst choice = response.choices?.[0];\n\n\t\tif (!choice) {\n\t\t\tthrow new Error(\n\t\t\t\t`Workers AI structured output returned no choices: ${JSON.stringify(response)}`,\n\t\t\t);\n\t\t}\n\n\t\tconst rawContent = choice.message?.content ?? \"\";\n\n\t\t// Workers AI REST endpoint may return `content` as an already-parsed object\n\t\t// when using json_schema response format, so normalise both cases.\n\t\tlet data: unknown;\n\t\tlet rawText: string;\n\n\t\tif (typeof rawContent === \"string\") {\n\t\t\trawText = rawContent;\n\t\t\ttry {\n\t\t\t\tdata = JSON.parse(rawText);\n\t\t\t} catch {\n\t\t\t\tdata = rawText;\n\t\t\t}\n\t\t} else {\n\t\t\t// Already an object — stringify for rawText, use directly for data\n\t\t\tdata = rawContent;\n\t\t\trawText = JSON.stringify(rawContent);\n\t\t}\n\n\t\treturn { data, rawText };\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Factory functions\n// ---------------------------------------------------------------------------\n\nexport function createWorkersAiChat(model: WorkersAiTextModel, config: WorkersAiAdapterConfig) {\n\treturn new WorkersAiTextAdapter(model, config);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createGatewayFetch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AIAJANLC.js";
|
|
4
4
|
|
|
5
5
|
// src/adapters/openrouter.ts
|
|
6
6
|
import {
|
|
@@ -54,4 +54,4 @@ export {
|
|
|
54
54
|
createOpenRouterImage,
|
|
55
55
|
createOpenRouterSummarize
|
|
56
56
|
};
|
|
57
|
-
//# sourceMappingURL=chunk-
|
|
57
|
+
//# sourceMappingURL=chunk-JRFPCMSE.js.map
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
isDirectBindingConfig,
|
|
11
11
|
isDirectCredentialsConfig,
|
|
12
12
|
validateWorkersAiConfig
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-AIAJANLC.js";
|
|
14
14
|
import {
|
|
15
15
|
__publicField
|
|
16
16
|
} from "./chunk-V6TY7KAL.js";
|
|
@@ -108,4 +108,4 @@ export {
|
|
|
108
108
|
WorkersAiTTSAdapter,
|
|
109
109
|
createWorkersAiTts
|
|
110
110
|
};
|
|
111
|
-
//# sourceMappingURL=chunk-
|
|
111
|
+
//# sourceMappingURL=chunk-KWYOUT2Y.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkWBTQKWFNcjs = require('./chunk-WBTQKWFN.cjs');
|
|
4
4
|
|
|
5
5
|
// src/adapters/openrouter.ts
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ var _aiopenrouter = require('@tanstack/ai-openrouter');
|
|
|
11
11
|
var _sdk = require('@openrouter/sdk');
|
|
12
12
|
function buildOpenRouterConfig(config) {
|
|
13
13
|
const httpClient = new (0, _sdk.HTTPClient)({
|
|
14
|
-
fetcher:
|
|
14
|
+
fetcher: _chunkWBTQKWFNcjs.createGatewayFetch.call(void 0, "openrouter", config)
|
|
15
15
|
});
|
|
16
16
|
return {
|
|
17
17
|
apiKey: _nullishCoalesce(config.apiKey, () => ( "unused")),
|
|
@@ -23,7 +23,7 @@ function buildOpenRouterConfig(config) {
|
|
|
23
23
|
}
|
|
24
24
|
function buildOpenRouterImageConfig(config) {
|
|
25
25
|
const httpClient = new (0, _sdk.HTTPClient)({
|
|
26
|
-
fetcher:
|
|
26
|
+
fetcher: _chunkWBTQKWFNcjs.createGatewayFetch.call(void 0, "openrouter", config)
|
|
27
27
|
});
|
|
28
28
|
return {
|
|
29
29
|
apiKey: _nullishCoalesce(config.apiKey, () => ( "unused")),
|
|
@@ -32,7 +32,7 @@ function buildOpenRouterImageConfig(config) {
|
|
|
32
32
|
}
|
|
33
33
|
function buildOpenRouterSummarizeConfig(config) {
|
|
34
34
|
const httpClient = new (0, _sdk.HTTPClient)({
|
|
35
|
-
fetcher:
|
|
35
|
+
fetcher: _chunkWBTQKWFNcjs.createGatewayFetch.call(void 0, "openrouter", config)
|
|
36
36
|
});
|
|
37
37
|
return {
|
|
38
38
|
apiKey: _nullishCoalesce(config.apiKey, () => ( "unused")),
|
|
@@ -54,4 +54,4 @@ function createOpenRouterSummarize(model, config) {
|
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
exports.createOpenRouterChat = createOpenRouterChat; exports.createOpenRouterImage = createOpenRouterImage; exports.createOpenRouterSummarize = createOpenRouterSummarize;
|
|
57
|
-
//# sourceMappingURL=chunk-
|
|
57
|
+
//# sourceMappingURL=chunk-MJ45L566.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-MJ45L566.cjs","../src/adapters/openrouter.ts"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACA;ACJA;AACC;AACA;AACA;AAAA,uDAIM;AACP,sCAA2B;AAY3B,SAAS,qBAAA,CAAsB,MAAA,EAAmD;AACjF,EAAA,MAAM,WAAA,EAAa,IAAI,oBAAA,CAAW;AAAA,IACjC,OAAA,EAAS,kDAAA,YAAmB,EAAc,MAAM;AAAA,EACjD,CAAC,CAAA;AACD,EAAA,OAAO;AAAA,IACN,MAAA,mBAAQ,MAAA,CAAO,MAAA,UAAU,UAAA;AAAA;AAAA;AAAA;AAAA,IAIzB;AAAA,EACD,CAAA;AACD;AAWA,SAAS,0BAAA,CAA2B,MAAA,EAAwD;AAC3F,EAAA,MAAM,WAAA,EAAa,IAAI,oBAAA,CAAW;AAAA,IACjC,OAAA,EAAS,kDAAA,YAAmB,EAAc,MAAM;AAAA,EACjD,CAAC,CAAA;AACD,EAAA,OAAO;AAAA,IACN,MAAA,mBAAQ,MAAA,CAAO,MAAA,UAAU,UAAA;AAAA,IACzB;AAAA,EACD,CAAA;AACD;AASA,SAAS,8BAAA,CACR,MAAA,EAC4B;AAC5B,EAAA,MAAM,WAAA,EAAa,IAAI,oBAAA,CAAW;AAAA,IACjC,OAAA,EAAS,kDAAA,YAAmB,EAAc,MAAM;AAAA,EACjD,CAAC,CAAA;AACD,EAAA,OAAO;AAAA,IACN,MAAA,mBAAQ,MAAA,CAAO,MAAA,UAAU,UAAA;AAAA,IACzB;AAAA,EACD,CAAA;AACD;AA0BO,SAAS,oBAAA,CACf,KAAA,EACA,MAAA,EACiB;AAEjB,EAAA,OAAO,IAAI,wCAAA,CAAsB,qBAAA,CAAsB,MAAM,CAAA,EAAG,KAAY,CAAA;AAC7E;AASO,SAAS,qBAAA,CACf,KAAA,EACA,MAAA,EACC;AAED,EAAA,OAAO,IAAI,yCAAA,CAAuB,0BAAA,CAA2B,MAAM,CAAA,EAAG,KAAY,CAAA;AACnF;AASO,SAAS,yBAAA,CACf,KAAA,EACA,MAAA,EACC;AAED,EAAA,OAAO,IAAI,6CAAA,CAA2B,8BAAA,CAA+B,MAAM,CAAA,EAAG,KAAY,CAAA;AAC3F;ADjFA;AACA;AACE;AACA;AACA;AACF,0KAAC","file":"/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-MJ45L566.cjs","sourcesContent":[null,"import {\n\tOpenRouterTextAdapter,\n\tOpenRouterImageAdapter,\n\tOpenRouterSummarizeAdapter,\n\ttype OpenRouterConfig,\n\ttype OpenRouterImageConfig,\n\ttype OpenRouterSummarizeConfig,\n} from \"@tanstack/ai-openrouter\";\nimport { HTTPClient } from \"@openrouter/sdk\";\nimport { createGatewayFetch, type AiGatewayAdapterConfig } from \"../utils/create-fetcher\";\nimport type { AnyTextAdapter } from \"@tanstack/ai\";\n\nexport type OpenRouterGatewayConfig = AiGatewayAdapterConfig;\n\n/**\n * Build OpenRouter config that routes requests through AI Gateway.\n *\n * The OpenRouter SDK accepts an `httpClient` with a custom `fetcher`,\n * which we use to inject the AI Gateway fetch.\n */\nfunction buildOpenRouterConfig(config: OpenRouterGatewayConfig): OpenRouterConfig {\n\tconst httpClient = new HTTPClient({\n\t\tfetcher: createGatewayFetch(\"openrouter\", config),\n\t});\n\treturn {\n\t\tapiKey: config.apiKey ?? \"unused\",\n\t\t// Cast needed: the installed @openrouter/sdk version may differ from the\n\t\t// version @tanstack/ai-openrouter was built against. The HTTPClient interface\n\t\t// is structurally compatible but TypeScript sees them as separate declarations.\n\t\thttpClient: httpClient as unknown as OpenRouterConfig[\"httpClient\"],\n\t};\n}\n\n/**\n * Build OpenRouter image config that routes requests through AI Gateway.\n *\n * `OpenRouterImageConfig` extends `OpenRouterClientConfig` which declares\n * `baseURL` and `apiKey` but not `httpClient`. However, the image adapter\n * internally creates an `OpenRouter` SDK instance (which does accept\n * `httpClient` via `SDKOptions`). The double-cast is needed because the\n * declared config type is narrower than what the SDK constructor accepts.\n */\nfunction buildOpenRouterImageConfig(config: OpenRouterGatewayConfig): OpenRouterImageConfig {\n\tconst httpClient = new HTTPClient({\n\t\tfetcher: createGatewayFetch(\"openrouter\", config),\n\t});\n\treturn {\n\t\tapiKey: config.apiKey ?? \"unused\",\n\t\thttpClient,\n\t} as unknown as OpenRouterImageConfig;\n}\n\n/**\n * Build OpenRouter summarize config.\n *\n * `OpenRouterSummarizeConfig` extends `OpenRouterConfig` with optional\n * `temperature` and `maxTokens` fields. Since those are optional, a plain\n * `OpenRouterConfig` is structurally compatible — no cast needed.\n */\nfunction buildOpenRouterSummarizeConfig(\n\tconfig: OpenRouterGatewayConfig,\n): OpenRouterSummarizeConfig {\n\tconst httpClient = new HTTPClient({\n\t\tfetcher: createGatewayFetch(\"openrouter\", config),\n\t});\n\treturn {\n\t\tapiKey: config.apiKey ?? \"unused\",\n\t\thttpClient: httpClient as unknown as OpenRouterSummarizeConfig[\"httpClient\"],\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Chat model type — OpenRouter supports many models; we use a loose string type\n// ---------------------------------------------------------------------------\n\n/** OpenRouter chat model identifier. Accepts any string since OpenRouter proxies hundreds of models. */\nexport type OpenRouterChatModel = string;\n\n/** OpenRouter image model identifier. */\nexport type OpenRouterImageModel = string;\n\n/** OpenRouter summarize model identifier (same as chat models). */\nexport type OpenRouterSummarizeModel = string;\n\n// ---------------------------------------------------------------------------\n// Factory functions\n// ---------------------------------------------------------------------------\n\n/**\n * Creates an OpenRouter chat adapter which uses Cloudflare AI Gateway.\n * Supports both binding and credential-based configurations.\n *\n * @param model The model to use (e.g. \"openai/gpt-4o\", \"anthropic/claude-sonnet-4-5\")\n * @param config Configuration options\n */\nexport function createOpenRouterChat(\n\tmodel: OpenRouterChatModel,\n\tconfig: OpenRouterGatewayConfig,\n): AnyTextAdapter {\n\t// Cast needed: we accept any string model while upstream expects a literal union\n\treturn new OpenRouterTextAdapter(buildOpenRouterConfig(config), model as any);\n}\n\n/**\n * Creates an OpenRouter image adapter which uses Cloudflare AI Gateway.\n * Supports both binding and credential-based configurations.\n *\n * @param model The image model to use\n * @param config Configuration options\n */\nexport function createOpenRouterImage(\n\tmodel: OpenRouterImageModel,\n\tconfig: OpenRouterGatewayConfig,\n) {\n\t// Cast needed: we accept any string model while upstream expects a literal union\n\treturn new OpenRouterImageAdapter(buildOpenRouterImageConfig(config), model as any);\n}\n\n/**\n * Creates an OpenRouter summarize adapter which uses Cloudflare AI Gateway.\n * Supports both binding and credential-based configurations.\n *\n * @param model The model to use for summarization\n * @param config Configuration options\n */\nexport function createOpenRouterSummarize(\n\tmodel: OpenRouterSummarizeModel,\n\tconfig: OpenRouterGatewayConfig,\n) {\n\t// Cast needed: we accept any string model while upstream expects a literal union\n\treturn new OpenRouterSummarizeAdapter(buildOpenRouterSummarizeConfig(config), model as any);\n}\n"]}
|
|
@@ -10,7 +10,7 @@ var _chunk7HSUHP63cjs = require('./chunk-7HSUHP63.cjs');
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
var
|
|
13
|
+
var _chunkWBTQKWFNcjs = require('./chunk-WBTQKWFN.cjs');
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
var _chunk4DE2IREAcjs = require('./chunk-4DE2IREA.cjs');
|
|
@@ -22,7 +22,7 @@ var WorkersAiTTSAdapter = class extends _adapters.BaseTTSAdapter {
|
|
|
22
22
|
super({}, model);
|
|
23
23
|
_chunk4DE2IREAcjs.__publicField.call(void 0, this, "name", "workers-ai-tts");
|
|
24
24
|
_chunk4DE2IREAcjs.__publicField.call(void 0, this, "adapterConfig");
|
|
25
|
-
|
|
25
|
+
_chunkWBTQKWFNcjs.validateWorkersAiConfig.call(void 0, config);
|
|
26
26
|
this.adapterConfig = config;
|
|
27
27
|
}
|
|
28
28
|
async generateSpeech(options) {
|
|
@@ -30,10 +30,10 @@ var WorkersAiTTSAdapter = class extends _adapters.BaseTTSAdapter {
|
|
|
30
30
|
const extra = { ...modelOptions };
|
|
31
31
|
if (voice) extra.voice = voice;
|
|
32
32
|
if (speed != null) extra.speed = speed;
|
|
33
|
-
if (
|
|
33
|
+
if (_chunkWBTQKWFNcjs.isDirectBindingConfig.call(void 0, this.adapterConfig)) {
|
|
34
34
|
return this.generateViaBinding(text, format, extra);
|
|
35
35
|
}
|
|
36
|
-
if (
|
|
36
|
+
if (_chunkWBTQKWFNcjs.isDirectCredentialsConfig.call(void 0, this.adapterConfig)) {
|
|
37
37
|
return this.generateViaRest(text, format, extra);
|
|
38
38
|
}
|
|
39
39
|
return this.generateViaGateway(text, format, extra);
|
|
@@ -56,7 +56,7 @@ var WorkersAiTTSAdapter = class extends _adapters.BaseTTSAdapter {
|
|
|
56
56
|
}
|
|
57
57
|
async generateViaGateway(text, format, options) {
|
|
58
58
|
const gatewayConfig = this.adapterConfig;
|
|
59
|
-
const gatewayFetch =
|
|
59
|
+
const gatewayFetch = _chunkWBTQKWFNcjs.createGatewayFetch.call(void 0, "workers-ai", gatewayConfig);
|
|
60
60
|
const response = await gatewayFetch("https://api.cloudflare.com/v1/audio/speech", {
|
|
61
61
|
method: "POST",
|
|
62
62
|
body: JSON.stringify({
|
|
@@ -108,4 +108,4 @@ function createWorkersAiTts(model, config) {
|
|
|
108
108
|
|
|
109
109
|
|
|
110
110
|
exports.WorkersAiTTSAdapter = WorkersAiTTSAdapter; exports.createWorkersAiTts = createWorkersAiTts;
|
|
111
|
-
//# sourceMappingURL=chunk-
|
|
111
|
+
//# sourceMappingURL=chunk-N6U27RQW.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-N6U27RQW.cjs","../src/adapters/workers-ai-tts.ts"],"names":[],"mappings":"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","file":"/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-N6U27RQW.cjs","sourcesContent":[null,"import { BaseTTSAdapter } from \"@tanstack/ai/adapters\";\nimport type { TTSOptions, TTSResult } from \"@tanstack/ai\";\nimport {\n\ttype WorkersAiAdapterConfig,\n\ttype WorkersAiDirectBindingConfig,\n\ttype WorkersAiDirectCredentialsConfig,\n\ttype AiGatewayAdapterConfig,\n\tcreateGatewayFetch,\n\tisDirectBindingConfig,\n\tisDirectCredentialsConfig,\n\tvalidateWorkersAiConfig,\n} from \"../utils/create-fetcher\";\nimport { workersAiRestFetch } from \"../utils/workers-ai-rest\";\nimport { binaryToBase64, uint8ArrayToBase64 } from \"../utils/binary\";\n\n// ---------------------------------------------------------------------------\n// Model types\n// ---------------------------------------------------------------------------\n\n/**\n * Workers AI models that support text-to-speech generation.\n *\n * Note: the typed `AiModels` interface in `@cloudflare/workers-types` may lag\n * behind what's deployed. We use a string union here that matches the known\n * models including Deepgram partner models.\n */\nexport type WorkersAiTTSModel =\n\t| \"@cf/deepgram/aura-1\"\n\t| \"@cf/deepgram/aura-2-en\"\n\t| \"@cf/deepgram/aura-2-es\"\n\t| (string & {});\n\n// ---------------------------------------------------------------------------\n// WorkersAiTTSAdapter\n// ---------------------------------------------------------------------------\n\nexport class WorkersAiTTSAdapter extends BaseTTSAdapter<WorkersAiTTSModel> {\n\treadonly name = \"workers-ai-tts\" as const;\n\tprivate adapterConfig: WorkersAiAdapterConfig;\n\n\tconstructor(config: WorkersAiAdapterConfig, model: WorkersAiTTSModel) {\n\t\tsuper({}, model);\n\t\tvalidateWorkersAiConfig(config);\n\t\tthis.adapterConfig = config;\n\t}\n\n\tasync generateSpeech(options: TTSOptions): Promise<TTSResult> {\n\t\tconst { text, voice, format, speed, modelOptions } = options;\n\n\t\t// Workers AI TTS models (Deepgram aura-1) accept { text, lang? }\n\t\tconst extra: Record<string, unknown> = { ...modelOptions };\n\t\tif (voice) extra.voice = voice;\n\t\tif (speed != null) extra.speed = speed;\n\n\t\tif (isDirectBindingConfig(this.adapterConfig)) {\n\t\t\treturn this.generateViaBinding(text, format, extra);\n\t\t}\n\n\t\tif (isDirectCredentialsConfig(this.adapterConfig)) {\n\t\t\treturn this.generateViaRest(text, format, extra);\n\t\t}\n\n\t\treturn this.generateViaGateway(text, format, extra);\n\t}\n\n\tprivate async generateViaBinding(\n\t\ttext: string,\n\t\tformat: string | undefined,\n\t\toptions: Record<string, unknown>,\n\t): Promise<TTSResult> {\n\t\tconst ai = (this.adapterConfig as WorkersAiDirectBindingConfig).binding;\n\t\tconst result = await ai.run(this.model, { text, ...options });\n\n\t\treturn this.normalizeResult(result, format);\n\t}\n\n\tprivate async generateViaRest(\n\t\ttext: string,\n\t\tformat: string | undefined,\n\t\toptions: Record<string, unknown>,\n\t): Promise<TTSResult> {\n\t\tconst config = this.adapterConfig as WorkersAiDirectCredentialsConfig;\n\t\tconst response = await workersAiRestFetch(\n\t\t\tconfig,\n\t\t\tthis.model,\n\t\t\t{ text, ...options },\n\t\t\t{ label: \"Workers AI TTS\", signal: (options as { signal?: AbortSignal }).signal },\n\t\t);\n\n\t\t// Workers AI TTS returns audio bytes directly\n\t\tconst buffer = await response.arrayBuffer();\n\t\treturn this.wrapAudioResult(new Uint8Array(buffer), format);\n\t}\n\n\tprivate async generateViaGateway(\n\t\ttext: string,\n\t\tformat: string | undefined,\n\t\toptions: Record<string, unknown>,\n\t): Promise<TTSResult> {\n\t\tconst gatewayConfig = this.adapterConfig as AiGatewayAdapterConfig;\n\t\tconst gatewayFetch = createGatewayFetch(\"workers-ai\", gatewayConfig);\n\n\t\t// The URL here is a placeholder — createGatewayFetch for \"workers-ai\" extracts\n\t\t// the model from the body, sets it as the endpoint, and routes through the gateway.\n\t\t// The actual URL path is not used.\n\t\tconst response = await gatewayFetch(\"https://api.cloudflare.com/v1/audio/speech\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify({\n\t\t\t\tmodel: this.model,\n\t\t\t\ttext,\n\t\t\t\t...options,\n\t\t\t}),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text();\n\t\t\tthrow new Error(\n\t\t\t\t`Workers AI TTS gateway request failed (${response.status}): ${errorText}`,\n\t\t\t);\n\t\t}\n\n\t\tconst buffer = await response.arrayBuffer();\n\t\treturn this.wrapAudioResult(new Uint8Array(buffer), format);\n\t}\n\n\t/**\n\t * Normalize binding results. Workers AI TTS can return:\n\t * - Uint8Array / ArrayBuffer (raw audio bytes)\n\t * - ReadableStream<Uint8Array> (streamed audio bytes)\n\t * - { audio: \"base64...\" } (JSON wrapper)\n\t */\n\tprivate async normalizeResult(result: unknown, format: string | undefined): Promise<TTSResult> {\n\t\t// Use the shared binaryToBase64 helper for Uint8Array/ArrayBuffer/ReadableStream\n\t\t// and { audio: \"base64...\" } JSON wrapper\n\t\tconst b64 = await binaryToBase64(result, \"audio\");\n\t\treturn {\n\t\t\tid: this.generateId(),\n\t\t\tmodel: this.model,\n\t\t\taudio: b64,\n\t\t\tformat: format ?? \"mp3\",\n\t\t\tcontentType: `audio/${format ?? \"mp3\"}`,\n\t\t};\n\t}\n\n\tprivate wrapAudioResult(bytes: Uint8Array, format: string | undefined): TTSResult {\n\t\treturn {\n\t\t\tid: this.generateId(),\n\t\t\tmodel: this.model,\n\t\t\taudio: uint8ArrayToBase64(bytes),\n\t\t\tformat: format ?? \"mp3\",\n\t\t\tcontentType: `audio/${format ?? \"mp3\"}`,\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Factory function\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a Workers AI text-to-speech adapter.\n *\n * Works with TanStack AI's `generateSpeech()` activity function:\n * ```ts\n * import { generateSpeech } from \"@tanstack/ai\";\n * import { createWorkersAiTts } from \"@cloudflare/tanstack-ai\";\n *\n * const adapter = createWorkersAiTts(\n * \"@cf/deepgram/aura-1\",\n * { binding: env.AI },\n * );\n *\n * const result = await generateSpeech({ adapter, text: \"Hello world\" });\n * // result.audio — base64-encoded audio\n * ```\n *\n * Note: Factory takes `(model, config)` for ergonomics — the class constructor\n * uses `(config, model)` to match TanStack AI's upstream convention.\n */\nexport function createWorkersAiTts(model: WorkersAiTTSModel, config: WorkersAiAdapterConfig) {\n\treturn new WorkersAiTTSAdapter(config, model);\n}\n"]}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
isDirectBindingConfig,
|
|
7
7
|
isDirectCredentialsConfig,
|
|
8
8
|
validateWorkersAiConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-AIAJANLC.js";
|
|
10
10
|
import {
|
|
11
11
|
__publicField
|
|
12
12
|
} from "./chunk-V6TY7KAL.js";
|
|
@@ -83,4 +83,4 @@ export {
|
|
|
83
83
|
WorkersAiSummarizeAdapter,
|
|
84
84
|
createWorkersAiSummarize
|
|
85
85
|
};
|
|
86
|
-
//# sourceMappingURL=chunk-
|
|
86
|
+
//# sourceMappingURL=chunk-NH3FF5JC.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkWBTQKWFNcjs = require('./chunk-WBTQKWFN.cjs');
|
|
4
4
|
|
|
5
5
|
// src/adapters/anthropic.ts
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ var _aianthropic = require('@tanstack/ai-anthropic');
|
|
|
11
11
|
function buildAnthropicConfig(config) {
|
|
12
12
|
return {
|
|
13
13
|
apiKey: _nullishCoalesce(config.apiKey, () => ( "unused")),
|
|
14
|
-
fetch:
|
|
14
|
+
fetch: _chunkWBTQKWFNcjs.createGatewayFetch.call(void 0, "anthropic", config, {
|
|
15
15
|
"anthropic-version": _nullishCoalesce(config.anthropicVersion, () => ( "2023-06-01"))
|
|
16
16
|
})
|
|
17
17
|
};
|
|
@@ -28,4 +28,4 @@ function createAnthropicSummarize(model, config) {
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
exports.ANTHROPIC_MODELS = _aianthropic.ANTHROPIC_MODELS; exports.createAnthropicChat = createAnthropicChat; exports.createAnthropicSummarize = createAnthropicSummarize;
|
|
31
|
-
//# sourceMappingURL=chunk-
|
|
31
|
+
//# sourceMappingURL=chunk-OFUYHQZE.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-OFUYHQZE.cjs","../src/adapters/anthropic.ts"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACA;ACJA;AACC;AACA;AACA;AAAA,qDAEM;AAKP,SAAS,oBAAA,CAAqB,MAAA,EAAgC;AAC7D,EAAA,OAAO;AAAA,IACN,MAAA,mBAAQ,MAAA,CAAO,MAAA,UAAU,UAAA;AAAA,IACzB,KAAA,EAAO,kDAAA,WAAmB,EAAa,MAAA,EAAQ;AAAA,MAC9C,mBAAA,mBAAqB,MAAA,CAAO,gBAAA,UAAoB;AAAA,IACjD,CAAC;AAAA,EACF,CAAA;AACD;AASO,SAAS,mBAAA,CACf,KAAA,EACA,MAAA,EAC2C;AAC3C,EAAA,OAAO,IAAI,sCAAA,CAAqB,oBAAA,CAAqB,MAAM,CAAA,EAAG,KAAK,CAAA;AACpE;AAMO,SAAS,wBAAA,CACf,KAAA,EACA,MAAA,EACC;AACD,EAAA,OAAO,IAAI,2CAAA,CAA0B,oBAAA,CAAqB,MAAM,CAAA,EAAG,KAAK,CAAA;AACzE;ADlBA;AACA;AACE;AACA;AACA;AACF,yKAAC","file":"/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-OFUYHQZE.cjs","sourcesContent":[null,"import {\n\tAnthropicTextAdapter,\n\tAnthropicSummarizeAdapter,\n\tANTHROPIC_MODELS,\n\ttype AnthropicChatModel,\n} from \"@tanstack/ai-anthropic\";\nimport { createGatewayFetch, type AiGatewayAdapterConfig } from \"../utils/create-fetcher\";\n\nexport type AnthropicGatewayConfig = AiGatewayAdapterConfig & { anthropicVersion?: string };\n\nfunction buildAnthropicConfig(config: AnthropicGatewayConfig) {\n\treturn {\n\t\tapiKey: config.apiKey ?? \"unused\",\n\t\tfetch: createGatewayFetch(\"anthropic\", config, {\n\t\t\t\"anthropic-version\": config.anthropicVersion ?? \"2023-06-01\",\n\t\t}),\n\t};\n}\n\n/**\n * Creates an Anthropic chat adapter which uses Cloudflare AI Gateway.\n * Supports both binding and credential-based configurations.\n *\n * Since AnthropicTextConfig extends the Anthropic SDK's ClientOptions,\n * we can inject the gateway fetch directly — no subclassing needed.\n */\nexport function createAnthropicChat(\n\tmodel: AnthropicChatModel,\n\tconfig: AnthropicGatewayConfig,\n): AnthropicTextAdapter<AnthropicChatModel> {\n\treturn new AnthropicTextAdapter(buildAnthropicConfig(config), model);\n}\n\n/**\n * Creates an Anthropic summarize adapter which uses Cloudflare AI Gateway.\n * Supports both binding and credential-based configurations.\n */\nexport function createAnthropicSummarize(\n\tmodel: AnthropicChatModel,\n\tconfig: AnthropicGatewayConfig,\n) {\n\treturn new AnthropicSummarizeAdapter(buildAnthropicConfig(config), model);\n}\n\nexport { ANTHROPIC_MODELS, type AnthropicChatModel };\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkWBTQKWFNcjs = require('./chunk-WBTQKWFN.cjs');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
var _chunk4DE2IREAcjs = require('./chunk-4DE2IREA.cjs');
|
|
@@ -15,18 +15,18 @@ var _chunk4DE2IREAcjs = require('./chunk-4DE2IREA.cjs');
|
|
|
15
15
|
var _adapters = require('@tanstack/ai/adapters');
|
|
16
16
|
var _openai = require('openai'); var _openai2 = _interopRequireDefault(_openai);
|
|
17
17
|
function buildWorkersAiClient(config) {
|
|
18
|
-
|
|
18
|
+
_chunkWBTQKWFNcjs.validateWorkersAiConfig.call(void 0, config);
|
|
19
19
|
const sessionHeaders = config.sessionAffinity ? { "x-session-affinity": config.sessionAffinity } : void 0;
|
|
20
|
-
if (
|
|
20
|
+
if (_chunkWBTQKWFNcjs.isDirectBindingConfig.call(void 0, config)) {
|
|
21
21
|
return new (0, _openai2.default)({
|
|
22
22
|
apiKey: "unused",
|
|
23
|
-
fetch:
|
|
23
|
+
fetch: _chunkWBTQKWFNcjs.createWorkersAiBindingFetch.call(void 0,
|
|
24
24
|
config.binding,
|
|
25
25
|
sessionHeaders ? { extraHeaders: sessionHeaders } : void 0
|
|
26
26
|
)
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
-
if (
|
|
29
|
+
if (_chunkWBTQKWFNcjs.isDirectCredentialsConfig.call(void 0, config)) {
|
|
30
30
|
return new (0, _openai2.default)({
|
|
31
31
|
baseURL: `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/ai/v1`,
|
|
32
32
|
apiKey: config.apiKey,
|
|
@@ -35,7 +35,7 @@ function buildWorkersAiClient(config) {
|
|
|
35
35
|
}
|
|
36
36
|
const gatewayConfig = config;
|
|
37
37
|
return new (0, _openai2.default)({
|
|
38
|
-
fetch:
|
|
38
|
+
fetch: _chunkWBTQKWFNcjs.createGatewayFetch.call(void 0, "workers-ai", gatewayConfig, sessionHeaders),
|
|
39
39
|
apiKey: _nullishCoalesce(gatewayConfig.apiKey, () => ( "unused"))
|
|
40
40
|
});
|
|
41
41
|
}
|
|
@@ -157,7 +157,7 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
|
|
|
157
157
|
this.client = buildWorkersAiClient(config);
|
|
158
158
|
}
|
|
159
159
|
async *chatStream(options) {
|
|
160
|
-
const { systemPrompts, messages, tools, temperature, model } = options;
|
|
160
|
+
const { systemPrompts, messages, tools, temperature, maxTokens, model } = options;
|
|
161
161
|
const openAIMessages = buildOpenAIMessages(systemPrompts, messages);
|
|
162
162
|
const openAITools = buildOpenAITools(tools);
|
|
163
163
|
const timestamp = Date.now();
|
|
@@ -179,6 +179,7 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
|
|
|
179
179
|
messages: openAIMessages,
|
|
180
180
|
tools: openAITools,
|
|
181
181
|
temperature,
|
|
182
|
+
max_tokens: maxTokens,
|
|
182
183
|
stream: true,
|
|
183
184
|
stream_options: { include_usage: true }
|
|
184
185
|
});
|
|
@@ -191,7 +192,8 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
|
|
|
191
192
|
model: _nullishCoalesce(model, () => ( this.model)),
|
|
192
193
|
messages: openAIMessages,
|
|
193
194
|
tools: openAITools,
|
|
194
|
-
temperature
|
|
195
|
+
temperature,
|
|
196
|
+
max_tokens: maxTokens
|
|
195
197
|
});
|
|
196
198
|
yield {
|
|
197
199
|
type: "RUN_STARTED",
|
|
@@ -518,4 +520,4 @@ function createWorkersAiChat(model, config) {
|
|
|
518
520
|
|
|
519
521
|
|
|
520
522
|
exports.WorkersAiTextAdapter = WorkersAiTextAdapter; exports.createWorkersAiChat = createWorkersAiChat;
|
|
521
|
-
//# sourceMappingURL=chunk-
|
|
523
|
+
//# sourceMappingURL=chunk-OUEAAP25.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-OUEAAP25.cjs","../src/adapters/workers-ai.ts"],"names":[],"mappings":"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","file":"/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-OUEAAP25.cjs","sourcesContent":[null,"import type { AiModels, BaseAiTextGeneration } from \"@cloudflare/workers-types\";\nimport type { ContentPart, ModelMessage, StreamChunk, TextOptions } from \"@tanstack/ai\";\nimport {\n\tBaseTextAdapter,\n\ttype StructuredOutputOptions,\n\ttype StructuredOutputResult,\n} from \"@tanstack/ai/adapters\";\nimport OpenAI from \"openai\";\nimport {\n\ttype WorkersAiAdapterConfig,\n\ttype AiGatewayAdapterConfig,\n\tcreateGatewayFetch,\n\tcreateWorkersAiBindingFetch,\n\tisDirectBindingConfig,\n\tisDirectCredentialsConfig,\n\tvalidateWorkersAiConfig,\n} from \"../utils/create-fetcher\";\n\n// ---------------------------------------------------------------------------\n// Model types derived from @cloudflare/workers-types\n// ---------------------------------------------------------------------------\n\nexport type WorkersAiTextModel =\n\t| {\n\t\t\t[K in keyof AiModels]: AiModels[K] extends BaseAiTextGeneration ? K : never;\n\t }[keyof AiModels]\n\t| (string & {});\n\n// ---------------------------------------------------------------------------\n// Helpers: build the right OpenAI client depending on config mode\n// ---------------------------------------------------------------------------\n\nfunction buildWorkersAiClient(config: WorkersAiAdapterConfig): OpenAI {\n\tvalidateWorkersAiConfig(config);\n\n\tconst sessionHeaders: Record<string, string> | undefined = config.sessionAffinity\n\t\t? { \"x-session-affinity\": config.sessionAffinity }\n\t\t: undefined;\n\n\tif (isDirectBindingConfig(config)) {\n\t\t// Plain binding mode: shim translates OpenAI fetch calls to env.AI.run()\n\t\treturn new OpenAI({\n\t\t\tapiKey: \"unused\",\n\t\t\tfetch: createWorkersAiBindingFetch(\n\t\t\t\tconfig.binding,\n\t\t\t\tsessionHeaders ? { extraHeaders: sessionHeaders } : undefined,\n\t\t\t),\n\t\t});\n\t}\n\n\tif (isDirectCredentialsConfig(config)) {\n\t\t// Plain REST mode: point OpenAI SDK at Workers AI's OpenAI-compatible endpoint\n\t\treturn new OpenAI({\n\t\t\tbaseURL: `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/ai/v1`,\n\t\t\tapiKey: config.apiKey,\n\t\t\tdefaultHeaders: sessionHeaders,\n\t\t});\n\t}\n\n\t// Gateway mode (existing): use createGatewayFetch\n\tconst gatewayConfig = config as AiGatewayAdapterConfig;\n\treturn new OpenAI({\n\t\tfetch: createGatewayFetch(\"workers-ai\", gatewayConfig, sessionHeaders),\n\t\tapiKey: gatewayConfig.apiKey ?? \"unused\",\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Shared message-building helpers\n// ---------------------------------------------------------------------------\n\nfunction extractTextContent(content: ModelMessage[\"content\"]): string {\n\tif (content === null) return \"\";\n\tif (typeof content === \"string\") return content;\n\treturn content.flatMap((p) => (p.type === \"text\" ? [p.content] : [])).join(\"\");\n}\n\n/**\n * Convert a single TanStack AI {@link ContentPart} to the OpenAI Chat\n * Completions multi-modal format.\n *\n * TODO: handle other content types (audio, video, document)\n */\nfunction convertContentPart(part: ContentPart): OpenAI.Chat.ChatCompletionContentPart | undefined {\n\tswitch (part.type) {\n\t\tcase \"text\":\n\t\t\tif (part.content) {\n\t\t\t\treturn { type: \"text\", text: part.content };\n\t\t\t}\n\t\t\treturn undefined;\n\t\tcase \"image\": {\n\t\t\tlet url: string;\n\t\t\tif (part.source.type === \"data\") {\n\t\t\t\turl = part.source.value.startsWith(\"data:\")\n\t\t\t\t\t? part.source.value\n\t\t\t\t\t: `data:${part.source.mimeType};base64,${part.source.value}`;\n\t\t\t} else {\n\t\t\t\turl = part.source.value;\n\t\t\t}\n\t\t\treturn { type: \"image_url\", image_url: { url } };\n\t\t}\n\t\tdefault:\n\t\t\t// audio, video, document — not supported for now\n\t\t\tconsole.warn(\n\t\t\t\t`[@cloudflare/tanstack-ai] Unsupported content part type \"${part.type}\" — skipping`,\n\t\t\t);\n\t\t\treturn undefined;\n\t}\n}\n\n/**\n * Build OpenAI-compatible user message content from TanStack AI content.\n *\n * If the content has only text parts, returns a plain string.\n * If it includes image parts, returns an array of content parts in\n * OpenAI's multi-modal format (text + image_url).\n */\nfunction buildUserContent(\n\tcontent: ModelMessage[\"content\"],\n): string | OpenAI.Chat.ChatCompletionContentPart[] {\n\tif (content === null) return \"\";\n\tif (typeof content === \"string\") return content;\n\n\tconst hasImages = content.some((p) => p.type === \"image\");\n\tif (!hasImages) {\n\t\treturn content.flatMap((p) => (p.type === \"text\" ? [p.content] : [])).join(\"\");\n\t}\n\n\tconst parts: OpenAI.Chat.ChatCompletionContentPart[] = [];\n\tfor (const part of content) {\n\t\tconst converted = convertContentPart(part);\n\t\tif (converted) {\n\t\t\tparts.push(converted);\n\t\t}\n\t}\n\treturn parts;\n}\n\nfunction buildOpenAIMessages(\n\tsystemPrompts: string[] | undefined,\n\tmessages: ModelMessage[],\n\toptions?: { includeToolMessages?: boolean },\n): OpenAI.Chat.ChatCompletionMessageParam[] {\n\tconst includeTools = options?.includeToolMessages ?? true;\n\tconst openAIMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [];\n\n\tif (systemPrompts && systemPrompts.length > 0) {\n\t\topenAIMessages.push({\n\t\t\trole: \"system\",\n\t\t\tcontent: systemPrompts.join(\"\\n\"),\n\t\t});\n\t}\n\n\tfor (const message of messages) {\n\t\tif (message.role === \"user\") {\n\t\t\topenAIMessages.push({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: buildUserContent(message.content),\n\t\t\t});\n\t\t} else if (message.role === \"assistant\") {\n\t\t\tconst assistantMessage: OpenAI.Chat.ChatCompletionAssistantMessageParam = {\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: extractTextContent(message.content),\n\t\t\t};\n\t\t\tif (includeTools && message.toolCalls && message.toolCalls.length > 0) {\n\t\t\t\tassistantMessage.tool_calls = message.toolCalls.map((tc) => ({\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\ttype: \"function\" as const,\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\t\targuments: tc.function.arguments,\n\t\t\t\t\t},\n\t\t\t\t}));\n\t\t\t}\n\t\t\topenAIMessages.push(assistantMessage);\n\t\t} else if (includeTools && message.role === \"tool\") {\n\t\t\tlet toolContent: string;\n\t\t\tif (typeof message.content === \"string\") {\n\t\t\t\ttry {\n\t\t\t\t\tJSON.parse(message.content);\n\t\t\t\t\ttoolContent = message.content;\n\t\t\t\t} catch {\n\t\t\t\t\ttoolContent = JSON.stringify(message.content);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttoolContent = JSON.stringify(message.content);\n\t\t\t}\n\t\t\topenAIMessages.push({\n\t\t\t\trole: \"tool\",\n\t\t\t\ttool_call_id: message.toolCallId || `tool_${crypto.randomUUID().slice(0, 8)}`,\n\t\t\t\tcontent: toolContent,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn openAIMessages;\n}\n\nfunction buildOpenAITools(\n\ttools: Array<{ name: string; description: string; inputSchema?: unknown }> | undefined,\n): OpenAI.Chat.ChatCompletionTool[] | undefined {\n\tif (!tools) return undefined;\n\treturn tools.map((tool) => ({\n\t\ttype: \"function\" as const,\n\t\tfunction: {\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: tool.inputSchema as Record<string, unknown>,\n\t\t},\n\t}));\n}\n\n// ---------------------------------------------------------------------------\n// ID generation\n// ---------------------------------------------------------------------------\n\nfunction generateId(prefix = \"chatcmpl\"): string {\n\treturn `${prefix}-${crypto.randomUUID().replace(/-/g, \"\").slice(0, 16)}`;\n}\n\n// ---------------------------------------------------------------------------\n// WorkersAiTextAdapter: chat / structured output via OpenAI Chat Completions\n// ---------------------------------------------------------------------------\n\n// TODO: Replace `any` generic params with proper types once BaseTextAdapter's\n// provider-options generics stabilize. Workers AI doesn't have provider-specific\n// options in the TanStack sense, so `any` is pragmatic for now.\nexport class WorkersAiTextAdapter<TModel extends WorkersAiTextModel> extends BaseTextAdapter<\n\tTModel,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any -- BaseTextAdapter generic params are opaque\n\tany,\n\tany,\n\tany\n> {\n\tname = \"workers-ai\" as const;\n\n\tprivate client: OpenAI;\n\n\tconstructor(model: TModel, config: WorkersAiAdapterConfig) {\n\t\tsuper({ apiKey: \"unused\" }, model);\n\t\tthis.client = buildWorkersAiClient(config);\n\t}\n\n\tasync *chatStream(options: TextOptions<any>): AsyncIterable<StreamChunk> {\n\t\tconst { systemPrompts, messages, tools, temperature, maxTokens, model } = options;\n\n\t\tconst openAIMessages = buildOpenAIMessages(systemPrompts, messages);\n\t\tconst openAITools = buildOpenAITools(tools);\n\n\t\tconst timestamp = Date.now();\n\t\tconst runId = generateId();\n\t\tconst messageId = generateId();\n\t\tlet hasEmittedRunStarted = false;\n\t\tlet hasEmittedTextMessageStart = false;\n\t\tlet accumulatedContent = \"\";\n\t\tlet hasEmittedStepStarted = false;\n\t\tlet accumulatedReasoning = \"\";\n\t\tconst stepId = generateId();\n\t\tlet hasReceivedFinishReason = false;\n\t\tconst toolCallsInProgress = new Map<\n\t\t\tnumber,\n\t\t\t{ id: string; name: string; arguments: string; started: boolean }\n\t\t>();\n\n\t\ttry {\n\t\t\tlet stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>;\n\t\t\ttry {\n\t\t\t\tstream = await this.client.chat.completions.create({\n\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\tmessages: openAIMessages,\n\t\t\t\t\ttools: openAITools,\n\t\t\t\t\ttemperature,\n\t\t\t\t\tmax_tokens: maxTokens,\n\t\t\t\t\tstream: true,\n\t\t\t\t\tstream_options: { include_usage: true },\n\t\t\t\t});\n\t\t\t} catch (streamError: unknown) {\n\t\t\t\t// Some models (e.g. GPT-OSS) don't support streaming via the REST API.\n\t\t\t\t// Fall back to a non-streaming call and yield the result as a single chunk.\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"[tanstack-ai] Streaming failed, falling back to non-streaming:\",\n\t\t\t\t\tstreamError instanceof Error ? streamError.message : streamError,\n\t\t\t\t);\n\t\t\t\tconst nonStreamResult = await this.client.chat.completions.create({\n\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\tmessages: openAIMessages,\n\t\t\t\t\ttools: openAITools,\n\t\t\t\t\ttemperature,\n\t\t\t\t\tmax_tokens: maxTokens,\n\t\t\t\t});\n\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"RUN_STARTED\",\n\t\t\t\t\trunId,\n\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\ttimestamp,\n\t\t\t\t} satisfies StreamChunk;\n\n\t\t\t\tconst msg = nonStreamResult.choices[0]?.message;\n\t\t\t\tif (msg?.content) {\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_START\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_CONTENT\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\tdelta: msg.content,\n\t\t\t\t\t\tcontent: msg.content,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_END\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\tif (msg?.tool_calls) {\n\t\t\t\t\tfor (const tc of msg.tool_calls) {\n\t\t\t\t\t\tif (tc.type !== \"function\") continue;\n\t\t\t\t\t\tconst fn = tc.function;\n\t\t\t\t\t\tlet parsedInput: unknown = {};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tparsedInput = fn.arguments ? JSON.parse(fn.arguments) : {};\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tparsedInput = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TOOL_CALL_START\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: fn.name,\n\t\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\tindex: 0,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TOOL_CALL_END\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: fn.name,\n\t\t\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\tinput: parsedInput,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst finishReason = nonStreamResult.choices[0]?.finish_reason;\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"RUN_FINISHED\",\n\t\t\t\t\trunId,\n\t\t\t\t\tmodel: nonStreamResult.model || model || this.model,\n\t\t\t\t\ttimestamp,\n\t\t\t\t\tusage: nonStreamResult.usage\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tpromptTokens: nonStreamResult.usage.prompt_tokens,\n\t\t\t\t\t\t\t\tcompletionTokens: nonStreamResult.usage.completion_tokens,\n\t\t\t\t\t\t\t\ttotalTokens: nonStreamResult.usage.total_tokens,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t\tfinishReason:\n\t\t\t\t\t\tfinishReason === \"tool_calls\" || finishReason === \"function_call\"\n\t\t\t\t\t\t\t? \"tool_calls\"\n\t\t\t\t\t\t\t: ((finishReason as \"stop\" | \"length\" | \"content_filter\") ?? \"stop\"),\n\t\t\t\t} satisfies StreamChunk;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor await (const chunk of stream) {\n\t\t\t\tif (!chunk.choices || chunk.choices.length === 0) continue;\n\t\t\t\tconst choice = chunk.choices[0];\n\t\t\t\tif (!choice) continue;\n\n\t\t\t\t// Emit RUN_STARTED on first chunk\n\t\t\t\tif (!hasEmittedRunStarted) {\n\t\t\t\t\thasEmittedRunStarted = true;\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"RUN_STARTED\",\n\t\t\t\t\t\trunId,\n\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\tconst delta = choice.delta;\n\n\t\t\t\t// Reasoning content (used by models like QwQ, DeepSeek R1, Kimi K2.5)\n\t\t\t\t// The OpenAI SDK doesn't type this field, but models send it as an extension.\n\t\t\t\tconst reasoningContent = ((delta as Record<string, unknown>).reasoning_content ??\n\t\t\t\t\t(delta as Record<string, unknown>).reasoning) as string | undefined;\n\t\t\t\tif (reasoningContent) {\n\t\t\t\t\t// RUN_STARTED is already guaranteed by the guard above\n\t\t\t\t\tif (!hasEmittedStepStarted) {\n\t\t\t\t\t\thasEmittedStepStarted = true;\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"STEP_STARTED\",\n\t\t\t\t\t\t\tstepId,\n\t\t\t\t\t\t\tstepType: \"thinking\",\n\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\t\t\t\t\taccumulatedReasoning += reasoningContent;\n\t\t\t\t\t// TODO: TanStack AI's StreamProcessor currently treats STEP_FINISHED as an\n\t\t\t\t\t// incremental reasoning event (with `delta` + accumulated `content`), so we\n\t\t\t\t\t// emit one per token. If TanStack AI adds a dedicated STEP_CONTENT event\n\t\t\t\t\t// type, this should be updated to emit STEP_CONTENT per token and a single\n\t\t\t\t\t// STEP_FINISHED when reasoning ends (i.e. when the first non-reasoning\n\t\t\t\t\t// content or finish_reason arrives).\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"STEP_FINISHED\",\n\t\t\t\t\t\tstepId,\n\t\t\t\t\t\tdelta: reasoningContent,\n\t\t\t\t\t\tcontent: accumulatedReasoning,\n\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\t// Text content\n\t\t\t\tif (delta.content) {\n\t\t\t\t\tif (!hasEmittedTextMessageStart) {\n\t\t\t\t\t\thasEmittedTextMessageStart = true;\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TEXT_MESSAGE_START\",\n\t\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\n\t\t\t\t\taccumulatedContent += delta.content;\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_CONTENT\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\tdelta: delta.content,\n\t\t\t\t\t\tcontent: accumulatedContent,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\t// Tool calls\n\t\t\t\tif (delta.tool_calls) {\n\t\t\t\t\tfor (const toolCallDelta of delta.tool_calls) {\n\t\t\t\t\t\tconst index = toolCallDelta.index;\n\n\t\t\t\t\t\tif (!toolCallsInProgress.has(index)) {\n\t\t\t\t\t\t\t// Always generate a unique ID per tool call index.\n\t\t\t\t\t\t\t// The backend may send the same ID for multiple tool calls,\n\t\t\t\t\t\t\t// so we cannot trust toolCallDelta.id to be unique.\n\t\t\t\t\t\t\ttoolCallsInProgress.set(index, {\n\t\t\t\t\t\t\t\tid: generateId(\"chatcmpl-tool\"),\n\t\t\t\t\t\t\t\tname: toolCallDelta.function?.name || \"\",\n\t\t\t\t\t\t\t\targuments: \"\",\n\t\t\t\t\t\t\t\tstarted: false,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst toolCall = toolCallsInProgress.get(index)!;\n\n\t\t\t\t\t\t// Only update name if provided (ID is already set at creation time\n\t\t\t\t\t\t// and should not be overwritten by subsequent chunks that may have\n\t\t\t\t\t\t// duplicate/shared IDs from the backend)\n\t\t\t\t\t\tif (toolCallDelta.function?.name) {\n\t\t\t\t\t\t\ttoolCall.name = toolCallDelta.function.name;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (toolCallDelta.function?.arguments) {\n\t\t\t\t\t\t\ttoolCall.arguments += toolCallDelta.function.arguments;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Emit TOOL_CALL_START once we have id and name\n\t\t\t\t\t\tif (toolCall.id && toolCall.name && !toolCall.started) {\n\t\t\t\t\t\t\ttoolCall.started = true;\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"TOOL_CALL_START\",\n\t\t\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Stream tool call arguments\n\t\t\t\t\t\tif (toolCallDelta.function?.arguments && toolCall.started) {\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"TOOL_CALL_ARGS\",\n\t\t\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\t\tdelta: toolCallDelta.function.arguments,\n\t\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Finish\n\t\t\t\tif (choice.finish_reason) {\n\t\t\t\t\thasReceivedFinishReason = true;\n\n\t\t\t\t\t// End tool calls\n\t\t\t\t\tif (choice.finish_reason === \"tool_calls\" || toolCallsInProgress.size > 0) {\n\t\t\t\t\t\tfor (const [, toolCall] of toolCallsInProgress) {\n\t\t\t\t\t\t\tlet parsedInput: unknown = {};\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tparsedInput = toolCall.arguments\n\t\t\t\t\t\t\t\t\t? JSON.parse(toolCall.arguments)\n\t\t\t\t\t\t\t\t\t: {};\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tparsedInput = {};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"TOOL_CALL_END\",\n\t\t\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\t\tinput: parsedInput,\n\t\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst computedFinishReason =\n\t\t\t\t\t\tchoice.finish_reason === \"tool_calls\" ||\n\t\t\t\t\t\tchoice.finish_reason === \"function_call\" ||\n\t\t\t\t\t\ttoolCallsInProgress.size > 0\n\t\t\t\t\t\t\t? \"tool_calls\"\n\t\t\t\t\t\t\t: (choice.finish_reason as \"stop\" | \"length\" | \"content_filter\");\n\n\t\t\t\t\t// End text message if started\n\t\t\t\t\tif (hasEmittedTextMessageStart) {\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TEXT_MESSAGE_END\",\n\t\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Emit RUN_FINISHED\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"RUN_FINISHED\",\n\t\t\t\t\t\trunId,\n\t\t\t\t\t\tmodel: chunk.model || model || this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\tusage: chunk.usage\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tpromptTokens: chunk.usage.prompt_tokens,\n\t\t\t\t\t\t\t\t\tcompletionTokens: chunk.usage.completion_tokens,\n\t\t\t\t\t\t\t\t\ttotalTokens: chunk.usage.total_tokens,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tfinishReason: computedFinishReason,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Premature stream termination: the stream ended without a finish_reason.\n\t\t\t// This can happen when Workers AI truncates a response or the connection drops.\n\t\t\t// Emit proper closing events so the consumer doesn't hang.\n\t\t\tif (hasEmittedRunStarted && !hasReceivedFinishReason) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"[tanstack-ai] Stream ended without finish_reason — possible truncation or connection drop\",\n\t\t\t\t);\n\n\t\t\t\t// Close any open tool calls\n\t\t\t\tfor (const [, toolCall] of toolCallsInProgress) {\n\t\t\t\t\tif (toolCall.started) {\n\t\t\t\t\t\tlet parsedInput: unknown = {};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tparsedInput = toolCall.arguments ? JSON.parse(toolCall.arguments) : {};\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tparsedInput = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"TOOL_CALL_END\",\n\t\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\tinput: parsedInput,\n\t\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Close text message if open\n\t\t\t\tif (hasEmittedTextMessageStart) {\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"TEXT_MESSAGE_END\",\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t} satisfies StreamChunk;\n\t\t\t\t}\n\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"RUN_FINISHED\",\n\t\t\t\t\trunId,\n\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\ttimestamp,\n\t\t\t\t\tfinishReason: \"stop\",\n\t\t\t\t} satisfies StreamChunk;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconst code =\n\t\t\t\terror instanceof Error ? (error as Error & { code?: string }).code : undefined;\n\t\t\tif (!hasEmittedRunStarted) {\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"RUN_STARTED\",\n\t\t\t\t\trunId,\n\t\t\t\t\tmodel: model ?? this.model,\n\t\t\t\t\ttimestamp,\n\t\t\t\t} satisfies StreamChunk;\n\t\t\t}\n\t\t\tyield {\n\t\t\t\ttype: \"RUN_ERROR\",\n\t\t\t\trunId,\n\t\t\t\tmodel: model ?? this.model,\n\t\t\t\ttimestamp,\n\t\t\t\terror: {\n\t\t\t\t\tmessage: message || \"Unknown error\",\n\t\t\t\t\tcode,\n\t\t\t\t},\n\t\t\t} satisfies StreamChunk;\n\t\t}\n\t}\n\n\tasync structuredOutput(\n\t\toptions: StructuredOutputOptions<any>,\n\t): Promise<StructuredOutputResult<unknown>> {\n\t\tconst { outputSchema, chatOptions } = options;\n\t\tconst { systemPrompts, messages, temperature, model } = chatOptions;\n\n\t\tconst openAIMessages = buildOpenAIMessages(systemPrompts, messages, {\n\t\t\tincludeToolMessages: false,\n\t\t});\n\n\t\tconst response = await this.client.chat.completions.create({\n\t\t\tmodel: model ?? this.model,\n\t\t\tmessages: openAIMessages,\n\t\t\ttemperature,\n\t\t\tstream: false,\n\t\t\tresponse_format: {\n\t\t\t\ttype: \"json_schema\",\n\t\t\t\tjson_schema: {\n\t\t\t\t\tname: \"structured_output\",\n\t\t\t\t\tstrict: true,\n\t\t\t\t\tschema: outputSchema,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\tconst choice = response.choices?.[0];\n\n\t\tif (!choice) {\n\t\t\tthrow new Error(\n\t\t\t\t`Workers AI structured output returned no choices: ${JSON.stringify(response)}`,\n\t\t\t);\n\t\t}\n\n\t\tconst rawContent = choice.message?.content ?? \"\";\n\n\t\t// Workers AI REST endpoint may return `content` as an already-parsed object\n\t\t// when using json_schema response format, so normalise both cases.\n\t\tlet data: unknown;\n\t\tlet rawText: string;\n\n\t\tif (typeof rawContent === \"string\") {\n\t\t\trawText = rawContent;\n\t\t\ttry {\n\t\t\t\tdata = JSON.parse(rawText);\n\t\t\t} catch {\n\t\t\t\tdata = rawText;\n\t\t\t}\n\t\t} else {\n\t\t\t// Already an object — stringify for rawText, use directly for data\n\t\t\tdata = rawContent;\n\t\t\trawText = JSON.stringify(rawContent);\n\t\t}\n\n\t\treturn { data, rawText };\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Factory functions\n// ---------------------------------------------------------------------------\n\nexport function createWorkersAiChat(model: WorkersAiTextModel, config: WorkersAiAdapterConfig) {\n\treturn new WorkersAiTextAdapter(model, config);\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createGatewayFetch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AIAJANLC.js";
|
|
4
4
|
|
|
5
5
|
// src/adapters/anthropic.ts
|
|
6
6
|
import {
|
|
@@ -28,4 +28,4 @@ export {
|
|
|
28
28
|
createAnthropicChat,
|
|
29
29
|
createAnthropicSummarize
|
|
30
30
|
};
|
|
31
|
-
//# sourceMappingURL=chunk-
|
|
31
|
+
//# sourceMappingURL=chunk-Q33U5I5S.js.map
|
|
@@ -135,7 +135,7 @@ function createWorkersAiBindingFetch(binding, options) {
|
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
const responseObj = typeof result === "object" && result !== null ? result : { response: String(result) };
|
|
138
|
-
const responseText = typeof responseObj.response === "string" ? responseObj.response : "";
|
|
138
|
+
const responseText = typeof responseObj.response === "string" ? responseObj.response : typeof responseObj.response === "object" && responseObj.response !== null ? JSON.stringify(responseObj.response) : "";
|
|
139
139
|
const message = {
|
|
140
140
|
role: "assistant",
|
|
141
141
|
content: responseText
|
|
@@ -324,4 +324,4 @@ function transformWorkersAiStream(source, model) {
|
|
|
324
324
|
|
|
325
325
|
|
|
326
326
|
exports.isDirectBindingConfig = isDirectBindingConfig; exports.isDirectCredentialsConfig = isDirectCredentialsConfig; exports.validateWorkersAiConfig = validateWorkersAiConfig; exports.createGatewayFetch = createGatewayFetch; exports.createWorkersAiBindingFetch = createWorkersAiBindingFetch;
|
|
327
|
-
//# sourceMappingURL=chunk-
|
|
327
|
+
//# sourceMappingURL=chunk-WBTQKWFN.cjs.map
|