@tanstack/ai 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -0
  3. package/dist/esm/base-adapter.d.ts +35 -0
  4. package/dist/esm/base-adapter.js +12 -0
  5. package/dist/esm/base-adapter.js.map +1 -0
  6. package/dist/esm/core/chat-common-options.d.ts +52 -0
  7. package/dist/esm/core/chat.d.ts +30 -0
  8. package/dist/esm/core/chat.js +533 -0
  9. package/dist/esm/core/chat.js.map +1 -0
  10. package/dist/esm/core/embedding.d.ts +8 -0
  11. package/dist/esm/core/embedding.js +33 -0
  12. package/dist/esm/core/embedding.js.map +1 -0
  13. package/dist/esm/core/summarize.d.ts +9 -0
  14. package/dist/esm/core/summarize.js +36 -0
  15. package/dist/esm/core/summarize.js.map +1 -0
  16. package/dist/esm/event-client.d.ts +311 -0
  17. package/dist/esm/event-client.js +62 -0
  18. package/dist/esm/event-client.js.map +1 -0
  19. package/dist/esm/index.d.ts +16 -0
  20. package/dist/esm/index.js +50 -0
  21. package/dist/esm/index.js.map +1 -0
  22. package/dist/esm/message-converters.d.ts +52 -0
  23. package/dist/esm/message-converters.js +162 -0
  24. package/dist/esm/message-converters.js.map +1 -0
  25. package/dist/esm/stream/index.d.ts +11 -0
  26. package/dist/esm/stream/json-parser.d.ts +38 -0
  27. package/dist/esm/stream/json-parser.js +28 -0
  28. package/dist/esm/stream/json-parser.js.map +1 -0
  29. package/dist/esm/stream/message-updaters.d.ts +44 -0
  30. package/dist/esm/stream/message-updaters.js +141 -0
  31. package/dist/esm/stream/message-updaters.js.map +1 -0
  32. package/dist/esm/stream/processor.d.ts +242 -0
  33. package/dist/esm/stream/processor.js +693 -0
  34. package/dist/esm/stream/processor.js.map +1 -0
  35. package/dist/esm/stream/strategies.d.ts +43 -0
  36. package/dist/esm/stream/strategies.js +54 -0
  37. package/dist/esm/stream/strategies.js.map +1 -0
  38. package/dist/esm/stream/types.d.ts +71 -0
  39. package/dist/esm/tools/tool-calls.d.ts +112 -0
  40. package/dist/esm/tools/tool-calls.js +302 -0
  41. package/dist/esm/tools/tool-calls.js.map +1 -0
  42. package/dist/esm/tools/tool-definition.d.ts +125 -0
  43. package/dist/esm/tools/tool-definition.js +25 -0
  44. package/dist/esm/tools/tool-definition.js.map +1 -0
  45. package/dist/esm/tools/zod-converter.d.ts +30 -0
  46. package/dist/esm/tools/zod-converter.js +36 -0
  47. package/dist/esm/tools/zod-converter.js.map +1 -0
  48. package/dist/esm/types.d.ts +619 -0
  49. package/dist/esm/utilities/agent-loop-strategies.d.ts +59 -0
  50. package/dist/esm/utilities/agent-loop-strategies.js +23 -0
  51. package/dist/esm/utilities/agent-loop-strategies.js.map +1 -0
  52. package/dist/esm/utilities/chat-options.d.ts +6 -0
  53. package/dist/esm/utilities/chat-options.js +7 -0
  54. package/dist/esm/utilities/chat-options.js.map +1 -0
  55. package/dist/esm/utilities/messages.d.ts +30 -0
  56. package/dist/esm/utilities/messages.js +7 -0
  57. package/dist/esm/utilities/messages.js.map +1 -0
  58. package/dist/esm/utilities/stream-to-response.d.ts +48 -0
  59. package/dist/esm/utilities/stream-to-response.js +62 -0
  60. package/dist/esm/utilities/stream-to-response.js.map +1 -0
  61. package/package.json +65 -0
  62. package/src/base-adapter.ts +85 -0
  63. package/src/core/chat-common-options.ts +55 -0
  64. package/src/core/chat.ts +771 -0
  65. package/src/core/embedding.ts +54 -0
  66. package/src/core/summarize.ts +56 -0
  67. package/src/event-client.ts +389 -0
  68. package/src/index.ts +68 -0
  69. package/src/message-converters.ts +285 -0
  70. package/src/stream/index.ts +41 -0
  71. package/src/stream/json-parser.ts +58 -0
  72. package/src/stream/message-updaters.ts +275 -0
  73. package/src/stream/processor.ts +1092 -0
  74. package/src/stream/strategies.ts +78 -0
  75. package/src/stream/types.ts +94 -0
  76. package/src/tools/tool-calls.ts +471 -0
  77. package/src/tools/tool-definition.ts +206 -0
  78. package/src/tools/zod-converter.ts +85 -0
  79. package/src/types.ts +872 -0
  80. package/src/utilities/agent-loop-strategies.ts +85 -0
  81. package/src/utilities/chat-options.ts +35 -0
  82. package/src/utilities/messages.ts +63 -0
  83. package/src/utilities/stream-to-response.ts +116 -0
