@tanstack/ai 0.35.0 → 0.36.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 (208) hide show
  1. package/package.json +2 -2
  2. package/skills/ai-core/tool-calling/SKILL.md +26 -1
  3. package/src/activities/chat/index.ts +8 -0
  4. package/src/activities/chat/tools/lazy-tool-manager.ts +12 -4
  5. package/src/activities/chat/tools/lazy-tools.ts +33 -0
  6. package/src/index.ts +5 -0
  7. package/src/types.ts +23 -1
  8. package/dist/esm/activities/chat/adapter.d.ts +0 -163
  9. package/dist/esm/activities/chat/adapter.js +0 -17
  10. package/dist/esm/activities/chat/adapter.js.map +0 -1
  11. package/dist/esm/activities/chat/agent-loop-strategies.d.ts +0 -59
  12. package/dist/esm/activities/chat/agent-loop-strategies.js +0 -23
  13. package/dist/esm/activities/chat/agent-loop-strategies.js.map +0 -1
  14. package/dist/esm/activities/chat/index.d.ts +0 -264
  15. package/dist/esm/activities/chat/index.js +0 -1723
  16. package/dist/esm/activities/chat/index.js.map +0 -1
  17. package/dist/esm/activities/chat/mcp/manager.d.ts +0 -25
  18. package/dist/esm/activities/chat/mcp/manager.js +0 -71
  19. package/dist/esm/activities/chat/mcp/manager.js.map +0 -1
  20. package/dist/esm/activities/chat/mcp/types.d.ts +0 -56
  21. package/dist/esm/activities/chat/messages.d.ts +0 -78
  22. package/dist/esm/activities/chat/messages.js +0 -374
  23. package/dist/esm/activities/chat/messages.js.map +0 -1
  24. package/dist/esm/activities/chat/middleware/builder.d.ts +0 -46
  25. package/dist/esm/activities/chat/middleware/builder.js +0 -17
  26. package/dist/esm/activities/chat/middleware/builder.js.map +0 -1
  27. package/dist/esm/activities/chat/middleware/capabilities.d.ts +0 -93
  28. package/dist/esm/activities/chat/middleware/capabilities.js +0 -45
  29. package/dist/esm/activities/chat/middleware/capabilities.js.map +0 -1
  30. package/dist/esm/activities/chat/middleware/compose.d.ts +0 -87
  31. package/dist/esm/activities/chat/middleware/compose.js +0 -510
  32. package/dist/esm/activities/chat/middleware/compose.js.map +0 -1
  33. package/dist/esm/activities/chat/middleware/define.d.ts +0 -20
  34. package/dist/esm/activities/chat/middleware/define.js +0 -7
  35. package/dist/esm/activities/chat/middleware/define.js.map +0 -1
  36. package/dist/esm/activities/chat/middleware/index.d.ts +0 -10
  37. package/dist/esm/activities/chat/middleware/tool-cache-middleware.d.ts +0 -89
  38. package/dist/esm/activities/chat/middleware/tool-cache-middleware.js +0 -76
  39. package/dist/esm/activities/chat/middleware/tool-cache-middleware.js.map +0 -1
  40. package/dist/esm/activities/chat/middleware/types.d.ts +0 -405
  41. package/dist/esm/activities/chat/middleware/validate.d.ts +0 -19
  42. package/dist/esm/activities/chat/middleware/validate.js +0 -30
  43. package/dist/esm/activities/chat/middleware/validate.js.map +0 -1
  44. package/dist/esm/activities/chat/runtime-context-types.d.ts +0 -43
  45. package/dist/esm/activities/chat/stream/index.d.ts +0 -11
  46. package/dist/esm/activities/chat/stream/json-parser.d.ts +0 -38
  47. package/dist/esm/activities/chat/stream/json-parser.js +0 -28
  48. package/dist/esm/activities/chat/stream/json-parser.js.map +0 -1
  49. package/dist/esm/activities/chat/stream/message-updaters.d.ts +0 -81
  50. package/dist/esm/activities/chat/stream/message-updaters.js +0 -253
  51. package/dist/esm/activities/chat/stream/message-updaters.js.map +0 -1
  52. package/dist/esm/activities/chat/stream/processor.d.ts +0 -439
  53. package/dist/esm/activities/chat/stream/processor.js +0 -1426
  54. package/dist/esm/activities/chat/stream/processor.js.map +0 -1
  55. package/dist/esm/activities/chat/stream/strategies.d.ts +0 -43
  56. package/dist/esm/activities/chat/stream/strategies.js +0 -54
  57. package/dist/esm/activities/chat/stream/strategies.js.map +0 -1
  58. package/dist/esm/activities/chat/stream/types.d.ts +0 -90
  59. package/dist/esm/activities/chat/tools/lazy-tool-manager.d.ts +0 -81
  60. package/dist/esm/activities/chat/tools/lazy-tool-manager.js +0 -188
  61. package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +0 -1
  62. package/dist/esm/activities/chat/tools/schema-converter.d.ts +0 -140
  63. package/dist/esm/activities/chat/tools/schema-converter.js +0 -167
  64. package/dist/esm/activities/chat/tools/schema-converter.js.map +0 -1
  65. package/dist/esm/activities/chat/tools/tool-calls.d.ts +0 -140
  66. package/dist/esm/activities/chat/tools/tool-calls.js +0 -512
  67. package/dist/esm/activities/chat/tools/tool-calls.js.map +0 -1
  68. package/dist/esm/activities/chat/tools/tool-definition.d.ts +0 -135
  69. package/dist/esm/activities/chat/tools/tool-definition.js +0 -25
  70. package/dist/esm/activities/chat/tools/tool-definition.js.map +0 -1
  71. package/dist/esm/activities/error-payload.d.ts +0 -30
  72. package/dist/esm/activities/error-payload.js +0 -54
  73. package/dist/esm/activities/error-payload.js.map +0 -1
  74. package/dist/esm/activities/generateAudio/adapter.d.ts +0 -62
  75. package/dist/esm/activities/generateAudio/adapter.js +0 -16
  76. package/dist/esm/activities/generateAudio/adapter.js.map +0 -1
  77. package/dist/esm/activities/generateAudio/index.d.ts +0 -85
  78. package/dist/esm/activities/generateAudio/index.js +0 -114
  79. package/dist/esm/activities/generateAudio/index.js.map +0 -1
  80. package/dist/esm/activities/generateImage/adapter.d.ts +0 -78
  81. package/dist/esm/activities/generateImage/adapter.js +0 -16
  82. package/dist/esm/activities/generateImage/adapter.js.map +0 -1
  83. package/dist/esm/activities/generateImage/index.d.ts +0 -134
  84. package/dist/esm/activities/generateImage/index.js +0 -121
  85. package/dist/esm/activities/generateImage/index.js.map +0 -1
  86. package/dist/esm/activities/generateSpeech/adapter.d.ts +0 -62
  87. package/dist/esm/activities/generateSpeech/adapter.js +0 -16
  88. package/dist/esm/activities/generateSpeech/adapter.js.map +0 -1
  89. package/dist/esm/activities/generateSpeech/index.d.ts +0 -96
  90. package/dist/esm/activities/generateSpeech/index.js +0 -119
  91. package/dist/esm/activities/generateSpeech/index.js.map +0 -1
  92. package/dist/esm/activities/generateTranscription/adapter.d.ts +0 -62
  93. package/dist/esm/activities/generateTranscription/adapter.js +0 -16
  94. package/dist/esm/activities/generateTranscription/adapter.js.map +0 -1
  95. package/dist/esm/activities/generateTranscription/index.d.ts +0 -109
  96. package/dist/esm/activities/generateTranscription/index.js +0 -109
  97. package/dist/esm/activities/generateTranscription/index.js.map +0 -1
  98. package/dist/esm/activities/generateVideo/adapter.d.ts +0 -145
  99. package/dist/esm/activities/generateVideo/adapter.js +0 -30
  100. package/dist/esm/activities/generateVideo/adapter.js.map +0 -1
  101. package/dist/esm/activities/generateVideo/index.d.ts +0 -223
  102. package/dist/esm/activities/generateVideo/index.js +0 -295
  103. package/dist/esm/activities/generateVideo/index.js.map +0 -1
  104. package/dist/esm/activities/generateVideo/snap.d.ts +0 -14
  105. package/dist/esm/activities/generateVideo/snap.js +0 -54
  106. package/dist/esm/activities/generateVideo/snap.js.map +0 -1
  107. package/dist/esm/activities/index.d.ts +0 -27
  108. package/dist/esm/activities/index.js +0 -43
  109. package/dist/esm/activities/index.js.map +0 -1
  110. package/dist/esm/activities/middleware/index.d.ts +0 -2
  111. package/dist/esm/activities/middleware/run.d.ts +0 -20
  112. package/dist/esm/activities/middleware/run.js +0 -42
  113. package/dist/esm/activities/middleware/run.js.map +0 -1
  114. package/dist/esm/activities/middleware/types.d.ts +0 -118
  115. package/dist/esm/activities/stream-generation-result.d.ts +0 -15
  116. package/dist/esm/activities/stream-generation-result.js +0 -49
  117. package/dist/esm/activities/stream-generation-result.js.map +0 -1
  118. package/dist/esm/activities/summarize/adapter.d.ts +0 -74
  119. package/dist/esm/activities/summarize/adapter.js +0 -16
  120. package/dist/esm/activities/summarize/adapter.js.map +0 -1
  121. package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +0 -45
  122. package/dist/esm/activities/summarize/chat-stream-summarize.js +0 -212
  123. package/dist/esm/activities/summarize/chat-stream-summarize.js.map +0 -1
  124. package/dist/esm/activities/summarize/index.d.ts +0 -108
  125. package/dist/esm/activities/summarize/index.js +0 -113
  126. package/dist/esm/activities/summarize/index.js.map +0 -1
  127. package/dist/esm/adapter-internals.d.ts +0 -5
  128. package/dist/esm/adapter-internals.js +0 -10
  129. package/dist/esm/adapter-internals.js.map +0 -1
  130. package/dist/esm/client.d.ts +0 -44
  131. package/dist/esm/client.js +0 -67
  132. package/dist/esm/client.js.map +0 -1
  133. package/dist/esm/extend-adapter.d.ts +0 -152
  134. package/dist/esm/extend-adapter.js +0 -21
  135. package/dist/esm/extend-adapter.js.map +0 -1
  136. package/dist/esm/index.d.ts +0 -44
  137. package/dist/esm/index.js +0 -106
  138. package/dist/esm/index.js.map +0 -1
  139. package/dist/esm/logger/console-logger.d.ts +0 -29
  140. package/dist/esm/logger/console-logger.js +0 -83
  141. package/dist/esm/logger/console-logger.js.map +0 -1
  142. package/dist/esm/logger/internal-logger.d.ts +0 -41
  143. package/dist/esm/logger/internal-logger.js +0 -86
  144. package/dist/esm/logger/internal-logger.js.map +0 -1
  145. package/dist/esm/logger/resolve.d.ts +0 -14
  146. package/dist/esm/logger/resolve.js +0 -54
  147. package/dist/esm/logger/resolve.js.map +0 -1
  148. package/dist/esm/logger/types.d.ts +0 -75
  149. package/dist/esm/middlewares/content-guard.d.ts +0 -77
  150. package/dist/esm/middlewares/content-guard.js +0 -156
  151. package/dist/esm/middlewares/content-guard.js.map +0 -1
  152. package/dist/esm/middlewares/index.d.ts +0 -2
  153. package/dist/esm/middlewares/index.js +0 -7
  154. package/dist/esm/middlewares/index.js.map +0 -1
  155. package/dist/esm/middlewares/otel.d.ts +0 -81
  156. package/dist/esm/middlewares/otel.js +0 -745
  157. package/dist/esm/middlewares/otel.js.map +0 -1
  158. package/dist/esm/middlewares/tool-cache.d.ts +0 -1
  159. package/dist/esm/middlewares/usage-attributes.d.ts +0 -24
  160. package/dist/esm/middlewares/usage-attributes.js +0 -43
  161. package/dist/esm/middlewares/usage-attributes.js.map +0 -1
  162. package/dist/esm/realtime/index.d.ts +0 -28
  163. package/dist/esm/realtime/index.js +0 -8
  164. package/dist/esm/realtime/index.js.map +0 -1
  165. package/dist/esm/realtime/types.d.ts +0 -282
  166. package/dist/esm/stream-to-response.d.ts +0 -102
  167. package/dist/esm/stream-to-response.js +0 -121
  168. package/dist/esm/stream-to-response.js.map +0 -1
  169. package/dist/esm/strip-to-spec-middleware.d.ts +0 -18
  170. package/dist/esm/strip-to-spec-middleware.js +0 -20
  171. package/dist/esm/strip-to-spec-middleware.js.map +0 -1
  172. package/dist/esm/system-prompts.d.ts +0 -66
  173. package/dist/esm/system-prompts.js +0 -23
  174. package/dist/esm/system-prompts.js.map +0 -1
  175. package/dist/esm/tool-registry.d.ts +0 -81
  176. package/dist/esm/tool-registry.js +0 -49
  177. package/dist/esm/tool-registry.js.map +0 -1
  178. package/dist/esm/tools/provider-tool.d.ts +0 -30
  179. package/dist/esm/tools/provider-tool.js +0 -7
  180. package/dist/esm/tools/provider-tool.js.map +0 -1
  181. package/dist/esm/types.d.ts +0 -1573
  182. package/dist/esm/utilities/ag-ui-wire.d.ts +0 -44
  183. package/dist/esm/utilities/ag-ui-wire.js +0 -107
  184. package/dist/esm/utilities/ag-ui-wire.js.map +0 -1
  185. package/dist/esm/utilities/chat-params.d.ts +0 -85
  186. package/dist/esm/utilities/chat-params.js +0 -100
  187. package/dist/esm/utilities/chat-params.js.map +0 -1
  188. package/dist/esm/utilities/errors.d.ts +0 -13
  189. package/dist/esm/utilities/errors.js +0 -22
  190. package/dist/esm/utilities/errors.js.map +0 -1
  191. package/dist/esm/utilities/media-prompt.d.ts +0 -35
  192. package/dist/esm/utilities/media-prompt.js +0 -43
  193. package/dist/esm/utilities/media-prompt.js.map +0 -1
  194. package/dist/esm/utilities/numbers.d.ts +0 -8
  195. package/dist/esm/utilities/numbers.js +0 -12
  196. package/dist/esm/utilities/numbers.js.map +0 -1
  197. package/dist/esm/utilities/sampling-keys.d.ts +0 -20
  198. package/dist/esm/utilities/sampling-keys.js +0 -20
  199. package/dist/esm/utilities/sampling-keys.js.map +0 -1
  200. package/dist/esm/utilities/tool-result.d.ts +0 -21
  201. package/dist/esm/utilities/tool-result.js +0 -37
  202. package/dist/esm/utilities/tool-result.js.map +0 -1
  203. package/dist/esm/utilities/usage.d.ts +0 -31
  204. package/dist/esm/utilities/usage.js +0 -11
  205. package/dist/esm/utilities/usage.js.map +0 -1
  206. package/dist/esm/utils.d.ts +0 -17
  207. package/dist/esm/utils.js +0 -20
  208. package/dist/esm/utils.js.map +0 -1
