@cloudflare/tanstack-ai 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +5 -5
  2. package/dist/_tsup-dts-rollup.d.cts +1 -1
  3. package/dist/_tsup-dts-rollup.d.ts +1 -1
  4. package/dist/adapters/anthropic.cjs +3 -3
  5. package/dist/adapters/anthropic.js +2 -2
  6. package/dist/adapters/grok.cjs +3 -3
  7. package/dist/adapters/grok.js +2 -2
  8. package/dist/adapters/openai.cjs +3 -3
  9. package/dist/adapters/openai.js +2 -2
  10. package/dist/adapters/openrouter.cjs +3 -3
  11. package/dist/adapters/openrouter.js +2 -2
  12. package/dist/adapters/workers-ai-image.cjs +3 -3
  13. package/dist/adapters/workers-ai-image.js +2 -2
  14. package/dist/adapters/workers-ai-summarize.cjs +3 -3
  15. package/dist/adapters/workers-ai-summarize.js +2 -2
  16. package/dist/adapters/workers-ai-transcription.cjs +3 -3
  17. package/dist/adapters/workers-ai-transcription.js +2 -2
  18. package/dist/adapters/workers-ai-tts.cjs +3 -3
  19. package/dist/adapters/workers-ai-tts.js +2 -2
  20. package/dist/adapters/workers-ai.cjs +3 -3
  21. package/dist/adapters/workers-ai.js +2 -2
  22. package/dist/{chunk-RQT7M6MU.js → chunk-2RO3A3R4.js} +2 -2
  23. package/dist/{chunk-XKSFDPDY.cjs → chunk-4ACSLQDI.cjs} +5 -5
  24. package/dist/{chunk-XKSFDPDY.cjs.map → chunk-4ACSLQDI.cjs.map} +1 -1
  25. package/dist/{chunk-BD4CRW3Q.js → chunk-5YEJ5ZRQ.js} +125 -11
  26. package/dist/chunk-5YEJ5ZRQ.js.map +1 -0
  27. package/dist/{chunk-GOU66I5T.cjs → chunk-6FBIXTAL.cjs} +2 -2
  28. package/dist/{chunk-GOU66I5T.cjs.map → chunk-6FBIXTAL.cjs.map} +1 -1
  29. package/dist/{chunk-M6NETFDR.cjs → chunk-6OXP4IVS.cjs} +5 -5
  30. package/dist/{chunk-M6NETFDR.cjs.map → chunk-6OXP4IVS.cjs.map} +1 -1
  31. package/dist/{chunk-IWZJCLOE.cjs → chunk-AHXFO2BB.cjs} +3 -3
  32. package/dist/{chunk-IWZJCLOE.cjs.map → chunk-AHXFO2BB.cjs.map} +1 -1
  33. package/dist/{chunk-XI2BOYEI.js → chunk-ALUCJNDE.js} +2 -2
  34. package/dist/chunk-ALUCJNDE.js.map +1 -0
  35. package/dist/{chunk-LIUHRGEK.cjs → chunk-AN23SOZX.cjs} +5 -5
  36. package/dist/{chunk-LIUHRGEK.cjs.map → chunk-AN23SOZX.cjs.map} +1 -1
  37. package/dist/{chunk-XCNU7EEC.js → chunk-F75IZQCM.js} +2 -2
  38. package/dist/{chunk-LBYDBPHY.cjs → chunk-GL2EQLMI.cjs} +5 -5
  39. package/dist/chunk-GL2EQLMI.cjs.map +1 -0
  40. package/dist/{chunk-7T4CVHKD.cjs → chunk-M64PETK7.cjs} +5 -5
  41. package/dist/{chunk-7T4CVHKD.cjs.map → chunk-M64PETK7.cjs.map} +1 -1
  42. package/dist/{chunk-U5YJQYLZ.cjs → chunk-OV65IEEY.cjs} +3 -3
  43. package/dist/{chunk-U5YJQYLZ.cjs.map → chunk-OV65IEEY.cjs.map} +1 -1
  44. package/dist/{chunk-VTDJEUFS.js → chunk-PAVBM57P.js} +2 -2
  45. package/dist/{chunk-2AJ6LV2D.js → chunk-R2MRGLZ4.js} +2 -2
  46. package/dist/{chunk-QRHKPL75.js → chunk-S3ALRROX.js} +5 -2
  47. package/dist/chunk-S3ALRROX.js.map +1 -0
  48. package/dist/{chunk-O2C4CR57.cjs → chunk-SFZAUNHJ.cjs} +8 -5
  49. package/dist/chunk-SFZAUNHJ.cjs.map +1 -0
  50. package/dist/{chunk-YIA5B3QT.js → chunk-SIOQQHXS.js} +2 -2
  51. package/dist/{chunk-F5YJMXZR.js → chunk-UUFEOQ6B.js} +2 -2
  52. package/dist/{chunk-F5YJMXZR.js.map → chunk-UUFEOQ6B.js.map} +1 -1
  53. package/dist/{chunk-PLTFCUMO.js → chunk-VV3JFKAN.js} +2 -2
  54. package/dist/{chunk-BPWGWJJV.cjs → chunk-VZJHRPOT.cjs} +138 -24
  55. package/dist/chunk-VZJHRPOT.cjs.map +1 -0
  56. package/dist/index.cjs +11 -11
  57. package/dist/index.js +10 -10
  58. package/package.json +14 -14
  59. package/dist/chunk-BD4CRW3Q.js.map +0 -1
  60. package/dist/chunk-BPWGWJJV.cjs.map +0 -1
  61. package/dist/chunk-LBYDBPHY.cjs.map +0 -1
  62. package/dist/chunk-O2C4CR57.cjs.map +0 -1
  63. package/dist/chunk-QRHKPL75.js.map +0 -1
  64. package/dist/chunk-XI2BOYEI.js.map +0 -1
  65. /package/dist/{chunk-RQT7M6MU.js.map → chunk-2RO3A3R4.js.map} +0 -0
  66. /package/dist/{chunk-XCNU7EEC.js.map → chunk-F75IZQCM.js.map} +0 -0
  67. /package/dist/{chunk-VTDJEUFS.js.map → chunk-PAVBM57P.js.map} +0 -0
  68. /package/dist/{chunk-2AJ6LV2D.js.map → chunk-R2MRGLZ4.js.map} +0 -0
  69. /package/dist/{chunk-YIA5B3QT.js.map → chunk-SIOQQHXS.js.map} +0 -0
  70. /package/dist/{chunk-PLTFCUMO.js.map → chunk-VV3JFKAN.js.map} +0 -0
@@ -3,7 +3,7 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkGOU66I5Tcjs = require('./chunk-GOU66I5T.cjs');
6
+ var _chunk6FBIXTALcjs = require('./chunk-6FBIXTAL.cjs');
7
7
 
8
8
 
9
9
  var _chunk4DE2IREAcjs = require('./chunk-4DE2IREA.cjs');
@@ -14,13 +14,13 @@ var _chunk4DE2IREAcjs = require('./chunk-4DE2IREA.cjs');
14
14
  var _adapters = require('@tanstack/ai/adapters');
15
15
  var _openai = require('openai'); var _openai2 = _interopRequireDefault(_openai);