@@ -0,0 +1,162 @@
1
+ function getTextContent(content) {
2
+ if (content === null) {
3
+ return "";
4
+ }
5
+ if (typeof content === "string") {
6
+ return content;
7
+ }
8
+ return content.filter((part) => part.type === "text").map((part) => part.content).join("");
9
+ }
10
+ function convertMessagesToModelMessages(messages) {
11
+ const modelMessages = [];
12
+ for (const msg of messages) {
13
+ if ("parts" in msg) {
14
+ modelMessages.push(...uiMessageToModelMessages(msg));
15
+ } else {
16
+ modelMessages.push(msg);
17
+ }
18
+ }
19
+ return modelMessages;
20
+ }
21
+ function uiMessageToModelMessages(uiMessage) {
22
+ const messages = [];
23
+ if (uiMessage.role === "system") {
24
+ return messages;
25
+ }
26
+ const textParts = [];
27
+ const toolCallParts = [];
28
+ const toolResultParts = [];
29
+ for (const part of uiMessage.parts) {
30
+ if (part.type === "text") {
31
+ textParts.push(part);
32
+ } else if (part.type === "tool-call") {
33
+ toolCallParts.push(part);
34
+ } else if (part.type === "tool-result") {
35
+ toolResultParts.push(part);
36
+ }
37
+ }
38
+ const content = textParts.map((p) => p.content).join("") || null;
39
+ const toolCalls = toolCallParts.length > 0 ? toolCallParts.filter(
40
+ (p) => p.state === "input-complete" || p.state === "approval-responded" || p.output !== void 0
41
+ // Include if has output (client tool result)
42
+ ).map((p) => ({
43
+ id: p.id,
44
+ type: "function",
45
+ function: {
46
+ name: p.name,
47
+ arguments: p.arguments
48
+ }
49
+ })) : void 0;
50
+ if (uiMessage.role !== "assistant" || content || !toolCalls) {
51
+ messages.push({
52
+ role: uiMessage.role,
53
+ content,
54
+ ...toolCalls && toolCalls.length > 0 && { toolCalls }
55
+ });
56
+ } else if (toolCalls.length > 0) {
57
+ messages.push({
58
+ role: "assistant",
59
+ content,
60
+ toolCalls
61
+ });
62
+ }
63
+ for (const toolResultPart of toolResultParts) {
64
+ if (toolResultPart.state === "complete" || toolResultPart.state === "error") {
65
+ messages.push({
66
+ role: "tool",
67
+ content: toolResultPart.content,
68
+ toolCallId: toolResultPart.toolCallId
69
+ });
70
+ }
71
+ }
72
+ return messages;
73
+ }
74
+ function modelMessageToUIMessage(modelMessage, id) {
75
+ const parts = [];
76
+ const textContent = getTextContent(modelMessage.content);
77
+ if (textContent) {
78
+ parts.push({
79
+ type: "text",
80
+ content: textContent
81
+ });
82
+ }
83
+ if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) {
84
+ for (const toolCall of modelMessage.toolCalls) {
85
+ parts.push({
86
+ type: "tool-call",
87
+ id: toolCall.id,
88
+ name: toolCall.function.name,
89
+ arguments: toolCall.function.arguments,
90
+ state: "input-complete"
91
+ // Model messages have complete arguments
92
+ });
93
+ }
94
+ }
95
+ if (modelMessage.role === "tool" && modelMessage.toolCallId) {
96
+ parts.push({
97
+ type: "tool-result",
98
+ toolCallId: modelMessage.toolCallId,
99
+ content: getTextContent(modelMessage.content),
100
+ state: "complete"
101
+ });
102
+ }
103
+ return {
104
+ id: id || generateMessageId(),
105
+ role: modelMessage.role === "tool" ? "assistant" : modelMessage.role,
106
+ parts
107
+ };
108
+ }
109
+ function modelMessagesToUIMessages(modelMessages) {
110
+ const uiMessages = [];
111
+ let currentAssistantMessage = null;
112
+ for (const msg of modelMessages) {
113
+ if (msg.role === "tool") {
114
+ if (currentAssistantMessage && currentAssistantMessage.role === "assistant") {
115
+ currentAssistantMessage.parts.push({
116
+ type: "tool-result",
117
+ toolCallId: msg.toolCallId,
118
+ content: getTextContent(msg.content),
119
+ state: "complete"
120
+ });
121
+ } else {
122
+ const toolResultUIMessage = modelMessageToUIMessage(msg);
123
+ uiMessages.push(toolResultUIMessage);
124
+ }
125
+ } else {
126
+ const uiMessage = modelMessageToUIMessage(msg);
127
+ uiMessages.push(uiMessage);
128
+ if (msg.role === "assistant") {
129
+ currentAssistantMessage = uiMessage;
130
+ } else {
131
+ currentAssistantMessage = null;
132
+ }
133
+ }
134
+ }
135
+ return uiMessages;
136
+ }
137
+ function normalizeToUIMessage(message, generateId) {
138
+ if ("parts" in message) {
139
+ return {
140
+ ...message,
141
+ id: message.id || generateId(),
142
+ createdAt: message.createdAt || /* @__PURE__ */ new Date()
143
+ };
144
+ } else {
145
+ return {
146
+ ...modelMessageToUIMessage(message, generateId()),
147
+ createdAt: /* @__PURE__ */ new Date()
148
+ };
149
+ }
150
+ }
151
+ function generateMessageId() {
152
+ return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`;
153
+ }
154
+ export {
155
+ convertMessagesToModelMessages,
156
+ generateMessageId,
157
+ modelMessageToUIMessage,
158
+ modelMessagesToUIMessages,
159
+ normalizeToUIMessage,
160
+ uiMessageToModelMessages
161
+ };
162
+ //# sourceMappingURL=message-converters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-converters.js","sources":["../../src/message-converters.ts"],"sourcesContent":["/**\n * Message Converters\n *\n * Functions for converting between UIMessage and ModelMessage formats.\n */\n\nimport type {\n ContentPart,\n MessagePart,\n ModelMessage,\n TextPart,\n ToolCallPart,\n ToolResultPart,\n UIMessage,\n} from './types'\n\n/**\n * Helper to extract text content from string or ContentPart array\n * For multimodal content, this extracts only the text parts\n */\nfunction getTextContent(content: string | null | Array<ContentPart>): string {\n if (content === null) {\n return ''\n }\n if (typeof content === 'string') {\n return content\n }\n // Extract text from ContentPart array\n return content\n .filter((part) => part.type === 'text')\n .map((part) => part.content)\n .join('')\n}\n\n/**\n * Convert UIMessages or ModelMessages to ModelMessages\n */\nexport function convertMessagesToModelMessages(\n messages: Array<UIMessage | ModelMessage>,\n): Array<ModelMessage> {\n const modelMessages: Array<ModelMessage> = []\n for (const msg of messages) {\n if ('parts' in msg) {\n // UIMessage - convert to ModelMessages\n modelMessages.push(...uiMessageToModelMessages(msg))\n } else {\n // Already ModelMessage\n modelMessages.push(msg)\n }\n }\n return modelMessages\n}\n\n/**\n * Convert a UIMessage to ModelMessage(s)\n *\n * This conversion handles the parts-based structure:\n * - Text parts → content field\n * - ToolCall parts → toolCalls array\n * - ToolResult parts → separate role=\"tool\" messages\n *\n * @param uiMessage - The UIMessage to convert\n * @returns An array of ModelMessages (may be multiple if tool results are present)\n */\nexport function uiMessageToModelMessages(\n uiMessage: UIMessage,\n): Array<ModelMessage> {\n const messages: Array<ModelMessage> = []\n\n // Skip system messages - they're handled via systemPrompts, not ModelMessages\n if (uiMessage.role === 'system') {\n return messages\n }\n\n // Separate parts by type\n // Note: thinking parts are UI-only and not included in ModelMessages\n const textParts: Array<TextPart> = []\n const toolCallParts: Array<ToolCallPart> = []\n const toolResultParts: Array<ToolResultPart> = []\n\n for (const part of uiMessage.parts) {\n if (part.type === 'text') {\n textParts.push(part)\n } else if (part.type === 'tool-call') {\n toolCallParts.push(part)\n } else if (part.type === 'tool-result') {\n toolResultParts.push(part)\n }\n // thinking parts are skipped - they're UI-only\n }\n\n // Build the main message (user or assistant)\n const content = textParts.map((p) => p.content).join('') || null\n const toolCalls =\n toolCallParts.length > 0\n ? toolCallParts\n .filter(\n (p) =>\n p.state === 'input-complete' ||\n p.state === 'approval-responded' ||\n p.output !== undefined, // Include if has output (client tool result)\n )\n .map((p) => ({\n id: p.id,\n type: 'function' as const,\n function: {\n name: p.name,\n arguments: p.arguments,\n },\n }))\n : undefined\n\n // Create the main message\n if (uiMessage.role !== 'assistant' || content || !toolCalls) {\n messages.push({\n role: uiMessage.role,\n content,\n ...(toolCalls && toolCalls.length > 0 && { toolCalls }),\n })\n } else if (toolCalls.length > 0) {\n // Assistant message with only tool calls\n messages.push({\n role: 'assistant',\n content,\n toolCalls,\n })\n }\n\n // Add tool result messages (only completed ones)\n for (const toolResultPart of toolResultParts) {\n if (\n toolResultPart.state === 'complete' ||\n toolResultPart.state === 'error'\n ) {\n messages.push({\n role: 'tool',\n content: toolResultPart.content,\n toolCallId: toolResultPart.toolCallId,\n })\n }\n }\n\n return messages\n}\n\n/**\n * Convert a ModelMessage to UIMessage\n *\n * This conversion creates a parts-based structure:\n * - content field → TextPart\n * - toolCalls array → ToolCallPart[]\n * - role=\"tool\" messages should be converted separately and merged\n *\n * @param modelMessage - The ModelMessage to convert\n * @param id - Optional ID for the UIMessage (generated if not provided)\n * @returns A UIMessage with parts\n */\nexport function modelMessageToUIMessage(\n modelMessage: ModelMessage,\n id?: string,\n): UIMessage {\n const parts: Array<MessagePart> = []\n\n // Handle content (convert multimodal content to text for UI)\n const textContent = getTextContent(modelMessage.content)\n if (textContent) {\n parts.push({\n type: 'text',\n content: textContent,\n })\n }\n\n // Handle tool calls\n if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) {\n for (const toolCall of modelMessage.toolCalls) {\n parts.push({\n type: 'tool-call',\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n state: 'input-complete', // Model messages have complete arguments\n })\n }\n }\n\n // Handle tool results (when role is \"tool\")\n if (modelMessage.role === 'tool' && modelMessage.toolCallId) {\n parts.push({\n type: 'tool-result',\n toolCallId: modelMessage.toolCallId,\n content: getTextContent(modelMessage.content),\n state: 'complete',\n })\n }\n\n return {\n id: id || generateMessageId(),\n role: modelMessage.role === 'tool' ? 'assistant' : modelMessage.role,\n parts,\n }\n}\n\n/**\n * Convert an array of ModelMessages to UIMessages\n *\n * This handles merging tool result messages with their corresponding assistant messages\n *\n * @param modelMessages - Array of ModelMessages to convert\n * @returns Array of UIMessages\n */\nexport function modelMessagesToUIMessages(\n modelMessages: Array<ModelMessage>,\n): Array<UIMessage> {\n const uiMessages: Array<UIMessage> = []\n let currentAssistantMessage: UIMessage | null = null\n\n for (const msg of modelMessages) {\n if (msg.role === 'tool') {\n // Tool result - merge into the last assistant message if possible\n if (\n currentAssistantMessage &&\n currentAssistantMessage.role === 'assistant'\n ) {\n currentAssistantMessage.parts.push({\n type: 'tool-result',\n toolCallId: msg.toolCallId!,\n content: getTextContent(msg.content),\n state: 'complete',\n })\n } else {\n // No assistant message to merge into, create a standalone one\n const toolResultUIMessage = modelMessageToUIMessage(msg)\n uiMessages.push(toolResultUIMessage)\n }\n } else {\n // Regular message\n const uiMessage = modelMessageToUIMessage(msg)\n uiMessages.push(uiMessage)\n\n // Track assistant messages for potential tool result merging\n if (msg.role === 'assistant') {\n currentAssistantMessage = uiMessage\n } else {\n currentAssistantMessage = null\n }\n }\n }\n\n return uiMessages\n}\n\n/**\n * Normalize a message (UIMessage or ModelMessage) to a UIMessage\n * Ensures the message has an ID and createdAt timestamp\n *\n * @param message - Either a UIMessage or ModelMessage\n * @param generateId - Function to generate a message ID if needed\n * @returns A UIMessage with guaranteed id and createdAt\n */\nexport function normalizeToUIMessage(\n message: UIMessage | ModelMessage,\n generateId: () => string,\n): UIMessage {\n if ('parts' in message) {\n // Already a UIMessage\n return {\n ...message,\n id: message.id || generateId(),\n createdAt: message.createdAt || new Date(),\n }\n } else {\n // ModelMessage - convert to UIMessage\n return {\n ...modelMessageToUIMessage(message, generateId()),\n createdAt: new Date(),\n }\n }\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`\n}\n"],"names":[],"mappings":"AAoBA,SAAS,eAAe,SAAqD;AAC3E,MAAI,YAAY,MAAM;AACpB,WAAO;AAAA,EACT;AACA,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,EACT;AAEA,SAAO,QACJ,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,EACrC,IAAI,CAAC,SAAS,KAAK,OAAO,EAC1B,KAAK,EAAE;AACZ;AAKO,SAAS,+BACd,UACqB;AACrB,QAAM,gBAAqC,CAAA;AAC3C,aAAW,OAAO,UAAU;AAC1B,QAAI,WAAW,KAAK;AAElB,oBAAc,KAAK,GAAG,yBAAyB,GAAG,CAAC;AAAA,IACrD,OAAO;AAEL,oBAAc,KAAK,GAAG;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;AAaO,SAAS,yBACd,WACqB;AACrB,QAAM,WAAgC,CAAA;AAGtC,MAAI,UAAU,SAAS,UAAU;AAC/B,WAAO;AAAA,EACT;AAIA,QAAM,YAA6B,CAAA;AACnC,QAAM,gBAAqC,CAAA;AAC3C,QAAM,kBAAyC,CAAA;AAE/C,aAAW,QAAQ,UAAU,OAAO;AAClC,QAAI,KAAK,SAAS,QAAQ;AACxB,gBAAU,KAAK,IAAI;AAAA,IACrB,WAAW,KAAK,SAAS,aAAa;AACpC,oBAAc,KAAK,IAAI;AAAA,IACzB,WAAW,KAAK,SAAS,eAAe;AACtC,sBAAgB,KAAK,IAAI;AAAA,IAC3B;AAAA,EAEF;AAGA,QAAM,UAAU,UAAU,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK;AAC5D,QAAM,YACJ,cAAc,SAAS,IACnB,cACG;AAAA,IACC,CAAC,MACC,EAAE,UAAU,oBACZ,EAAE,UAAU,wBACZ,EAAE,WAAW;AAAA;AAAA,EAAA,EAEhB,IAAI,CAAC,OAAO;AAAA,IACX,IAAI,EAAE;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,MACR,MAAM,EAAE;AAAA,MACR,WAAW,EAAE;AAAA,IAAA;AAAA,EACf,EACA,IACJ;AAGN,MAAI,UAAU,SAAS,eAAe,WAAW,CAAC,WAAW;AAC3D,aAAS,KAAK;AAAA,MACZ,MAAM,UAAU;AAAA,MAChB;AAAA,MACA,GAAI,aAAa,UAAU,SAAS,KAAK,EAAE,UAAA;AAAA,IAAU,CACtD;AAAA,EACH,WAAW,UAAU,SAAS,GAAG;AAE/B,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IAAA,CACD;AAAA,EACH;AAGA,aAAW,kBAAkB,iBAAiB;AAC5C,QACE,eAAe,UAAU,cACzB,eAAe,UAAU,SACzB;AACA,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,eAAe;AAAA,QACxB,YAAY,eAAe;AAAA,MAAA,CAC5B;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAcO,SAAS,wBACd,cACA,IACW;AACX,QAAM,QAA4B,CAAA;AAGlC,QAAM,cAAc,eAAe,aAAa,OAAO;AACvD,MAAI,aAAa;AACf,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAGA,MAAI,aAAa,aAAa,aAAa,UAAU,SAAS,GAAG;AAC/D,eAAW,YAAY,aAAa,WAAW;AAC7C,YAAM,KAAK;AAAA,QACT,MAAM;AAAA,QACN,IAAI,SAAS;AAAA,QACb,MAAM,SAAS,SAAS;AAAA,QACxB,WAAW,SAAS,SAAS;AAAA,QAC7B,OAAO;AAAA;AAAA,MAAA,CACR;AAAA,IACH;AAAA,EACF;AAGA,MAAI,aAAa,SAAS,UAAU,aAAa,YAAY;AAC3D,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,YAAY,aAAa;AAAA,MACzB,SAAS,eAAe,aAAa,OAAO;AAAA,MAC5C,OAAO;AAAA,IAAA,CACR;AAAA,EACH;AAEA,SAAO;AAAA,IACL,IAAI,MAAM,kBAAA;AAAA,IACV,MAAM,aAAa,SAAS,SAAS,cAAc,aAAa;AAAA,IAChE;AAAA,EAAA;AAEJ;AAUO,SAAS,0BACd,eACkB;AAClB,QAAM,aAA+B,CAAA;AACrC,MAAI,0BAA4C;AAEhD,aAAW,OAAO,eAAe;AAC/B,QAAI,IAAI,SAAS,QAAQ;AAEvB,UACE,2BACA,wBAAwB,SAAS,aACjC;AACA,gCAAwB,MAAM,KAAK;AAAA,UACjC,MAAM;AAAA,UACN,YAAY,IAAI;AAAA,UAChB,SAAS,eAAe,IAAI,OAAO;AAAA,UACnC,OAAO;AAAA,QAAA,CACR;AAAA,MACH,OAAO;AAEL,cAAM,sBAAsB,wBAAwB,GAAG;AACvD,mBAAW,KAAK,mBAAmB;AAAA,MACrC;AAAA,IACF,OAAO;AAEL,YAAM,YAAY,wBAAwB,GAAG;AAC7C,iBAAW,KAAK,SAAS;AAGzB,UAAI,IAAI,SAAS,aAAa;AAC5B,kCAA0B;AAAA,MAC5B,OAAO;AACL,kCAA0B;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAUO,SAAS,qBACd,SACA,YACW;AACX,MAAI,WAAW,SAAS;AAEtB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,IAAI,QAAQ,MAAM,WAAA;AAAA,MAClB,WAAW,QAAQ,aAAa,oBAAI,KAAA;AAAA,IAAK;AAAA,EAE7C,OAAO;AAEL,WAAO;AAAA,MACL,GAAG,wBAAwB,SAAS,YAAY;AAAA,MAChD,+BAAe,KAAA;AAAA,IAAK;AAAA,EAExB;AACF;AAKO,SAAS,oBAA4B;AAC1C,SAAO,OAAO,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,UAAU,CAAC,CAAC;AACrE;"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Stream Processing Module
3
+ *
4
+ * Unified stream processing for both server and client.
5
+ */
6
+ export { StreamProcessor, createReplayStream } from './processor.js';
7
+ export type { StreamProcessorEvents, StreamProcessorHandlers, StreamProcessorOptions, } from './processor.js';
8
+ export { ImmediateStrategy, PunctuationStrategy, BatchStrategy, WordBoundaryStrategy, CompositeStrategy, } from './strategies.js';
9
+ export { PartialJSONParser, defaultJSONParser, parsePartialJSON, } from './json-parser.js';
10
+ export type { JSONParser } from './json-parser.js';
11
+ export type { ChunkStrategy, ChunkRecording, InternalToolCallState, ProcessorResult, ProcessorState, ToolCallState, ToolResultState, } from './types.js';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * JSON Parser for partial/incomplete JSON strings
3
+ *
4
+ * Used during streaming to parse tool call arguments that may be incomplete.
5
+ */
6
+ /**
7
+ * JSON Parser interface - allows for custom parser implementations
8
+ */
9
+ export interface JSONParser {
10
+ /**
11
+ * Parse a JSON string (may be incomplete/partial)
12
+ * @param jsonString - The JSON string to parse
13
+ * @returns The parsed object, or undefined if parsing fails
14
+ */
15
+ parse: (jsonString: string) => any;
16
+ }
17
+ /**
18
+ * Partial JSON Parser implementation using the partial-json library
19
+ * This parser can handle incomplete JSON strings during streaming
20
+ */
21
+ export declare class PartialJSONParser implements JSONParser {
22
+ /**
23
+ * Parse a potentially incomplete JSON string
24
+ * @param jsonString - The JSON string to parse (may be incomplete)
25
+ * @returns The parsed object, or undefined if parsing fails
26
+ */
27
+ parse(jsonString: string): any;
28
+ }
29
+ /**
30
+ * Default parser instance
31
+ */
32
+ export declare const defaultJSONParser: PartialJSONParser;
33
+ /**
34
+ * Parse partial JSON string (convenience function)
35
+ * @param jsonString - The JSON string to parse (may be incomplete)
36
+ * @returns The parsed object, or undefined if parsing fails
37
+ */
38
+ export declare function parsePartialJSON(jsonString: string): any;
@@ -0,0 +1,28 @@
1
+ import { parse } from "partial-json";
2
+ class PartialJSONParser {
3
+ /**
4
+ * Parse a potentially incomplete JSON string
5
+ * @param jsonString - The JSON string to parse (may be incomplete)
6
+ * @returns The parsed object, or undefined if parsing fails
7
+ */
8
+ parse(jsonString) {
9
+ if (!jsonString || jsonString.trim() === "") {
10
+ return void 0;
11
+ }
12
+ try {
13
+ return parse(jsonString);
14
+ } catch {
15
+ return void 0;
16
+ }
17
+ }
18
+ }
19
+ const defaultJSONParser = new PartialJSONParser();
20
+ function parsePartialJSON(jsonString) {
21
+ return defaultJSONParser.parse(jsonString);
22
+ }
23
+ export {
24
+ PartialJSONParser,
25
+ defaultJSONParser,
26
+ parsePartialJSON
27
+ };
28
+ //# sourceMappingURL=json-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-parser.js","sources":["../../../src/stream/json-parser.ts"],"sourcesContent":["/**\n * JSON Parser for partial/incomplete JSON strings\n *\n * Used during streaming to parse tool call arguments that may be incomplete.\n */\n\nimport { parse as parsePartialJSONLib } from 'partial-json'\n\n/**\n * JSON Parser interface - allows for custom parser implementations\n */\nexport interface JSONParser {\n /**\n * Parse a JSON string (may be incomplete/partial)\n * @param jsonString - The JSON string to parse\n * @returns The parsed object, or undefined if parsing fails\n */\n parse: (jsonString: string) => any\n}\n\n/**\n * Partial JSON Parser implementation using the partial-json library\n * This parser can handle incomplete JSON strings during streaming\n */\nexport class PartialJSONParser implements JSONParser {\n /**\n * Parse a potentially incomplete JSON string\n * @param jsonString - The JSON string to parse (may be incomplete)\n * @returns The parsed object, or undefined if parsing fails\n */\n parse(jsonString: string): any {\n if (!jsonString || jsonString.trim() === '') {\n return undefined\n }\n\n try {\n return parsePartialJSONLib(jsonString)\n } catch {\n // If partial parsing fails, return undefined\n // This is expected during early streaming when we have very little data\n return undefined\n }\n }\n}\n\n/**\n * Default parser instance\n */\nexport const defaultJSONParser = new PartialJSONParser()\n\n/**\n * Parse partial JSON string (convenience function)\n * @param jsonString - The JSON string to parse (may be incomplete)\n * @returns The parsed object, or undefined if parsing fails\n */\nexport function parsePartialJSON(jsonString: string): any {\n return defaultJSONParser.parse(jsonString)\n}\n"],"names":["parsePartialJSONLib"],"mappings":";AAwBO,MAAM,kBAAwC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnD,MAAM,YAAyB;AAC7B,QAAI,CAAC,cAAc,WAAW,KAAA,MAAW,IAAI;AAC3C,aAAO;AAAA,IACT;AAEA,QAAI;AACF,aAAOA,MAAoB,UAAU;AAAA,IACvC,QAAQ;AAGN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAKO,MAAM,oBAAoB,IAAI,kBAAA;AAO9B,SAAS,iBAAiB,YAAyB;AACxD,SAAO,kBAAkB,MAAM,UAAU;AAC3C;"}
@@ -0,0 +1,44 @@
1
+ import { UIMessage } from '../types.js';
2
+ import { ToolCallState, ToolResultState } from './types.js';
3
+ /**
4
+ * Update or add a text part to a message.
5
+ *
6
+ * If the last part is a text part, update it (continuing the same text segment).
7
+ * Otherwise, create a new text part (starting a new text segment after tool calls).
8
+ */
9
+ export declare function updateTextPart(messages: Array<UIMessage>, messageId: string, content: string): Array<UIMessage>;
10
+ /**
11
+ * Update or add a tool call part to a message.
12
+ */
13
+ export declare function updateToolCallPart(messages: Array<UIMessage>, messageId: string, toolCall: {
14
+ id: string;
15
+ name: string;
16
+ arguments: string;
17
+ state: ToolCallState;
18
+ }): Array<UIMessage>;
19
+ /**
20
+ * Update or add a tool result part to a message.
21
+ */
22
+ export declare function updateToolResultPart(messages: Array<UIMessage>, messageId: string, toolCallId: string, content: string, state: ToolResultState, error?: string): Array<UIMessage>;
23
+ /**
24
+ * Update a tool call part with approval request metadata.
25
+ */
26
+ export declare function updateToolCallApproval(messages: Array<UIMessage>, messageId: string, toolCallId: string, approvalId: string): Array<UIMessage>;
27
+ /**
28
+ * Update a tool call part's state (e.g., to "input-complete").
29
+ */
30
+ export declare function updateToolCallState(messages: Array<UIMessage>, messageId: string, toolCallId: string, state: ToolCallState): Array<UIMessage>;
31
+ /**
32
+ * Update a tool call part with output.
33
+ * Searches all messages to find the tool call by ID.
34
+ */
35
+ export declare function updateToolCallWithOutput(messages: Array<UIMessage>, toolCallId: string, output: any, state?: ToolCallState, errorText?: string): Array<UIMessage>;
36
+ /**
37
+ * Update a tool call part with approval response.
38
+ * Searches all messages to find the tool call by approval ID.
39
+ */
40
+ export declare function updateToolCallApprovalResponse(messages: Array<UIMessage>, approvalId: string, approved: boolean): Array<UIMessage>;
41
+ /**
42
+ * Update or add a thinking part to a message.
43
+ */
44
+ export declare function updateThinkingPart(messages: Array<UIMessage>, messageId: string, content: string): Array<UIMessage>;
@@ -0,0 +1,141 @@
1
+ function updateTextPart(messages, messageId, content) {
2
+ return messages.map((msg) => {
3
+ if (msg.id !== messageId) {
4
+ return msg;
5
+ }
6
+ const parts = [...msg.parts];
7
+ const lastPart = parts.length > 0 ? parts[parts.length - 1] : null;
8
+ if (lastPart && lastPart.type === "text") {
9
+ parts[parts.length - 1] = { type: "text", content };
10
+ } else {
11
+ parts.push({ type: "text", content });
12
+ }
13
+ return { ...msg, parts };
14
+ });
15
+ }
16
+ function updateToolCallPart(messages, messageId, toolCall) {
17
+ return messages.map((msg) => {
18
+ if (msg.id !== messageId) {
19
+ return msg;
20
+ }
21
+ const parts = [...msg.parts];
22
+ const existingPartIndex = parts.findIndex(
23
+ (p) => p.type === "tool-call" && p.id === toolCall.id
24
+ );
25
+ const toolCallPart = {
26
+ type: "tool-call",
27
+ id: toolCall.id,
28
+ name: toolCall.name,
29
+ arguments: toolCall.arguments,
30
+ state: toolCall.state
31
+ };
32
+ if (existingPartIndex >= 0) {
33
+ parts[existingPartIndex] = toolCallPart;
34
+ } else {
35
+ parts.push(toolCallPart);
36
+ }
37
+ return { ...msg, parts };
38
+ });
39
+ }
40
+ function updateToolResultPart(messages, messageId, toolCallId, content, state, error) {
41
+ return messages.map((msg) => {
42
+ if (msg.id !== messageId) {
43
+ return msg;
44
+ }
45
+ const parts = [...msg.parts];
46
+ const resultPartIndex = parts.findIndex(
47
+ (p) => p.type === "tool-result" && p.toolCallId === toolCallId
48
+ );
49
+ const toolResultPart = {
50
+ type: "tool-result",
51
+ toolCallId,
52
+ content,
53
+ state,
54
+ ...error && { error }
55
+ };
56
+ if (resultPartIndex >= 0) {
57
+ parts[resultPartIndex] = toolResultPart;
58
+ } else {
59
+ parts.push(toolResultPart);
60
+ }
61
+ return { ...msg, parts };
62
+ });
63
+ }
64
+ function updateToolCallApproval(messages, messageId, toolCallId, approvalId) {
65
+ return messages.map((msg) => {
66
+ if (msg.id !== messageId) {
67
+ return msg;
68
+ }
69
+ const parts = [...msg.parts];
70
+ const toolCallPart = parts.find(
71
+ (p) => p.type === "tool-call" && p.id === toolCallId
72
+ );
73
+ if (toolCallPart) {
74
+ toolCallPart.state = "approval-requested";
75
+ toolCallPart.approval = {
76
+ id: approvalId,
77
+ needsApproval: true
78
+ };
79
+ }
80
+ return { ...msg, parts };
81
+ });
82
+ }
83
+ function updateToolCallWithOutput(messages, toolCallId, output, state, errorText) {
84
+ return messages.map((msg) => {
85
+ const parts = [...msg.parts];
86
+ const toolCallPart = parts.find(
87
+ (p) => p.type === "tool-call" && p.id === toolCallId
88
+ );
89
+ if (toolCallPart) {
90
+ toolCallPart.output = errorText ? { error: errorText } : output;
91
+ if (state) {
92
+ toolCallPart.state = state;
93
+ } else {
94
+ toolCallPart.state = "input-complete";
95
+ }
96
+ }
97
+ return { ...msg, parts };
98
+ });
99
+ }
100
+ function updateToolCallApprovalResponse(messages, approvalId, approved) {
101
+ return messages.map((msg) => {
102
+ const parts = [...msg.parts];
103
+ const toolCallPart = parts.find(
104
+ (p) => p.type === "tool-call" && p.approval?.id === approvalId
105
+ );
106
+ if (toolCallPart && toolCallPart.approval) {
107
+ toolCallPart.approval.approved = approved;
108
+ toolCallPart.state = "approval-responded";
109
+ }
110
+ return { ...msg, parts };
111
+ });
112
+ }
113
+ function updateThinkingPart(messages, messageId, content) {
114
+ return messages.map((msg) => {
115
+ if (msg.id !== messageId) {
116
+ return msg;
117
+ }
118
+ const parts = [...msg.parts];
119
+ const thinkingPartIndex = parts.findIndex((p) => p.type === "thinking");
120
+ const thinkingPart = {
121
+ type: "thinking",
122
+ content
123
+ };
124
+ if (thinkingPartIndex >= 0) {
125
+ parts[thinkingPartIndex] = thinkingPart;
126
+ } else {
127
+ parts.push(thinkingPart);
128
+ }
129
+ return { ...msg, parts };
130
+ });
131
+ }
132
+ export {
133
+ updateTextPart,
134
+ updateThinkingPart,
135
+ updateToolCallApproval,
136
+ updateToolCallApprovalResponse,
137
+ updateToolCallPart,
138
+ updateToolCallWithOutput,
139
+ updateToolResultPart
140
+ };
141
+ //# sourceMappingURL=message-updaters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-updaters.js","sources":["../../../src/stream/message-updaters.ts"],"sourcesContent":["/**\n * Message Updaters (Internal)\n *\n * Internal helper functions for updating UIMessage parts.\n * These are used by StreamProcessor to manage the message array.\n */\n\nimport type {\n ThinkingPart,\n ToolCallPart,\n ToolResultPart,\n UIMessage,\n} from '../types'\nimport type { ToolCallState, ToolResultState } from './types'\n\n/**\n * Update or add a text part to a message.\n *\n * If the last part is a text part, update it (continuing the same text segment).\n * Otherwise, create a new text part (starting a new text segment after tool calls).\n */\nexport function updateTextPart(\n messages: Array<UIMessage>,\n messageId: string,\n content: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const lastPart = parts.length > 0 ? parts[parts.length - 1] : null\n\n if (lastPart && lastPart.type === 'text') {\n // Update the last text part (continuing same text segment)\n parts[parts.length - 1] = { type: 'text', content }\n } else {\n // Create new text part (starting new text segment after tool calls/results)\n parts.push({ type: 'text', content })\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a tool call part to a message.\n */\nexport function updateToolCallPart(\n messages: Array<UIMessage>,\n messageId: string,\n toolCall: {\n id: string\n name: string\n arguments: string\n state: ToolCallState\n },\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n // Find by ID, not index!\n const existingPartIndex = parts.findIndex(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCall.id,\n )\n\n const toolCallPart: ToolCallPart = {\n type: 'tool-call',\n id: toolCall.id,\n name: toolCall.name,\n arguments: toolCall.arguments,\n state: toolCall.state,\n }\n\n if (existingPartIndex >= 0) {\n // Update existing tool call\n parts[existingPartIndex] = toolCallPart\n } else {\n // Add new tool call at the end (preserve natural streaming order)\n parts.push(toolCallPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a tool result part to a message.\n */\nexport function updateToolResultPart(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n content: string,\n state: ToolResultState,\n error?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const resultPartIndex = parts.findIndex(\n (p): p is ToolResultPart =>\n p.type === 'tool-result' && p.toolCallId === toolCallId,\n )\n\n const toolResultPart: ToolResultPart = {\n type: 'tool-result',\n toolCallId,\n content,\n state,\n ...(error && { error }),\n }\n\n if (resultPartIndex >= 0) {\n parts[resultPartIndex] = toolResultPart\n } else {\n parts.push(toolResultPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with approval request metadata.\n */\nexport function updateToolCallApproval(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n approvalId: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n toolCallPart.state = 'approval-requested'\n toolCallPart.approval = {\n id: approvalId,\n needsApproval: true,\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part's state (e.g., to \"input-complete\").\n */\nexport function updateToolCallState(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n state: ToolCallState,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n toolCallPart.state = state\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with output.\n * Searches all messages to find the tool call by ID.\n */\nexport function updateToolCallWithOutput(\n messages: Array<UIMessage>,\n toolCallId: string,\n output: any,\n state?: ToolCallState,\n errorText?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n toolCallPart.output = errorText ? { error: errorText } : output\n if (state) {\n toolCallPart.state = state\n } else {\n toolCallPart.state = 'input-complete'\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with approval response.\n * Searches all messages to find the tool call by approval ID.\n */\nexport function updateToolCallApprovalResponse(\n messages: Array<UIMessage>,\n approvalId: string,\n approved: boolean,\n): Array<UIMessage> {\n return messages.map((msg) => {\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart =>\n p.type === 'tool-call' && p.approval?.id === approvalId,\n )\n\n if (toolCallPart && toolCallPart.approval) {\n toolCallPart.approval.approved = approved\n toolCallPart.state = 'approval-responded'\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a thinking part to a message.\n */\nexport function updateThinkingPart(\n messages: Array<UIMessage>,\n messageId: string,\n content: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const thinkingPartIndex = parts.findIndex((p) => p.type === 'thinking')\n\n const thinkingPart: ThinkingPart = {\n type: 'thinking',\n content,\n }\n\n if (thinkingPartIndex >= 0) {\n // Update existing thinking part\n parts[thinkingPartIndex] = thinkingPart\n } else {\n // Add new thinking part at the end (preserve natural streaming order)\n parts.push(thinkingPart)\n }\n\n return { ...msg, parts }\n })\n}\n"],"names":[],"mappings":"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"}