@tanstack/ai 0.47.3 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +2 -1
  2. package/dist/esm/activities/chat/adapter.d.ts +5 -4
  3. package/dist/esm/activities/chat/adapter.js.map +1 -1
  4. package/dist/esm/activities/chat/index.d.ts +4 -7
  5. package/dist/esm/activities/chat/index.js +201 -243
  6. package/dist/esm/activities/chat/index.js.map +1 -1
  7. package/dist/esm/activities/chat/messages.js +115 -25
  8. package/dist/esm/activities/chat/messages.js.map +1 -1
  9. package/dist/esm/activities/chat/stream/processor.d.ts +38 -17
  10. package/dist/esm/activities/chat/stream/processor.js +186 -101
  11. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  12. package/dist/esm/activities/chat/tools/tool-calls.d.ts +3 -2
  13. package/dist/esm/activities/chat/tools/tool-calls.js +15 -10
  14. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  15. package/dist/esm/activities/generateVideo/index.js +6 -6
  16. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  17. package/dist/esm/activities/stream-generation-result.js +7 -8
  18. package/dist/esm/activities/stream-generation-result.js.map +1 -1
  19. package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +2 -1
  20. package/dist/esm/activities/summarize/chat-stream-summarize.js +56 -53
  21. package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
  22. package/dist/esm/adapter-internals.d.ts +2 -0
  23. package/dist/esm/adapter-internals.js +3 -1
  24. package/dist/esm/client.d.ts +8 -1
  25. package/dist/esm/client.js +7 -2
  26. package/dist/esm/client.js.map +1 -1
  27. package/dist/esm/index.d.ts +6 -0
  28. package/dist/esm/index.js +6 -2
  29. package/dist/esm/middlewares/otel.js +11 -4
  30. package/dist/esm/middlewares/otel.js.map +1 -1
  31. package/dist/esm/stream-to-response.js +8 -5
  32. package/dist/esm/stream-to-response.js.map +1 -1
  33. package/dist/esm/stream-to-websocket.js +4 -2
  34. package/dist/esm/stream-to-websocket.js.map +1 -1
  35. package/dist/esm/strip-to-spec-middleware.d.ts +10 -13
  36. package/dist/esm/strip-to-spec-middleware.js +24 -22
  37. package/dist/esm/strip-to-spec-middleware.js.map +1 -1
  38. package/dist/esm/types.d.ts +82 -305
  39. package/dist/esm/utilities/adapter-yield-chunk.d.ts +31 -0
  40. package/dist/esm/utilities/ag-ui-usage.d.ts +24 -0
  41. package/dist/esm/utilities/ag-ui-usage.js +66 -0
  42. package/dist/esm/utilities/ag-ui-usage.js.map +1 -0
  43. package/dist/esm/utilities/ag-ui-wire.d.ts +14 -7
  44. package/dist/esm/utilities/ag-ui-wire.js +71 -30
  45. package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
  46. package/dist/esm/utilities/chat-params.d.ts +3 -3
  47. package/dist/esm/utilities/chat-params.js +10 -30
  48. package/dist/esm/utilities/chat-params.js.map +1 -1
  49. package/dist/esm/utilities/chunk-ids.d.ts +5 -0
  50. package/dist/esm/utilities/chunk-ids.js +25 -0
  51. package/dist/esm/utilities/chunk-ids.js.map +1 -0
  52. package/dist/esm/utilities/merge-metadata.d.ts +14 -0
  53. package/dist/esm/utilities/merge-metadata.js +43 -0
  54. package/dist/esm/utilities/merge-metadata.js.map +1 -0
  55. package/dist/esm/utilities/normalize-stream-chunk.d.ts +3 -0
  56. package/dist/esm/utilities/normalize-stream-chunk.js +100 -0
  57. package/dist/esm/utilities/normalize-stream-chunk.js.map +1 -0
  58. package/dist/esm/utilities/reasoning-encrypted-value.d.ts +8 -0
  59. package/dist/esm/utilities/reasoning-encrypted-value.js +16 -0
  60. package/dist/esm/utilities/reasoning-encrypted-value.js.map +1 -0
  61. package/dist/esm/utilities/restore-inbound-chunk.d.ts +15 -0
  62. package/dist/esm/utilities/restore-inbound-chunk.js +43 -0
  63. package/dist/esm/utilities/restore-inbound-chunk.js.map +1 -0
  64. package/dist/esm/utilities/spec-event-keys.d.ts +2 -0
  65. package/dist/esm/utilities/spec-event-keys.js +56 -0
  66. package/dist/esm/utilities/spec-event-keys.js.map +1 -0
  67. package/dist/esm/utilities/structured-output-events.d.ts +3 -3
  68. package/dist/esm/utilities/structured-output-events.js.map +1 -1
  69. package/package.json +2 -2
  70. package/src/activities/chat/adapter.ts +4 -4
  71. package/src/activities/chat/index.ts +398 -400
  72. package/src/activities/chat/messages.ts +174 -34
  73. package/src/activities/chat/stream/processor.ts +289 -218
  74. package/src/activities/chat/tools/tool-calls.ts +23 -22
  75. package/src/activities/generateVideo/index.ts +7 -6
  76. package/src/activities/stream-generation-result.ts +8 -12
  77. package/src/activities/summarize/chat-stream-summarize.ts +94 -70
  78. package/src/adapter-internals.ts +2 -0
  79. package/src/client.ts +13 -0
  80. package/src/index.ts +6 -0
  81. package/src/middlewares/otel.ts +16 -8
  82. package/src/stream-to-response.ts +11 -4
  83. package/src/stream-to-websocket.ts +3 -1
  84. package/src/strip-to-spec-middleware.ts +48 -24
  85. package/src/types.ts +109 -393
  86. package/src/utilities/adapter-yield-chunk.ts +30 -0
  87. package/src/utilities/ag-ui-usage.test.ts +194 -0
  88. package/src/utilities/ag-ui-usage.ts +148 -0
  89. package/src/utilities/ag-ui-wire.ts +149 -31
  90. package/src/utilities/chat-params.ts +22 -39
  91. package/src/utilities/chunk-ids.ts +24 -0
  92. package/src/utilities/merge-metadata.test.ts +117 -0
  93. package/src/utilities/merge-metadata.ts +59 -0
  94. package/src/utilities/normalize-stream-chunk.test.ts +423 -0
  95. package/src/utilities/normalize-stream-chunk.ts +186 -0
  96. package/src/utilities/reasoning-encrypted-value.ts +18 -0
  97. package/src/utilities/restore-inbound-chunk.test.ts +133 -0
  98. package/src/utilities/restore-inbound-chunk.ts +72 -0
  99. package/src/utilities/spec-event-keys.test.ts +34 -0
  100. package/src/utilities/spec-event-keys.ts +74 -0
  101. package/src/utilities/structured-output-events.ts +3 -3
@@ -1,3 +1,4 @@
1
+ import { AdapterYieldChunk } from '../../utilities/adapter-yield-chunk.js';
1
2
  import { BaseSummarizeAdapter } from './adapter.js';
2
3
  import { StreamChunk, SummarizationOptions, SummarizationResult, TextOptions } from '../../types.js';
3
4
  /**
@@ -12,7 +13,7 @@ import { StreamChunk, SummarizationOptions, SummarizationResult, TextOptions } f
12
13
  * `SummarizationOptions<TProviderOptions>` on the wrapper itself.
13
14
  */
14
15
  export interface ChatStreamCapable {
15
- chatStream: (options: TextOptions<any>) => AsyncIterable<StreamChunk>;
16
+ chatStream: (options: TextOptions<any>) => AsyncIterable<AdapterYieldChunk>;
16
17
  }
