@tambo-ai/client 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 (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +100 -0
  3. package/dist/index.d.ts +43 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +78 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/mcp/elicitation.d.ts +59 -0
  8. package/dist/mcp/elicitation.d.ts.map +1 -0
  9. package/dist/mcp/elicitation.js +27 -0
  10. package/dist/mcp/elicitation.js.map +1 -0
  11. package/dist/mcp/index.d.ts +6 -0
  12. package/dist/mcp/index.d.ts.map +1 -0
  13. package/dist/mcp/index.js +14 -0
  14. package/dist/mcp/index.js.map +1 -0
  15. package/dist/mcp/mcp-client.d.ts +185 -0
  16. package/dist/mcp/mcp-client.d.ts.map +1 -0
  17. package/dist/mcp/mcp-client.js +219 -0
  18. package/dist/mcp/mcp-client.js.map +1 -0
  19. package/dist/mcp/mcp-constants.d.ts +19 -0
  20. package/dist/mcp/mcp-constants.d.ts.map +1 -0
  21. package/dist/mcp/mcp-constants.js +21 -0
  22. package/dist/mcp/mcp-constants.js.map +1 -0
  23. package/dist/model/component-metadata.d.ts +390 -0
  24. package/dist/model/component-metadata.d.ts.map +1 -0
  25. package/dist/model/component-metadata.js +3 -0
  26. package/dist/model/component-metadata.js.map +1 -0
  27. package/dist/model/mcp-server-info.d.ts +72 -0
  28. package/dist/model/mcp-server-info.d.ts.map +1 -0
  29. package/dist/model/mcp-server-info.js +29 -0
  30. package/dist/model/mcp-server-info.js.map +1 -0
  31. package/dist/schema/index.d.ts +5 -0
  32. package/dist/schema/index.d.ts.map +1 -0
  33. package/dist/schema/index.js +15 -0
  34. package/dist/schema/index.js.map +1 -0
  35. package/dist/schema/json-schema.d.ts +42 -0
  36. package/dist/schema/json-schema.d.ts.map +1 -0
  37. package/dist/schema/json-schema.js +114 -0
  38. package/dist/schema/json-schema.js.map +1 -0
  39. package/dist/schema/schema.d.ts +49 -0
  40. package/dist/schema/schema.d.ts.map +1 -0
  41. package/dist/schema/schema.js +129 -0
  42. package/dist/schema/schema.js.map +1 -0
  43. package/dist/schema/standard-schema.d.ts +22 -0
  44. package/dist/schema/standard-schema.d.ts.map +1 -0
  45. package/dist/schema/standard-schema.js +42 -0
  46. package/dist/schema/standard-schema.js.map +1 -0
  47. package/dist/schema/validate.d.ts +14 -0
  48. package/dist/schema/validate.d.ts.map +1 -0
  49. package/dist/schema/validate.js +148 -0
  50. package/dist/schema/validate.js.map +1 -0
  51. package/dist/tambo-client.d.ts +292 -0
  52. package/dist/tambo-client.d.ts.map +1 -0
  53. package/dist/tambo-client.js +508 -0
  54. package/dist/tambo-client.js.map +1 -0
  55. package/dist/tambo-stream.d.ts +112 -0
  56. package/dist/tambo-stream.d.ts.map +1 -0
  57. package/dist/tambo-stream.js +345 -0
  58. package/dist/tambo-stream.js.map +1 -0
  59. package/dist/types/auth.d.ts +24 -0
  60. package/dist/types/auth.d.ts.map +1 -0
  61. package/dist/types/auth.js +3 -0
  62. package/dist/types/auth.js.map +1 -0
  63. package/dist/types/event.d.ts +89 -0
  64. package/dist/types/event.d.ts.map +1 -0
  65. package/dist/types/event.js +57 -0
  66. package/dist/types/event.js.map +1 -0
  67. package/dist/types/message.d.ts +122 -0
  68. package/dist/types/message.d.ts.map +1 -0
  69. package/dist/types/message.js +10 -0
  70. package/dist/types/message.js.map +1 -0
  71. package/dist/types/thread.d.ts +58 -0
  72. package/dist/types/thread.d.ts.map +1 -0
  73. package/dist/types/thread.js +9 -0
  74. package/dist/types/thread.js.map +1 -0
  75. package/dist/types/tool-choice.d.ts +8 -0
  76. package/dist/types/tool-choice.d.ts.map +1 -0
  77. package/dist/types/tool-choice.js +3 -0
  78. package/dist/types/tool-choice.js.map +1 -0
  79. package/dist/utils/event-accumulator.d.ts +165 -0
  80. package/dist/utils/event-accumulator.d.ts.map +1 -0
  81. package/dist/utils/event-accumulator.js +1278 -0
  82. package/dist/utils/event-accumulator.js.map +1 -0
  83. package/dist/utils/json-patch.d.ts +18 -0
  84. package/dist/utils/json-patch.d.ts.map +1 -0
  85. package/dist/utils/json-patch.js +35 -0
  86. package/dist/utils/json-patch.js.map +1 -0
  87. package/dist/utils/keyed-throttle.d.ts +42 -0
  88. package/dist/utils/keyed-throttle.d.ts.map +1 -0
  89. package/dist/utils/keyed-throttle.js +86 -0
  90. package/dist/utils/keyed-throttle.js.map +1 -0
  91. package/dist/utils/registry-conversion.d.ts +53 -0
  92. package/dist/utils/registry-conversion.d.ts.map +1 -0
  93. package/dist/utils/registry-conversion.js +115 -0
  94. package/dist/utils/registry-conversion.js.map +1 -0
  95. package/dist/utils/send-message.d.ts +140 -0
  96. package/dist/utils/send-message.d.ts.map +1 -0
  97. package/dist/utils/send-message.js +183 -0
  98. package/dist/utils/send-message.js.map +1 -0
  99. package/dist/utils/stream-handler.d.ts +45 -0
  100. package/dist/utils/stream-handler.d.ts.map +1 -0
  101. package/dist/utils/stream-handler.js +47 -0
  102. package/dist/utils/stream-handler.js.map +1 -0
  103. package/dist/utils/thread-utils.d.ts +16 -0
  104. package/dist/utils/thread-utils.d.ts.map +1 -0
  105. package/dist/utils/thread-utils.js +34 -0
  106. package/dist/utils/thread-utils.js.map +1 -0
  107. package/dist/utils/tool-call-tracker.d.ts +74 -0
  108. package/dist/utils/tool-call-tracker.d.ts.map +1 -0
  109. package/dist/utils/tool-call-tracker.js +181 -0
  110. package/dist/utils/tool-call-tracker.js.map +1 -0
  111. package/dist/utils/tool-executor.d.ts +67 -0
  112. package/dist/utils/tool-executor.d.ts.map +1 -0
  113. package/dist/utils/tool-executor.js +160 -0
  114. package/dist/utils/tool-executor.js.map +1 -0
  115. package/dist/utils/unstrictify.d.ts +32 -0
  116. package/dist/utils/unstrictify.d.ts.map +1 -0
  117. package/dist/utils/unstrictify.js +160 -0
  118. package/dist/utils/unstrictify.js.map +1 -0
  119. package/esm/index.d.ts +43 -0
  120. package/esm/index.d.ts.map +1 -0
  121. package/esm/index.js +78 -0
  122. package/esm/index.js.map +1 -0
  123. package/esm/mcp/elicitation.d.ts +59 -0
  124. package/esm/mcp/elicitation.d.ts.map +1 -0
  125. package/esm/mcp/elicitation.js +27 -0
  126. package/esm/mcp/elicitation.js.map +1 -0
  127. package/esm/mcp/index.d.ts +6 -0
  128. package/esm/mcp/index.d.ts.map +1 -0
  129. package/esm/mcp/index.js +14 -0
  130. package/esm/mcp/index.js.map +1 -0
  131. package/esm/mcp/mcp-client.d.ts +185 -0
  132. package/esm/mcp/mcp-client.d.ts.map +1 -0
  133. package/esm/mcp/mcp-client.js +219 -0
  134. package/esm/mcp/mcp-client.js.map +1 -0
  135. package/esm/mcp/mcp-constants.d.ts +19 -0
  136. package/esm/mcp/mcp-constants.d.ts.map +1 -0
  137. package/esm/mcp/mcp-constants.js +21 -0
  138. package/esm/mcp/mcp-constants.js.map +1 -0
  139. package/esm/model/component-metadata.d.ts +390 -0
  140. package/esm/model/component-metadata.d.ts.map +1 -0
  141. package/esm/model/component-metadata.js +3 -0
  142. package/esm/model/component-metadata.js.map +1 -0
  143. package/esm/model/mcp-server-info.d.ts +72 -0
  144. package/esm/model/mcp-server-info.d.ts.map +1 -0
  145. package/esm/model/mcp-server-info.js +29 -0
  146. package/esm/model/mcp-server-info.js.map +1 -0
  147. package/esm/schema/index.d.ts +5 -0
  148. package/esm/schema/index.d.ts.map +1 -0
  149. package/esm/schema/index.js +15 -0
  150. package/esm/schema/index.js.map +1 -0
  151. package/esm/schema/json-schema.d.ts +42 -0
  152. package/esm/schema/json-schema.d.ts.map +1 -0
  153. package/esm/schema/json-schema.js +114 -0
  154. package/esm/schema/json-schema.js.map +1 -0
  155. package/esm/schema/schema.d.ts +49 -0
  156. package/esm/schema/schema.d.ts.map +1 -0
  157. package/esm/schema/schema.js +129 -0
  158. package/esm/schema/schema.js.map +1 -0
  159. package/esm/schema/standard-schema.d.ts +22 -0
  160. package/esm/schema/standard-schema.d.ts.map +1 -0
  161. package/esm/schema/standard-schema.js +42 -0
  162. package/esm/schema/standard-schema.js.map +1 -0
  163. package/esm/schema/validate.d.ts +14 -0
  164. package/esm/schema/validate.d.ts.map +1 -0
  165. package/esm/schema/validate.js +148 -0
  166. package/esm/schema/validate.js.map +1 -0
  167. package/esm/tambo-client.d.ts +292 -0
  168. package/esm/tambo-client.d.ts.map +1 -0
  169. package/esm/tambo-client.js +508 -0
  170. package/esm/tambo-client.js.map +1 -0
  171. package/esm/tambo-stream.d.ts +112 -0
  172. package/esm/tambo-stream.d.ts.map +1 -0
  173. package/esm/tambo-stream.js +345 -0
  174. package/esm/tambo-stream.js.map +1 -0
  175. package/esm/types/auth.d.ts +24 -0
  176. package/esm/types/auth.d.ts.map +1 -0
  177. package/esm/types/auth.js +3 -0
  178. package/esm/types/auth.js.map +1 -0
  179. package/esm/types/event.d.ts +89 -0
  180. package/esm/types/event.d.ts.map +1 -0
  181. package/esm/types/event.js +57 -0
  182. package/esm/types/event.js.map +1 -0
  183. package/esm/types/message.d.ts +122 -0
  184. package/esm/types/message.d.ts.map +1 -0
  185. package/esm/types/message.js +10 -0
  186. package/esm/types/message.js.map +1 -0
  187. package/esm/types/thread.d.ts +58 -0
  188. package/esm/types/thread.d.ts.map +1 -0
  189. package/esm/types/thread.js +9 -0
  190. package/esm/types/thread.js.map +1 -0
  191. package/esm/types/tool-choice.d.ts +8 -0
  192. package/esm/types/tool-choice.d.ts.map +1 -0
  193. package/esm/types/tool-choice.js +3 -0
  194. package/esm/types/tool-choice.js.map +1 -0
  195. package/esm/utils/event-accumulator.d.ts +165 -0
  196. package/esm/utils/event-accumulator.d.ts.map +1 -0
  197. package/esm/utils/event-accumulator.js +1278 -0
  198. package/esm/utils/event-accumulator.js.map +1 -0
  199. package/esm/utils/json-patch.d.ts +18 -0
  200. package/esm/utils/json-patch.d.ts.map +1 -0
  201. package/esm/utils/json-patch.js +35 -0
  202. package/esm/utils/json-patch.js.map +1 -0
  203. package/esm/utils/keyed-throttle.d.ts +42 -0
  204. package/esm/utils/keyed-throttle.d.ts.map +1 -0
  205. package/esm/utils/keyed-throttle.js +86 -0
  206. package/esm/utils/keyed-throttle.js.map +1 -0
  207. package/esm/utils/registry-conversion.d.ts +53 -0
  208. package/esm/utils/registry-conversion.d.ts.map +1 -0
  209. package/esm/utils/registry-conversion.js +115 -0
  210. package/esm/utils/registry-conversion.js.map +1 -0
  211. package/esm/utils/send-message.d.ts +140 -0
  212. package/esm/utils/send-message.d.ts.map +1 -0
  213. package/esm/utils/send-message.js +183 -0
  214. package/esm/utils/send-message.js.map +1 -0
  215. package/esm/utils/stream-handler.d.ts +45 -0
  216. package/esm/utils/stream-handler.d.ts.map +1 -0
  217. package/esm/utils/stream-handler.js +47 -0
  218. package/esm/utils/stream-handler.js.map +1 -0
  219. package/esm/utils/thread-utils.d.ts +16 -0
  220. package/esm/utils/thread-utils.d.ts.map +1 -0
  221. package/esm/utils/thread-utils.js +34 -0
  222. package/esm/utils/thread-utils.js.map +1 -0
  223. package/esm/utils/tool-call-tracker.d.ts +74 -0
  224. package/esm/utils/tool-call-tracker.d.ts.map +1 -0
  225. package/esm/utils/tool-call-tracker.js +181 -0
  226. package/esm/utils/tool-call-tracker.js.map +1 -0
  227. package/esm/utils/tool-executor.d.ts +67 -0
  228. package/esm/utils/tool-executor.d.ts.map +1 -0
  229. package/esm/utils/tool-executor.js +160 -0
  230. package/esm/utils/tool-executor.js.map +1 -0
  231. package/esm/utils/unstrictify.d.ts +32 -0
  232. package/esm/utils/unstrictify.d.ts.map +1 -0
  233. package/esm/utils/unstrictify.js +160 -0
  234. package/esm/utils/unstrictify.js.map +1 -0
  235. package/package.json +90 -0
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Send Message Utilities
3
+ *
4
+ * Framework-agnostic functions for sending messages and handling streaming
5
+ * responses. Extracted from the React SDK's useTamboSendMessage hook to enable
6
+ * reuse across different UI frameworks.
7
+ */
8
+ import type TamboAI from "@tambo-ai/typescript-sdk";
9
+ import type { Stream } from "@tambo-ai/typescript-sdk/core/streaming";
10
+ import type { ToolResultContent } from "@tambo-ai/typescript-sdk/resources/threads/threads";
11
+ import type { RunAwaitingInputEvent } from "../types/event";
12
+ import type { InitialInputMessage, InputMessage } from "../types/message";
13
+ import type { ToolChoice } from "../types/tool-choice";
14
+ import type { StreamAction } from "./event-accumulator";
15
+ import type { ComponentRegistry, TamboToolRegistry } from "../model/component-metadata";
16
+ import type { ToolCallTracker } from "./tool-call-tracker";
17
+ /**
18
+ * Stream type for run responses on an existing thread.
19
+ */
20
+ export type RunStream = Stream<TamboAI.Threads.Runs.RunRunResponse>;
21
+ /**
22
+ * Stream type for creating a new thread with a run.
23
+ */
24
+ export type CreateStream = Stream<TamboAI.Threads.Runs.RunCreateResponse>;
25
+ /**
26
+ * Options for sending a message.
27
+ */
28
+ export interface SendMessageOptions {
29
+ /** The message to send. */
30
+ message: InputMessage;
31
+ /**
32
+ * User message text for optimistic display.
33
+ * If provided, synthetic AG-UI events will be dispatched to show
34
+ * the user message in the thread immediately after getting the threadId.
35
+ */
36
+ userMessageText?: string;
37
+ /** Enable debug logging for the stream. */
38
+ debug?: boolean;
39
+ /**
40
+ * How the model should use tools. Defaults to "auto".
41
+ * - "auto": Model decides whether to use tools
42
+ * - "required": Model must use at least one tool
43
+ * - "none": Model cannot use tools
44
+ * - { name: "toolName" }: Model must use the specified tool
45
+ */
46
+ toolChoice?: ToolChoice;
47
+ }
48
+ /**
49
+ * Parameters for creating a run stream.
50
+ */
51
+ export interface CreateRunStreamParams {
52
+ client: TamboAI;
53
+ threadId: string | undefined;
54
+ message: InputMessage;
55
+ componentList: ComponentRegistry;
56
+ toolRegistry: TamboToolRegistry;
57
+ userKey: string | undefined;
58
+ /**
59
+ * Previous run ID for continuing a thread with existing messages.
60
+ * Required when threadId is provided and the thread has previous runs.
61
+ */
62
+ previousRunId: string | undefined;
63
+ /**
64
+ * Additional context gathered from context helpers (including interactables).
65
+ * Merged into the message's additionalContext before sending.
66
+ */
67
+ additionalContext?: Record<string, unknown>;
68
+ /** How the model should use tools. */
69
+ toolChoice?: ToolChoice;
70
+ /**
71
+ * Initial messages to seed the thread with when creating a new thread.
72
+ * Only used when threadId is undefined (new thread creation).
73
+ */
74
+ initialMessages?: InitialInputMessage[];
75
+ }
76
+ /**
77
+ * Result from creating a run stream.
78
+ */
79
+ export interface CreateRunStreamResult {
80
+ stream: RunStream | CreateStream;
81
+ initialThreadId: string | undefined;
82
+ }
83
+ /**
84
+ * Parameters for executing tools and continuing the run.
85
+ */
86
+ export interface ExecuteToolsParams {
87
+ event: RunAwaitingInputEvent;
88
+ toolTracker: ToolCallTracker;
89
+ toolRegistry: TamboToolRegistry;
90
+ componentList: ComponentRegistry;
91
+ client: TamboAI;
92
+ threadId: string;
93
+ runId: string;
94
+ userKey: string | undefined;
95
+ additionalContext?: Record<string, unknown>;
96
+ toolChoice?: ToolChoice;
97
+ }
98
+ /**
99
+ * Result from executing tools and continuing the run.
100
+ */
101
+ export interface ExecuteToolsResult {
102
+ stream: RunStream;
103
+ toolResults: ToolResultContent[];
104
+ }
105
+ /**
106
+ * Dispatches synthetic AG-UI events to show a user message in the thread.
107
+ * @param dispatch - Stream state dispatcher
108
+ * @param targetThreadId - Thread to add the message to
109
+ * @param messageId - Stable ID for the user message
110
+ * @param messageText - Text content of the message
111
+ */
112
+ export declare function dispatchUserMessage(dispatch: (action: StreamAction) => void, targetThreadId: string, messageId: string, messageText: string): void;
113
+ /**
114
+ * Dispatches synthetic events for tool results as optimistic local state.
115
+ * The server doesn't echo these back for client-side tools.
116
+ * @param dispatch - Stream state dispatcher
117
+ * @param targetThreadId - Thread to add results to
118
+ * @param toolResults - Tool execution results to dispatch
119
+ */
120
+ export declare function dispatchToolResults(dispatch: (action: StreamAction) => void, targetThreadId: string, toolResults: ToolResultContent[]): void;
121
+ /**
122
+ * Creates a run stream by calling the appropriate API method.
123
+ *
124
+ * If threadId is provided, runs on existing thread via client.threads.runs.run().
125
+ * If no threadId, creates new thread via client.threads.runs.create().
126
+ * @param params - The parameters for creating the run stream
127
+ * @returns The stream and initial thread ID (undefined if creating new thread)
128
+ */
129
+ export declare function createRunStream(params: CreateRunStreamParams): Promise<CreateRunStreamResult>;
130
+ /**
131
+ * Executes pending tools and returns a continuation stream.
132
+ *
133
+ * This function does NOT process the continuation stream - it just executes
134
+ * the tools and returns the new stream for the caller to process. This enables
135
+ * the flat loop pattern that correctly handles multi-round tool execution.
136
+ * @param params - The parameters for tool execution
137
+ * @returns The continuation stream and tool results for optimistic local state updates
138
+ */
139
+ export declare function executeToolsAndContinue(params: ExecuteToolsParams): Promise<ExecuteToolsResult>;
140
+ //# sourceMappingURL=send-message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-message.d.ts","sourceRoot":"","sources":["../../src/utils/send-message.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oDAAoD,CAAC;AAG5F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,2BAA2B;IAC3B,OAAO,EAAE,YAAY,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,aAAa,EAAE,iBAAiB,CAAC;IACjC,YAAY,EAAE,iBAAiB,CAAC;IAChC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B;;;OAGG;IACH,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,sCAAsC;IACtC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,SAAS,GAAG,YAAY,CAAC;IACjC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,qBAAqB,CAAC;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,YAAY,EAAE,iBAAiB,CAAC;IAChC,aAAa,EAAE,iBAAiB,CAAC;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,iBAAiB,EAAE,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,EACxC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,IAAI,CA6BN;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,EACxC,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,iBAAiB,EAAE,GAC/B,IAAI,CAwCN;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CA6DhC;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CA2C7B"}
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ /**
3
+ * Send Message Utilities
4
+ *
5
+ * Framework-agnostic functions for sending messages and handling streaming
6
+ * responses. Extracted from the React SDK's useTamboSendMessage hook to enable
7
+ * reuse across different UI frameworks.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.dispatchUserMessage = dispatchUserMessage;
11
+ exports.dispatchToolResults = dispatchToolResults;
12
+ exports.createRunStream = createRunStream;
13
+ exports.executeToolsAndContinue = executeToolsAndContinue;
14
+ const core_1 = require("@ag-ui/core");
15
+ const registry_conversion_1 = require("./registry-conversion");
16
+ const tool_executor_1 = require("./tool-executor");
17
+ /**
18
+ * Dispatches synthetic AG-UI events to show a user message in the thread.
19
+ * @param dispatch - Stream state dispatcher
20
+ * @param targetThreadId - Thread to add the message to
21
+ * @param messageId - Stable ID for the user message
22
+ * @param messageText - Text content of the message
23
+ */
24
+ function dispatchUserMessage(dispatch, targetThreadId, messageId, messageText) {
25
+ dispatch({
26
+ type: "EVENT",
27
+ threadId: targetThreadId,
28
+ event: {
29
+ type: core_1.EventType.TEXT_MESSAGE_START,
30
+ messageId,
31
+ role: "user",
32
+ },
33
+ });
34
+ dispatch({
35
+ type: "EVENT",
36
+ threadId: targetThreadId,
37
+ event: {
38
+ type: core_1.EventType.TEXT_MESSAGE_CONTENT,
39
+ messageId,
40
+ delta: messageText,
41
+ },
42
+ });
43
+ dispatch({
44
+ type: "EVENT",
45
+ threadId: targetThreadId,
46
+ event: {
47
+ type: core_1.EventType.TEXT_MESSAGE_END,
48
+ messageId,
49
+ },
50
+ });
51
+ }
52
+ /**
53
+ * Dispatches synthetic events for tool results as optimistic local state.
54
+ * The server doesn't echo these back for client-side tools.
55
+ * @param dispatch - Stream state dispatcher
56
+ * @param targetThreadId - Thread to add results to
57
+ * @param toolResults - Tool execution results to dispatch
58
+ */
59
+ function dispatchToolResults(dispatch, targetThreadId, toolResults) {
60
+ if (toolResults.length === 0)
61
+ return;
62
+ const toolResultMessageId = `msg_tool_result_${Date.now()}`;
63
+ dispatch({
64
+ type: "EVENT",
65
+ threadId: targetThreadId,
66
+ event: {
67
+ type: core_1.EventType.TEXT_MESSAGE_START,
68
+ messageId: toolResultMessageId,
69
+ role: "user",
70
+ },
71
+ });
72
+ for (const result of toolResults) {
73
+ dispatch({
74
+ type: "EVENT",
75
+ threadId: targetThreadId,
76
+ event: {
77
+ type: core_1.EventType.TOOL_CALL_RESULT,
78
+ toolCallId: result.toolUseId,
79
+ messageId: toolResultMessageId,
80
+ content: result.content
81
+ .filter((c) => c.type === "text")
82
+ .map((c) => c.text)
83
+ .join("") || JSON.stringify(result.content),
84
+ },
85
+ });
86
+ }
87
+ dispatch({
88
+ type: "EVENT",
89
+ threadId: targetThreadId,
90
+ event: {
91
+ type: core_1.EventType.TEXT_MESSAGE_END,
92
+ messageId: toolResultMessageId,
93
+ },
94
+ });
95
+ }
96
+ /**
97
+ * Creates a run stream by calling the appropriate API method.
98
+ *
99
+ * If threadId is provided, runs on existing thread via client.threads.runs.run().
100
+ * If no threadId, creates new thread via client.threads.runs.create().
101
+ * @param params - The parameters for creating the run stream
102
+ * @returns The stream and initial thread ID (undefined if creating new thread)
103
+ */
104
+ async function createRunStream(params) {
105
+ const { client, threadId, message, componentList, toolRegistry, userKey, previousRunId, additionalContext, toolChoice, initialMessages, } = params;
106
+ // Merge helper context with any caller-provided additionalContext on the message
107
+ const mergedContext = additionalContext || message.additionalContext
108
+ ? {
109
+ ...(message.additionalContext ?? {}),
110
+ ...additionalContext,
111
+ }
112
+ : undefined;
113
+ const messageWithContext = mergedContext
114
+ ? { ...message, additionalContext: mergedContext }
115
+ : message;
116
+ // Convert registry components/tools to API format
117
+ const availableComponents = (0, registry_conversion_1.toAvailableComponents)(componentList);
118
+ const availableTools = (0, registry_conversion_1.toAvailableTools)(toolRegistry);
119
+ if (threadId) {
120
+ // Run on existing thread
121
+ const stream = await client.threads.runs.run(threadId, {
122
+ message: messageWithContext,
123
+ availableComponents,
124
+ tools: availableTools,
125
+ userKey,
126
+ previousRunId,
127
+ toolChoice,
128
+ });
129
+ return { stream, initialThreadId: threadId };
130
+ }
131
+ else {
132
+ // Create new thread - include initialMessages if provided
133
+ const threadConfig = {};
134
+ if (userKey) {
135
+ threadConfig.userKey = userKey;
136
+ }
137
+ if (initialMessages?.length) {
138
+ threadConfig.initialMessages = initialMessages;
139
+ }
140
+ const stream = await client.threads.runs.create({
141
+ message: messageWithContext,
142
+ availableComponents,
143
+ tools: availableTools,
144
+ thread: Object.keys(threadConfig).length > 0 ? threadConfig : undefined,
145
+ toolChoice,
146
+ });
147
+ // threadId will be extracted from first event (RUN_STARTED)
148
+ return { stream, initialThreadId: undefined };
149
+ }
150
+ }
151
+ /**
152
+ * Executes pending tools and returns a continuation stream.
153
+ *
154
+ * This function does NOT process the continuation stream - it just executes
155
+ * the tools and returns the new stream for the caller to process. This enables
156
+ * the flat loop pattern that correctly handles multi-round tool execution.
157
+ * @param params - The parameters for tool execution
158
+ * @returns The continuation stream and tool results for optimistic local state updates
159
+ */
160
+ async function executeToolsAndContinue(params) {
161
+ const { event, toolTracker, toolRegistry, componentList, client, threadId, runId, userKey, additionalContext, toolChoice, } = params;
162
+ const pendingToolCallIds = event.value.pendingToolCalls.map((tc) => tc.toolCallId);
163
+ const toolCallsToExecute = toolTracker.getToolCallsById(pendingToolCallIds);
164
+ // Execute tools
165
+ const toolResults = await (0, tool_executor_1.executeAllPendingTools)(toolCallsToExecute, toolRegistry);
166
+ // Clear executed tool calls before continuing
167
+ toolTracker.clearToolCalls(pendingToolCallIds);
168
+ // Return the continuation stream and tool results
169
+ const stream = await client.threads.runs.run(threadId, {
170
+ message: {
171
+ role: "user",
172
+ content: toolResults,
173
+ additionalContext,
174
+ },
175
+ previousRunId: runId,
176
+ availableComponents: (0, registry_conversion_1.toAvailableComponents)(componentList),
177
+ tools: (0, registry_conversion_1.toAvailableTools)(toolRegistry),
178
+ userKey,
179
+ toolChoice,
180
+ });
181
+ return { stream, toolResults };
182
+ }
183
+ //# sourceMappingURL=send-message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-message.js","sourceRoot":"","sources":["../../src/utils/send-message.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Send Message Utilities\n *\n * Framework-agnostic functions for sending messages and handling streaming\n * responses. Extracted from the React SDK's useTamboSendMessage hook to enable\n * reuse across different UI frameworks.\n */\n\nimport { EventType } from \"@ag-ui/core\";\nimport type TamboAI from \"@tambo-ai/typescript-sdk\";\nimport type { Stream } from \"@tambo-ai/typescript-sdk/core/streaming\";\nimport type { ToolResultContent } from \"@tambo-ai/typescript-sdk/resources/threads/threads\";\nimport type { RunCreateParams } from \"@tambo-ai/typescript-sdk/resources/threads/runs\";\n\nimport type { RunAwaitingInputEvent } from \"../types/event\";\nimport type { InitialInputMessage, InputMessage } from \"../types/message\";\nimport type { ToolChoice } from \"../types/tool-choice\";\nimport type { StreamAction } from \"./event-accumulator\";\nimport type {\n ComponentRegistry,\n TamboToolRegistry,\n} from \"../model/component-metadata\";\nimport { toAvailableComponents, toAvailableTools } from \"./registry-conversion\";\nimport { executeAllPendingTools } from \"./tool-executor\";\nimport type { ToolCallTracker } from \"./tool-call-tracker\";\n\n/**\n * Stream type for run responses on an existing thread.\n */\nexport type RunStream = Stream<TamboAI.Threads.Runs.RunRunResponse>;\n\n/**\n * Stream type for creating a new thread with a run.\n */\nexport type CreateStream = Stream<TamboAI.Threads.Runs.RunCreateResponse>;\n\n/**\n * Options for sending a message.\n */\nexport interface SendMessageOptions {\n /** The message to send. */\n message: InputMessage;\n\n /**\n * User message text for optimistic display.\n * If provided, synthetic AG-UI events will be dispatched to show\n * the user message in the thread immediately after getting the threadId.\n */\n userMessageText?: string;\n\n /** Enable debug logging for the stream. */\n debug?: boolean;\n\n /**\n * How the model should use tools. Defaults to \"auto\".\n * - \"auto\": Model decides whether to use tools\n * - \"required\": Model must use at least one tool\n * - \"none\": Model cannot use tools\n * - { name: \"toolName\" }: Model must use the specified tool\n */\n toolChoice?: ToolChoice;\n}\n\n/**\n * Parameters for creating a run stream.\n */\nexport interface CreateRunStreamParams {\n client: TamboAI;\n threadId: string | undefined;\n message: InputMessage;\n componentList: ComponentRegistry;\n toolRegistry: TamboToolRegistry;\n userKey: string | undefined;\n /**\n * Previous run ID for continuing a thread with existing messages.\n * Required when threadId is provided and the thread has previous runs.\n */\n previousRunId: string | undefined;\n /**\n * Additional context gathered from context helpers (including interactables).\n * Merged into the message's additionalContext before sending.\n */\n additionalContext?: Record<string, unknown>;\n /** How the model should use tools. */\n toolChoice?: ToolChoice;\n /**\n * Initial messages to seed the thread with when creating a new thread.\n * Only used when threadId is undefined (new thread creation).\n */\n initialMessages?: InitialInputMessage[];\n}\n\n/**\n * Result from creating a run stream.\n */\nexport interface CreateRunStreamResult {\n stream: RunStream | CreateStream;\n initialThreadId: string | undefined;\n}\n\n/**\n * Parameters for executing tools and continuing the run.\n */\nexport interface ExecuteToolsParams {\n event: RunAwaitingInputEvent;\n toolTracker: ToolCallTracker;\n toolRegistry: TamboToolRegistry;\n componentList: ComponentRegistry;\n client: TamboAI;\n threadId: string;\n runId: string;\n userKey: string | undefined;\n additionalContext?: Record<string, unknown>;\n toolChoice?: ToolChoice;\n}\n\n/**\n * Result from executing tools and continuing the run.\n */\nexport interface ExecuteToolsResult {\n stream: RunStream;\n toolResults: ToolResultContent[];\n}\n\n/**\n * Dispatches synthetic AG-UI events to show a user message in the thread.\n * @param dispatch - Stream state dispatcher\n * @param targetThreadId - Thread to add the message to\n * @param messageId - Stable ID for the user message\n * @param messageText - Text content of the message\n */\nexport function dispatchUserMessage(\n dispatch: (action: StreamAction) => void,\n targetThreadId: string,\n messageId: string,\n messageText: string,\n): void {\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n role: \"user\" as const,\n },\n });\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n delta: messageText,\n },\n });\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n },\n });\n}\n\n/**\n * Dispatches synthetic events for tool results as optimistic local state.\n * The server doesn't echo these back for client-side tools.\n * @param dispatch - Stream state dispatcher\n * @param targetThreadId - Thread to add results to\n * @param toolResults - Tool execution results to dispatch\n */\nexport function dispatchToolResults(\n dispatch: (action: StreamAction) => void,\n targetThreadId: string,\n toolResults: ToolResultContent[],\n): void {\n if (toolResults.length === 0) return;\n\n const toolResultMessageId = `msg_tool_result_${Date.now()}`;\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: toolResultMessageId,\n role: \"user\" as const,\n },\n });\n\n for (const result of toolResults) {\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TOOL_CALL_RESULT,\n toolCallId: result.toolUseId,\n messageId: toolResultMessageId,\n content:\n result.content\n .filter((c) => c.type === \"text\")\n .map((c) => (c as { type: \"text\"; text: string }).text)\n .join(\"\") || JSON.stringify(result.content),\n },\n });\n }\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: toolResultMessageId,\n },\n });\n}\n\n/**\n * Creates a run stream by calling the appropriate API method.\n *\n * If threadId is provided, runs on existing thread via client.threads.runs.run().\n * If no threadId, creates new thread via client.threads.runs.create().\n * @param params - The parameters for creating the run stream\n * @returns The stream and initial thread ID (undefined if creating new thread)\n */\nexport async function createRunStream(\n params: CreateRunStreamParams,\n): Promise<CreateRunStreamResult> {\n const {\n client,\n threadId,\n message,\n componentList,\n toolRegistry,\n userKey,\n previousRunId,\n additionalContext,\n toolChoice,\n initialMessages,\n } = params;\n\n // Merge helper context with any caller-provided additionalContext on the message\n const mergedContext =\n additionalContext || message.additionalContext\n ? {\n ...((message.additionalContext as Record<string, unknown>) ?? {}),\n ...additionalContext,\n }\n : undefined;\n const messageWithContext: InputMessage = mergedContext\n ? { ...message, additionalContext: mergedContext }\n : message;\n\n // Convert registry components/tools to API format\n const availableComponents = toAvailableComponents(componentList);\n const availableTools = toAvailableTools(toolRegistry);\n\n if (threadId) {\n // Run on existing thread\n const stream = await client.threads.runs.run(threadId, {\n message: messageWithContext,\n availableComponents,\n tools: availableTools,\n userKey,\n previousRunId,\n toolChoice,\n });\n return { stream, initialThreadId: threadId };\n } else {\n // Create new thread - include initialMessages if provided\n const threadConfig: RunCreateParams.Thread = {};\n if (userKey) {\n threadConfig.userKey = userKey;\n }\n if (initialMessages?.length) {\n threadConfig.initialMessages = initialMessages;\n }\n\n const stream = await client.threads.runs.create({\n message: messageWithContext,\n availableComponents,\n tools: availableTools,\n thread: Object.keys(threadConfig).length > 0 ? threadConfig : undefined,\n toolChoice,\n });\n // threadId will be extracted from first event (RUN_STARTED)\n return { stream, initialThreadId: undefined };\n }\n}\n\n/**\n * Executes pending tools and returns a continuation stream.\n *\n * This function does NOT process the continuation stream - it just executes\n * the tools and returns the new stream for the caller to process. This enables\n * the flat loop pattern that correctly handles multi-round tool execution.\n * @param params - The parameters for tool execution\n * @returns The continuation stream and tool results for optimistic local state updates\n */\nexport async function executeToolsAndContinue(\n params: ExecuteToolsParams,\n): Promise<ExecuteToolsResult> {\n const {\n event,\n toolTracker,\n toolRegistry,\n componentList,\n client,\n threadId,\n runId,\n userKey,\n additionalContext,\n toolChoice,\n } = params;\n\n const pendingToolCallIds = event.value.pendingToolCalls.map(\n (tc) => tc.toolCallId,\n );\n const toolCallsToExecute = toolTracker.getToolCallsById(pendingToolCallIds);\n\n // Execute tools\n const toolResults = await executeAllPendingTools(\n toolCallsToExecute,\n toolRegistry,\n );\n\n // Clear executed tool calls before continuing\n toolTracker.clearToolCalls(pendingToolCallIds);\n\n // Return the continuation stream and tool results\n const stream = await client.threads.runs.run(threadId, {\n message: {\n role: \"user\",\n content: toolResults,\n additionalContext,\n },\n previousRunId: runId,\n availableComponents: toAvailableComponents(componentList),\n tools: toAvailableTools(toolRegistry),\n userKey,\n toolChoice,\n });\n\n return { stream, toolResults };\n}\n"]}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Stream Handler for Streaming API
3
+ *
4
+ * Provides utilities for handling event streams from the TypeScript SDK.
5
+ * The SDK's client.threads.runs.run() already returns an async iterable,
6
+ * so this module just adds optional debug logging.
7
+ */
8
+ import type { AGUIEvent } from "@ag-ui/core";
9
+ /**
10
+ * Options for stream handling.
11
+ */
12
+ export interface StreamHandlerOptions {
13
+ /**
14
+ * Enable debug logging (development mode only).
15
+ * Logs all events to console.
16
+ */
17
+ debug?: boolean;
18
+ }
19
+ /**
20
+ * Handle an event stream from the TypeScript SDK and yield AG-UI event types.
21
+ *
22
+ * The TypeScript SDK's client.threads.runs.run() and client.threads.runs.create()
23
+ * return async iterables that yield events compatible with AG-UI's AGUIEvent.
24
+ * This function wraps the stream to add optional debug logging and ensures
25
+ * proper typing.
26
+ *
27
+ * Note: SDK events have `type: string` rather than `type: EventType` enum,
28
+ * but the values are compatible with AG-UI event types.
29
+ * @param stream - Async iterable of events from SDK
30
+ * @param options - Optional configuration for stream handling
31
+ * @yields {AGUIEvent} AG-UI event types from the stream
32
+ * @returns Async iterable of AG-UI event types
33
+ * @example
34
+ * ```typescript
35
+ * const stream = await client.threads.runs.run(threadId, {
36
+ * message: { role: "user", content: [{ type: "text", text: "hello" }] },
37
+ * });
38
+ *
39
+ * for await (const event of handleEventStream(stream, { debug: true })) {
40
+ * dispatch({ type: 'EVENT', event }); // Send to reducer
41
+ * }
42
+ * ```
43
+ */
44
+ export declare function handleEventStream(stream: AsyncIterable<unknown>, options?: StreamHandlerOptions): AsyncIterable<AGUIEvent>;
45
+ //# sourceMappingURL=stream-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-handler.d.ts","sourceRoot":"","sources":["../../src/utils/stream-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAuB,iBAAiB,CACtC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,aAAa,CAAC,SAAS,CAAC,CAY1B"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /**
3
+ * Stream Handler for Streaming API
4
+ *
5
+ * Provides utilities for handling event streams from the TypeScript SDK.
6
+ * The SDK's client.threads.runs.run() already returns an async iterable,
7
+ * so this module just adds optional debug logging.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.handleEventStream = handleEventStream;
11
+ /**
12
+ * Handle an event stream from the TypeScript SDK and yield AG-UI event types.
13
+ *
14
+ * The TypeScript SDK's client.threads.runs.run() and client.threads.runs.create()
15
+ * return async iterables that yield events compatible with AG-UI's AGUIEvent.
16
+ * This function wraps the stream to add optional debug logging and ensures
17
+ * proper typing.
18
+ *
19
+ * Note: SDK events have `type: string` rather than `type: EventType` enum,
20
+ * but the values are compatible with AG-UI event types.
21
+ * @param stream - Async iterable of events from SDK
22
+ * @param options - Optional configuration for stream handling
23
+ * @yields {AGUIEvent} AG-UI event types from the stream
24
+ * @returns Async iterable of AG-UI event types
25
+ * @example
26
+ * ```typescript
27
+ * const stream = await client.threads.runs.run(threadId, {
28
+ * message: { role: "user", content: [{ type: "text", text: "hello" }] },
29
+ * });
30
+ *
31
+ * for await (const event of handleEventStream(stream, { debug: true })) {
32
+ * dispatch({ type: 'EVENT', event }); // Send to reducer
33
+ * }
34
+ * ```
35
+ */
36
+ async function* handleEventStream(stream, options) {
37
+ const { debug = false } = options ?? {};
38
+ for await (const event of stream) {
39
+ if (debug && process.env.NODE_ENV !== "production") {
40
+ // eslint-disable-next-line no-console -- debug logging behind flag
41
+ console.log("[StreamHandler] Event:", event);
42
+ }
43
+ // SDK events are compatible with AG-UI AGUIEvent discriminated union
44
+ yield event;
45
+ }
46
+ }
47
+ //# sourceMappingURL=stream-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-handler.js","sourceRoot":"","sources":["../../src/utils/stream-handler.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAwCH,8CAeC;AAxCD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACI,KAAK,SAAS,CAAC,CAAC,iBAAiB,CACtC,MAA8B,EAC9B,OAA8B;IAE9B,MAAM,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;IAExC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YACnD,mEAAmE;YACnE,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC;QAED,qEAAqE;QACrE,MAAM,KAAkB,CAAC;IAC3B,CAAC;AACH,CAAC","sourcesContent":["/**\n * Stream Handler for Streaming API\n *\n * Provides utilities for handling event streams from the TypeScript SDK.\n * The SDK's client.threads.runs.run() already returns an async iterable,\n * so this module just adds optional debug logging.\n */\n\nimport type { AGUIEvent } from \"@ag-ui/core\";\n\n/**\n * Options for stream handling.\n */\nexport interface StreamHandlerOptions {\n /**\n * Enable debug logging (development mode only).\n * Logs all events to console.\n */\n debug?: boolean;\n}\n\n/**\n * Handle an event stream from the TypeScript SDK and yield AG-UI event types.\n *\n * The TypeScript SDK's client.threads.runs.run() and client.threads.runs.create()\n * return async iterables that yield events compatible with AG-UI's AGUIEvent.\n * This function wraps the stream to add optional debug logging and ensures\n * proper typing.\n *\n * Note: SDK events have `type: string` rather than `type: EventType` enum,\n * but the values are compatible with AG-UI event types.\n * @param stream - Async iterable of events from SDK\n * @param options - Optional configuration for stream handling\n * @yields {AGUIEvent} AG-UI event types from the stream\n * @returns Async iterable of AG-UI event types\n * @example\n * ```typescript\n * const stream = await client.threads.runs.run(threadId, {\n * message: { role: \"user\", content: [{ type: \"text\", text: \"hello\" }] },\n * });\n *\n * for await (const event of handleEventStream(stream, { debug: true })) {\n * dispatch({ type: 'EVENT', event }); // Send to reducer\n * }\n * ```\n */\nexport async function* handleEventStream(\n stream: AsyncIterable<unknown>,\n options?: StreamHandlerOptions,\n): AsyncIterable<AGUIEvent> {\n const { debug = false } = options ?? {};\n\n for await (const event of stream) {\n if (debug && process.env.NODE_ENV !== \"production\") {\n // eslint-disable-next-line no-console -- debug logging behind flag\n console.log(\"[StreamHandler] Event:\", event);\n }\n\n // SDK events are compatible with AG-UI AGUIEvent discriminated union\n yield event as AGUIEvent;\n }\n}\n"]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Thread utility functions for searching and accessing thread content.
3
+ */
4
+ import type { StreamState } from "./event-accumulator";
5
+ import type { TamboComponentContent } from "../types/message";
6
+ /**
7
+ * Find a component content block by ID in a specific thread.
8
+ * Searches from most recent messages first since active components are likely near the tail.
9
+ * Only searches the specified thread to prevent cross-thread data access.
10
+ * @param streamState - The current stream state containing thread data
11
+ * @param threadId - The thread ID to search in
12
+ * @param componentId - The component ID to find
13
+ * @returns The component content block, or undefined if not found
14
+ */
15
+ export declare function findComponentContent(streamState: StreamState, threadId: string, componentId: string): TamboComponentContent | undefined;
16
+ //# sourceMappingURL=thread-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-utils.d.ts","sourceRoot":"","sources":["../../src/utils/thread-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,qBAAqB,GAAG,SAAS,CAkBnC"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * Thread utility functions for searching and accessing thread content.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.findComponentContent = findComponentContent;
7
+ /**
8
+ * Find a component content block by ID in a specific thread.
9
+ * Searches from most recent messages first since active components are likely near the tail.
10
+ * Only searches the specified thread to prevent cross-thread data access.
11
+ * @param streamState - The current stream state containing thread data
12
+ * @param threadId - The thread ID to search in
13
+ * @param componentId - The component ID to find
14
+ * @returns The component content block, or undefined if not found
15
+ */
16
+ function findComponentContent(streamState, threadId, componentId) {
17
+ const threadState = streamState.threadMap[threadId];
18
+ if (!threadState) {
19
+ return undefined;
20
+ }
21
+ // Search from most recent messages first for better performance
22
+ const messages = threadState.thread.messages;
23
+ for (let i = messages.length - 1; i >= 0; i--) {
24
+ const content = messages[i].content;
25
+ for (let j = content.length - 1; j >= 0; j--) {
26
+ const block = content[j];
27
+ if (block.type === "component" && block.id === componentId) {
28
+ return block;
29
+ }
30
+ }
31
+ }
32
+ return undefined;
33
+ }
34
+ //# sourceMappingURL=thread-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-utils.js","sourceRoot":"","sources":["../../src/utils/thread-utils.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAcH,oDAsBC;AA/BD;;;;;;;;GAQG;AACH,SAAgB,oBAAoB,CAClC,WAAwB,EACxB,QAAgB,EAChB,WAAmB;IAEnB,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACpD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,gEAAgE;IAChE,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACpC,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,EAAE,KAAK,WAAW,EAAE,CAAC;gBAC3D,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["/**\n * Thread utility functions for searching and accessing thread content.\n */\n\nimport type { StreamState } from \"./event-accumulator\";\nimport type { TamboComponentContent } from \"../types/message\";\n\n/**\n * Find a component content block by ID in a specific thread.\n * Searches from most recent messages first since active components are likely near the tail.\n * Only searches the specified thread to prevent cross-thread data access.\n * @param streamState - The current stream state containing thread data\n * @param threadId - The thread ID to search in\n * @param componentId - The component ID to find\n * @returns The component content block, or undefined if not found\n */\nexport function findComponentContent(\n streamState: StreamState,\n threadId: string,\n componentId: string,\n): TamboComponentContent | undefined {\n const threadState = streamState.threadMap[threadId];\n if (!threadState) {\n return undefined;\n }\n\n // Search from most recent messages first for better performance\n const messages = threadState.thread.messages;\n for (let i = messages.length - 1; i >= 0; i--) {\n const content = messages[i].content;\n for (let j = content.length - 1; j >= 0; j--) {\n const block = content[j];\n if (block.type === \"component\" && block.id === componentId) {\n return block;\n }\n }\n }\n return undefined;\n}\n"]}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Tool Call Tracker
3
+ *
4
+ * Tracks tool calls during streaming, accumulating arguments until complete.
5
+ * Owns the tool name → JSON Schema mapping and handles unstrictification
6
+ * so callers don't need to know about schema conversion.
7
+ */
8
+ import { type AGUIEvent } from "@ag-ui/core";
9
+ import type { JSONSchema7 } from "json-schema";
10
+ import type { TamboTool } from "../model/component-metadata";
11
+ import type { PendingToolCall } from "./tool-executor";
12
+ /**
13
+ * Tracks tool calls during streaming, accumulating arguments until complete.
14
+ *
15
+ * Tool calls arrive as a sequence of events:
16
+ * 1. TOOL_CALL_START - initializes the tool call with name
17
+ * 2. TOOL_CALL_ARGS (multiple) - streams JSON argument fragments
18
+ * 3. TOOL_CALL_END - marks the tool call as complete, triggers JSON parsing
19
+ *
20
+ * When constructed with a tool registry, the tracker unstrictifies parsed
21
+ * args (both partial and final) using the original JSON Schemas.
22
+ */
23
+ export declare class ToolCallTracker {
24
+ private pendingToolCalls;
25
+ private accumulatingArgs;
26
+ private _toolSchemas;
27
+ constructor(toolRegistry?: Record<string, TamboTool>);
28
+ /**
29
+ * The tool-name → JSONSchema7 map, for passing to the reducer.
30
+ * @returns The tool schemas map
31
+ */
32
+ get toolSchemas(): Map<string, JSONSchema7>;
33
+ /**
34
+ * Handles a streaming event, tracking tool call state as needed.
35
+ * @param event - The streaming event to process
36
+ * @throws {Error} If JSON parsing fails on TOOL_CALL_END (fail-fast, no silent fallback)
37
+ */
38
+ handleEvent(event: AGUIEvent): void;
39
+ /**
40
+ * Parses partial JSON from the accumulated args for a tool call and
41
+ * unstrictifies the result. Used during streaming to get the current
42
+ * best-effort parsed args.
43
+ * @param toolCallId - ID of the tool call to parse
44
+ * @returns Parsed and unstrictified args, or undefined if not parseable yet
45
+ */
46
+ parsePartialArgs(toolCallId: string): Record<string, unknown> | undefined;
47
+ /**
48
+ * Gets the name and accumulated args for a tool call that is still accumulating.
49
+ * @param toolCallId - ID of the tool call to look up
50
+ * @returns The tool name and raw accumulated args string, or undefined if not found
51
+ */
52
+ getAccumulatingToolCall(toolCallId: string): {
53
+ name: string;
54
+ accumulatedArgs: string;
55
+ } | undefined;
56
+ /**
57
+ * Gets tool calls for the given IDs, filtered to only those that exist.
58
+ * @param toolCallIds - IDs of tool calls to retrieve
59
+ * @returns Map of tool call ID to pending tool call
60
+ */
61
+ getToolCallsById(toolCallIds: string[]): Map<string, PendingToolCall>;
62
+ /**
63
+ * Clears tracked tool calls for the given IDs.
64
+ * @param toolCallIds - IDs of tool calls to clear
65
+ */
66
+ clearToolCalls(toolCallIds: string[]): void;
67
+ /**
68
+ * Unstrictify params using the schema for the given tool name.
69
+ * Returns params unchanged if no schema is available.
70
+ * @returns The unstrictified params.
71
+ */
72
+ private unstrictify;
73
+ }
74
+ //# sourceMappingURL=tool-call-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-call-tracker.d.ts","sourceRoot":"","sources":["../../src/utils/tool-call-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AA4BvD;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,gBAAgB,CAAsC;IAC9D,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,YAAY,CAA2B;gBAEnC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;IAMpD;;;OAGG;IACH,IAAI,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAE1C;IAED;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IA6CnC;;;;;;OAMG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAsBzE;;;;OAIG;IACH,uBAAuB,CACrB,UAAU,EAAE,MAAM,GACjB;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAOxD;;;;OAIG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;IAWrE;;;OAGG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI;IAO3C;;;;OAIG;IACH,OAAO,CAAC,WAAW;CAQpB"}