16
16
  function buildWorkersAiClient(config) {
17
- if (_chunkGOU66I5Tcjs.isDirectBindingConfig.call(void 0, config)) {
17
+ if (_chunk6FBIXTALcjs.isDirectBindingConfig.call(void 0, config)) {
18
18
  return new (0, _openai2.default)({
19
19
  apiKey: "unused",
20
- fetch: _chunkGOU66I5Tcjs.createWorkersAiBindingFetch.call(void 0, config.binding)
20
+ fetch: _chunk6FBIXTALcjs.createWorkersAiBindingFetch.call(void 0, config.binding)
21
21
  });
22
22
  }
23
- if (_chunkGOU66I5Tcjs.isDirectCredentialsConfig.call(void 0, config)) {
23
+ if (_chunk6FBIXTALcjs.isDirectCredentialsConfig.call(void 0, config)) {
24
24
  return new (0, _openai2.default)({
25
25
  baseURL: `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/ai/v1`,
26
26
  apiKey: config.apiKey
@@ -28,7 +28,7 @@ function buildWorkersAiClient(config) {
28
28
  }
29
29
  const gatewayConfig = config;
30
30
  return new (0, _openai2.default)({
31
- fetch: _chunkGOU66I5Tcjs.createGatewayFetch.call(void 0, "workers-ai", gatewayConfig),
31
+ fetch: _chunk6FBIXTALcjs.createGatewayFetch.call(void 0, "workers-ai", gatewayConfig),
32
32
  apiKey: _nullishCoalesce(gatewayConfig.apiKey, () => ( "unused"))
33
33
  });
34
34
  }
@@ -37,6 +37,31 @@ function extractTextContent(content) {
37
37
  if (typeof content === "string") return content;
38
38
  return content.filter((p) => p.type === "text").map((p) => p.content || "").join("");
39
39
  }
40
+ function buildUserContent(content) {
41
+ if (content === null) return "";
42
+ if (typeof content === "string") return content;
43
+ const hasImages = content.some((p) => p.type === "image_url" || p.type === "image");
44
+ if (!hasImages) {
45
+ return content.filter((p) => p.type === "text").map((p) => p.content || "").join("");
46
+ }
47
+ const parts = [];
48
+ for (const part of content) {
49
+ if (part.type === "text" && part.content) {
50
+ parts.push({ type: "text", text: part.content });
51
+ } else if (part.type === "image_url" && part.content) {
52
+ parts.push({
53
+ type: "image_url",
54
+ image_url: { url: part.content }
55
+ });
56
+ } else if (part.type === "image_url" && part.image_url) {
57
+ parts.push({
58
+ type: "image_url",
59
+ image_url: part.image_url
60
+ });
61
+ }
62
+ }
63
+ return parts;
64
+ }
40
65
  function buildOpenAIMessages(systemPrompts, messages, options) {
41
66
  const includeTools = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _ => _.includeToolMessages]), () => ( true));
42
67
  const openAIMessages = [];
@@ -50,7 +75,7 @@ function buildOpenAIMessages(systemPrompts, messages, options) {
50
75
  if (message.role === "user") {
51
76
  openAIMessages.push({
52
77
  role: "user",
53
- content: extractTextContent(message.content)
78
+ content: buildUserContent(message.content)
54
79
  });
55
80
  } else if (message.role === "assistant") {
56
81
  const assistantMessage = {
@@ -126,14 +151,100 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
126
151
  let hasReceivedFinishReason = false;
127
152
  const toolCallsInProgress = /* @__PURE__ */ new Map();
128
153
  try {
129
- const stream = await this.client.chat.completions.create({
130
- model: _nullishCoalesce(model, () => ( this.model)),
131
- messages: openAIMessages,
132
- tools: openAITools,
133
- temperature,
134
- stream: true,
135
- stream_options: { include_usage: true }
136
- });
154
+ let stream;
155
+ try {
156
+ stream = await this.client.chat.completions.create({
157
+ model: _nullishCoalesce(model, () => ( this.model)),
158
+ messages: openAIMessages,
159
+ tools: openAITools,
160
+ temperature,
161
+ stream: true,
162
+ stream_options: { include_usage: true }
163
+ });
164
+ } catch (streamError) {
165
+ console.warn(
166
+ "[tanstack-ai] Streaming failed, falling back to non-streaming:",
167
+ streamError instanceof Error ? streamError.message : streamError
168
+ );
169
+ const nonStreamResult = await this.client.chat.completions.create({
170
+ model: _nullishCoalesce(model, () => ( this.model)),
171
+ messages: openAIMessages,
172
+ tools: openAITools,
173
+ temperature
174
+ });
175
+ yield {
176
+ type: "RUN_STARTED",
177
+ runId,
178
+ model: nonStreamResult.model || model || this.model,
179
+ timestamp
180
+ };
181
+ const msg = _optionalChain([nonStreamResult, 'access', _2 => _2.choices, 'access', _3 => _3[0], 'optionalAccess', _4 => _4.message]);
182
+ if (_optionalChain([msg, 'optionalAccess', _5 => _5.content])) {
183
+ yield {
184
+ type: "TEXT_MESSAGE_START",
185
+ messageId,
186
+ model: nonStreamResult.model || model || this.model,
187
+ timestamp,
188
+ role: "assistant"
189
+ };
190
+ yield {
191
+ type: "TEXT_MESSAGE_CONTENT",
192
+ messageId,
193
+ model: nonStreamResult.model || model || this.model,
194
+ timestamp,
195
+ delta: msg.content,
196
+ content: msg.content
197
+ };
198
+ yield {
199
+ type: "TEXT_MESSAGE_END",
200
+ messageId,
201
+ model: nonStreamResult.model || model || this.model,
202
+ timestamp
203
+ };
204
+ }
205
+ if (_optionalChain([msg, 'optionalAccess', _6 => _6.tool_calls])) {
206
+ for (const tc of msg.tool_calls) {
207
+ if (tc.type !== "function") continue;
208
+ const fn = tc.function;
209
+ let parsedInput = {};
210
+ try {
211
+ parsedInput = fn.arguments ? JSON.parse(fn.arguments) : {};
212
+ } catch (e2) {
213
+ parsedInput = {};
214
+ }
215
+ yield {
216
+ type: "TOOL_CALL_START",
217
+ toolCallId: tc.id,
218
+ toolName: fn.name,
219
+ model: nonStreamResult.model || model || this.model,
220
+ timestamp,
221
+ index: 0
222
+ };
223
+ yield {
224
+ type: "TOOL_CALL_END",
225
+ toolCallId: tc.id,
226
+ toolName: fn.name,
227
+ model: nonStreamResult.model || model || this.model,
228
+ timestamp,
229
+ input: parsedInput
230
+ };
231
+ }
232
+ }
233
+ const finishReason = _optionalChain([nonStreamResult, 'access', _7 => _7.choices, 'access', _8 => _8[0], 'optionalAccess', _9 => _9.finish_reason]);
234
+ yield {
235
+ type: "RUN_FINISHED",
236
+ runId,
237
+ model: nonStreamResult.model || model || this.model,
238
+ timestamp,
239
+ usage: nonStreamResult.usage ? {
240
+ promptTokens: nonStreamResult.usage.prompt_tokens,
241
+ completionTokens: nonStreamResult.usage.completion_tokens,
242
+ totalTokens: nonStreamResult.usage.total_tokens
243
+ } : void 0,
244
+ finishReason: finishReason === "tool_calls" || finishReason === "function_call" ? "tool_calls" : _nullishCoalesce(finishReason, () => ( "stop"))
245
+ };
246
+ return;
247
+ }
137
248
  for await (const chunk of stream) {
138
249
  if (!chunk.choices || chunk.choices.length === 0) continue;
139
250
  const choice = chunk.choices[0];
@@ -197,7 +308,7 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
197
308
  if (!toolCallsInProgress.has(index)) {
198
309
  toolCallsInProgress.set(index, {
199
310
  id: toolCallDelta.id || "",
200
- name: _optionalChain([toolCallDelta, 'access', _2 => _2.function, 'optionalAccess', _3 => _3.name]) || "",
311
+ name: _optionalChain([toolCallDelta, 'access', _10 => _10.function, 'optionalAccess', _11 => _11.name]) || "",
201
312
  arguments: "",
202
313
  started: false
203
314
  });
@@ -206,10 +317,10 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
206
317
  if (toolCallDelta.id) {
207
318
  toolCall.id = toolCallDelta.id;
208
319
  }
209
- if (_optionalChain([toolCallDelta, 'access', _4 => _4.function, 'optionalAccess', _5 => _5.name])) {
320
+ if (_optionalChain([toolCallDelta, 'access', _12 => _12.function, 'optionalAccess', _13 => _13.name])) {
210
321
  toolCall.name = toolCallDelta.function.name;
211
322
  }
212
- if (_optionalChain([toolCallDelta, 'access', _6 => _6.function, 'optionalAccess', _7 => _7.arguments])) {
323
+ if (_optionalChain([toolCallDelta, 'access', _14 => _14.function, 'optionalAccess', _15 => _15.arguments])) {
213
324
  toolCall.arguments += toolCallDelta.function.arguments;
214
325
  }
215
326
  if (toolCall.id && toolCall.name && !toolCall.started) {
@@ -223,7 +334,7 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
223
334
  index
224
335
  };
225
336
  }
226
- if (_optionalChain([toolCallDelta, 'access', _8 => _8.function, 'optionalAccess', _9 => _9.arguments]) && toolCall.started) {
337
+ if (_optionalChain([toolCallDelta, 'access', _16 => _16.function, 'optionalAccess', _17 => _17.arguments]) && toolCall.started) {
227
338
  yield {
228
339
  type: "TOOL_CALL_ARGS",
229
340
  toolCallId: toolCall.id,
@@ -241,7 +352,7 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
241
352
  let parsedInput = {};
242
353
  try {
243
354
  parsedInput = toolCall.arguments ? JSON.parse(toolCall.arguments) : {};
244
- } catch (e2) {
355
+ } catch (e3) {
245
356
  parsedInput = {};
246
357
  }
247
358
  yield {
@@ -278,12 +389,15 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
278
389
  }
279
390
  }
280
391
  if (hasEmittedRunStarted && !hasReceivedFinishReason) {
392
+ console.warn(
393
+ "[tanstack-ai] Stream ended without finish_reason \u2014 possible truncation or connection drop"
394
+ );
281
395
  for (const [, toolCall] of toolCallsInProgress) {
282
396
  if (toolCall.started) {
283
397
  let parsedInput = {};
284
398
  try {
285
399
  parsedInput = toolCall.arguments ? JSON.parse(toolCall.arguments) : {};
286
- } catch (e3) {
400
+ } catch (e4) {
287
401
  parsedInput = {};
288
402
  }
289
403
  yield {
@@ -355,20 +469,20 @@ var WorkersAiTextAdapter = class extends _adapters.BaseTextAdapter {
355
469
  }
356
470
  }
357
471
  });
358
- const choice = _optionalChain([response, 'access', _10 => _10.choices, 'optionalAccess', _11 => _11[0]]);
472
+ const choice = _optionalChain([response, 'access', _18 => _18.choices, 'optionalAccess', _19 => _19[0]]);
359
473
  if (!choice) {
360
474
  throw new Error(
361
475
  `Workers AI structured output returned no choices: ${JSON.stringify(response)}`
362
476
  );
363
477
  }
364
- const rawContent = _nullishCoalesce(_optionalChain([choice, 'access', _12 => _12.message, 'optionalAccess', _13 => _13.content]), () => ( ""));
478
+ const rawContent = _nullishCoalesce(_optionalChain([choice, 'access', _20 => _20.message, 'optionalAccess', _21 => _21.content]), () => ( ""));
365
479
  let data;
366
480
  let rawText;
367
481
  if (typeof rawContent === "string") {
368
482
  rawText = rawContent;
369
483
  try {
370
484
  data = JSON.parse(rawText);
371
- } catch (e4) {
485
+ } catch (e5) {
372
486
  data = rawText;
373
487
  }
374
488
  } else {
@@ -386,4 +500,4 @@ function createWorkersAiChat(model, config) {
386
500
 
387
501
 
388
502
  exports.WorkersAiTextAdapter = WorkersAiTextAdapter; exports.createWorkersAiChat = createWorkersAiChat;
389
- //# sourceMappingURL=chunk-BPWGWJJV.cjs.map
503
+ //# sourceMappingURL=chunk-VZJHRPOT.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-VZJHRPOT.cjs","../src/adapters/workers-ai.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;ACRA;AACC;AAAA,iDAGM;AACP,gFAAmB;AAsBnB,SAAS,oBAAA,CAAqB,MAAA,EAAwC;AACrE,EAAA,GAAA,CAAI,qDAAA,MAA4B,CAAA,EAAG;AAElC,IAAA,OAAO,IAAI,qBAAA,CAAO;AAAA,MACjB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,2DAAA,MAA4B,CAAO,OAAO;AAAA,IAClD,CAAC,CAAA;AAAA,EACF;AAEA,EAAA,GAAA,CAAI,yDAAA,MAAgC,CAAA,EAAG;AAEtC,IAAA,OAAO,IAAI,qBAAA,CAAO;AAAA,MACjB,OAAA,EAAS,CAAA,8CAAA,EAAiD,MAAA,CAAO,SAAS,CAAA,MAAA,CAAA;AAAA,MAC1E,MAAA,EAAQ,MAAA,CAAO;AAAA,IAChB,CAAC,CAAA;AAAA,EACF;AAGA,EAAA,MAAM,cAAA,EAAgB,MAAA;AACtB,EAAA,OAAO,IAAI,qBAAA,CAAO;AAAA,IACjB,KAAA,EAAO,kDAAA,YAAmB,EAAc,aAAa,CAAA;AAAA,IACrD,MAAA,mBAAQ,aAAA,CAAc,MAAA,UAAU;AAAA,EACjC,CAAC,CAAA;AACF;AAgBA,SAAS,kBAAA,CACR,OAAA,EACS;AACT,EAAA,GAAA,CAAI,QAAA,IAAY,IAAA,EAAM,OAAO,EAAA;AAC7B,EAAA,GAAA,CAAI,OAAO,QAAA,IAAY,QAAA,EAAU,OAAO,OAAA;AACxC,EAAA,OAAO,OAAA,CACL,MAAA,CAAO,CAAC,CAAA,EAAA,GAAM,CAAA,CAAE,KAAA,IAAS,MAAM,CAAA,CAC/B,GAAA,CAAI,CAAC,CAAA,EAAA,GAAM,CAAA,CAAE,QAAA,GAAW,EAAE,CAAA,CAC1B,IAAA,CAAK,EAAE,CAAA;AACV;AASA,SAAS,gBAAA,CACR,OAAA,EACmD;AACnD,EAAA,GAAA,CAAI,QAAA,IAAY,IAAA,EAAM,OAAO,EAAA;AAC7B,EAAA,GAAA,CAAI,OAAO,QAAA,IAAY,QAAA,EAAU,OAAO,OAAA;AAExC,EAAA,MAAM,UAAA,EAAY,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAA,GAAM,CAAA,CAAE,KAAA,IAAS,YAAA,GAAe,CAAA,CAAE,KAAA,IAAS,OAAO,CAAA;AAClF,EAAA,GAAA,CAAI,CAAC,SAAA,EAAW;AAEf,IAAA,OAAO,OAAA,CACL,MAAA,CAAO,CAAC,CAAA,EAAA,GAAM,CAAA,CAAE,KAAA,IAAS,MAAM,CAAA,CAC/B,GAAA,CAAI,CAAC,CAAA,EAAA,GAAM,CAAA,CAAE,QAAA,GAAW,EAAE,CAAA,CAC1B,IAAA,CAAK,EAAE,CAAA;AAAA,EACV;AAGA,EAAA,MAAM,MAAA,EAAiD,CAAC,CAAA;AACxD,EAAA,IAAA,CAAA,MAAW,KAAA,GAAQ,OAAA,EAAS;AAC3B,IAAA,GAAA,CAAI,IAAA,CAAK,KAAA,IAAS,OAAA,GAAU,IAAA,CAAK,OAAA,EAAS;AACzC,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,QAAQ,CAAC,CAAA;AAAA,IAChD,EAAA,KAAA,GAAA,CAAW,IAAA,CAAK,KAAA,IAAS,YAAA,GAAe,IAAA,CAAK,OAAA,EAAS;AACrD,MAAA,KAAA,CAAM,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,WAAA;AAAA,QACN,SAAA,EAAW,EAAE,GAAA,EAAK,IAAA,CAAK,QAAQ;AAAA,MAChC,CAAC,CAAA;AAAA,IACF,EAAA,KAAA,GAAA,CAAW,IAAA,CAAK,KAAA,IAAS,YAAA,GAAe,IAAA,CAAK,SAAA,EAAW;AACvD,MAAA,KAAA,CAAM,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,WAAA;AAAA,QACN,SAAA,EAAW,IAAA,CAAK;AAAA,MACjB,CAAC,CAAA;AAAA,IACF;AAAA,EACD;AACA,EAAA,OAAO,KAAA;AACR;AAEA,SAAS,mBAAA,CACR,aAAA,EACA,QAAA,EACA,OAAA,EAC2C;AAC3C,EAAA,MAAM,aAAA,mCAAe,OAAA,2BAAS,qBAAA,UAAuB,MAAA;AACrD,EAAA,MAAM,eAAA,EAA2D,CAAC,CAAA;AAElE,EAAA,GAAA,CAAI,cAAA,GAAiB,aAAA,CAAc,OAAA,EAAS,CAAA,EAAG;AAC9C,IAAA,cAAA,CAAe,IAAA,CAAK;AAAA,MACnB,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,aAAA,CAAc,IAAA,CAAK,IAAI;AAAA,IACjC,CAAC,CAAA;AAAA,EACF;AAEA,EAAA,IAAA,CAAA,MAAW,QAAA,GAAW,QAAA,EAAU;AAC/B,IAAA,GAAA,CAAI,OAAA,CAAQ,KAAA,IAAS,MAAA,EAAQ;AAC5B,MAAA,cAAA,CAAe,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,gBAAA,CAAiB,OAAA,CAAQ,OAAO;AAAA,MAC1C,CAAC,CAAA;AAAA,IACF,EAAA,KAAA,GAAA,CAAW,OAAA,CAAQ,KAAA,IAAS,WAAA,EAAa;AACxC,MAAA,MAAM,iBAAA,EAAoE;AAAA,QACzE,IAAA,EAAM,WAAA;AAAA,QACN,OAAA,EAAS,kBAAA,CAAmB,OAAA,CAAQ,OAAO;AAAA,MAC5C,CAAA;AACA,MAAA,GAAA,CAAI,aAAA,GAAgB,OAAA,CAAQ,UAAA,GAAa,OAAA,CAAQ,SAAA,CAAU,OAAA,EAAS,CAAA,EAAG;AACtE,QAAA,gBAAA,CAAiB,WAAA,EAAa,OAAA,CAAQ,SAAA,CAAU,GAAA,CAAI,CAAC,EAAA,EAAA,GAAA,CAAQ;AAAA,UAC5D,EAAA,EAAI,EAAA,CAAG,EAAA;AAAA,UACP,IAAA,EAAM,UAAA;AAAA,UACN,QAAA,EAAU;AAAA,YACT,IAAA,EAAM,EAAA,CAAG,QAAA,CAAS,IAAA;AAAA,YAClB,SAAA,EAAW,EAAA,CAAG,QAAA,CAAS;AAAA,UACxB;AAAA,QACD,CAAA,CAAE,CAAA;AAAA,MACH;AACA,MAAA,cAAA,CAAe,IAAA,CAAK,gBAAgB,CAAA;AAAA,IACrC,EAAA,KAAA,GAAA,CAAW,aAAA,GAAgB,OAAA,CAAQ,KAAA,IAAS,MAAA,EAAQ;AACnD,MAAA,IAAI,WAAA;AACJ,MAAA,GAAA,CAAI,OAAO,OAAA,CAAQ,QAAA,IAAY,QAAA,EAAU;AACxC,QAAA,IAAI;AACH,UAAA,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA;AAC1B,UAAA,YAAA,EAAc,OAAA,CAAQ,OAAA;AAAA,QACvB,EAAA,UAAQ;AACP,UAAA,YAAA,EAAc,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,OAAO,CAAA;AAAA,QAC7C;AAAA,MACD,EAAA,KAAO;AACN,QAAA,YAAA,EAAc,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,OAAO,CAAA;AAAA,MAC7C;AACA,MAAA,cAAA,CAAe,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,MAAA;AAAA,QACN,YAAA,EAAc,OAAA,CAAQ,WAAA,GAAc,CAAA,KAAA,EAAQ,MAAA,CAAO,UAAA,CAAW,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAClE,QAAA;AACT,MAAA;AACF,IAAA;AACD,EAAA;AAEO,EAAA;AACR;AAIgD;AAC5B,EAAA;AACS,EAAA;AACrB,IAAA;AACI,IAAA;AACE,MAAA;AACO,MAAA;AACD,MAAA;AAClB,IAAA;AACC,EAAA;AACH;AAM4C;AACJ,EAAA;AACxC;AAeE;AAK0D,EAAA;AACzB,IAAA;AAL3B,IAAA;AAEC,IAAA;AAIkC,IAAA;AAC1C,EAAA;AAEyE,EAAA;AACT,IAAA;AAEG,IAAA;AACxB,IAAA;AAEf,IAAA;AACU,IAAA;AACI,IAAA;AACd,IAAA;AACM,IAAA;AACR,IAAA;AACG,IAAA;AACD,IAAA;AACgB,IAAA;AACb,IAAA;AAI5B,IAAA;AAEE,IAAA;AACC,MAAA;AACA,MAAA;AACgD,QAAA;AAC7B,UAAA;AACX,UAAA;AACH,UAAA;AACP,UAAA;AACQ,UAAA;AAC8B,UAAA;AACtC,QAAA;AAC6B,MAAA;AAGtB,QAAA;AACP,UAAA;AACqD,UAAA;AACtD,QAAA;AACkE,QAAA;AAC5C,UAAA;AACX,UAAA;AACH,UAAA;AACP,UAAA;AACA,QAAA;AAEK,QAAA;AACC,UAAA;AACN,UAAA;AAC8C,UAAA;AAC9C,UAAA;AACD,QAAA;AAEwC,QAAA;AACtB,QAAA;AACX,UAAA;AACC,YAAA;AACN,YAAA;AAC8C,YAAA;AAC9C,YAAA;AACM,YAAA;AACP,UAAA;AACM,UAAA;AACC,YAAA;AACN,YAAA;AAC8C,YAAA;AAC9C,YAAA;AACW,YAAA;AACE,YAAA;AACd,UAAA;AACM,UAAA;AACC,YAAA;AACN,YAAA;AAC8C,YAAA;AAC9C,YAAA;AACD,UAAA;AACD,QAAA;AAEqB,QAAA;AACa,UAAA;AACJ,YAAA;AACd,YAAA;AACc,YAAA;AACxB,YAAA;AACsD,cAAA;AAClD,YAAA;AACQ,cAAA;AAChB,YAAA;AACM,YAAA;AACC,cAAA;AACS,cAAA;AACF,cAAA;AACiC,cAAA;AAC9C,cAAA;AACO,cAAA;AACR,YAAA;AACM,YAAA;AACC,cAAA;AACS,cAAA;AACF,cAAA;AACiC,cAAA;AAC9C,cAAA;AACO,cAAA;AACR,YAAA;AACD,UAAA;AACD,QAAA;AAEiD,QAAA;AAC3C,QAAA;AACC,UAAA;AACN,UAAA;AAC8C,UAAA;AAC9C,UAAA;AAEG,UAAA;AACoC,YAAA;AACI,YAAA;AACL,YAAA;AAEnC,UAAA;AAEgD,UAAA;AAGpD,QAAA;AACA,QAAA;AACD,MAAA;AAEkC,MAAA;AACiB,QAAA;AACpB,QAAA;AACjB,QAAA;AAGc,QAAA;AACH,UAAA;AACjB,UAAA;AACC,YAAA;AACN,YAAA;AACoC,YAAA;AACpC,YAAA;AACD,UAAA;AACD,QAAA;AAEqB,QAAA;AAIuC,QAAA;AAGtC,QAAA;AAEO,UAAA;AACH,YAAA;AAClB,YAAA;AACC,cAAA;AACN,cAAA;AACU,cAAA;AAC0B,cAAA;AACpC,cAAA;AACD,YAAA;AACD,UAAA;AACwB,UAAA;AAOlB,UAAA;AACC,YAAA;AACN,YAAA;AACO,YAAA;AACE,YAAA;AAC2B,YAAA;AACpC,YAAA;AACD,UAAA;AACD,QAAA;AAGmB,QAAA;AACe,UAAA;AACH,YAAA;AACvB,YAAA;AACC,cAAA;AACN,cAAA;AACoC,cAAA;AACpC,cAAA;AACM,cAAA;AACP,YAAA;AACD,UAAA;AAE4B,UAAA;AACtB,UAAA;AACC,YAAA;AACN,YAAA;AACoC,YAAA;AACpC,YAAA;AACa,YAAA;AACJ,YAAA;AACV,UAAA;AACD,QAAA;AAGsB,QAAA;AACyB,UAAA;AACjB,YAAA;AAES,YAAA;AACL,cAAA;AACN,gBAAA;AACc,gBAAA;AAC3B,gBAAA;AACF,gBAAA;AACT,cAAA;AACF,YAAA;AAE8C,YAAA;AAExB,YAAA;AACO,cAAA;AAC7B,YAAA;AACkC,YAAA;AACM,cAAA;AACxC,YAAA;AACuC,YAAA;AACO,cAAA;AAC9C,YAAA;AAGuD,YAAA;AACnC,cAAA;AACb,cAAA;AACC,gBAAA;AACe,gBAAA;AACF,gBAAA;AACiB,gBAAA;AACpC,gBAAA;AACA,gBAAA;AACD,cAAA;AACD,YAAA;AAG2D,YAAA;AACpD,cAAA;AACC,gBAAA;AACe,gBAAA;AACe,gBAAA;AACpC,gBAAA;AAC8B,gBAAA;AAC/B,cAAA;AACD,YAAA;AACD,UAAA;AACD,QAAA;AAG0B,QAAA;AACC,UAAA;AAG8C,UAAA;AACvB,YAAA;AACnB,cAAA;AACxB,cAAA;AAGA,gBAAA;AACI,cAAA;AACQ,gBAAA;AAChB,cAAA;AACM,cAAA;AACC,gBAAA;AACe,gBAAA;AACF,gBAAA;AACiB,gBAAA;AACpC,gBAAA;AACO,gBAAA;AACR,cAAA;AACD,YAAA;AACD,UAAA;AAIC,UAAA;AAM+B,UAAA;AACzB,YAAA;AACC,cAAA;AACN,cAAA;AACoC,cAAA;AACpC,cAAA;AACD,YAAA;AACD,UAAA;AAGM,UAAA;AACC,YAAA;AACN,YAAA;AACoC,YAAA;AACpC,YAAA;AAEG,YAAA;AAC0B,cAAA;AACI,cAAA;AACL,cAAA;AAEzB,YAAA;AACW,YAAA;AACf,UAAA;AACD,QAAA;AACD,MAAA;AAKsD,MAAA;AAC7C,QAAA;AACP,UAAA;AACD,QAAA;AAGgD,QAAA;AACzB,UAAA;AACO,YAAA;AACxB,YAAA;AACkE,cAAA;AAC9D,YAAA;AACQ,cAAA;AAChB,YAAA;AACM,YAAA;AACC,cAAA;AACe,cAAA;AACF,cAAA;AACE,cAAA;AACrB,cAAA;AACO,cAAA;AACR,YAAA;AACD,UAAA;AACD,QAAA;AAGgC,QAAA;AACzB,UAAA;AACC,YAAA;AACN,YAAA;AACqB,YAAA;AACrB,YAAA;AACD,UAAA;AACD,QAAA;AAEM,QAAA;AACC,UAAA;AACN,UAAA;AACqB,UAAA;AACrB,UAAA;AACc,UAAA;AACf,QAAA;AACD,MAAA;AACe,IAAA;AACsD,MAAA;AAEC,MAAA;AAC3C,MAAA;AACpB,QAAA;AACC,UAAA;AACN,UAAA;AACqB,UAAA;AACrB,UAAA;AACD,QAAA;AACD,MAAA;AACM,MAAA;AACC,QAAA;AACN,QAAA;AACqB,QAAA;AACrB,QAAA;AACO,QAAA;AACc,UAAA;AACpB,UAAA;AACD,QAAA;AACD,MAAA;AACD,IAAA;AACD,EAAA;AAI4C,EAAA;AACL,IAAA;AACkB,IAAA;AAEY,IAAA;AAC9C,MAAA;AACrB,IAAA;AAE0D,IAAA;AACrC,MAAA;AACX,MAAA;AACV,MAAA;AACQ,MAAA;AACS,MAAA;AACV,QAAA;AACO,QAAA;AACN,UAAA;AACE,UAAA;AACA,UAAA;AACT,QAAA;AACD,MAAA;AACA,IAAA;AAEkC,IAAA;AAEtB,IAAA;AACF,MAAA;AACmE,QAAA;AAC7E,MAAA;AACD,IAAA;AAE8C,IAAA;AAI1C,IAAA;AACA,IAAA;AAEgC,IAAA;AACzB,MAAA;AACN,MAAA;AACsB,QAAA;AAClB,MAAA;AACA,QAAA;AACR,MAAA;AACM,IAAA;AAEC,MAAA;AAC4B,MAAA;AACpC,IAAA;AAEuB,IAAA;AACxB,EAAA;AACD;AAM+F;AACjD,EAAA;AAC9C;ADpLoF;AACA;AACA;AACA;AACA","file":"/home/runner/work/ai/ai/packages/tanstack-ai/dist/chunk-VZJHRPOT.cjs","sourcesContent":[null,"import type { AiModels, BaseAiTextGeneration } from \"@cloudflare/workers-types\";\nimport type { 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} from \"../utils/create-fetcher\";\n\n// ---------------------------------------------------------------------------\n// Model types derived from @cloudflare/workers-types\n// ---------------------------------------------------------------------------\n\nexport type WorkersAiTextModel = {\n\t[K in keyof AiModels]: AiModels[K] extends BaseAiTextGeneration ? K : never;\n}[keyof AiModels];\n\n// ---------------------------------------------------------------------------\n// Helpers: build the right OpenAI client depending on config mode\n// ---------------------------------------------------------------------------\n\nfunction buildWorkersAiClient(config: WorkersAiAdapterConfig): OpenAI {\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(config.binding),\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});\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),\n\t\tapiKey: gatewayConfig.apiKey ?? \"unused\",\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Shared message-building helpers\n// ---------------------------------------------------------------------------\n\ninterface MessageLike {\n\trole: string;\n\tcontent: string | null | Array<{ type: string; content?: string }>;\n\ttoolCalls?: Array<{\n\t\tid: string;\n\t\tfunction: { name: string; arguments: string };\n\t}>;\n\ttoolCallId?: string;\n}\n\nfunction extractTextContent(\n\tcontent: string | null | Array<{ type: string; content?: string }>,\n): string {\n\tif (content === null) return \"\";\n\tif (typeof content === \"string\") return content;\n\treturn content\n\t\t.filter((p) => p.type === \"text\")\n\t\t.map((p) => p.content || \"\")\n\t\t.join(\"\");\n}\n\n/**\n * Build OpenAI-compatible user message content, preserving image parts.\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: string | null | Array<{ type: string; content?: string; image_url?: unknown }>,\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_url\" || p.type === \"image\");\n\tif (!hasImages) {\n\t\t// No images — return plain text for simpler messages\n\t\treturn content\n\t\t\t.filter((p) => p.type === \"text\")\n\t\t\t.map((p) => p.content || \"\")\n\t\t\t.join(\"\");\n\t}\n\n\t// Multi-modal: build array of text + image_url parts\n\tconst parts: OpenAI.Chat.ChatCompletionContentPart[] = [];\n\tfor (const part of content) {\n\t\tif (part.type === \"text\" && part.content) {\n\t\t\tparts.push({ type: \"text\", text: part.content });\n\t\t} else if (part.type === \"image_url\" && part.content) {\n\t\t\tparts.push({\n\t\t\t\ttype: \"image_url\",\n\t\t\t\timage_url: { url: part.content },\n\t\t\t});\n\t\t} else if (part.type === \"image_url\" && part.image_url) {\n\t\t\tparts.push({\n\t\t\t\ttype: \"image_url\",\n\t\t\t\timage_url: part.image_url as OpenAI.Chat.ChatCompletionContentPartImage.ImageURL,\n\t\t\t});\n\t\t}\n\t}\n\treturn parts;\n}\n\nfunction buildOpenAIMessages(\n\tsystemPrompts: string[] | undefined,\n\tmessages: MessageLike[],\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: string): string {\n\treturn `${prefix}-${crypto.randomUUID()}`;\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, 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(\"workers-ai\");\n\t\tconst messageId = generateId(\"workers-ai\");\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(\"workers-ai-step\");\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\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});\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 as\n\t\t\t\t\t| string\n\t\t\t\t\t| 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\ttoolCallsInProgress.set(index, {\n\t\t\t\t\t\t\t\tid: toolCallDelta.id || \"\",\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\tif (toolCallDelta.id) {\n\t\t\t\t\t\t\ttoolCall.id = toolCallDelta.id;\n\t\t\t\t\t\t}\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"]}
package/dist/index.cjs CHANGED
@@ -1,17 +1,17 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkXKSFDPDYcjs = require('./chunk-XKSFDPDY.cjs');
3
+ var _chunk4ACSLQDIcjs = require('./chunk-4ACSLQDI.cjs');
4
4
 
5
5
 
6
- var _chunkLBYDBPHYcjs = require('./chunk-LBYDBPHY.cjs');
6
+ var _chunkGL2EQLMIcjs = require('./chunk-GL2EQLMI.cjs');
7
7
 
8
8
 
9
- var _chunkBPWGWJJVcjs = require('./chunk-BPWGWJJV.cjs');
9
+ var _chunkVZJHRPOTcjs = require('./chunk-VZJHRPOT.cjs');
10
10
 
11
11
 
12
12
 
13
13
 
14
- var _chunkIWZJCLOEcjs = require('./chunk-IWZJCLOE.cjs');
14
+ var _chunkAHXFO2BBcjs = require('./chunk-AHXFO2BB.cjs');
15
15
 
16
16
 
17
17
 
@@ -28,7 +28,7 @@ var _chunkRGDUK5KXcjs = require('./chunk-RGDUK5KX.cjs');
28
28
 
29
29
 
30
30
 
31
- var _chunkM6NETFDRcjs = require('./chunk-M6NETFDR.cjs');
31
+ var _chunk6OXP4IVScjs = require('./chunk-6OXP4IVS.cjs');
32
32
 
33
33
 
34
34
 
@@ -41,21 +41,21 @@ var _chunkM6NETFDRcjs = require('./chunk-M6NETFDR.cjs');
41
41
 
42
42
 
43
43
 
44
- var _chunkU5YJQYLZcjs = require('./chunk-U5YJQYLZ.cjs');
44
+ var _chunkOV65IEEYcjs = require('./chunk-OV65IEEY.cjs');
45
45
 
46
46
 
47
47
 
48
48
 
49
- var _chunkO2C4CR57cjs = require('./chunk-O2C4CR57.cjs');
49
+ var _chunkSFZAUNHJcjs = require('./chunk-SFZAUNHJ.cjs');
50
50
 
51
51
 
52
- var _chunkLIUHRGEKcjs = require('./chunk-LIUHRGEK.cjs');
52
+ var _chunkAN23SOZXcjs = require('./chunk-AN23SOZX.cjs');
53
53
  require('./chunk-3VQDXJLW.cjs');
54
54
 
55
55
 
56
- var _chunk7T4CVHKDcjs = require('./chunk-7T4CVHKD.cjs');
56
+ var _chunkM64PETK7cjs = require('./chunk-M64PETK7.cjs');
57
57
  require('./chunk-7HSUHP63.cjs');
58
- require('./chunk-GOU66I5T.cjs');
58
+ require('./chunk-6FBIXTAL.cjs');
59
59
  require('./chunk-4DE2IREA.cjs');
60
60
 
61
61
 
@@ -93,5 +93,5 @@ require('./chunk-4DE2IREA.cjs');
93
93
 
94
94
 
95
95
 
96
- exports.ANTHROPIC_MODELS = _chunkIWZJCLOEcjs.ANTHROPIC_MODELS; exports.GROK_CHAT_MODELS = _chunkM6NETFDRcjs.GROK_CHAT_MODELS; exports.GROK_IMAGE_MODELS = _chunkM6NETFDRcjs.GROK_IMAGE_MODELS; exports.GeminiImageModels = _chunkRGDUK5KXcjs.GeminiImageModels; exports.GeminiSummarizeModels = _chunkRGDUK5KXcjs.GeminiSummarizeModels; exports.GeminiTTSModels = _chunkRGDUK5KXcjs.GeminiTTSModels; exports.GeminiTextModels = _chunkRGDUK5KXcjs.GeminiTextModels; exports.OPENAI_CHAT_MODELS = _chunkU5YJQYLZcjs.OPENAI_CHAT_MODELS; exports.OPENAI_IMAGE_MODELS = _chunkU5YJQYLZcjs.OPENAI_IMAGE_MODELS; exports.OPENAI_TRANSCRIPTION_MODELS = _chunkU5YJQYLZcjs.OPENAI_TRANSCRIPTION_MODELS; exports.OPENAI_TTS_MODELS = _chunkU5YJQYLZcjs.OPENAI_TTS_MODELS; exports.OPENAI_VIDEO_MODELS = _chunkU5YJQYLZcjs.OPENAI_VIDEO_MODELS; exports.createAnthropicChat = _chunkIWZJCLOEcjs.createAnthropicChat; exports.createAnthropicSummarize = _chunkIWZJCLOEcjs.createAnthropicSummarize; exports.createGeminiChat = _chunkRGDUK5KXcjs.createGeminiChat; exports.createGeminiImage = _chunkRGDUK5KXcjs.createGeminiImage; exports.createGeminiSummarize = _chunkRGDUK5KXcjs.createGeminiSummarize; exports.createGeminiTts = _chunkRGDUK5KXcjs.createGeminiTts; exports.createGrokChat = _chunkM6NETFDRcjs.createGrokChat; exports.createGrokImage = _chunkM6NETFDRcjs.createGrokImage; exports.createGrokSummarize = _chunkM6NETFDRcjs.createGrokSummarize; exports.createOpenAiChat = _chunkU5YJQYLZcjs.createOpenAiChat; exports.createOpenAiImage = _chunkU5YJQYLZcjs.createOpenAiImage; exports.createOpenAiSummarize = _chunkU5YJQYLZcjs.createOpenAiSummarize; exports.createOpenAiTranscription = _chunkU5YJQYLZcjs.createOpenAiTranscription; exports.createOpenAiTts = _chunkU5YJQYLZcjs.createOpenAiTts; exports.createOpenAiVideo = _chunkU5YJQYLZcjs.createOpenAiVideo; exports.createOpenRouterChat = _chunkO2C4CR57cjs.createOpenRouterChat; exports.createOpenRouterImage = _chunkO2C4CR57cjs.createOpenRouterImage; exports.createOpenRouterSummarize = _chunkO2C4CR57cjs.createOpenRouterSummarize; exports.createWorkersAiChat = _chunkBPWGWJJVcjs.createWorkersAiChat; exports.createWorkersAiImage = _chunkLIUHRGEKcjs.createWorkersAiImage; exports.createWorkersAiSummarize = _chunk7T4CVHKDcjs.createWorkersAiSummarize; exports.createWorkersAiTranscription = _chunkXKSFDPDYcjs.createWorkersAiTranscription; exports.createWorkersAiTts = _chunkLBYDBPHYcjs.createWorkersAiTts;
96
+ exports.ANTHROPIC_MODELS = _chunkAHXFO2BBcjs.ANTHROPIC_MODELS; exports.GROK_CHAT_MODELS = _chunk6OXP4IVScjs.GROK_CHAT_MODELS; exports.GROK_IMAGE_MODELS = _chunk6OXP4IVScjs.GROK_IMAGE_MODELS; exports.GeminiImageModels = _chunkRGDUK5KXcjs.GeminiImageModels; exports.GeminiSummarizeModels = _chunkRGDUK5KXcjs.GeminiSummarizeModels; exports.GeminiTTSModels = _chunkRGDUK5KXcjs.GeminiTTSModels; exports.GeminiTextModels = _chunkRGDUK5KXcjs.GeminiTextModels; exports.OPENAI_CHAT_MODELS = _chunkOV65IEEYcjs.OPENAI_CHAT_MODELS; exports.OPENAI_IMAGE_MODELS = _chunkOV65IEEYcjs.OPENAI_IMAGE_MODELS; exports.OPENAI_TRANSCRIPTION_MODELS = _chunkOV65IEEYcjs.OPENAI_TRANSCRIPTION_MODELS; exports.OPENAI_TTS_MODELS = _chunkOV65IEEYcjs.OPENAI_TTS_MODELS; exports.OPENAI_VIDEO_MODELS = _chunkOV65IEEYcjs.OPENAI_VIDEO_MODELS; exports.createAnthropicChat = _chunkAHXFO2BBcjs.createAnthropicChat; exports.createAnthropicSummarize = _chunkAHXFO2BBcjs.createAnthropicSummarize; exports.createGeminiChat = _chunkRGDUK5KXcjs.createGeminiChat; exports.createGeminiImage = _chunkRGDUK5KXcjs.createGeminiImage; exports.createGeminiSummarize = _chunkRGDUK5KXcjs.createGeminiSummarize; exports.createGeminiTts = _chunkRGDUK5KXcjs.createGeminiTts; exports.createGrokChat = _chunk6OXP4IVScjs.createGrokChat; exports.createGrokImage = _chunk6OXP4IVScjs.createGrokImage; exports.createGrokSummarize = _chunk6OXP4IVScjs.createGrokSummarize; exports.createOpenAiChat = _chunkOV65IEEYcjs.createOpenAiChat; exports.createOpenAiImage = _chunkOV65IEEYcjs.createOpenAiImage; exports.createOpenAiSummarize = _chunkOV65IEEYcjs.createOpenAiSummarize; exports.createOpenAiTranscription = _chunkOV65IEEYcjs.createOpenAiTranscription; exports.createOpenAiTts = _chunkOV65IEEYcjs.createOpenAiTts; exports.createOpenAiVideo = _chunkOV65IEEYcjs.createOpenAiVideo; exports.createOpenRouterChat = _chunkSFZAUNHJcjs.createOpenRouterChat; exports.createOpenRouterImage = _chunkSFZAUNHJcjs.createOpenRouterImage; exports.createOpenRouterSummarize = _chunkSFZAUNHJcjs.createOpenRouterSummarize; exports.createWorkersAiChat = _chunkVZJHRPOTcjs.createWorkersAiChat; exports.createWorkersAiImage = _chunkAN23SOZXcjs.createWorkersAiImage; exports.createWorkersAiSummarize = _chunkM64PETK7cjs.createWorkersAiSummarize; exports.createWorkersAiTranscription = _chunk4ACSLQDIcjs.createWorkersAiTranscription; exports.createWorkersAiTts = _chunkGL2EQLMIcjs.createWorkersAiTts;
97
97
  //# sourceMappingURL=index.cjs.map
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  createWorkersAiTranscription
3
- } from "./chunk-PLTFCUMO.js";
3
+ } from "./chunk-VV3JFKAN.js";
4
4
  import {
5
5
  createWorkersAiTts
6
- } from "./chunk-XI2BOYEI.js";
6
+ } from "./chunk-ALUCJNDE.js";
7
7
  import {
8
8
  createWorkersAiChat
9
- } from "./chunk-BD4CRW3Q.js";
9
+ } from "./chunk-5YEJ5ZRQ.js";
10
10
  import {
11
11
  ANTHROPIC_MODELS,
12
12
  createAnthropicChat,
13
13
  createAnthropicSummarize
14
- } from "./chunk-YIA5B3QT.js";
14
+ } from "./chunk-SIOQQHXS.js";
15
15
  import {
16
16
  GeminiImageModels,
17
17
  GeminiSummarizeModels,
@@ -28,7 +28,7 @@ import {
28
28
  createGrokChat,
29
29
  createGrokImage,
30
30
  createGrokSummarize
31
- } from "./chunk-XCNU7EEC.js";
31
+ } from "./chunk-F75IZQCM.js";
32
32
  import {
33
33
  OPENAI_CHAT_MODELS,
34
34
  OPENAI_IMAGE_MODELS,
@@ -41,21 +41,21 @@ import {
41
41
  createOpenAiTranscription,
42
42
  createOpenAiTts,
43
43
  createOpenAiVideo
44
- } from "./chunk-VTDJEUFS.js";
44
+ } from "./chunk-PAVBM57P.js";
45
45
  import {
46
46
  createOpenRouterChat,
47
47
  createOpenRouterImage,
48
48
  createOpenRouterSummarize
49
- } from "./chunk-QRHKPL75.js";
49
+ } from "./chunk-S3ALRROX.js";
50
50
  import {
51
51
  createWorkersAiImage
52
- } from "./chunk-RQT7M6MU.js";
52
+ } from "./chunk-2RO3A3R4.js";
53
53
  import "./chunk-XU7YEPML.js";
54
54
  import {
55
55
  createWorkersAiSummarize
56
- } from "./chunk-2AJ6LV2D.js";
56
+ } from "./chunk-R2MRGLZ4.js";
57
57
  import "./chunk-2VII5BK2.js";
58
- import "./chunk-F5YJMXZR.js";
58
+ import "./chunk-UUFEOQ6B.js";
59
59
  import "./chunk-V6TY7KAL.js";
60
60
  export {
61
61
  ANTHROPIC_MODELS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudflare/tanstack-ai",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Use TanStack AI with Cloudflare Workers AI and AI Gateway",
5
5
  "keywords": [
6
6
  "ai",
@@ -88,26 +88,26 @@
88
88
  "access": "public"
89
89
  },
90
90
  "dependencies": {
91
- "openai": "^6.16.0"
91
+ "openai": "^6.21.0"
92
92
  },
93
93
  "devDependencies": {
94
+ "@cloudflare/workers-types": "^4.20260212.0",
94
95
  "@microsoft/api-extractor": "^7.56.3",
95
- "@tanstack/ai": "^0.4.2",
96
- "dotenv": "^17.2.3"
96
+ "@tanstack/ai": "^0.5.0",
97
+ "dotenv": "^17.2.4"
97
98
  },
98
99
  "peerDependencies": {
99
- "@tanstack/ai": "^0.4.2"
100
+ "@tanstack/ai": "^0.5.0"
100
101
  },
101
102
  "optionalDependencies": {
102
- "@anthropic-ai/sdk": "^0.71.2",
103
- "@cloudflare/workers-types": "^4.20260128.0",
104
- "@google/genai": "^1.35.0",
105
- "@openrouter/sdk": "^0.3.15",
106
- "@tanstack/ai-anthropic": "^0.4.2",
107
- "@tanstack/ai-gemini": "^0.4.1",
108
- "@tanstack/ai-grok": "^0.4.1",
109
- "@tanstack/ai-openai": "^0.4.0",
110
- "@tanstack/ai-openrouter": "^0.4.2"
103
+ "@anthropic-ai/sdk": "^0.74.0",
104
+ "@google/genai": "^1.41.0",
105
+ "@openrouter/sdk": "^0.8.0",
106
+ "@tanstack/ai-anthropic": "^0.5.0",
107
+ "@tanstack/ai-gemini": "^0.5.0",
108
+ "@tanstack/ai-grok": "^0.5.0",
109
+ "@tanstack/ai-openai": "^0.5.0",
110
+ "@tanstack/ai-openrouter": "^0.5.0"
111
111
  },
112
112
  "scripts": {
113
113
  "build": "rm -rf dist && tsup --config tsup.config.ts",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/workers-ai.ts"],"sourcesContent":["import type { AiModels, BaseAiTextGeneration } from \"@cloudflare/workers-types\";\nimport type { 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} from \"../utils/create-fetcher\";\n\n// ---------------------------------------------------------------------------\n// Model types derived from @cloudflare/workers-types\n// ---------------------------------------------------------------------------\n\nexport type WorkersAiTextModel = {\n\t[K in keyof AiModels]: AiModels[K] extends BaseAiTextGeneration ? K : never;\n}[keyof AiModels];\n\n// ---------------------------------------------------------------------------\n// Helpers: build the right OpenAI client depending on config mode\n// ---------------------------------------------------------------------------\n\nfunction buildWorkersAiClient(config: WorkersAiAdapterConfig): OpenAI {\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(config.binding),\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});\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),\n\t\tapiKey: gatewayConfig.apiKey ?? \"unused\",\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Shared message-building helpers\n// ---------------------------------------------------------------------------\n\ninterface MessageLike {\n\trole: string;\n\tcontent: string | null | Array<{ type: string; content?: string }>;\n\ttoolCalls?: Array<{\n\t\tid: string;\n\t\tfunction: { name: string; arguments: string };\n\t}>;\n\ttoolCallId?: string;\n}\n\nfunction extractTextContent(\n\tcontent: string | null | Array<{ type: string; content?: string }>,\n): string {\n\tif (content === null) return \"\";\n\tif (typeof content === \"string\") return content;\n\treturn content\n\t\t.filter((p) => p.type === \"text\")\n\t\t.map((p) => p.content || \"\")\n\t\t.join(\"\");\n}\n\nfunction buildOpenAIMessages(\n\tsystemPrompts: string[] | undefined,\n\tmessages: MessageLike[],\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: extractTextContent(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: string): string {\n\treturn `${prefix}-${crypto.randomUUID()}`;\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, 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(\"workers-ai\");\n\t\tconst messageId = generateId(\"workers-ai\");\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(\"workers-ai-step\");\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\tconst stream = await this.client.chat.completions.create({\n\t\t\t\tmodel: model ?? this.model,\n\t\t\t\tmessages: openAIMessages,\n\t\t\t\ttools: openAITools,\n\t\t\t\ttemperature,\n\t\t\t\tstream: true,\n\t\t\t\tstream_options: { include_usage: true },\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 as\n\t\t\t\t\t| string\n\t\t\t\t\t| 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\ttoolCallsInProgress.set(index, {\n\t\t\t\t\t\t\t\tid: toolCallDelta.id || \"\",\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\tif (toolCallDelta.id) {\n\t\t\t\t\t\t\ttoolCall.id = toolCallDelta.id;\n\t\t\t\t\t\t}\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\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":[]}