17
18
  /**
18
19
  * Extract the per-model `modelOptions` type a text adapter accepts. Used by
@@ -1,8 +1,29 @@
1
1
  import { toRunErrorPayload } from "../error-payload.js";
2
+ import { rebuildTokenUsage } from "../../utilities/ag-ui-usage.js";
3
+ import { tanstackMetadata } from "../../utilities/merge-metadata.js";
4
+ import { normalizeStreamChunk } from "../../utilities/normalize-stream-chunk.js";
2
5
  import { BaseSummarizeAdapter } from "./adapter.js";
3
6
  import { MAX_TOKENS_KEYS } from "../../utilities/sampling-keys.js";
4
7
  import { EventType } from "@ag-ui/core";
5
8
  //#region src/activities/summarize/chat-stream-summarize.ts
9
+ function consumeSpecSummarizeChunk(chunk, state) {
10
+ if (chunk.type === EventType.TEXT_MESSAGE_CONTENT) {
11
+ if (chunk.delta) state.summary += chunk.delta;
12
+ return;
13
+ }
14
+ const tanstack = tanstackMetadata(chunk);
15
+ if ((chunk.type === EventType.RUN_STARTED || chunk.type === EventType.RUN_FINISHED || chunk.type === EventType.TEXT_MESSAGE_START) && typeof tanstack?.model === "string") state.model = tanstack.model;
16
+ if (chunk.type === EventType.RUN_FINISHED) {
17
+ const rebuilt = rebuildTokenUsage(chunk.usage, tanstack?.usage);
18
+ if (rebuilt) state.usage = rebuilt;
19
+ }
20
+ }
21
+ function throwRunError(chunk) {
22
+ const message = typeof chunk.message === "string" && chunk.message.length > 0 ? chunk.message : "Summarization failed";
23
+ const err = new Error(message);
24
+ if (typeof chunk.code === "string") err.code = chunk.code;
25
+ throw err;
26
+ }
6
27
  /**
7
28
  * Provider-native max-output-tokens key per summarize-adapter `name`. summarize
8
29
  * is provider-agnostic and forwards `modelOptions` opaquely to the wrapped text
@@ -118,35 +139,24 @@ var ChatStreamSummarizeAdapter = class extends BaseSummarizeAdapter {
118
139
  }
119
140
  async summarize(options) {
120
141
  const systemPrompt = this.buildSummarizationPrompt(options);
121
- let summary = "";
122
142
  const id = this.generateId();
123
- let model = options.model;
124
- let usage = {
125
- promptTokens: 0,
126
- completionTokens: 0,
127
- totalTokens: 0
143
+ const state = {
144
+ summary: "",
145
+ model: options.model,
146
+ usage: {
147
+ promptTokens: 0,
148
+ completionTokens: 0,
149
+ totalTokens: 0
150
+ }
128
151
  };
129
152
  options.logger.request(`activity=summarize provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? "unset"}`, {
130
153
  provider: this.name,
131
154
  model: options.model
132
155
  });
133
156
  try {
134
- for await (const chunk of this.textAdapter.chatStream(this.buildTextOptions(options, systemPrompt))) {
135
- if (chunk.type === "TEXT_MESSAGE_CONTENT") {
136
- if (chunk.content) summary = chunk.content;
137
- else if (chunk.delta) summary += chunk.delta;
138
- model = chunk.model || model;
139
- }
140
- if (chunk.type === "RUN_FINISHED") {
141
- if (chunk.usage) usage = chunk.usage;
142
- }
143
- if (chunk.type === "RUN_ERROR") {
144
- const message = (chunk.error && typeof chunk.error.message === "string" ? chunk.error.message : null) ?? "Summarization failed";
145
- const code = chunk.error && typeof chunk.error.code === "string" ? chunk.error.code : void 0;
146
- const err = new Error(message);
147
- if (code) err.code = code;
148
- throw err;
149
- }
157
+ for await (const raw of this.textAdapter.chatStream(this.buildTextOptions(options, systemPrompt))) for (const chunk of normalizeStreamChunk(raw)) {
158
+ if (chunk.type === EventType.RUN_ERROR) throwRunError(chunk);
159
+ consumeSpecSummarizeChunk(chunk, state);
150
160
  }
151
161
  } catch (error) {
152
162
  options.logger.errors(`${this.name}.summarize fatal`, {
@@ -157,9 +167,9 @@ var ChatStreamSummarizeAdapter = class extends BaseSummarizeAdapter {
157
167
  }
158
168
  return {
159
169
  id,
160
- model,
161
- summary,
162
- usage
170
+ model: state.model,
171
+ summary: state.summary,
172
+ usage: state.usage
163
173
  };
164
174
  }
165
175
  async *summarizeStream(options) {
@@ -169,36 +179,29 @@ var ChatStreamSummarizeAdapter = class extends BaseSummarizeAdapter {
169
179
  model: options.model
170
180
  });
171
181
  const id = this.generateId();
172
- let summary = "";
173
- let model = options.model;
174
- let usage = {
175
- promptTokens: 0,
176
- completionTokens: 0,
177
- totalTokens: 0
182
+ const state = {
183
+ summary: "",
184
+ model: options.model,
185
+ usage: {
186
+ promptTokens: 0,
187
+ completionTokens: 0,
188
+ totalTokens: 0
189
+ }
178
190
  };
179
191
  try {
180
- for await (const chunk of this.textAdapter.chatStream(this.buildTextOptions(options, systemPrompt))) {
181
- if (chunk.type === "TEXT_MESSAGE_CONTENT") {
182
- if (chunk.content) summary = chunk.content;
183
- else if (chunk.delta) summary += chunk.delta;
184
- if (chunk.model) model = chunk.model;
185
- }
186
- if (chunk.type === "RUN_FINISHED") {
187
- if (chunk.usage) usage = chunk.usage;
188
- if (chunk.model) model = chunk.model;
189
- yield {
190
- type: EventType.CUSTOM,
191
- name: "generation:result",
192
- value: {
193
- id,
194
- model,
195
- summary,
196
- usage
197
- },
198
- model,
199
- timestamp: Date.now()
200
- };
201
- }
192
+ for await (const raw of this.textAdapter.chatStream(this.buildTextOptions(options, systemPrompt))) for (const chunk of normalizeStreamChunk(raw)) {
193
+ consumeSpecSummarizeChunk(chunk, state);
194
+ if (chunk.type === EventType.RUN_FINISHED) yield {
195
+ type: EventType.CUSTOM,
196
+ name: "generation:result",
197
+ value: {
198
+ id,
199
+ model: state.model,
200
+ summary: state.summary,
201
+ usage: state.usage
202
+ },
203
+ timestamp: Date.now()
204
+ };
202
205
  yield chunk;
203
206
  }
204
207
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"chat-stream-summarize.js","names":[],"sources":["../../../../src/activities/summarize/chat-stream-summarize.ts"],"sourcesContent":["import { EventType } from '@ag-ui/core'\nimport { toRunErrorPayload } from '../error-payload'\nimport { MAX_TOKENS_KEYS } from '../../utilities/sampling-keys'\nimport { BaseSummarizeAdapter } from './adapter'\nimport type {\n StreamChunk,\n SummarizationOptions,\n SummarizationResult,\n TextOptions,\n} from '../../types'\n\n/**\n * Minimal contract for a text adapter that supports `chatStream`. Lets\n * `ChatStreamSummarizeAdapter` work with any text adapter without coupling\n * to a specific implementation.\n *\n * The provider-options shape is intentionally `any` here — the wrapper only\n * forwards `modelOptions` straight through, so a text adapter with a richer\n * per-model options type (e.g. `ResolveProviderOptions<TModel>`) is still\n * acceptable. Summarize-level type safety is enforced via\n * `SummarizationOptions<TProviderOptions>` on the wrapper itself.\n */\nexport interface ChatStreamCapable {\n chatStream: (options: TextOptions<any>) => AsyncIterable<StreamChunk>\n}\n\n/**\n * Provider-native max-output-tokens key per summarize-adapter `name`. summarize\n * is provider-agnostic and forwards `modelOptions` opaquely to the wrapped text\n * adapter, so `maxLength` must be written under the exact key the underlying\n * provider reads — no adapter reads a generic `maxTokens`. Ollama is the one\n * exception: it nests sampling under `options`, so it has no entry here and is\n * handled as a special nested case in `applyMaxLength`/`applyDefaultTemperature`.\n *\n * Keep in sync with each adapter's wire mapping:\n * - OpenAI (Responses): `max_output_tokens`\n * - Anthropic / Grok: `max_tokens`\n * - Groq: `max_completion_tokens`\n * - Gemini: `maxOutputTokens`\n * - OpenRouter: `maxCompletionTokens`\n * - LLM Gateway: `max_tokens`\n * - Ollama: nested `options.num_predict` (no entry — see `applyMaxLength`)\n */\nconst MAX_TOKENS_KEY_BY_ADAPTER: Record<string, string> = {\n openai: 'max_output_tokens',\n anthropic: 'max_tokens',\n grok: 'max_tokens',\n groq: 'max_completion_tokens',\n gemini: 'maxOutputTokens',\n openrouter: 'maxCompletionTokens',\n // LLM Gateway exposes an OpenAI-compatible Chat Completions surface whose\n // only output cap is `max_tokens` — it does not read `max_completion_tokens`.\n llmgateway: 'max_tokens',\n}\n\n/**\n * Every flat key any supported provider uses to cap output tokens (plus the\n * generic `maxTokens` spelling no adapter reads). Used to detect a\n * caller-supplied token limit so the summarize default never overrides an\n * explicit caller value. Shared with the OTel middleware via\n * `MAX_TOKENS_KEYS` so the two spelling sets cannot drift.\n */\nconst KNOWN_MAX_TOKENS_KEYS = MAX_TOKENS_KEYS\n\n/**\n * Whether `applyMaxLength` knows how to place a token limit for this adapter\n * `name` (either the nested Ollama shape or a flat provider-native key).\n * Used to surface a warning when `maxLength` would otherwise be silently\n * dropped for an unrecognised adapter name.\n */\nfunction isKnownMaxTokensAdapter(adapterName: string): boolean {\n return (\n adapterName === 'ollama' ||\n MAX_TOKENS_KEY_BY_ADAPTER[adapterName] !== undefined\n )\n}\n\n/**\n * Apply the low-temperature summarize default to a working copy of the\n * caller's `modelOptions`, placed where the wrapped provider actually reads\n * it (nested under `options` for Ollama, flat otherwise). The caller always\n * wins: if they already set `temperature` in that location, it is untouched.\n */\nfunction applyDefaultTemperature(\n adapterName: string,\n temperature: number,\n modelOptions: Record<string, unknown>,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...modelOptions }\n\n if (adapterName === 'ollama') {\n const existing =\n merged.options && typeof merged.options === 'object'\n ? (merged.options as Record<string, unknown>)\n : undefined\n if (existing && 'temperature' in existing) return merged\n merged.options = { temperature, ...existing }\n return merged\n }\n\n if ('temperature' in merged) return merged\n merged.temperature = temperature\n return merged\n}\n\n/**\n * Resolve `maxLength` to the provider-native max-output-tokens key for the\n * given summarize-adapter `name` (this wrapper's OWN `name`, not the wrapped\n * text adapter's) and merge it into a working copy of the caller's\n * `modelOptions`. The caller always wins: if they already set any recognised\n * token-limit key (flat or, for Ollama, nested `options.num_predict`), the\n * default is left untouched. Unknown/unrecognised adapter names fall back to\n * NOT setting a token key (the prompt hint still asks the model to stay under\n * `maxLength`) rather than writing a dead key no provider reads.\n *\n * Caveat (intentional): \"caller wins\" keys off ANY recognised spelling in\n * `KNOWN_MAX_TOKENS_KEYS`, but only the adapter's native key is read on the\n * wire. So a caller who sets a NON-native spelling for this provider — e.g.\n * `maxTokens`, or Anthropic's `max_tokens` against an OpenAI adapter — suppresses\n * the summarize default WITHOUT getting their own value applied either: neither\n * cap reaches the wire. This favours never clobbering a migration leftover over\n * guaranteeing a cap; the prompt-level hint still asks the model to stay under\n * `maxLength`. Rename the key to the provider-native spelling to forward it.\n */\nfunction applyMaxLength(\n adapterName: string,\n maxLength: number,\n modelOptions: Record<string, unknown>,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...modelOptions }\n\n if (adapterName === 'ollama') {\n // Honor a caller-set limit in either shape: a recognised flat key (e.g.\n // left over from a migration) or the nested `options.num_predict`.\n const callerSetFlatLimit = KNOWN_MAX_TOKENS_KEYS.some(\n (k) => typeof merged[k] === 'number',\n )\n const existing =\n merged.options && typeof merged.options === 'object'\n ? (merged.options as Record<string, unknown>)\n : undefined\n if (\n callerSetFlatLimit ||\n (existing && typeof existing.num_predict === 'number')\n ) {\n return merged\n }\n merged.options = { num_predict: maxLength, ...existing }\n return merged\n }\n\n const key = MAX_TOKENS_KEY_BY_ADAPTER[adapterName]\n if (key === undefined) return merged\n\n const callerSetLimit = KNOWN_MAX_TOKENS_KEYS.some(\n (k) => typeof merged[k] === 'number',\n )\n if (callerSetLimit) return merged\n\n merged[key] = maxLength\n return merged\n}\n\n/**\n * Extract the per-model `modelOptions` type a text adapter accepts. Used by\n * provider summarize factories so their `modelOptions` IntelliSense matches\n * what the underlying text adapter actually understands.\n */\nexport type InferTextProviderOptions<TAdapter> = TAdapter extends {\n '~types': { providerOptions: infer P }\n}\n ? P extends object\n ? P\n : object\n : object\n\n/**\n * Summarize adapter that wraps any `ChatStreamCapable` text adapter and\n * prompts it for summarization. Not tied to any wire format.\n */\nexport class ChatStreamSummarizeAdapter<\n TModel extends string,\n TProviderOptions extends object = Record<string, unknown>,\n> extends BaseSummarizeAdapter<TModel, TProviderOptions> {\n readonly name: string\n\n private readonly textAdapter: ChatStreamCapable\n\n constructor(\n textAdapter: ChatStreamCapable,\n model: TModel,\n name: string = 'chat-stream-summarize',\n ) {\n super({}, model)\n this.name = name\n this.textAdapter = textAdapter\n }\n\n async summarize(\n options: SummarizationOptions<TProviderOptions>,\n ): Promise<SummarizationResult> {\n const systemPrompt = this.buildSummarizationPrompt(options)\n\n let summary = ''\n const id = this.generateId()\n let model = options.model\n let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 }\n\n options.logger.request(\n `activity=summarize provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? 'unset'}`,\n { provider: this.name, model: options.model },\n )\n\n try {\n for await (const chunk of this.textAdapter.chatStream(\n this.buildTextOptions(options, systemPrompt),\n )) {\n if (chunk.type === 'TEXT_MESSAGE_CONTENT') {\n if (chunk.content) {\n summary = chunk.content\n } else if (chunk.delta) {\n // Append delta only when present — a content-less chunk with no\n // delta would otherwise concat literal `'undefined'`.\n summary += chunk.delta\n }\n model = chunk.model || model\n }\n if (chunk.type === 'RUN_FINISHED') {\n if (chunk.usage) {\n usage = chunk.usage\n }\n }\n // Surface failures: the underlying chatStream emits RUN_ERROR instead\n // of throwing, so without this branch summarize() would return an\n // empty summary and pretend a failed run succeeded.\n if (chunk.type === 'RUN_ERROR') {\n const message =\n (chunk.error && typeof chunk.error.message === 'string'\n ? chunk.error.message\n : null) ?? 'Summarization failed'\n const code =\n chunk.error && typeof chunk.error.code === 'string'\n ? chunk.error.code\n : undefined\n const err = new Error(message)\n if (code) {\n ;(err as Error & { code?: string }).code = code\n }\n throw err\n }\n }\n } catch (error: unknown) {\n // Narrow before logging: raw SDK errors can carry request metadata\n // (including auth headers) which we must never surface to user loggers.\n options.logger.errors(`${this.name}.summarize fatal`, {\n error: toRunErrorPayload(error, `${this.name}.summarize failed`),\n source: `${this.name}.summarize`,\n })\n throw error\n }\n\n return { id, model, summary, usage }\n }\n\n override async *summarizeStream(\n options: SummarizationOptions<TProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n const systemPrompt = this.buildSummarizationPrompt(options)\n\n options.logger.request(\n `activity=summarizeStream provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? 'unset'}`,\n { provider: this.name, model: options.model },\n )\n\n const id = this.generateId()\n let summary = ''\n let model = options.model\n let usage: SummarizationResult['usage'] = {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n }\n\n try {\n for await (const chunk of this.textAdapter.chatStream(\n this.buildTextOptions(options, systemPrompt),\n )) {\n // Accumulate the same way `summarize()` does so consumers see deltas\n // AND the terminal `generation:result` event below carries the same\n // final summary that non-streaming returns.\n if (chunk.type === 'TEXT_MESSAGE_CONTENT') {\n if (chunk.content) {\n summary = chunk.content\n } else if (chunk.delta) {\n summary += chunk.delta\n }\n if (chunk.model) model = chunk.model\n }\n\n // Emit the GenerationClient-shaped result event just before the\n // terminal RUN_FINISHED so subscribers (useSummarize) populate\n // `result` before flipping `status` to success.\n if (chunk.type === 'RUN_FINISHED') {\n if (chunk.usage) usage = chunk.usage\n if (chunk.model) model = chunk.model\n yield {\n type: EventType.CUSTOM,\n name: 'generation:result',\n value: { id, model, summary, usage } satisfies SummarizationResult,\n model,\n timestamp: Date.now(),\n }\n }\n\n yield chunk\n }\n } catch (error: unknown) {\n options.logger.errors(`${this.name}.summarizeStream fatal`, {\n error: toRunErrorPayload(error, `${this.name}.summarizeStream failed`),\n source: `${this.name}.summarizeStream`,\n })\n throw error\n }\n }\n\n /**\n * Build the TextOptions passed to the underlying chatStream. Provider\n * `modelOptions` from the summarize call are forwarded as-is so knobs like\n * Anthropic cache headers, Gemini safety settings, or Ollama tuning params\n * still reach the wire layer.\n */\n protected buildTextOptions(\n options: SummarizationOptions<TProviderOptions>,\n systemPrompt: string,\n ): TextOptions<TProviderOptions> {\n // Sampling knobs now live in provider-native `modelOptions`. Apply the\n // low-temperature default where the wrapped provider actually reads it\n // (nested under `options` for Ollama, flat otherwise) so callers can still\n // override it. Resolving the placement from this summarize adapter's OWN\n // `name` keeps the default off the wire correctly per provider — a flat\n // `temperature` would be silently dropped by Ollama while still showing up\n // in OTel.\n let working: Record<string, unknown> = {\n ...(options.modelOptions as Record<string, unknown> | undefined),\n }\n working = applyDefaultTemperature(this.name, 0.3, working)\n // `maxLength` must reach the wire under the provider-native token key (it\n // differs per provider, and no adapter reads a generic `maxTokens`).\n // Resolve it from this summarize adapter's `name` (the constructor arg,\n // not the wrapped text adapter's name), never overriding a caller-supplied\n // token limit.\n if (options.maxLength !== undefined) {\n if (!isKnownMaxTokensAdapter(this.name)) {\n options.logger.warn(\n `summarize: maxLength=${options.maxLength} could not be mapped to a provider token key for adapter name \"${this.name}\" — it was dropped from modelOptions (the prompt still asks the model to stay under it). Construct ChatStreamSummarizeAdapter with a recognised provider name to forward the cap.`,\n { provider: this.name },\n )\n }\n working = applyMaxLength(this.name, options.maxLength, working)\n }\n const modelOptions = working as TProviderOptions\n\n return {\n model: options.model,\n messages: [{ role: 'user', content: options.text }],\n systemPrompts: [systemPrompt],\n modelOptions,\n logger: options.logger,\n // Forward the run identity so the wrapped chat stamps it onto RUN_STARTED\n // (chat uses `runId` as its `runIdOverride`). Conditional spreads keep the\n // fields absent when unset, under `exactOptionalPropertyTypes`.\n ...(options.runId !== undefined ? { runId: options.runId } : {}),\n ...(options.threadId !== undefined ? { threadId: options.threadId } : {}),\n }\n }\n\n protected buildSummarizationPrompt(\n options: SummarizationOptions<TProviderOptions>,\n ): string {\n let prompt = 'You are a professional summarizer. '\n\n switch (options.style) {\n case 'bullet-points':\n prompt += 'Provide a summary in bullet point format. '\n break\n case 'paragraph':\n prompt += 'Provide a summary in paragraph format. '\n break\n case 'concise':\n prompt += 'Provide a very concise summary in 1-2 sentences. '\n break\n case undefined:\n prompt += 'Provide a clear and concise summary. '\n break\n default:\n prompt += 'Provide a clear and concise summary. '\n }\n\n if (options.focus && options.focus.length > 0) {\n prompt += `Focus on the following aspects: ${options.focus.join(', ')}. `\n }\n\n if (options.maxLength) {\n prompt += `Keep the summary under ${options.maxLength} tokens. `\n }\n\n return prompt\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chat-stream-summarize.js","names":[],"sources":["../../../../src/activities/summarize/chat-stream-summarize.ts"],"sourcesContent":["import { EventType } from '@ag-ui/core'\nimport { toRunErrorPayload } from '../error-payload'\nimport { MAX_TOKENS_KEYS } from '../../utilities/sampling-keys'\nimport { rebuildTokenUsage } from '../../utilities/ag-ui-usage'\nimport type { AdapterYieldChunk } from '../../utilities/adapter-yield-chunk'\nimport { tanstackMetadata } from '../../utilities/merge-metadata'\nimport { normalizeStreamChunk } from '../../utilities/normalize-stream-chunk'\nimport { BaseSummarizeAdapter } from './adapter'\nimport type {\n StreamChunk,\n SummarizationOptions,\n SummarizationResult,\n TextOptions,\n TokenUsage,\n} from '../../types'\n\nfunction consumeSpecSummarizeChunk(\n chunk: StreamChunk,\n state: { summary: string; model: string; usage: TokenUsage },\n): void {\n if (chunk.type === EventType.TEXT_MESSAGE_CONTENT) {\n if (chunk.delta) state.summary += chunk.delta\n return\n }\n\n const tanstack = tanstackMetadata(chunk)\n if (\n (chunk.type === EventType.RUN_STARTED ||\n chunk.type === EventType.RUN_FINISHED ||\n chunk.type === EventType.TEXT_MESSAGE_START) &&\n typeof tanstack?.model === 'string'\n ) {\n state.model = tanstack.model\n }\n\n if (chunk.type === EventType.RUN_FINISHED) {\n const rebuilt = rebuildTokenUsage(chunk.usage, tanstack?.usage)\n if (rebuilt) state.usage = rebuilt\n }\n}\n\nfunction throwRunError(\n chunk: Extract<StreamChunk, { type: 'RUN_ERROR' }>,\n): never {\n const message =\n typeof chunk.message === 'string' && chunk.message.length > 0\n ? chunk.message\n : 'Summarization failed'\n const err = new Error(message)\n if (typeof chunk.code === 'string') {\n ;(err as Error & { code?: string }).code = chunk.code\n }\n throw err\n}\n\n/**\n * Minimal contract for a text adapter that supports `chatStream`. Lets\n * `ChatStreamSummarizeAdapter` work with any text adapter without coupling\n * to a specific implementation.\n *\n * The provider-options shape is intentionally `any` here — the wrapper only\n * forwards `modelOptions` straight through, so a text adapter with a richer\n * per-model options type (e.g. `ResolveProviderOptions<TModel>`) is still\n * acceptable. Summarize-level type safety is enforced via\n * `SummarizationOptions<TProviderOptions>` on the wrapper itself.\n */\nexport interface ChatStreamCapable {\n chatStream: (options: TextOptions<any>) => AsyncIterable<AdapterYieldChunk>\n}\n\n/**\n * Provider-native max-output-tokens key per summarize-adapter `name`. summarize\n * is provider-agnostic and forwards `modelOptions` opaquely to the wrapped text\n * adapter, so `maxLength` must be written under the exact key the underlying\n * provider reads — no adapter reads a generic `maxTokens`. Ollama is the one\n * exception: it nests sampling under `options`, so it has no entry here and is\n * handled as a special nested case in `applyMaxLength`/`applyDefaultTemperature`.\n *\n * Keep in sync with each adapter's wire mapping:\n * - OpenAI (Responses): `max_output_tokens`\n * - Anthropic / Grok: `max_tokens`\n * - Groq: `max_completion_tokens`\n * - Gemini: `maxOutputTokens`\n * - OpenRouter: `maxCompletionTokens`\n * - LLM Gateway: `max_tokens`\n * - Ollama: nested `options.num_predict` (no entry — see `applyMaxLength`)\n */\nconst MAX_TOKENS_KEY_BY_ADAPTER: Record<string, string> = {\n openai: 'max_output_tokens',\n anthropic: 'max_tokens',\n grok: 'max_tokens',\n groq: 'max_completion_tokens',\n gemini: 'maxOutputTokens',\n openrouter: 'maxCompletionTokens',\n // LLM Gateway exposes an OpenAI-compatible Chat Completions surface whose\n // only output cap is `max_tokens` — it does not read `max_completion_tokens`.\n llmgateway: 'max_tokens',\n}\n\n/**\n * Every flat key any supported provider uses to cap output tokens (plus the\n * generic `maxTokens` spelling no adapter reads). Used to detect a\n * caller-supplied token limit so the summarize default never overrides an\n * explicit caller value. Shared with the OTel middleware via\n * `MAX_TOKENS_KEYS` so the two spelling sets cannot drift.\n */\nconst KNOWN_MAX_TOKENS_KEYS = MAX_TOKENS_KEYS\n\n/**\n * Whether `applyMaxLength` knows how to place a token limit for this adapter\n * `name` (either the nested Ollama shape or a flat provider-native key).\n * Used to surface a warning when `maxLength` would otherwise be silently\n * dropped for an unrecognised adapter name.\n */\nfunction isKnownMaxTokensAdapter(adapterName: string): boolean {\n return (\n adapterName === 'ollama' ||\n MAX_TOKENS_KEY_BY_ADAPTER[adapterName] !== undefined\n )\n}\n\n/**\n * Apply the low-temperature summarize default to a working copy of the\n * caller's `modelOptions`, placed where the wrapped provider actually reads\n * it (nested under `options` for Ollama, flat otherwise). The caller always\n * wins: if they already set `temperature` in that location, it is untouched.\n */\nfunction applyDefaultTemperature(\n adapterName: string,\n temperature: number,\n modelOptions: Record<string, unknown>,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...modelOptions }\n\n if (adapterName === 'ollama') {\n const existing =\n merged.options && typeof merged.options === 'object'\n ? (merged.options as Record<string, unknown>)\n : undefined\n if (existing && 'temperature' in existing) return merged\n merged.options = { temperature, ...existing }\n return merged\n }\n\n if ('temperature' in merged) return merged\n merged.temperature = temperature\n return merged\n}\n\n/**\n * Resolve `maxLength` to the provider-native max-output-tokens key for the\n * given summarize-adapter `name` (this wrapper's OWN `name`, not the wrapped\n * text adapter's) and merge it into a working copy of the caller's\n * `modelOptions`. The caller always wins: if they already set any recognised\n * token-limit key (flat or, for Ollama, nested `options.num_predict`), the\n * default is left untouched. Unknown/unrecognised adapter names fall back to\n * NOT setting a token key (the prompt hint still asks the model to stay under\n * `maxLength`) rather than writing a dead key no provider reads.\n *\n * Caveat (intentional): \"caller wins\" keys off ANY recognised spelling in\n * `KNOWN_MAX_TOKENS_KEYS`, but only the adapter's native key is read on the\n * wire. So a caller who sets a NON-native spelling for this provider — e.g.\n * `maxTokens`, or Anthropic's `max_tokens` against an OpenAI adapter — suppresses\n * the summarize default WITHOUT getting their own value applied either: neither\n * cap reaches the wire. This favours never clobbering a migration leftover over\n * guaranteeing a cap; the prompt-level hint still asks the model to stay under\n * `maxLength`. Rename the key to the provider-native spelling to forward it.\n */\nfunction applyMaxLength(\n adapterName: string,\n maxLength: number,\n modelOptions: Record<string, unknown>,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...modelOptions }\n\n if (adapterName === 'ollama') {\n // Honor a caller-set limit in either shape: a recognised flat key (e.g.\n // left over from a migration) or the nested `options.num_predict`.\n const callerSetFlatLimit = KNOWN_MAX_TOKENS_KEYS.some(\n (k) => typeof merged[k] === 'number',\n )\n const existing =\n merged.options && typeof merged.options === 'object'\n ? (merged.options as Record<string, unknown>)\n : undefined\n if (\n callerSetFlatLimit ||\n (existing && typeof existing.num_predict === 'number')\n ) {\n return merged\n }\n merged.options = { num_predict: maxLength, ...existing }\n return merged\n }\n\n const key = MAX_TOKENS_KEY_BY_ADAPTER[adapterName]\n if (key === undefined) return merged\n\n const callerSetLimit = KNOWN_MAX_TOKENS_KEYS.some(\n (k) => typeof merged[k] === 'number',\n )\n if (callerSetLimit) return merged\n\n merged[key] = maxLength\n return merged\n}\n\n/**\n * Extract the per-model `modelOptions` type a text adapter accepts. Used by\n * provider summarize factories so their `modelOptions` IntelliSense matches\n * what the underlying text adapter actually understands.\n */\nexport type InferTextProviderOptions<TAdapter> = TAdapter extends {\n '~types': { providerOptions: infer P }\n}\n ? P extends object\n ? P\n : object\n : object\n\n/**\n * Summarize adapter that wraps any `ChatStreamCapable` text adapter and\n * prompts it for summarization. Not tied to any wire format.\n */\nexport class ChatStreamSummarizeAdapter<\n TModel extends string,\n TProviderOptions extends object = Record<string, unknown>,\n> extends BaseSummarizeAdapter<TModel, TProviderOptions> {\n readonly name: string\n\n private readonly textAdapter: ChatStreamCapable\n\n constructor(\n textAdapter: ChatStreamCapable,\n model: TModel,\n name: string = 'chat-stream-summarize',\n ) {\n super({}, model)\n this.name = name\n this.textAdapter = textAdapter\n }\n\n async summarize(\n options: SummarizationOptions<TProviderOptions>,\n ): Promise<SummarizationResult> {\n const systemPrompt = this.buildSummarizationPrompt(options)\n\n const id = this.generateId()\n const state = {\n summary: '',\n model: options.model,\n usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },\n }\n\n options.logger.request(\n `activity=summarize provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? 'unset'}`,\n { provider: this.name, model: options.model },\n )\n\n try {\n for await (const raw of this.textAdapter.chatStream(\n this.buildTextOptions(options, systemPrompt),\n )) {\n for (const chunk of normalizeStreamChunk(raw as AdapterYieldChunk)) {\n // Surface failures: the underlying chatStream emits RUN_ERROR instead\n // of throwing, so without this branch summarize() would return an\n // empty summary and pretend a failed run succeeded.\n if (chunk.type === EventType.RUN_ERROR) throwRunError(chunk)\n consumeSpecSummarizeChunk(chunk, state)\n }\n }\n } catch (error: unknown) {\n // Narrow before logging: raw SDK errors can carry request metadata\n // (including auth headers) which we must never surface to user loggers.\n options.logger.errors(`${this.name}.summarize fatal`, {\n error: toRunErrorPayload(error, `${this.name}.summarize failed`),\n source: `${this.name}.summarize`,\n })\n throw error\n }\n\n return {\n id,\n model: state.model,\n summary: state.summary,\n usage: state.usage,\n }\n }\n\n override async *summarizeStream(\n options: SummarizationOptions<TProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n const systemPrompt = this.buildSummarizationPrompt(options)\n\n options.logger.request(\n `activity=summarizeStream provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? 'unset'}`,\n { provider: this.name, model: options.model },\n )\n\n const id = this.generateId()\n const state = {\n summary: '',\n model: options.model,\n usage: {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n } satisfies SummarizationResult['usage'],\n }\n\n try {\n for await (const raw of this.textAdapter.chatStream(\n this.buildTextOptions(options, systemPrompt),\n )) {\n for (const chunk of normalizeStreamChunk(raw as AdapterYieldChunk)) {\n // Accumulate the same way `summarize()` does so consumers see deltas\n // AND the terminal `generation:result` event below carries the same\n // final summary that non-streaming returns.\n consumeSpecSummarizeChunk(chunk, state)\n\n // Emit the GenerationClient-shaped result event just before the\n // terminal RUN_FINISHED so subscribers (useSummarize) populate\n // `result` before flipping `status` to success.\n if (chunk.type === EventType.RUN_FINISHED) {\n yield {\n type: EventType.CUSTOM,\n name: 'generation:result',\n value: {\n id,\n model: state.model,\n summary: state.summary,\n usage: state.usage,\n } satisfies SummarizationResult,\n timestamp: Date.now(),\n }\n }\n\n yield chunk\n }\n }\n } catch (error: unknown) {\n options.logger.errors(`${this.name}.summarizeStream fatal`, {\n error: toRunErrorPayload(error, `${this.name}.summarizeStream failed`),\n source: `${this.name}.summarizeStream`,\n })\n throw error\n }\n }\n\n /**\n * Build the TextOptions passed to the underlying chatStream. Provider\n * `modelOptions` from the summarize call are forwarded as-is so knobs like\n * Anthropic cache headers, Gemini safety settings, or Ollama tuning params\n * still reach the wire layer.\n */\n protected buildTextOptions(\n options: SummarizationOptions<TProviderOptions>,\n systemPrompt: string,\n ): TextOptions<TProviderOptions> {\n // Sampling knobs now live in provider-native `modelOptions`. Apply the\n // low-temperature default where the wrapped provider actually reads it\n // (nested under `options` for Ollama, flat otherwise) so callers can still\n // override it. Resolving the placement from this summarize adapter's OWN\n // `name` keeps the default off the wire correctly per provider — a flat\n // `temperature` would be silently dropped by Ollama while still showing up\n // in OTel.\n let working: Record<string, unknown> = {\n ...(options.modelOptions as Record<string, unknown> | undefined),\n }\n working = applyDefaultTemperature(this.name, 0.3, working)\n // `maxLength` must reach the wire under the provider-native token key (it\n // differs per provider, and no adapter reads a generic `maxTokens`).\n // Resolve it from this summarize adapter's `name` (the constructor arg,\n // not the wrapped text adapter's name), never overriding a caller-supplied\n // token limit.\n if (options.maxLength !== undefined) {\n if (!isKnownMaxTokensAdapter(this.name)) {\n options.logger.warn(\n `summarize: maxLength=${options.maxLength} could not be mapped to a provider token key for adapter name \"${this.name}\" — it was dropped from modelOptions (the prompt still asks the model to stay under it). Construct ChatStreamSummarizeAdapter with a recognised provider name to forward the cap.`,\n { provider: this.name },\n )\n }\n working = applyMaxLength(this.name, options.maxLength, working)\n }\n const modelOptions = working as TProviderOptions\n\n return {\n model: options.model,\n messages: [{ role: 'user', content: options.text }],\n systemPrompts: [systemPrompt],\n modelOptions,\n logger: options.logger,\n // Forward the run identity so the wrapped chat stamps it onto RUN_STARTED\n // (chat uses `runId` as its `runIdOverride`). Conditional spreads keep the\n // fields absent when unset, under `exactOptionalPropertyTypes`.\n ...(options.runId !== undefined ? { runId: options.runId } : {}),\n ...(options.threadId !== undefined ? { threadId: options.threadId } : {}),\n }\n }\n\n protected buildSummarizationPrompt(\n options: SummarizationOptions<TProviderOptions>,\n ): string {\n let prompt = 'You are a professional summarizer. '\n\n switch (options.style) {\n case 'bullet-points':\n prompt += 'Provide a summary in bullet point format. '\n break\n case 'paragraph':\n prompt += 'Provide a summary in paragraph format. '\n break\n case 'concise':\n prompt += 'Provide a very concise summary in 1-2 sentences. '\n break\n case undefined:\n prompt += 'Provide a clear and concise summary. '\n break\n default:\n prompt += 'Provide a clear and concise summary. '\n }\n\n if (options.focus && options.focus.length > 0) {\n prompt += `Focus on the following aspects: ${options.focus.join(', ')}. `\n }\n\n if (options.maxLength) {\n prompt += `Keep the summary under ${options.maxLength} tokens. `\n }\n\n return prompt\n }\n}\n"],"mappings":"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"}
@@ -15,3 +15,5 @@ export type { PendingInterruptResumeRecord } from './interrupt-resume.js';
15
15
  export { assertUniqueToolNames, DuplicateToolNameError, } from './activities/chat/tools/unique-tool-names.js';
16
16
  export { appendOutputSchemaInstruction, parseJsonFromAssistantText, } from './utilities/structured-output-text.js';
17
17
  export { structuredOutputCompleteChunk, structuredOutputStartChunk, } from './utilities/structured-output-events.js';
18
+ export { tanstackMetadata } from './utilities/merge-metadata.js';
19
+ export { isSpecTopLevelKey } from './utilities/spec-event-keys.js';
@@ -1,4 +1,6 @@
1
1
  import { toRunErrorPayload, toRunErrorRawEvent } from "./activities/error-payload.js";
2
+ import { tanstackMetadata } from "./utilities/merge-metadata.js";
3
+ import { isSpecTopLevelKey } from "./utilities/spec-event-keys.js";
2
4
  import { InternalLogger } from "./logger/internal-logger.js";
3
5
  import { resolveDebugOption } from "./logger/resolve.js";
4
6
  import { readInterruptBinding, validateInterruptResumeBatch } from "./interrupt-resume.js";
@@ -10,4 +12,4 @@ import { GenericInterruptDefinitionRegistryCapability, getGenericInterruptDefini
10
12
  import { PendingTurnCapability, getPendingTurn, providePendingTurn } from "./activities/chat/middleware/pending-turn.js";
11
13
  import { appendOutputSchemaInstruction, parseJsonFromAssistantText } from "./utilities/structured-output-text.js";
12
14
  import { structuredOutputCompleteChunk, structuredOutputStartChunk } from "./utilities/structured-output-events.js";
13
- export { DuplicateToolNameError, GenericInterruptDefinitionRegistryCapability, InternalLogger, PendingTurnCapability, RunDisconnectCapability, SandboxRuntimeCapability, appendOutputSchemaInstruction, assertUniqueToolNames, createInterruptBinding, getGenericInterruptDefinitionRegistry, getInterruptRequestInput, getPendingTurn, getRunDisconnect, getSandboxRuntime, parseJsonFromAssistantText, provideGenericInterruptDefinitionRegistry, providePendingTurn, provideRunDisconnect, provideSandboxRuntime, readInterruptBinding, rehydrateInterruptRequest, resolveDebugOption, structuredOutputCompleteChunk, structuredOutputStartChunk, toRunErrorPayload, toRunErrorRawEvent, validateInterruptResumeBatch };
15
+ export { DuplicateToolNameError, GenericInterruptDefinitionRegistryCapability, InternalLogger, PendingTurnCapability, RunDisconnectCapability, SandboxRuntimeCapability, appendOutputSchemaInstruction, assertUniqueToolNames, createInterruptBinding, getGenericInterruptDefinitionRegistry, getInterruptRequestInput, getPendingTurn, getRunDisconnect, getSandboxRuntime, isSpecTopLevelKey, parseJsonFromAssistantText, provideGenericInterruptDefinitionRegistry, providePendingTurn, provideRunDisconnect, provideSandboxRuntime, readInterruptBinding, rehydrateInterruptRequest, resolveDebugOption, structuredOutputCompleteChunk, structuredOutputStartChunk, tanstackMetadata, toRunErrorPayload, toRunErrorRawEvent, validateInterruptResumeBatch };
@@ -58,8 +58,15 @@ export { convertMessagesToModelMessages, generateMessageId, modelMessageToUIMess
58
58
  export { BatchStrategy, CompositeStrategy, defaultJSONParser, ImmediateStrategy, parsePartialJSON, PartialJSONParser, PunctuationStrategy, StreamProcessor, WordBoundaryStrategy, } from './activities/chat/stream/index.js';
59
59
  export type { ChunkRecording, ChunkStrategy, InternalToolCallState, JSONParser, ProcessorResult, ProcessorState, StreamProcessorEvents, StreamProcessorOptions, ToolCallState, ToolResultState, } from './activities/chat/stream/index.js';
60
60
  export { uiMessagesToWire } from './utilities/ag-ui-wire.js';
61
+ export { mergeMetadata, tanstackMetadata, withTanstackMetadata, } from './utilities/merge-metadata.js';
62
+ export { fromSpecTokenUsage, toSpecTokenUsage } from './utilities/ag-ui-usage.js';
63
+ export type { SpecTokenUsage } from './utilities/ag-ui-usage.js';
64
+ export { normalizeStreamChunk } from './utilities/normalize-stream-chunk.js';
65
+ export { restoreInboundChunk } from './utilities/restore-inbound-chunk.js';
66
+ export type { AdapterYieldChunk } from './utilities/adapter-yield-chunk.js';
67
+ export { getChunkRunId, getChunkThreadId } from './utilities/chunk-ids.js';
61
68
  export type { WireMessage } from './utilities/ag-ui-wire.js';
62
- export type { AudioPart, ContentPart, ContentPartDataSource, ContentPartSource, ContentPartUrlSource, CustomEvent, DocumentPart, ImagePart, MediaInputMetadata, MediaInputRole, MediaPrompt, MediaPromptPart, MessagePart, ModelMessage, PersistedArtifactActivity, PersistedArtifactRef, PersistedArtifactRole, Interrupt, RunAgentResumeItem, RunErrorEvent, RunFinishedEvent, RunFinishedOutcome, SchemaInput, StreamChunk, StructuredOutputPart, TextPart, ThinkingPart, ToolCall, ToolCallPart, ToolResultPart, UIMessage, UIResourcePart, VideoPart, InferSchemaType, } from './types.js';
69
+ export type { AudioPart, ContentPart, ContentPartDataSource, ContentPartSource, ContentPartUrlSource, CustomEvent, DocumentPart, ImagePart, MediaInputMetadata, MediaInputRole, MediaPrompt, MediaPromptPart, MessagePart, ModelMessage, PersistedArtifactActivity, PersistedArtifactRef, PersistedArtifactRole, Interrupt, RunAgentResumeItem, RunErrorEvent, RunFinishedEvent, RunFinishedOutcome, SchemaInput, StreamChunk, StructuredOutputPart, TextPart, TanStackMessageMetadata, TanStackRunMetadata, ThinkingPart, ToolCall, ToolCallPart, ToolResultPart, UIMessage, UIResourcePart, VideoPart, InferSchemaType, } from './types.js';
63
70
  export { INTERRUPT_BINDING_VERSION, canonicalizeInterruptResolutions, } from './interrupts.js';
64
71
  export { defineInterrupt, hashInterruptDefinitionSchema, INTERRUPT_PAYLOAD_METADATA_KEY, } from './interrupt-definition.js';
65
72
  export { INTERRUPT_CONTINUATION_METADATA_KEY, INTERRUPT_CONTINUATION_VERSION, genericInterruptContinuationFromDescriptor, readGenericInterruptContinuation, wrapGenericInterruptContinuation, } from './generic-interrupt-continuation.js';
@@ -1,3 +1,6 @@
1
+ import { fromSpecTokenUsage, toSpecTokenUsage } from "./utilities/ag-ui-usage.js";
2
+ import { mergeMetadata, tanstackMetadata, withTanstackMetadata } from "./utilities/merge-metadata.js";
3
+ import { normalizeStreamChunk } from "./utilities/normalize-stream-chunk.js";
1
4
  import { canonicalInterruptJson, cloneAndDeepFreezeJson, digestInterruptJson } from "./interrupt-serialization.js";
2
5
  import { INTERRUPT_BINDING_VERSION, canonicalizeInterruptResolutions } from "./interrupts.js";
3
6
  import { convertSchemaToJsonSchema, isStandardSchema, parseWithStandardSchema, validateWithStandardSchema } from "./activities/chat/tools/schema-converter.js";
@@ -5,12 +8,14 @@ import { hashSchemaInput, normalizeApprovalSchema } from "./activities/chat/tool
5
8
  import { INTERRUPT_BINDING_METADATA_KEY, readInterruptBinding, readUnopenedInterruptBinding, withInterruptBinding, withoutInterruptBinding } from "./interrupt-resume.js";
6
9
  import { INTERRUPT_PAYLOAD_METADATA_KEY, defineInterrupt, hashInterruptDefinitionSchema } from "./interrupt-definition.js";
7
10
  import { INTERRUPT_CONTINUATION_METADATA_KEY, INTERRUPT_CONTINUATION_VERSION, genericInterruptContinuationFromDescriptor, readGenericInterruptContinuation, wrapGenericInterruptContinuation } from "./generic-interrupt-continuation.js";
11
+ import { uiMessagesToWire } from "./utilities/ag-ui-wire.js";
12
+ import { restoreInboundChunk } from "./utilities/restore-inbound-chunk.js";
8
13
  import { convertMessagesToModelMessages, generateMessageId, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeToUIMessage, uiMessageToModelMessages } from "./activities/chat/messages.js";
9
14
  import { toolDefinition } from "./activities/chat/tools/tool-definition.js";
15
+ import { getChunkRunId, getChunkThreadId } from "./utilities/chunk-ids.js";
10
16
  import { PartialJSONParser, defaultJSONParser, parsePartialJSON } from "./activities/chat/stream/json-parser.js";
11
17
  import { BatchStrategy, CompositeStrategy, ImmediateStrategy, PunctuationStrategy, WordBoundaryStrategy } from "./activities/chat/stream/strategies.js";
12
18
  import { StreamProcessor } from "./activities/chat/stream/processor.js";
13
- import { uiMessagesToWire } from "./utilities/ag-ui-wire.js";
14
19
  //#region src/client.ts
15
20
  var generationKinds = [
16
21
  "image",
@@ -131,6 +136,6 @@ var EventType = /* @__PURE__ */ function(EventType) {
131
136
  return EventType;
132
137
  }({});
133
138
  //#endregion
134
- export { BatchStrategy, CompositeStrategy, EventType, INTERRUPT_BINDING_METADATA_KEY, INTERRUPT_BINDING_VERSION, INTERRUPT_CONTINUATION_METADATA_KEY, INTERRUPT_CONTINUATION_VERSION, INTERRUPT_PAYLOAD_METADATA_KEY, ImmediateStrategy, PartialJSONParser, PunctuationStrategy, StreamProcessor, WordBoundaryStrategy, canonicalInterruptJson, canonicalizeInterruptResolutions, cloneAndDeepFreezeJson, convertMessagesToModelMessages, convertSchemaToJsonSchema, defaultJSONParser, defineInterrupt, digestInterruptJson, generateMessageId, generationParamsFromBody, generationParamsFromRequest, genericInterruptContinuationFromDescriptor, hashInterruptDefinitionSchema, hashSchemaInput, isStandardSchema, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeApprovalSchema, normalizeToUIMessage, parsePartialJSON, parseWithStandardSchema, readGenericInterruptContinuation, readInterruptBinding, readUnopenedInterruptBinding, toolDefinition, uiMessageToModelMessages, uiMessagesToWire, validateWithStandardSchema, withInterruptBinding, withoutInterruptBinding, wrapGenericInterruptContinuation };
139
+ export { BatchStrategy, CompositeStrategy, EventType, INTERRUPT_BINDING_METADATA_KEY, INTERRUPT_BINDING_VERSION, INTERRUPT_CONTINUATION_METADATA_KEY, INTERRUPT_CONTINUATION_VERSION, INTERRUPT_PAYLOAD_METADATA_KEY, ImmediateStrategy, PartialJSONParser, PunctuationStrategy, StreamProcessor, WordBoundaryStrategy, canonicalInterruptJson, canonicalizeInterruptResolutions, cloneAndDeepFreezeJson, convertMessagesToModelMessages, convertSchemaToJsonSchema, defaultJSONParser, defineInterrupt, digestInterruptJson, fromSpecTokenUsage, generateMessageId, generationParamsFromBody, generationParamsFromRequest, genericInterruptContinuationFromDescriptor, getChunkRunId, getChunkThreadId, hashInterruptDefinitionSchema, hashSchemaInput, isStandardSchema, mergeMetadata, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeApprovalSchema, normalizeStreamChunk, normalizeToUIMessage, parsePartialJSON, parseWithStandardSchema, readGenericInterruptContinuation, readInterruptBinding, readUnopenedInterruptBinding, restoreInboundChunk, tanstackMetadata, toSpecTokenUsage, toolDefinition, uiMessageToModelMessages, uiMessagesToWire, validateWithStandardSchema, withInterruptBinding, withTanstackMetadata, withoutInterruptBinding, wrapGenericInterruptContinuation };
135
140
 
136
141
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":[],"sources":["../../src/client.ts"],"sourcesContent":["import type {\n AudioGenerationOptions,\n ImageGenerationOptions,\n TTSOptions,\n TranscriptionOptions,\n VideoGenerationOptions,\n} from './types'\n\nexport type GenerationKind =\n | 'image'\n | 'audio'\n | 'tts'\n | 'video'\n | 'transcription'\n\ntype GenerationInputByKind = {\n image: Omit<ImageGenerationOptions, 'logger' | 'model'>\n audio: Omit<AudioGenerationOptions, 'logger' | 'model'>\n tts: Omit<TTSOptions, 'logger' | 'model'>\n video: Omit<VideoGenerationOptions, 'logger' | 'model'>\n transcription: Omit<TranscriptionOptions, 'logger' | 'model'>\n}\n\nexport interface GenerationParams<TKind extends GenerationKind> {\n input: GenerationInputByKind[TKind]\n forwardedProps: Record<string, unknown>\n threadId?: string\n runId?: string\n}\n\nconst generationKinds = [\n 'image',\n 'audio',\n 'tts',\n 'video',\n 'transcription',\n] as const satisfies ReadonlyArray<GenerationKind>\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction hasOwnKey(value: Record<string, unknown>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(value, key)\n}\n\nfunction isGenerationEnvelope(body: unknown): body is Record<string, unknown> {\n return (\n isRecord(body) &&\n (hasOwnKey(body, 'data') || hasOwnKey(body, 'forwardedProps'))\n )\n}\n\nfunction assertGenerationKind(kind: unknown): asserts kind is GenerationKind {\n if (!generationKinds.includes(kind as GenerationKind)) {\n throw new Error(\n `Unsupported generation kind: ${String(\n kind,\n )}. Expected one of ${generationKinds.join(', ')}.`,\n )\n }\n}\n\nfunction assertInputForKind(\n kind: GenerationKind,\n input: unknown,\n): asserts input is GenerationInputByKind[GenerationKind] {\n if (!isRecord(input)) {\n throw new Error(`Generation ${kind} input must be an object.`)\n }\n\n const requiredKey =\n kind === 'tts' ? 'text' : kind === 'transcription' ? 'audio' : 'prompt'\n\n if (!hasOwnKey(input, requiredKey)) {\n throw new Error(`Generation ${kind} input must include ${requiredKey}.`)\n }\n}\n\nfunction isInputForKind(kind: GenerationKind, input: unknown): boolean {\n if (!isRecord(input)) return false\n\n const requiredKey =\n kind === 'tts' ? 'text' : kind === 'transcription' ? 'audio' : 'prompt'\n\n return hasOwnKey(input, requiredKey)\n}\n\nfunction forwardedPropsFromEnvelope(\n envelope: Record<string, unknown>,\n): Record<string, unknown> {\n if (!hasOwnKey(envelope, 'forwardedProps')) {\n return {}\n }\n\n if (!isRecord(envelope.forwardedProps)) {\n throw new Error('Generation envelope forwardedProps must be an object.')\n }\n\n return envelope.forwardedProps\n}\n\nfunction optionalStringField(\n envelope: Record<string, unknown>,\n key: 'threadId' | 'runId',\n): string | undefined {\n if (!hasOwnKey(envelope, key)) {\n return undefined\n }\n\n const value = envelope[key]\n if (typeof value !== 'string') {\n throw new Error(`Generation envelope ${key} must be a string.`)\n }\n\n return value\n}\n\nfunction generationIdentityFields(envelope: Record<string, unknown>): {\n threadId?: string\n runId?: string\n} {\n const identity: {\n threadId?: string\n runId?: string\n } = {}\n const threadId = optionalStringField(envelope, 'threadId')\n const runId = optionalStringField(envelope, 'runId')\n\n if (threadId !== undefined) identity.threadId = threadId\n if (runId !== undefined) identity.runId = runId\n\n return identity\n}\n\nexport function generationParamsFromBody<TKind extends GenerationKind>(\n kind: TKind,\n body: unknown,\n): GenerationParams<TKind> {\n assertGenerationKind(kind)\n\n if (isInputForKind(kind, body)) {\n assertInputForKind(kind, body)\n return {\n input: body as GenerationInputByKind[TKind],\n forwardedProps: {},\n }\n }\n\n if (!isGenerationEnvelope(body)) {\n assertInputForKind(kind, body)\n return {\n input: body as GenerationInputByKind[TKind],\n forwardedProps: {},\n }\n }\n\n if (!hasOwnKey(body, 'data')) {\n throw new Error(`Generation ${kind} envelope must include data.`)\n }\n\n const input = body.data\n assertInputForKind(kind, input)\n\n const forwardedProps = forwardedPropsFromEnvelope(body)\n\n return {\n input: input as GenerationInputByKind[TKind],\n forwardedProps,\n ...generationIdentityFields(body),\n }\n}\n\nexport async function generationParamsFromRequest<TKind extends GenerationKind>(\n kind: TKind,\n request: Request,\n): Promise<GenerationParams<TKind>> {\n let body: unknown\n try {\n body = await request.json()\n } catch (error) {\n throw new Error('Invalid JSON request body.', { cause: error })\n }\n\n if (!isRecord(body)) {\n throw new Error('Generation request body must be a JSON object.')\n }\n\n return generationParamsFromBody(kind, body)\n}\n\nexport enum EventType {\n TEXT_MESSAGE_START = 'TEXT_MESSAGE_START',\n TEXT_MESSAGE_CONTENT = 'TEXT_MESSAGE_CONTENT',\n TEXT_MESSAGE_END = 'TEXT_MESSAGE_END',\n TEXT_MESSAGE_CHUNK = 'TEXT_MESSAGE_CHUNK',\n TOOL_CALL_START = 'TOOL_CALL_START',\n TOOL_CALL_ARGS = 'TOOL_CALL_ARGS',\n TOOL_CALL_END = 'TOOL_CALL_END',\n TOOL_CALL_CHUNK = 'TOOL_CALL_CHUNK',\n TOOL_CALL_RESULT = 'TOOL_CALL_RESULT',\n THINKING_START = 'THINKING_START',\n THINKING_END = 'THINKING_END',\n THINKING_TEXT_MESSAGE_START = 'THINKING_TEXT_MESSAGE_START',\n THINKING_TEXT_MESSAGE_CONTENT = 'THINKING_TEXT_MESSAGE_CONTENT',\n THINKING_TEXT_MESSAGE_END = 'THINKING_TEXT_MESSAGE_END',\n STATE_SNAPSHOT = 'STATE_SNAPSHOT',\n STATE_DELTA = 'STATE_DELTA',\n MESSAGES_SNAPSHOT = 'MESSAGES_SNAPSHOT',\n ACTIVITY_SNAPSHOT = 'ACTIVITY_SNAPSHOT',\n ACTIVITY_DELTA = 'ACTIVITY_DELTA',\n RAW = 'RAW',\n CUSTOM = 'CUSTOM',\n RUN_STARTED = 'RUN_STARTED',\n RUN_FINISHED = 'RUN_FINISHED',\n RUN_ERROR = 'RUN_ERROR',\n STEP_STARTED = 'STEP_STARTED',\n STEP_FINISHED = 'STEP_FINISHED',\n REASONING_START = 'REASONING_START',\n REASONING_MESSAGE_START = 'REASONING_MESSAGE_START',\n REASONING_MESSAGE_CONTENT = 'REASONING_MESSAGE_CONTENT',\n REASONING_MESSAGE_END = 'REASONING_MESSAGE_END',\n REASONING_MESSAGE_CHUNK = 'REASONING_MESSAGE_CHUNK',\n REASONING_END = 'REASONING_END',\n REASONING_ENCRYPTED_VALUE = 'REASONING_ENCRYPTED_VALUE',\n}\n\nexport {\n toolDefinition,\n type AnyClientTool,\n type ClientTool,\n type InferToolInput,\n type InferToolName,\n type InferToolOutput,\n type ApprovalCapabilityOf,\n type ApprovalSchemaConfig,\n type ApprovalSchemaOf,\n type InputSchemaOf,\n type OutputSchemaOf,\n type NoSchema,\n type ToolDefinition,\n type ToolDefinitionConfig,\n type ToolDefinitionInstance,\n} from './activities/chat/tools/tool-definition'\n\nexport {\n hashSchemaInput,\n normalizeApprovalSchema,\n type NormalizedApprovalSchema,\n type NormalizedSchemaInput,\n} from './activities/chat/tools/approval-schema'\n\nexport {\n canonicalInterruptJson,\n cloneAndDeepFreezeJson,\n digestInterruptJson,\n} from './interrupt-serialization'\n\nexport {\n convertSchemaToJsonSchema,\n isStandardSchema,\n parseWithStandardSchema,\n validateWithStandardSchema,\n} from './activities/chat/tools/schema-converter'\n\nexport {\n convertMessagesToModelMessages,\n generateMessageId,\n modelMessageToUIMessage,\n modelMessagesToUIMessages,\n normalizeToUIMessage,\n uiMessageToModelMessages,\n} from './activities/chat/messages'\n\nexport {\n BatchStrategy,\n CompositeStrategy,\n defaultJSONParser,\n ImmediateStrategy,\n parsePartialJSON,\n PartialJSONParser,\n PunctuationStrategy,\n StreamProcessor,\n WordBoundaryStrategy,\n} from './activities/chat/stream/index'\nexport type {\n ChunkRecording,\n ChunkStrategy,\n InternalToolCallState,\n JSONParser,\n ProcessorResult,\n ProcessorState,\n StreamProcessorEvents,\n StreamProcessorOptions,\n ToolCallState,\n ToolResultState,\n} from './activities/chat/stream/index'\n\nexport { uiMessagesToWire } from './utilities/ag-ui-wire'\nexport type { WireMessage } from './utilities/ag-ui-wire'\n\nexport type {\n AudioPart,\n ContentPart,\n ContentPartDataSource,\n ContentPartSource,\n ContentPartUrlSource,\n CustomEvent,\n DocumentPart,\n ImagePart,\n MediaInputMetadata,\n MediaInputRole,\n MediaPrompt,\n MediaPromptPart,\n MessagePart,\n ModelMessage,\n PersistedArtifactActivity,\n PersistedArtifactRef,\n PersistedArtifactRole,\n Interrupt,\n RunAgentResumeItem,\n RunErrorEvent,\n RunFinishedEvent,\n RunFinishedOutcome,\n SchemaInput,\n StreamChunk,\n StructuredOutputPart,\n TextPart,\n ThinkingPart,\n ToolCall,\n ToolCallPart,\n ToolResultPart,\n UIMessage,\n UIResourcePart,\n VideoPart,\n InferSchemaType,\n} from './types'\n\n// Enumerated, not `export *` — see the matching note in `index.ts`. The\n// interrupt protocol surface is a commitment, so it is published field by\n// field.\nexport {\n INTERRUPT_BINDING_VERSION,\n canonicalizeInterruptResolutions,\n} from './interrupts'\nexport {\n defineInterrupt,\n hashInterruptDefinitionSchema,\n INTERRUPT_PAYLOAD_METADATA_KEY,\n} from './interrupt-definition'\nexport {\n INTERRUPT_CONTINUATION_METADATA_KEY,\n INTERRUPT_CONTINUATION_VERSION,\n genericInterruptContinuationFromDescriptor,\n readGenericInterruptContinuation,\n wrapGenericInterruptContinuation,\n} from './generic-interrupt-continuation'\nexport type {\n GenericInterruptContinuation,\n GenericInterruptContinuationReadResult,\n} from './generic-interrupt-continuation'\nexport type {\n GenericInterruptRequest,\n InterruptDefinition,\n} from './interrupt-definition'\nexport type {\n BatchInterruptError,\n BatchInterruptErrorCode,\n InterruptBinding,\n InterruptCorrelation,\n InterruptSubmissionError,\n ItemInterruptError,\n ItemInterruptErrorCode,\n ToolApprovalResolution,\n UnopenedInterruptBinding,\n} from './interrupts'\n\nexport {\n INTERRUPT_BINDING_METADATA_KEY,\n readInterruptBinding,\n readUnopenedInterruptBinding,\n withInterruptBinding,\n withoutInterruptBinding,\n} from './interrupt-resume'\n\nexport type {\n AudioVisualization,\n RealtimeAdapter,\n RealtimeConnection,\n RealtimeError,\n RealtimeErrorCode,\n RealtimeEvent,\n RealtimeEventHandler,\n RealtimeEventPayloads,\n RealtimeMessage,\n RealtimeMessagePart,\n RealtimeMode,\n RealtimeSessionConfig,\n RealtimeStatus,\n RealtimeToken,\n RealtimeAudioPart,\n RealtimeImagePart,\n RealtimeTextPart,\n RealtimeToolCallPart,\n RealtimeToolResultPart,\n VADConfig,\n} from './realtime/types'\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":[],"sources":["../../src/client.ts"],"sourcesContent":["import type {\n AudioGenerationOptions,\n ImageGenerationOptions,\n TTSOptions,\n TranscriptionOptions,\n VideoGenerationOptions,\n} from './types'\n\nexport type GenerationKind =\n | 'image'\n | 'audio'\n | 'tts'\n | 'video'\n | 'transcription'\n\ntype GenerationInputByKind = {\n image: Omit<ImageGenerationOptions, 'logger' | 'model'>\n audio: Omit<AudioGenerationOptions, 'logger' | 'model'>\n tts: Omit<TTSOptions, 'logger' | 'model'>\n video: Omit<VideoGenerationOptions, 'logger' | 'model'>\n transcription: Omit<TranscriptionOptions, 'logger' | 'model'>\n}\n\nexport interface GenerationParams<TKind extends GenerationKind> {\n input: GenerationInputByKind[TKind]\n forwardedProps: Record<string, unknown>\n threadId?: string\n runId?: string\n}\n\nconst generationKinds = [\n 'image',\n 'audio',\n 'tts',\n 'video',\n 'transcription',\n] as const satisfies ReadonlyArray<GenerationKind>\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction hasOwnKey(value: Record<string, unknown>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(value, key)\n}\n\nfunction isGenerationEnvelope(body: unknown): body is Record<string, unknown> {\n return (\n isRecord(body) &&\n (hasOwnKey(body, 'data') || hasOwnKey(body, 'forwardedProps'))\n )\n}\n\nfunction assertGenerationKind(kind: unknown): asserts kind is GenerationKind {\n if (!generationKinds.includes(kind as GenerationKind)) {\n throw new Error(\n `Unsupported generation kind: ${String(\n kind,\n )}. Expected one of ${generationKinds.join(', ')}.`,\n )\n }\n}\n\nfunction assertInputForKind(\n kind: GenerationKind,\n input: unknown,\n): asserts input is GenerationInputByKind[GenerationKind] {\n if (!isRecord(input)) {\n throw new Error(`Generation ${kind} input must be an object.`)\n }\n\n const requiredKey =\n kind === 'tts' ? 'text' : kind === 'transcription' ? 'audio' : 'prompt'\n\n if (!hasOwnKey(input, requiredKey)) {\n throw new Error(`Generation ${kind} input must include ${requiredKey}.`)\n }\n}\n\nfunction isInputForKind(kind: GenerationKind, input: unknown): boolean {\n if (!isRecord(input)) return false\n\n const requiredKey =\n kind === 'tts' ? 'text' : kind === 'transcription' ? 'audio' : 'prompt'\n\n return hasOwnKey(input, requiredKey)\n}\n\nfunction forwardedPropsFromEnvelope(\n envelope: Record<string, unknown>,\n): Record<string, unknown> {\n if (!hasOwnKey(envelope, 'forwardedProps')) {\n return {}\n }\n\n if (!isRecord(envelope.forwardedProps)) {\n throw new Error('Generation envelope forwardedProps must be an object.')\n }\n\n return envelope.forwardedProps\n}\n\nfunction optionalStringField(\n envelope: Record<string, unknown>,\n key: 'threadId' | 'runId',\n): string | undefined {\n if (!hasOwnKey(envelope, key)) {\n return undefined\n }\n\n const value = envelope[key]\n if (typeof value !== 'string') {\n throw new Error(`Generation envelope ${key} must be a string.`)\n }\n\n return value\n}\n\nfunction generationIdentityFields(envelope: Record<string, unknown>): {\n threadId?: string\n runId?: string\n} {\n const identity: {\n threadId?: string\n runId?: string\n } = {}\n const threadId = optionalStringField(envelope, 'threadId')\n const runId = optionalStringField(envelope, 'runId')\n\n if (threadId !== undefined) identity.threadId = threadId\n if (runId !== undefined) identity.runId = runId\n\n return identity\n}\n\nexport function generationParamsFromBody<TKind extends GenerationKind>(\n kind: TKind,\n body: unknown,\n): GenerationParams<TKind> {\n assertGenerationKind(kind)\n\n if (isInputForKind(kind, body)) {\n assertInputForKind(kind, body)\n return {\n input: body as GenerationInputByKind[TKind],\n forwardedProps: {},\n }\n }\n\n if (!isGenerationEnvelope(body)) {\n assertInputForKind(kind, body)\n return {\n input: body as GenerationInputByKind[TKind],\n forwardedProps: {},\n }\n }\n\n if (!hasOwnKey(body, 'data')) {\n throw new Error(`Generation ${kind} envelope must include data.`)\n }\n\n const input = body.data\n assertInputForKind(kind, input)\n\n const forwardedProps = forwardedPropsFromEnvelope(body)\n\n return {\n input: input as GenerationInputByKind[TKind],\n forwardedProps,\n ...generationIdentityFields(body),\n }\n}\n\nexport async function generationParamsFromRequest<TKind extends GenerationKind>(\n kind: TKind,\n request: Request,\n): Promise<GenerationParams<TKind>> {\n let body: unknown\n try {\n body = await request.json()\n } catch (error) {\n throw new Error('Invalid JSON request body.', { cause: error })\n }\n\n if (!isRecord(body)) {\n throw new Error('Generation request body must be a JSON object.')\n }\n\n return generationParamsFromBody(kind, body)\n}\n\nexport enum EventType {\n TEXT_MESSAGE_START = 'TEXT_MESSAGE_START',\n TEXT_MESSAGE_CONTENT = 'TEXT_MESSAGE_CONTENT',\n TEXT_MESSAGE_END = 'TEXT_MESSAGE_END',\n TEXT_MESSAGE_CHUNK = 'TEXT_MESSAGE_CHUNK',\n TOOL_CALL_START = 'TOOL_CALL_START',\n TOOL_CALL_ARGS = 'TOOL_CALL_ARGS',\n TOOL_CALL_END = 'TOOL_CALL_END',\n TOOL_CALL_CHUNK = 'TOOL_CALL_CHUNK',\n TOOL_CALL_RESULT = 'TOOL_CALL_RESULT',\n THINKING_START = 'THINKING_START',\n THINKING_END = 'THINKING_END',\n THINKING_TEXT_MESSAGE_START = 'THINKING_TEXT_MESSAGE_START',\n THINKING_TEXT_MESSAGE_CONTENT = 'THINKING_TEXT_MESSAGE_CONTENT',\n THINKING_TEXT_MESSAGE_END = 'THINKING_TEXT_MESSAGE_END',\n STATE_SNAPSHOT = 'STATE_SNAPSHOT',\n STATE_DELTA = 'STATE_DELTA',\n MESSAGES_SNAPSHOT = 'MESSAGES_SNAPSHOT',\n ACTIVITY_SNAPSHOT = 'ACTIVITY_SNAPSHOT',\n ACTIVITY_DELTA = 'ACTIVITY_DELTA',\n RAW = 'RAW',\n CUSTOM = 'CUSTOM',\n RUN_STARTED = 'RUN_STARTED',\n RUN_FINISHED = 'RUN_FINISHED',\n RUN_ERROR = 'RUN_ERROR',\n STEP_STARTED = 'STEP_STARTED',\n STEP_FINISHED = 'STEP_FINISHED',\n REASONING_START = 'REASONING_START',\n REASONING_MESSAGE_START = 'REASONING_MESSAGE_START',\n REASONING_MESSAGE_CONTENT = 'REASONING_MESSAGE_CONTENT',\n REASONING_MESSAGE_END = 'REASONING_MESSAGE_END',\n REASONING_MESSAGE_CHUNK = 'REASONING_MESSAGE_CHUNK',\n REASONING_END = 'REASONING_END',\n REASONING_ENCRYPTED_VALUE = 'REASONING_ENCRYPTED_VALUE',\n}\n\nexport {\n toolDefinition,\n type AnyClientTool,\n type ClientTool,\n type InferToolInput,\n type InferToolName,\n type InferToolOutput,\n type ApprovalCapabilityOf,\n type ApprovalSchemaConfig,\n type ApprovalSchemaOf,\n type InputSchemaOf,\n type OutputSchemaOf,\n type NoSchema,\n type ToolDefinition,\n type ToolDefinitionConfig,\n type ToolDefinitionInstance,\n} from './activities/chat/tools/tool-definition'\n\nexport {\n hashSchemaInput,\n normalizeApprovalSchema,\n type NormalizedApprovalSchema,\n type NormalizedSchemaInput,\n} from './activities/chat/tools/approval-schema'\n\nexport {\n canonicalInterruptJson,\n cloneAndDeepFreezeJson,\n digestInterruptJson,\n} from './interrupt-serialization'\n\nexport {\n convertSchemaToJsonSchema,\n isStandardSchema,\n parseWithStandardSchema,\n validateWithStandardSchema,\n} from './activities/chat/tools/schema-converter'\n\nexport {\n convertMessagesToModelMessages,\n generateMessageId,\n modelMessageToUIMessage,\n modelMessagesToUIMessages,\n normalizeToUIMessage,\n uiMessageToModelMessages,\n} from './activities/chat/messages'\n\nexport {\n BatchStrategy,\n CompositeStrategy,\n defaultJSONParser,\n ImmediateStrategy,\n parsePartialJSON,\n PartialJSONParser,\n PunctuationStrategy,\n StreamProcessor,\n WordBoundaryStrategy,\n} from './activities/chat/stream/index'\nexport type {\n ChunkRecording,\n ChunkStrategy,\n InternalToolCallState,\n JSONParser,\n ProcessorResult,\n ProcessorState,\n StreamProcessorEvents,\n StreamProcessorOptions,\n ToolCallState,\n ToolResultState,\n} from './activities/chat/stream/index'\n\nexport { uiMessagesToWire } from './utilities/ag-ui-wire'\nexport {\n mergeMetadata,\n tanstackMetadata,\n withTanstackMetadata,\n} from './utilities/merge-metadata'\nexport { fromSpecTokenUsage, toSpecTokenUsage } from './utilities/ag-ui-usage'\nexport type { SpecTokenUsage } from './utilities/ag-ui-usage'\nexport { normalizeStreamChunk } from './utilities/normalize-stream-chunk'\nexport { restoreInboundChunk } from './utilities/restore-inbound-chunk'\nexport type { AdapterYieldChunk } from './utilities/adapter-yield-chunk'\nexport { getChunkRunId, getChunkThreadId } from './utilities/chunk-ids'\nexport type { WireMessage } from './utilities/ag-ui-wire'\n\nexport type {\n AudioPart,\n ContentPart,\n ContentPartDataSource,\n ContentPartSource,\n ContentPartUrlSource,\n CustomEvent,\n DocumentPart,\n ImagePart,\n MediaInputMetadata,\n MediaInputRole,\n MediaPrompt,\n MediaPromptPart,\n MessagePart,\n ModelMessage,\n PersistedArtifactActivity,\n PersistedArtifactRef,\n PersistedArtifactRole,\n Interrupt,\n RunAgentResumeItem,\n RunErrorEvent,\n RunFinishedEvent,\n RunFinishedOutcome,\n SchemaInput,\n StreamChunk,\n StructuredOutputPart,\n TextPart,\n TanStackMessageMetadata,\n TanStackRunMetadata,\n ThinkingPart,\n ToolCall,\n ToolCallPart,\n ToolResultPart,\n UIMessage,\n UIResourcePart,\n VideoPart,\n InferSchemaType,\n} from './types'\n\n// Enumerated, not `export *` — see the matching note in `index.ts`. The\n// interrupt protocol surface is a commitment, so it is published field by\n// field.\nexport {\n INTERRUPT_BINDING_VERSION,\n canonicalizeInterruptResolutions,\n} from './interrupts'\nexport {\n defineInterrupt,\n hashInterruptDefinitionSchema,\n INTERRUPT_PAYLOAD_METADATA_KEY,\n} from './interrupt-definition'\nexport {\n INTERRUPT_CONTINUATION_METADATA_KEY,\n INTERRUPT_CONTINUATION_VERSION,\n genericInterruptContinuationFromDescriptor,\n readGenericInterruptContinuation,\n wrapGenericInterruptContinuation,\n} from './generic-interrupt-continuation'\nexport type {\n GenericInterruptContinuation,\n GenericInterruptContinuationReadResult,\n} from './generic-interrupt-continuation'\nexport type {\n GenericInterruptRequest,\n InterruptDefinition,\n} from './interrupt-definition'\nexport type {\n BatchInterruptError,\n BatchInterruptErrorCode,\n InterruptBinding,\n InterruptCorrelation,\n InterruptSubmissionError,\n ItemInterruptError,\n ItemInterruptErrorCode,\n ToolApprovalResolution,\n UnopenedInterruptBinding,\n} from './interrupts'\n\nexport {\n INTERRUPT_BINDING_METADATA_KEY,\n readInterruptBinding,\n readUnopenedInterruptBinding,\n withInterruptBinding,\n withoutInterruptBinding,\n} from './interrupt-resume'\n\nexport type {\n AudioVisualization,\n RealtimeAdapter,\n RealtimeConnection,\n RealtimeError,\n RealtimeErrorCode,\n RealtimeEvent,\n RealtimeEventHandler,\n RealtimeEventPayloads,\n RealtimeMessage,\n RealtimeMessagePart,\n RealtimeMode,\n RealtimeSessionConfig,\n RealtimeStatus,\n RealtimeToken,\n RealtimeAudioPart,\n RealtimeImagePart,\n RealtimeTextPart,\n RealtimeToolCallPart,\n RealtimeToolResultPart,\n VADConfig,\n} from './realtime/types'\n"],"mappings":"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"}
@@ -68,6 +68,12 @@ export { chatParamsFromRequest, chatParamsFromRequestBody, mergeAgentTools, } fr
68
68
  export type { ClientToolDeclaration, MergedAgentTools, } from './utilities/chat-params.js';
69
69
  export { generationParamsFromBody, generationParamsFromRequest } from './client.js';
70
70
  export { uiMessagesToWire } from './utilities/ag-ui-wire.js';
71
+ export { mergeMetadata, withTanstackMetadata } from './utilities/merge-metadata.js';
72
+ export { fromSpecTokenUsage, toSpecTokenUsage } from './utilities/ag-ui-usage.js';
73
+ export type { SpecTokenUsage } from './utilities/ag-ui-usage.js';
74
+ export { normalizeStreamChunk } from './utilities/normalize-stream-chunk.js';
75
+ export type { AdapterYieldChunk } from './utilities/adapter-yield-chunk.js';
76
+ export { getChunkRunId, getChunkThreadId } from './utilities/chunk-ids.js';
71
77
  export type { WireMessage } from './utilities/ag-ui-wire.js';
72
78
  export { isContentPart, isContentPartArray, normalizeToolResult, } from './utilities/tool-result.js';
73
79
  export { getProviderExecutedMetadata, isProviderExecutedToolCall, } from './utilities/provider-executed.js';
package/dist/esm/index.js CHANGED
@@ -3,6 +3,9 @@ import { createCapability } from "./activities/chat/middleware/capabilities.js";
3
3
  import { DetachableRunCapability, InMemoryRunStore, RunDetachedCapability, defineRunStore, getDetachableRun, getRunDetached, isRunStatus, isTerminalRunStatus, provideDetachableRun, provideRunDetached } from "./activities/chat/middleware/run-store.js";
4
4
  import { memoryStream, replayRunStream, resolveResumeRunId } from "./stream-durability.js";
5
5
  import { EventType } from "./types.js";
6
+ import { fromSpecTokenUsage, toSpecTokenUsage } from "./utilities/ag-ui-usage.js";
7
+ import { mergeMetadata, withTanstackMetadata } from "./utilities/merge-metadata.js";
8
+ import { normalizeStreamChunk } from "./utilities/normalize-stream-chunk.js";
6
9
  import { ConsoleLogger } from "./logger/console-logger.js";
7
10
  import { RUN_ACCEPTED_EVENT, resumeHttpResponse, resumeServerSentEventsResponse, streamToText, toHttpResponse, toHttpStream, toServerSentEventsResponse, toServerSentEventsStream } from "./stream-to-response.js";
8
11
  import { canonicalInterruptJson, cloneAndDeepFreezeJson, digestInterruptJson } from "./interrupt-serialization.js";
@@ -12,6 +15,7 @@ import { hashSchemaInput, normalizeApprovalSchema } from "./activities/chat/tool
12
15
  import { INTERRUPT_BINDING_METADATA_KEY, InterruptResumeValidationError, interruptItemError, readInterruptBinding, readUnopenedInterruptBinding, validateInterruptResumeBatch, withInterruptBinding, withoutInterruptBinding } from "./interrupt-resume.js";
13
16
  import { INTERRUPT_PAYLOAD_METADATA_KEY, createInterruptBinding, defineInterrupt } from "./interrupt-definition.js";
14
17
  import { INTERRUPT_CONTINUATION_METADATA_KEY, INTERRUPT_CONTINUATION_VERSION, genericInterruptContinuationFromDescriptor, readGenericInterruptContinuation, wrapGenericInterruptContinuation } from "./generic-interrupt-continuation.js";
18
+ import { uiMessagesToWire } from "./utilities/ag-ui-wire.js";
15
19
  import { isContentPart, isContentPartArray, normalizeToolResult } from "./utilities/tool-result.js";
16
20
  import { getProviderExecutedMetadata, isProviderExecutedToolCall } from "./utilities/provider-executed.js";
17
21
  import { firstSentence, renderLazyCatalogEntry } from "./activities/chat/tools/lazy-tools.js";
@@ -47,10 +51,10 @@ import { normalizeSystemPrompts } from "./system-prompts.js";
47
51
  import { detectImageMimeType } from "./utils.js";
48
52
  import { createRealtimeEventEmitter } from "./realtime/event-emitter.js";
49
53
  import { realtimeToken } from "./realtime/index.js";
54
+ import { getChunkRunId, getChunkThreadId } from "./utilities/chunk-ids.js";
50
55
  import { PartialJSONParser, defaultJSONParser, parsePartialJSON } from "./activities/chat/stream/json-parser.js";
51
56
  import { BatchStrategy, CompositeStrategy, ImmediateStrategy, PunctuationStrategy, WordBoundaryStrategy } from "./activities/chat/stream/strategies.js";
52
57
  import { StreamProcessor, createReplayStream } from "./activities/chat/stream/processor.js";
53
- import { uiMessagesToWire } from "./utilities/ag-ui-wire.js";
54
58
  import { generationParamsFromBody, generationParamsFromRequest } from "./client.js";
55
59
  import { createModel, extendAdapter } from "./extend-adapter.js";
56
- export { BaseRerankAdapter, BatchStrategy, CUSTOM_EVENT, CompositeStrategy, ConsoleLogger, DISCOVERY_TOOL_NAME, DetachableRunCapability, DuplicateToolNameError, EventType, INTERRUPT_BINDING_METADATA_KEY, INTERRUPT_BINDING_VERSION, INTERRUPT_BOUNDARY_PHASES, INTERRUPT_CONTINUATION_METADATA_KEY, INTERRUPT_CONTINUATION_VERSION, INTERRUPT_PAYLOAD_METADATA_KEY, INTERRUPT_TOOL_RESUMES, ImmediateStrategy, InMemoryRunStore, InterruptResumeValidationError, MCPDuplicateToolNameError, PartialJSONParser, PunctuationStrategy, RUN_ACCEPTED_EVENT, RUN_CANCEL_REASON, RunDetachedCapability, StandardSchemaValidationError, StreamProcessor, ToolCallManager, WordBoundaryStrategy, brandProviderTool, buildBaseUsage, canonicalInterruptJson, canonicalizeInterruptResolutions, chat, chatParamsFromRequest, chatParamsFromRequestBody, cloneAndDeepFreezeJson, combineStrategies, convertMessagesToModelMessages, convertSchemaToJsonSchema, countEmbeddingInputModalities, createAudioOptions, createCapability, createChatMiddleware, createChatOptions, createEmbedOptions, createFrozenRegistry, createImageOptions, createInterruptBinding, createModel, createRealtimeEventEmitter, createReplayStream, createRerankOptions, createSpeechOptions, createSummarizeOptions, createToolRegistry, createTranscriptionOptions, createVideoOptions, decodeWsFrame, defaultJSONParser, defineChatMiddleware, defineInterrupt, defineRunStore, detectImageMimeType, digestInterruptJson, embed, encodeWsFrame, extendAdapter, firstSentence, generateAudio, generateImage, generateMessageId, generateSpeech, generateTranscription, generateVideo, generationParamsFromBody, generationParamsFromRequest, genericInterruptContinuationFromDescriptor, getDetachableRun, getProviderExecutedMetadata, getRunDetached, getVideoJobStatus, hashSchemaInput, interruptItemError, isCancelRequestedReason, isContentPart, isContentPartArray, isCustomEvent, isProviderExecutedToolCall, isRunStatus, isStandardSchema, isTerminalRunStatus, maxIterations, memoryStream, mergeAgentTools, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeApprovalSchema, normalizeSystemPrompts, normalizeToUIMessage, normalizeToolResult, parsePartialJSON, parseWithStandardSchema, provideDetachableRun, provideRunDetached, readGenericInterruptContinuation, readInterruptBinding, readUnopenedInterruptBinding, realtimeToken, renderLazyCatalogEntry, replayRunStream, requestRunCancel, requireTextOnlyEmbeddingInput, rerank, resolveEmbeddingInput, resolveMediaPrompt, resolveResumeRunId, resumeHttpResponse, resumeServerSentEventsResponse, resumeWebSocketResponse, resumeWebSocketStream, streamToText, summarize, toHttpResponse, toHttpStream, toServerSentEventsResponse, toServerSentEventsStream, toWebSocketResponse, toWebSocketStream, toolDefinition, uiMessageToModelMessages, uiMessagesToWire, untilFinishReason, validateInterruptResumeBatch, validateWithStandardSchema, wasCancelRequested, withInterruptBinding, withoutInterruptBinding, wrapGenericInterruptContinuation };
60
+ export { BaseRerankAdapter, BatchStrategy, CUSTOM_EVENT, CompositeStrategy, ConsoleLogger, DISCOVERY_TOOL_NAME, DetachableRunCapability, DuplicateToolNameError, EventType, INTERRUPT_BINDING_METADATA_KEY, INTERRUPT_BINDING_VERSION, INTERRUPT_BOUNDARY_PHASES, INTERRUPT_CONTINUATION_METADATA_KEY, INTERRUPT_CONTINUATION_VERSION, INTERRUPT_PAYLOAD_METADATA_KEY, INTERRUPT_TOOL_RESUMES, ImmediateStrategy, InMemoryRunStore, InterruptResumeValidationError, MCPDuplicateToolNameError, PartialJSONParser, PunctuationStrategy, RUN_ACCEPTED_EVENT, RUN_CANCEL_REASON, RunDetachedCapability, StandardSchemaValidationError, StreamProcessor, ToolCallManager, WordBoundaryStrategy, brandProviderTool, buildBaseUsage, canonicalInterruptJson, canonicalizeInterruptResolutions, chat, chatParamsFromRequest, chatParamsFromRequestBody, cloneAndDeepFreezeJson, combineStrategies, convertMessagesToModelMessages, convertSchemaToJsonSchema, countEmbeddingInputModalities, createAudioOptions, createCapability, createChatMiddleware, createChatOptions, createEmbedOptions, createFrozenRegistry, createImageOptions, createInterruptBinding, createModel, createRealtimeEventEmitter, createReplayStream, createRerankOptions, createSpeechOptions, createSummarizeOptions, createToolRegistry, createTranscriptionOptions, createVideoOptions, decodeWsFrame, defaultJSONParser, defineChatMiddleware, defineInterrupt, defineRunStore, detectImageMimeType, digestInterruptJson, embed, encodeWsFrame, extendAdapter, firstSentence, fromSpecTokenUsage, generateAudio, generateImage, generateMessageId, generateSpeech, generateTranscription, generateVideo, generationParamsFromBody, generationParamsFromRequest, genericInterruptContinuationFromDescriptor, getChunkRunId, getChunkThreadId, getDetachableRun, getProviderExecutedMetadata, getRunDetached, getVideoJobStatus, hashSchemaInput, interruptItemError, isCancelRequestedReason, isContentPart, isContentPartArray, isCustomEvent, isProviderExecutedToolCall, isRunStatus, isStandardSchema, isTerminalRunStatus, maxIterations, memoryStream, mergeAgentTools, mergeMetadata, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeApprovalSchema, normalizeStreamChunk, normalizeSystemPrompts, normalizeToUIMessage, normalizeToolResult, parsePartialJSON, parseWithStandardSchema, provideDetachableRun, provideRunDetached, readGenericInterruptContinuation, readInterruptBinding, readUnopenedInterruptBinding, realtimeToken, renderLazyCatalogEntry, replayRunStream, requestRunCancel, requireTextOnlyEmbeddingInput, rerank, resolveEmbeddingInput, resolveMediaPrompt, resolveResumeRunId, resumeHttpResponse, resumeServerSentEventsResponse, resumeWebSocketResponse, resumeWebSocketStream, streamToText, summarize, toHttpResponse, toHttpStream, toServerSentEventsResponse, toServerSentEventsStream, toSpecTokenUsage, toWebSocketResponse, toWebSocketStream, toolDefinition, uiMessageToModelMessages, uiMessagesToWire, untilFinishReason, validateInterruptResumeBatch, validateWithStandardSchema, wasCancelRequested, withInterruptBinding, withTanstackMetadata, withoutInterruptBinding, wrapGenericInterruptContinuation };
@@ -1,3 +1,5 @@
1
+ import { rebuildTokenUsage } from "../utilities/ag-ui-usage.js";
2
+ import { tanstackMetadata } from "../utilities/merge-metadata.js";
1
3
  import { errorMessage, errorTypeName } from "../utilities/errors.js";
2
4
  import { MAX_TOKENS_KEYS, NESTED_MAX_TOKENS_KEY } from "../utilities/sampling-keys.js";
3
5
  import { firstNumber } from "../utilities/numbers.js";
@@ -297,12 +299,17 @@ function otelMiddleware(options) {
297
299
  if (!state) return;
298
300
  if (captureContent && chunk.type === "TEXT_MESSAGE_CONTENT") appendAssistantText(state, chunk.delta);
299
301
  if (chunk.type !== "RUN_FINISHED") return;
300
- if (chunk.finishReason) state.lastFinishReason = chunk.finishReason;
302
+ const tanstack = tanstackMetadata(chunk);
303
+ const extra = chunk;
304
+ const finishReason = extra.finishReason ?? tanstack?.finishReason;
305
+ const model = extra.model ?? tanstack?.model;
306
+ if (finishReason) state.lastFinishReason = finishReason;
301
307
  const span = state.currentIterationSpan;
302
308
  if (!span) return;
303
- if (chunk.finishReason) span.setAttribute("gen_ai.response.finish_reasons", [chunk.finishReason]);
304
- if (chunk.model) span.setAttribute("gen_ai.response.model", chunk.model);
305
- if (chunk.usage) span.setAttributes(usageAttributes(chunk.usage));
309
+ if (finishReason) span.setAttribute("gen_ai.response.finish_reasons", [finishReason]);
310
+ if (model) span.setAttribute("gen_ai.response.model", model);
311
+ const tokenUsage = rebuildTokenUsage(chunk.usage, tanstack?.usage);
312
+ if (tokenUsage) span.setAttributes(usageAttributes(tokenUsage));
306
313
  if (captureContent && state.assistantTextBuffer.length > 0) {
307
314
  const completion = redactContent(state.assistantTextBuffer);
308
315
  const outputJson = JSON.stringify([{