@@ -1,121 +0,0 @@
1
- import { toRunErrorPayload } from "./activities/error-payload.js";
2
- async function streamToText(stream) {
3
- let accumulatedContent = "";
4
- for await (const chunk of stream) {
5
- if (chunk.type === "TEXT_MESSAGE_CONTENT" && chunk.delta) {
6
- accumulatedContent += chunk.delta;
7
- }
8
- }
9
- return accumulatedContent;
10
- }
11
- function toServerSentEventsStream(stream, abortController) {
12
- const encoder = new TextEncoder();
13
- return new ReadableStream({
14
- async start(controller) {
15
- try {
16
- for await (const chunk of stream) {
17
- if (abortController?.signal.aborted) {
18
- break;
19
- }
20
- controller.enqueue(
21
- encoder.encode(`data: ${JSON.stringify(chunk)}
22
-
23
- `)
24
- );
25
- }
26
- controller.close();
27
- } catch (error) {
28
- if (abortController?.signal.aborted) {
29
- controller.close();
30
- return;
31
- }
32
- controller.enqueue(
33
- encoder.encode(
34
- `data: ${JSON.stringify({
35
- type: "RUN_ERROR",
36
- timestamp: Date.now(),
37
- error: toRunErrorPayload(error)
38
- })}
39
-
40
- `
41
- )
42
- );
43
- controller.close();
44
- }
45
- },
46
- cancel() {
47
- if (abortController) {
48
- abortController.abort();
49
- }
50
- }
51
- });
52
- }
53
- function toServerSentEventsResponse(stream, init) {
54
- const { headers, abortController, ...responseInit } = init ?? {};
55
- const mergedHeaders = new Headers({
56
- "Content-Type": "text/event-stream",
57
- "Cache-Control": "no-cache",
58
- Connection: "keep-alive"
59
- });
60
- if (headers) {
61
- const userHeaders = new Headers(headers);
62
- userHeaders.forEach((value, key) => {
63
- mergedHeaders.set(key, value);
64
- });
65
- }
66
- return new Response(toServerSentEventsStream(stream, abortController), {
67
- ...responseInit,
68
- headers: mergedHeaders
69
- });
70
- }
71
- function toHttpStream(stream, abortController) {
72
- const encoder = new TextEncoder();
73
- return new ReadableStream({
74
- async start(controller) {
75
- try {
76
- for await (const chunk of stream) {
77
- if (abortController?.signal.aborted) {
78
- break;
79
- }
80
- controller.enqueue(encoder.encode(`${JSON.stringify(chunk)}
81
- `));
82
- }
83
- controller.close();
84
- } catch (error) {
85
- if (abortController?.signal.aborted) {
86
- controller.close();
87
- return;
88
- }
89
- controller.enqueue(
90
- encoder.encode(
91
- `${JSON.stringify({
92
- type: "RUN_ERROR",
93
- timestamp: Date.now(),
94
- error: toRunErrorPayload(error)
95
- })}
96
- `
97
- )
98
- );
99
- controller.close();
100
- }
101
- },
102
- cancel() {
103
- if (abortController) {
104
- abortController.abort();
105
- }
106
- }
107
- });
108
- }
109
- function toHttpResponse(stream, init) {
110
- return new Response(toHttpStream(stream, init?.abortController), {
111
- ...init
112
- });
113
- }
114
- export {
115
- streamToText,
116
- toHttpResponse,
117
- toHttpStream,
118
- toServerSentEventsResponse,
119
- toServerSentEventsStream
120
- };
121
- //# sourceMappingURL=stream-to-response.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream-to-response.js","sources":["../../src/stream-to-response.ts"],"sourcesContent":["import { toRunErrorPayload } from './activities/error-payload'\nimport type { StreamChunk } from './types'\n\n/**\n * Collect all text content from a StreamChunk async iterable and return as a string.\n *\n * This function consumes the entire stream, accumulating content from TEXT_MESSAGE_CONTENT events,\n * and returns the final concatenated text.\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @returns Promise<string> - The accumulated text content\n *\n * @example\n * ```typescript\n * const stream = chat({\n * adapter: openaiText(),\n * model: 'gpt-4o',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n * const text = await streamToText(stream);\n * console.log(text); // \"Hello! How can I help you today?\"\n * ```\n */\nexport async function streamToText(\n stream: AsyncIterable<StreamChunk>,\n): Promise<string> {\n let accumulatedContent = ''\n\n for await (const chunk of stream) {\n if (chunk.type === 'TEXT_MESSAGE_CONTENT' && chunk.delta) {\n accumulatedContent += chunk.delta\n }\n }\n\n return accumulatedContent\n}\n\n/**\n * Convert a StreamChunk async iterable to a ReadableStream in Server-Sent Events format\n *\n * This creates a ReadableStream that emits chunks in SSE format:\n * - Each chunk is prefixed with \"data: \"\n * - Each chunk is followed by \"\\n\\n\"\n * - Stream ends when the underlying iterable is exhausted (RUN_FINISHED is the terminal event)\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param abortController - Optional AbortController to abort when stream is cancelled\n * @returns ReadableStream in Server-Sent Events format\n */\nexport function toServerSentEventsStream(\n stream: AsyncIterable<StreamChunk>,\n abortController?: AbortController,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder()\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Check if stream was cancelled/aborted\n if (abortController?.signal.aborted) {\n break\n }\n\n // Send each chunk as Server-Sent Events format\n controller.enqueue(\n encoder.encode(`data: ${JSON.stringify(chunk)}\\n\\n`),\n )\n }\n\n controller.close()\n } catch (error: unknown) {\n // Don't send error if aborted\n if (abortController?.signal.aborted) {\n controller.close()\n return\n }\n\n // Send error event (AG-UI RUN_ERROR)\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({\n type: 'RUN_ERROR',\n timestamp: Date.now(),\n error: toRunErrorPayload(error),\n })}\\n\\n`,\n ),\n )\n controller.close()\n }\n },\n cancel() {\n // When the ReadableStream is cancelled (e.g., client disconnects),\n // abort the underlying stream\n if (abortController) {\n abortController.abort()\n }\n },\n })\n}\n\n/**\n * Convert a StreamChunk async iterable to a Response in Server-Sent Events format\n *\n * This creates a Response that emits chunks in SSE format:\n * - Each chunk is prefixed with \"data: \"\n * - Each chunk is followed by \"\\n\\n\"\n * - Stream ends when the underlying iterable is exhausted (RUN_FINISHED is the terminal event)\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param init - Optional Response initialization options (including `abortController`)\n * @returns Response in Server-Sent Events format\n *\n * @example\n * ```typescript\n * const stream = chat({ adapter: openaiText(), model: \"gpt-4o\", messages: [...] });\n * return toServerSentEventsResponse(stream, { abortController });\n * ```\n */\nexport function toServerSentEventsResponse(\n stream: AsyncIterable<StreamChunk>,\n init?: ResponseInit & { abortController?: AbortController },\n): Response {\n const { headers, abortController, ...responseInit } = init ?? {}\n\n // Start with default SSE headers\n const mergedHeaders = new Headers({\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n })\n\n // Override with user headers if provided, handling all HeadersInit forms:\n // Headers instance, string[][], or plain object\n if (headers) {\n const userHeaders = new Headers(headers)\n userHeaders.forEach((value, key) => {\n mergedHeaders.set(key, value)\n })\n }\n\n return new Response(toServerSentEventsStream(stream, abortController), {\n ...responseInit,\n headers: mergedHeaders,\n })\n}\n\n/**\n * Convert a StreamChunk async iterable to a ReadableStream in HTTP stream format (newline-delimited JSON)\n *\n * This creates a ReadableStream that emits chunks as newline-delimited JSON:\n * - Each chunk is JSON.stringify'd and followed by \"\\n\"\n * - No SSE formatting (no \"data: \" prefix)\n *\n * This format is compatible with `fetchHttpStream` connection adapter.\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param abortController - Optional AbortController to abort when stream is cancelled\n * @returns ReadableStream in HTTP stream format (newline-delimited JSON)\n *\n * @example\n * ```typescript\n * const stream = chat({ adapter: openaiText(), model: \"gpt-4o\", messages: [...] });\n * const readableStream = toHttpStream(stream);\n * // Use with Response for HTTP streaming (not SSE)\n * return new Response(readableStream, {\n * headers: { 'Content-Type': 'application/x-ndjson' }\n * });\n * ```\n */\nexport function toHttpStream(\n stream: AsyncIterable<StreamChunk>,\n abortController?: AbortController,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder()\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Check if stream was cancelled/aborted\n if (abortController?.signal.aborted) {\n break\n }\n\n // Send each chunk as newline-delimited JSON\n controller.enqueue(encoder.encode(`${JSON.stringify(chunk)}\\n`))\n }\n\n controller.close()\n } catch (error: unknown) {\n // Don't send error if aborted\n if (abortController?.signal.aborted) {\n controller.close()\n return\n }\n\n // Send error event (AG-UI RUN_ERROR)\n controller.enqueue(\n encoder.encode(\n `${JSON.stringify({\n type: 'RUN_ERROR',\n timestamp: Date.now(),\n error: toRunErrorPayload(error),\n })}\\n`,\n ),\n )\n controller.close()\n }\n },\n cancel() {\n // When the ReadableStream is cancelled (e.g., client disconnects),\n // abort the underlying stream\n if (abortController) {\n abortController.abort()\n }\n },\n })\n}\n\n/**\n * Convert a StreamChunk async iterable to a Response in HTTP stream format (newline-delimited JSON)\n *\n * This creates a Response that emits chunks in HTTP stream format:\n * - Each chunk is JSON.stringify'd and followed by \"\\n\"\n * - No SSE formatting (no \"data: \" prefix)\n *\n * This format is compatible with `fetchHttpStream` connection adapter.\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param init - Optional Response initialization options (including `abortController`)\n * @returns Response in HTTP stream format (newline-delimited JSON)\n *\n * @example\n * ```typescript\n * const stream = chat({ adapter: openaiText(), model: \"gpt-4o\", messages: [...] });\n * return toHttpResponse(stream, { abortController });\n * ```\n */\nexport function toHttpResponse(\n stream: AsyncIterable<StreamChunk>,\n init?: ResponseInit & { abortController?: AbortController },\n): Response {\n return new Response(toHttpStream(stream, init?.abortController), {\n ...init,\n })\n}\n"],"names":[],"mappings":";AAuBA,eAAsB,aACpB,QACiB;AACjB,MAAI,qBAAqB;AAEzB,mBAAiB,SAAS,QAAQ;AAChC,QAAI,MAAM,SAAS,0BAA0B,MAAM,OAAO;AACxD,4BAAsB,MAAM;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AACT;AAcO,SAAS,yBACd,QACA,iBAC4B;AAC5B,QAAM,UAAU,IAAI,YAAA;AAEpB,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,MAAM,YAAY;AACtB,UAAI;AACF,yBAAiB,SAAS,QAAQ;AAEhC,cAAI,iBAAiB,OAAO,SAAS;AACnC;AAAA,UACF;AAGA,qBAAW;AAAA,YACT,QAAQ,OAAO,SAAS,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA,CAAM;AAAA,UAAA;AAAA,QAEvD;AAEA,mBAAW,MAAA;AAAA,MACb,SAAS,OAAgB;AAEvB,YAAI,iBAAiB,OAAO,SAAS;AACnC,qBAAW,MAAA;AACX;AAAA,QACF;AAGA,mBAAW;AAAA,UACT,QAAQ;AAAA,YACN,SAAS,KAAK,UAAU;AAAA,cACtB,MAAM;AAAA,cACN,WAAW,KAAK,IAAA;AAAA,cAChB,OAAO,kBAAkB,KAAK;AAAA,YAAA,CAC/B,CAAC;AAAA;AAAA;AAAA,UAAA;AAAA,QACJ;AAEF,mBAAW,MAAA;AAAA,MACb;AAAA,IACF;AAAA,IACA,SAAS;AAGP,UAAI,iBAAiB;AACnB,wBAAgB,MAAA;AAAA,MAClB;AAAA,IACF;AAAA,EAAA,CACD;AACH;AAoBO,SAAS,2BACd,QACA,MACU;AACV,QAAM,EAAE,SAAS,iBAAiB,GAAG,aAAA,IAAiB,QAAQ,CAAA;AAG9D,QAAM,gBAAgB,IAAI,QAAQ;AAAA,IAChC,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,YAAY;AAAA,EAAA,CACb;AAID,MAAI,SAAS;AACX,UAAM,cAAc,IAAI,QAAQ,OAAO;AACvC,gBAAY,QAAQ,CAAC,OAAO,QAAQ;AAClC,oBAAc,IAAI,KAAK,KAAK;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,SAAO,IAAI,SAAS,yBAAyB,QAAQ,eAAe,GAAG;AAAA,IACrE,GAAG;AAAA,IACH,SAAS;AAAA,EAAA,CACV;AACH;AAyBO,SAAS,aACd,QACA,iBAC4B;AAC5B,QAAM,UAAU,IAAI,YAAA;AAEpB,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,MAAM,YAAY;AACtB,UAAI;AACF,yBAAiB,SAAS,QAAQ;AAEhC,cAAI,iBAAiB,OAAO,SAAS;AACnC;AAAA,UACF;AAGA,qBAAW,QAAQ,QAAQ,OAAO,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI,CAAC;AAAA,QACjE;AAEA,mBAAW,MAAA;AAAA,MACb,SAAS,OAAgB;AAEvB,YAAI,iBAAiB,OAAO,SAAS;AACnC,qBAAW,MAAA;AACX;AAAA,QACF;AAGA,mBAAW;AAAA,UACT,QAAQ;AAAA,YACN,GAAG,KAAK,UAAU;AAAA,cAChB,MAAM;AAAA,cACN,WAAW,KAAK,IAAA;AAAA,cAChB,OAAO,kBAAkB,KAAK;AAAA,YAAA,CAC/B,CAAC;AAAA;AAAA,UAAA;AAAA,QACJ;AAEF,mBAAW,MAAA;AAAA,MACb;AAAA,IACF;AAAA,IACA,SAAS;AAGP,UAAI,iBAAiB;AACnB,wBAAgB,MAAA;AAAA,MAClB;AAAA,IACF;AAAA,EAAA,CACD;AACH;AAqBO,SAAS,eACd,QACA,MACU;AACV,SAAO,IAAI,SAAS,aAAa,QAAQ,MAAM,eAAe,GAAG;AAAA,IAC/D,GAAG;AAAA,EAAA,CACJ;AACH;"}
@@ -1,18 +0,0 @@
1
- import { ChatMiddleware } from './activities/chat/middleware/types.js';
2
- import { StreamChunk } from './types.js';
3
- /**
4
- * Strip only the deprecated nested `error` object from RUN_ERROR events.
5
- * The flat `message`/`code` fields are the spec-compliant form.
6
- *
7
- * All other fields pass through unchanged. @ag-ui/core's BaseEventSchema
8
- * uses `.passthrough()`, so extra fields (model, content, usage,
9
- * finishReason, toolName, stepId, etc.) are allowed and won't break
10
- * spec validation or verifyEvents.
11
- */
12
- export declare function stripToSpec(chunk: StreamChunk): StreamChunk;
13
- /**
14
- * Middleware that ensures events are AG-UI spec compliant.
15
- * Currently only strips the deprecated nested `error` object from RUN_ERROR.
16
- * All other fields pass through unchanged (passthrough allowed by spec).
17
- */
18
- export declare function stripToSpecMiddleware(): ChatMiddleware;
@@ -1,20 +0,0 @@
1
- function stripToSpec(chunk) {
2
- if (chunk.type === "RUN_ERROR" && "error" in chunk) {
3
- const { error: _deprecated, ...rest } = chunk;
4
- return rest;
5
- }
6
- return chunk;
7
- }
8
- function stripToSpecMiddleware() {
9
- return {
10
- name: "strip-to-spec",
11
- onChunk(_ctx, chunk) {
12
- return stripToSpec(chunk);
13
- }
14
- };
15
- }
16
- export {
17
- stripToSpec,
18
- stripToSpecMiddleware
19
- };
20
- //# sourceMappingURL=strip-to-spec-middleware.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"strip-to-spec-middleware.js","sources":["../../src/strip-to-spec-middleware.ts"],"sourcesContent":["import type { ChatMiddleware } from './activities/chat/middleware/types'\nimport type { StreamChunk } from './types'\n\n/**\n * Strip only the deprecated nested `error` object from RUN_ERROR events.\n * The flat `message`/`code` fields are the spec-compliant form.\n *\n * All other fields pass through unchanged. @ag-ui/core's BaseEventSchema\n * uses `.passthrough()`, so extra fields (model, content, usage,\n * finishReason, toolName, stepId, etc.) are allowed and won't break\n * spec validation or verifyEvents.\n */\nexport function stripToSpec(chunk: StreamChunk): StreamChunk {\n // Only strip the deprecated nested error object from RUN_ERROR\n if (chunk.type === 'RUN_ERROR' && 'error' in chunk) {\n const { error: _deprecated, ...rest } = chunk as Record<string, unknown>\n return rest as StreamChunk\n }\n return chunk\n}\n\n/**\n * Middleware that ensures events are AG-UI spec compliant.\n * Currently only strips the deprecated nested `error` object from RUN_ERROR.\n * All other fields pass through unchanged (passthrough allowed by spec).\n */\nexport function stripToSpecMiddleware(): ChatMiddleware {\n return {\n name: 'strip-to-spec',\n onChunk(_ctx, chunk) {\n return stripToSpec(chunk)\n },\n }\n}\n"],"names":[],"mappings":"AAYO,SAAS,YAAY,OAAiC;AAE3D,MAAI,MAAM,SAAS,eAAe,WAAW,OAAO;AAClD,UAAM,EAAE,OAAO,aAAa,GAAG,SAAS;AACxC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAOO,SAAS,wBAAwC;AACtD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,MAAM,OAAO;AACnB,aAAO,YAAY,KAAK;AAAA,IAC1B;AAAA,EAAA;AAEJ;"}
@@ -1,66 +0,0 @@
1
- /**
2
- * A single entry in `chat({ systemPrompts: [...] })`.
3
- *
4
- * Accepts a plain string (the common case) or a structured object that lets
5
- * providers attach typed metadata to the prompt — e.g. Anthropic
6
- * `cache_control` for prompt caching, future per-prompt safety overrides for
7
- * Gemini, etc.
8
- *
9
- * At the chat call site, `metadata` is narrowed by the adapter via
10
- * `~types['systemPromptMetadata']`. Providers that don't declare one inherit
11
- * the default `never`, which makes the field carry no meaningful value: TS
12
- * only accepts `undefined` there, and provider-foreign metadata that reaches
13
- * an adapter via JS / `as any` is silently dropped, never written to the
14
- * wire. For type-safe per-provider metadata, refer to the provider's
15
- * `<Provider>SystemPromptMetadata` interface (e.g. `AnthropicSystemPromptMetadata`).
16
- *
17
- * @example
18
- * // The 90% case — plain strings work everywhere.
19
- * systemPrompts: ['Be concise.', 'Cite sources.']
20
- *
21
- * @example
22
- * // Provider-specific metadata via the object form. No `satisfies` cast
23
- * // is needed — the adapter narrows the `metadata` field's type at the
24
- * // call site so users get autocomplete and structural checking
25
- * // automatically.
26
- * import { anthropicText } from '@tanstack/ai-anthropic'
27
- *
28
- * chat({
29
- * adapter: anthropicText(),
30
- * systemPrompts: [
31
- * {
32
- * content: 'Stable instructions — cache me.',
33
- * metadata: { cache_control: { type: 'ephemeral' } },
34
- * },
35
- * 'Volatile per-request instruction.',
36
- * ],
37
- * })
38
- */
39
- export type SystemPrompt<TMetadata = unknown> = string | {
40
- content: string;
41
- metadata?: TMetadata;
42
- };
43
- /**
44
- * Normalised shape adapters see after the chat layer turns string entries
45
- * into `{ content }` objects. Adapters call `normalizeSystemPrompts` once at
46
- * the top of their option-mapping pipeline so the rest of the code only has
47
- * to handle one shape.
48
- */
49
- export interface NormalizedSystemPrompt<TMetadata = unknown> {
50
- content: string;
51
- metadata?: TMetadata;
52
- }
53
- /**
54
- * Normalise the public `systemPrompts` shape (`Array<string | { content, metadata? }>`)
55
- * to a homogenous `Array<{ content, metadata? }>`. Adapters use this so they
56
- * don't have to type-narrow string vs object inline.
57
- *
58
- * Returns an empty array (never `undefined`) so callers can chain `.map` /
59
- * `.join` without an extra null check.
60
- *
61
- * Throws a `TypeError` (naming the offending index) if an object-form entry's
62
- * `content` isn't a string. Public API boundary — callers reaching this
63
- * function through `as any` / external JS would otherwise stream a literal
64
- * `"undefined"` into the model's system prompt with no signal.
65
- */
66
- export declare function normalizeSystemPrompts<TMetadata = unknown>(prompts: ReadonlyArray<SystemPrompt> | undefined): Array<NormalizedSystemPrompt<TMetadata>>;
@@ -1,23 +0,0 @@
1
- function normalizeSystemPrompts(prompts) {
2
- if (!prompts || prompts.length === 0) return [];
3
- return prompts.map((p, i) => {
4
- if (typeof p === "string") return { content: p };
5
- const candidate = p;
6
- if (candidate === null || typeof candidate !== "object") {
7
- throw new TypeError(
8
- `systemPrompts[${i}]: expected a string or { content, metadata? }, got ${candidate === null ? "null" : typeof candidate}`
9
- );
10
- }
11
- const { content } = candidate;
12
- if (typeof content !== "string") {
13
- throw new TypeError(
14
- `systemPrompts[${i}]: content must be a string, got ${typeof content}`
15
- );
16
- }
17
- return p;
18
- });
19
- }
20
- export {
21
- normalizeSystemPrompts
22
- };
23
- //# sourceMappingURL=system-prompts.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"system-prompts.js","sources":["../../src/system-prompts.ts"],"sourcesContent":["/**\n * A single entry in `chat({ systemPrompts: [...] })`.\n *\n * Accepts a plain string (the common case) or a structured object that lets\n * providers attach typed metadata to the prompt — e.g. Anthropic\n * `cache_control` for prompt caching, future per-prompt safety overrides for\n * Gemini, etc.\n *\n * At the chat call site, `metadata` is narrowed by the adapter via\n * `~types['systemPromptMetadata']`. Providers that don't declare one inherit\n * the default `never`, which makes the field carry no meaningful value: TS\n * only accepts `undefined` there, and provider-foreign metadata that reaches\n * an adapter via JS / `as any` is silently dropped, never written to the\n * wire. For type-safe per-provider metadata, refer to the provider's\n * `<Provider>SystemPromptMetadata` interface (e.g. `AnthropicSystemPromptMetadata`).\n *\n * @example\n * // The 90% case — plain strings work everywhere.\n * systemPrompts: ['Be concise.', 'Cite sources.']\n *\n * @example\n * // Provider-specific metadata via the object form. No `satisfies` cast\n * // is needed — the adapter narrows the `metadata` field's type at the\n * // call site so users get autocomplete and structural checking\n * // automatically.\n * import { anthropicText } from '@tanstack/ai-anthropic'\n *\n * chat({\n * adapter: anthropicText(),\n * systemPrompts: [\n * {\n * content: 'Stable instructions — cache me.',\n * metadata: { cache_control: { type: 'ephemeral' } },\n * },\n * 'Volatile per-request instruction.',\n * ],\n * })\n */\nexport type SystemPrompt<TMetadata = unknown> =\n | string\n | {\n content: string\n metadata?: TMetadata\n }\n\n/**\n * Normalised shape adapters see after the chat layer turns string entries\n * into `{ content }` objects. Adapters call `normalizeSystemPrompts` once at\n * the top of their option-mapping pipeline so the rest of the code only has\n * to handle one shape.\n */\nexport interface NormalizedSystemPrompt<TMetadata = unknown> {\n content: string\n metadata?: TMetadata\n}\n\n/**\n * Normalise the public `systemPrompts` shape (`Array<string | { content, metadata? }>`)\n * to a homogenous `Array<{ content, metadata? }>`. Adapters use this so they\n * don't have to type-narrow string vs object inline.\n *\n * Returns an empty array (never `undefined`) so callers can chain `.map` /\n * `.join` without an extra null check.\n *\n * Throws a `TypeError` (naming the offending index) if an object-form entry's\n * `content` isn't a string. Public API boundary — callers reaching this\n * function through `as any` / external JS would otherwise stream a literal\n * `\"undefined\"` into the model's system prompt with no signal.\n */\nexport function normalizeSystemPrompts<TMetadata = unknown>(\n // Accept the wide public shape (`SystemPrompt<unknown>`) regardless of the\n // caller's `TMetadata`. Adapters know their own metadata shape; the\n // generic narrows the *output* so adapter code can read `p.metadata.X`\n // without an additional cast.\n prompts: ReadonlyArray<SystemPrompt> | undefined,\n): Array<NormalizedSystemPrompt<TMetadata>> {\n if (!prompts || prompts.length === 0) return []\n return prompts.map((p, i) => {\n if (typeof p === 'string') return { content: p }\n // Defence in depth: TypeScript narrows `p` to the object arm here, but\n // this function is a public API boundary that callers can reach via\n // plain JS or `as any`. Re-validate at runtime so we never stream a\n // literal `\"undefined\"` into the model.\n const candidate = p as unknown\n if (candidate === null || typeof candidate !== 'object') {\n throw new TypeError(\n `systemPrompts[${i}]: expected a string or { content, metadata? }, got ${candidate === null ? 'null' : typeof candidate}`,\n )\n }\n const { content } = candidate as { content?: unknown }\n if (typeof content !== 'string') {\n throw new TypeError(\n `systemPrompts[${i}]: content must be a string, got ${typeof content}`,\n )\n }\n return p as NormalizedSystemPrompt<TMetadata>\n })\n}\n"],"names":[],"mappings":"AAqEO,SAAS,uBAKd,SAC0C;AAC1C,MAAI,CAAC,WAAW,QAAQ,WAAW,UAAU,CAAA;AAC7C,SAAO,QAAQ,IAAI,CAAC,GAAG,MAAM;AAC3B,QAAI,OAAO,MAAM,SAAU,QAAO,EAAE,SAAS,EAAA;AAK7C,UAAM,YAAY;AAClB,QAAI,cAAc,QAAQ,OAAO,cAAc,UAAU;AACvD,YAAM,IAAI;AAAA,QACR,iBAAiB,CAAC,uDAAuD,cAAc,OAAO,SAAS,OAAO,SAAS;AAAA,MAAA;AAAA,IAE3H;AACA,UAAM,EAAE,YAAY;AACpB,QAAI,OAAO,YAAY,UAAU;AAC/B,YAAM,IAAI;AAAA,QACR,iBAAiB,CAAC,oCAAoC,OAAO,OAAO;AAAA,MAAA;AAAA,IAExE;AACA,WAAO;AAAA,EACT,CAAC;AACH;"}
@@ -1,81 +0,0 @@
1
- import { AnyTool } from './types.js';
2
- /**
3
- * A registry that holds tools and allows dynamic tool management.
4
- *
5
- * The registry can be either mutable (allowing additions/removals during execution)
6
- * or frozen (static tool list, for backward compatibility with tools arrays).
7
- */
8
- export interface ToolRegistry<TTool extends AnyTool = AnyTool> {
9
- /**
10
- * Get all current tools in the registry.
11
- * Called each agent loop iteration to get the latest tool list.
12
- */
13
- getTools: () => Array<TTool>;
14
- /**
15
- * Add a tool to the registry dynamically.
16
- * For frozen registries, this is a no-op.
17
- *
18
- * @param tool - The tool to add
19
- */
20
- add: (tool: TTool) => void;
21
- /**
22
- * Remove a tool from the registry by name.
23
- * For frozen registries, this always returns false.
24
- *
25
- * @param name - The name of the tool to remove
26
- * @returns true if the tool was removed, false if not found or frozen
27
- */
28
- remove: (name: string) => boolean;
29
- /**
30
- * Check if a tool exists in the registry.
31
- *
32
- * @param name - The name of the tool to check
33
- */
34
- has: (name: string) => boolean;
35
- /**
36
- * Get a tool by name.
37
- *
38
- * @param name - The name of the tool to get
39
- * @returns The tool if found, undefined otherwise
40
- */
41
- get: (name: string) => TTool | undefined;
42
- /**
43
- * Whether this registry is frozen (immutable).
44
- * Frozen registries don't allow add/remove operations.
45
- */
46
- readonly isFrozen: boolean;
47
- }
48
- /**
49
- * Create a mutable tool registry for dynamic tool scenarios.
50
- *
51
- * Tools can be added and removed during chat execution, and the
52
- * changes will be reflected in subsequent agent loop iterations.
53
- *
54
- * @param initialTools - Optional initial set of tools
55
- * @returns A mutable ToolRegistry
56
- *
57
- * @example
58
- * ```typescript
59
- * const registry = createToolRegistry([toolA, toolB])
60
- *
61
- * const stream = chat({
62
- * adapter,
63
- * messages,
64
- * toolRegistry: registry,
65
- * })
66
- *
67
- * // Later, during tool execution:
68
- * registry.add(newTool) // Immediately available to LLM
69
- * ```
70
- */
71
- export declare function createToolRegistry<TTool extends AnyTool = AnyTool>(initialTools?: Array<TTool>): ToolRegistry<TTool>;
72
- /**
73
- * Create a frozen (immutable) tool registry from a tools array.
74
- *
75
- * This is used internally to wrap static `tools` arrays for backward compatibility.
76
- * Add and remove operations are no-ops on frozen registries.
77
- *
78
- * @param tools - The static array of tools
79
- * @returns A frozen ToolRegistry
80
- */
81
- export declare function createFrozenRegistry<TTool extends AnyTool = AnyTool>(tools?: Array<TTool>): ToolRegistry<TTool>;
@@ -1,49 +0,0 @@
1
- function createToolRegistry(initialTools = []) {
2
- const tools = /* @__PURE__ */ new Map();
3
- for (const tool of initialTools) {
4
- tools.set(tool.name, tool);
5
- }
6
- return {
7
- getTools: () => Array.from(tools.values()),
8
- add: (tool) => {
9
- tools.set(tool.name, tool);
10
- },
11
- remove: (name) => {
12
- return tools.delete(name);
13
- },
14
- has: (name) => {
15
- return tools.has(name);
16
- },
17
- get: (name) => {
18
- return tools.get(name);
19
- },
20
- isFrozen: false
21
- };
22
- }
23
- function createFrozenRegistry(tools = []) {
24
- const toolMap = /* @__PURE__ */ new Map();
25
- for (const tool of tools) {
26
- toolMap.set(tool.name, tool);
27
- }
28
- const frozenTools = Object.freeze([...tools]);
29
- return {
30
- getTools: () => [...frozenTools],
31
- add: (_tool) => {
32
- },
33
- remove: (_name) => {
34
- return false;
35
- },
36
- has: (name) => {
37
- return toolMap.has(name);
38
- },
39
- get: (name) => {
40
- return toolMap.get(name);
41
- },
42
- isFrozen: true
43
- };
44
- }
45
- export {
46
- createFrozenRegistry,
47
- createToolRegistry
48
- };
49
- //# sourceMappingURL=tool-registry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool-registry.js","sources":["../../src/tool-registry.ts"],"sourcesContent":["import type { AnyTool } from './types'\n\n/**\n * A registry that holds tools and allows dynamic tool management.\n *\n * The registry can be either mutable (allowing additions/removals during execution)\n * or frozen (static tool list, for backward compatibility with tools arrays).\n */\nexport interface ToolRegistry<TTool extends AnyTool = AnyTool> {\n /**\n * Get all current tools in the registry.\n * Called each agent loop iteration to get the latest tool list.\n */\n getTools: () => Array<TTool>\n\n /**\n * Add a tool to the registry dynamically.\n * For frozen registries, this is a no-op.\n *\n * @param tool - The tool to add\n */\n add: (tool: TTool) => void\n\n /**\n * Remove a tool from the registry by name.\n * For frozen registries, this always returns false.\n *\n * @param name - The name of the tool to remove\n * @returns true if the tool was removed, false if not found or frozen\n */\n remove: (name: string) => boolean\n\n /**\n * Check if a tool exists in the registry.\n *\n * @param name - The name of the tool to check\n */\n has: (name: string) => boolean\n\n /**\n * Get a tool by name.\n *\n * @param name - The name of the tool to get\n * @returns The tool if found, undefined otherwise\n */\n get: (name: string) => TTool | undefined\n\n /**\n * Whether this registry is frozen (immutable).\n * Frozen registries don't allow add/remove operations.\n */\n readonly isFrozen: boolean\n}\n\n/**\n * Create a mutable tool registry for dynamic tool scenarios.\n *\n * Tools can be added and removed during chat execution, and the\n * changes will be reflected in subsequent agent loop iterations.\n *\n * @param initialTools - Optional initial set of tools\n * @returns A mutable ToolRegistry\n *\n * @example\n * ```typescript\n * const registry = createToolRegistry([toolA, toolB])\n *\n * const stream = chat({\n * adapter,\n * messages,\n * toolRegistry: registry,\n * })\n *\n * // Later, during tool execution:\n * registry.add(newTool) // Immediately available to LLM\n * ```\n */\nexport function createToolRegistry<TTool extends AnyTool = AnyTool>(\n initialTools: Array<TTool> = [],\n): ToolRegistry<TTool> {\n const tools = new Map<string, TTool>()\n\n for (const tool of initialTools) {\n tools.set(tool.name, tool)\n }\n\n return {\n getTools: () => Array.from(tools.values()),\n\n add: (tool: TTool) => {\n tools.set(tool.name, tool)\n },\n\n remove: (name: string) => {\n return tools.delete(name)\n },\n\n has: (name: string) => {\n return tools.has(name)\n },\n\n get: (name: string) => {\n return tools.get(name)\n },\n\n isFrozen: false,\n }\n}\n\n/**\n * Create a frozen (immutable) tool registry from a tools array.\n *\n * This is used internally to wrap static `tools` arrays for backward compatibility.\n * Add and remove operations are no-ops on frozen registries.\n *\n * @param tools - The static array of tools\n * @returns A frozen ToolRegistry\n */\nexport function createFrozenRegistry<TTool extends AnyTool = AnyTool>(\n tools: Array<TTool> = [],\n): ToolRegistry<TTool> {\n const toolMap = new Map<string, TTool>()\n\n for (const tool of tools) {\n toolMap.set(tool.name, tool)\n }\n\n const frozenTools = Object.freeze([...tools])\n\n return {\n getTools: () => [...frozenTools],\n\n add: (_tool: TTool) => {\n // No-op for frozen registry\n },\n\n remove: (_name: string) => {\n // No-op for frozen registry\n return false\n },\n\n has: (name: string) => {\n return toolMap.has(name)\n },\n\n get: (name: string) => {\n return toolMap.get(name)\n },\n\n isFrozen: true,\n }\n}\n"],"names":[],"mappings":"AA6EO,SAAS,mBACd,eAA6B,IACR;AACrB,QAAM,4BAAY,IAAA;AAElB,aAAW,QAAQ,cAAc;AAC/B,UAAM,IAAI,KAAK,MAAM,IAAI;AAAA,EAC3B;AAEA,SAAO;AAAA,IACL,UAAU,MAAM,MAAM,KAAK,MAAM,QAAQ;AAAA,IAEzC,KAAK,CAAC,SAAgB;AACpB,YAAM,IAAI,KAAK,MAAM,IAAI;AAAA,IAC3B;AAAA,IAEA,QAAQ,CAAC,SAAiB;AACxB,aAAO,MAAM,OAAO,IAAI;AAAA,IAC1B;AAAA,IAEA,KAAK,CAAC,SAAiB;AACrB,aAAO,MAAM,IAAI,IAAI;AAAA,IACvB;AAAA,IAEA,KAAK,CAAC,SAAiB;AACrB,aAAO,MAAM,IAAI,IAAI;AAAA,IACvB;AAAA,IAEA,UAAU;AAAA,EAAA;AAEd;AAWO,SAAS,qBACd,QAAsB,IACD;AACrB,QAAM,8BAAc,IAAA;AAEpB,aAAW,QAAQ,OAAO;AACxB,YAAQ,IAAI,KAAK,MAAM,IAAI;AAAA,EAC7B;AAEA,QAAM,cAAc,OAAO,OAAO,CAAC,GAAG,KAAK,CAAC;AAE5C,SAAO;AAAA,IACL,UAAU,MAAM,CAAC,GAAG,WAAW;AAAA,IAE/B,KAAK,CAAC,UAAiB;AAAA,IAEvB;AAAA,IAEA,QAAQ,CAAC,UAAkB;AAEzB,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,CAAC,SAAiB;AACrB,aAAO,QAAQ,IAAI,IAAI;AAAA,IACzB;AAAA,IAEA,KAAK,CAAC,SAAiB;AACrB,aAAO,QAAQ,IAAI,IAAI;AAAA,IACzB;AAAA,IAEA,UAAU;AAAA,EAAA;AAEd;"}
@@ -1,30 +0,0 @@
1
- import { Tool } from '../types.js';
2
- /**
3
- * A provider-specific tool produced by an adapter-package factory
4
- * (e.g. `webSearchTool` from `@tanstack/ai-anthropic/tools`).
5
- *
6
- * The two `~`-prefixed fields are type-only phantom brands — they are never
7
- * assigned at runtime. They allow the core type system to match a factory's
8
- * output against the selected model's `supports.tools` list and surface a
9
- * compile-time error when the combination is unsupported.
10
- *
11
- * User-defined tools (via `toolDefinition()`) remain plain `Tool` and stay
12
- * assignable to any model.
13
- *
14
- * @template TProvider - Provider identifier (e.g. `'anthropic'`, `'openai'`).
15
- * @template TKind - Canonical tool-kind string matching the provider's
16
- * `supports.tools` entries (e.g. `'web_search'`, `'code_execution'`).
17
- */
18
- export interface ProviderTool<TProvider extends string, TKind extends string> extends Tool {
19
- readonly '~provider': TProvider;
20
- readonly '~toolKind': TKind;
21
- }
22
- /**
23
- * Attach the `ProviderTool` phantom brand to a plain `Tool`-shaped object.
24
- *
25
- * The brand fields (`'~provider'`, `'~toolKind'`) exist only in the type
26
- * system and are never assigned at runtime, so this is a single audited
27
- * type-only assertion. Use it inside adapter `xxxTool()` factories instead
28
- * of `as unknown as` — the cast collapses to one named site.
29
- */
30
- export declare function brandProviderTool<T extends ProviderTool<string, string>>(tool: Omit<T, '~provider' | '~toolKind'>): T;
@@ -1,7 +0,0 @@
1
- function brandProviderTool(tool) {
2
- return tool;
3
- }
4
- export {
5
- brandProviderTool
6
- };
7
- //# sourceMappingURL=provider-tool.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"provider-tool.js","sources":["../../../src/tools/provider-tool.ts"],"sourcesContent":["import type { Tool } from '../types'\n\n/**\n * A provider-specific tool produced by an adapter-package factory\n * (e.g. `webSearchTool` from `@tanstack/ai-anthropic/tools`).\n *\n * The two `~`-prefixed fields are type-only phantom brands — they are never\n * assigned at runtime. They allow the core type system to match a factory's\n * output against the selected model's `supports.tools` list and surface a\n * compile-time error when the combination is unsupported.\n *\n * User-defined tools (via `toolDefinition()`) remain plain `Tool` and stay\n * assignable to any model.\n *\n * @template TProvider - Provider identifier (e.g. `'anthropic'`, `'openai'`).\n * @template TKind - Canonical tool-kind string matching the provider's\n * `supports.tools` entries (e.g. `'web_search'`, `'code_execution'`).\n */\nexport interface ProviderTool<\n TProvider extends string,\n TKind extends string,\n> extends Tool {\n readonly '~provider': TProvider\n readonly '~toolKind': TKind\n}\n\n/**\n * Attach the `ProviderTool` phantom brand to a plain `Tool`-shaped object.\n *\n * The brand fields (`'~provider'`, `'~toolKind'`) exist only in the type\n * system and are never assigned at runtime, so this is a single audited\n * type-only assertion. Use it inside adapter `xxxTool()` factories instead\n * of `as unknown as` — the cast collapses to one named site.\n */\nexport function brandProviderTool<T extends ProviderTool<string, string>>(\n tool: Omit<T, '~provider' | '~toolKind'>,\n): T {\n return tool as T\n}\n"],"names":[],"mappings":"AAkCO,SAAS,kBACd,MACG;AACH,SAAO;AACT;"}