@tambo-ai/react 0.70.0 → 0.71.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 (257) hide show
  1. package/dist/v1/hooks/use-tambo-v1-messages.d.ts +58 -0
  2. package/dist/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -0
  3. package/dist/v1/hooks/use-tambo-v1-messages.js +54 -0
  4. package/dist/v1/hooks/use-tambo-v1-messages.js.map +1 -0
  5. package/dist/v1/hooks/use-tambo-v1-messages.test.d.ts +2 -0
  6. package/dist/v1/hooks/use-tambo-v1-messages.test.d.ts.map +1 -0
  7. package/dist/v1/hooks/use-tambo-v1-messages.test.js +137 -0
  8. package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -0
  9. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +96 -0
  10. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -0
  11. package/dist/v1/hooks/use-tambo-v1-send-message.js +227 -0
  12. package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -0
  13. package/dist/v1/hooks/use-tambo-v1-send-message.test.d.ts +2 -0
  14. package/dist/v1/hooks/use-tambo-v1-send-message.test.d.ts.map +1 -0
  15. package/dist/v1/hooks/use-tambo-v1-send-message.test.js +827 -0
  16. package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -0
  17. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +61 -0
  18. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -0
  19. package/dist/v1/hooks/use-tambo-v1-thread-list.js +56 -0
  20. package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -0
  21. package/dist/v1/hooks/use-tambo-v1-thread-list.test.d.ts +2 -0
  22. package/dist/v1/hooks/use-tambo-v1-thread-list.test.d.ts.map +1 -0
  23. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +98 -0
  24. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -0
  25. package/dist/v1/hooks/use-tambo-v1-thread.d.ts +37 -0
  26. package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -0
  27. package/dist/v1/hooks/use-tambo-v1-thread.js +49 -0
  28. package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -0
  29. package/dist/v1/hooks/use-tambo-v1-thread.test.d.ts +2 -0
  30. package/dist/v1/hooks/use-tambo-v1-thread.test.d.ts.map +1 -0
  31. package/dist/v1/hooks/use-tambo-v1-thread.test.js +83 -0
  32. package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -0
  33. package/dist/v1/hooks/use-tambo-v1.d.ts +107 -0
  34. package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -0
  35. package/dist/v1/hooks/use-tambo-v1.js +87 -0
  36. package/dist/v1/hooks/use-tambo-v1.js.map +1 -0
  37. package/dist/v1/hooks/use-tambo-v1.test.d.ts +2 -0
  38. package/dist/v1/hooks/use-tambo-v1.test.d.ts.map +1 -0
  39. package/dist/v1/hooks/use-tambo-v1.test.js +150 -0
  40. package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -0
  41. package/dist/v1/index.d.ts +54 -16
  42. package/dist/v1/index.d.ts.map +1 -1
  43. package/dist/v1/index.js +85 -26
  44. package/dist/v1/index.js.map +1 -1
  45. package/dist/v1/providers/tambo-v1-provider.d.ts +91 -0
  46. package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -0
  47. package/dist/v1/providers/tambo-v1-provider.js +110 -0
  48. package/dist/v1/providers/tambo-v1-provider.js.map +1 -0
  49. package/dist/v1/providers/tambo-v1-provider.test.d.ts +2 -0
  50. package/dist/v1/providers/tambo-v1-provider.test.d.ts.map +1 -0
  51. package/dist/v1/providers/tambo-v1-provider.test.js +123 -0
  52. package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -0
  53. package/dist/v1/providers/tambo-v1-stream-context.d.ts +136 -0
  54. package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -0
  55. package/dist/v1/providers/tambo-v1-stream-context.js +230 -0
  56. package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -0
  57. package/dist/v1/providers/tambo-v1-stream-context.test.d.ts +2 -0
  58. package/dist/v1/providers/tambo-v1-stream-context.test.d.ts.map +1 -0
  59. package/dist/v1/providers/tambo-v1-stream-context.test.js +85 -0
  60. package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -0
  61. package/dist/v1/types/component.d.ts +5 -2
  62. package/dist/v1/types/component.d.ts.map +1 -1
  63. package/dist/v1/types/component.js +5 -2
  64. package/dist/v1/types/component.js.map +1 -1
  65. package/dist/v1/types/event.d.ts +21 -12
  66. package/dist/v1/types/event.d.ts.map +1 -1
  67. package/dist/v1/types/event.js +46 -1
  68. package/dist/v1/types/event.js.map +1 -1
  69. package/dist/v1/types/event.test.d.ts +2 -0
  70. package/dist/v1/types/event.test.d.ts.map +1 -0
  71. package/dist/v1/types/event.test.js +70 -0
  72. package/dist/v1/types/event.test.js.map +1 -0
  73. package/dist/v1/types/message.d.ts +4 -8
  74. package/dist/v1/types/message.d.ts.map +1 -1
  75. package/dist/v1/types/message.js +1 -1
  76. package/dist/v1/types/message.js.map +1 -1
  77. package/dist/v1/types/thread.d.ts +1 -3
  78. package/dist/v1/types/thread.d.ts.map +1 -1
  79. package/dist/v1/types/thread.js +1 -1
  80. package/dist/v1/types/thread.js.map +1 -1
  81. package/dist/v1/utils/event-accumulator.d.ts +100 -0
  82. package/dist/v1/utils/event-accumulator.d.ts.map +1 -0
  83. package/dist/v1/utils/event-accumulator.js +715 -0
  84. package/dist/v1/utils/event-accumulator.js.map +1 -0
  85. package/dist/v1/utils/event-accumulator.test.d.ts +2 -0
  86. package/dist/v1/utils/event-accumulator.test.d.ts.map +1 -0
  87. package/dist/v1/utils/event-accumulator.test.js +1010 -0
  88. package/dist/v1/utils/event-accumulator.test.js.map +1 -0
  89. package/dist/v1/utils/json-patch.d.ts +18 -0
  90. package/dist/v1/utils/json-patch.d.ts.map +1 -0
  91. package/dist/v1/utils/json-patch.js +35 -0
  92. package/dist/v1/utils/json-patch.js.map +1 -0
  93. package/dist/v1/utils/json-patch.test.d.ts +2 -0
  94. package/dist/v1/utils/json-patch.test.d.ts.map +1 -0
  95. package/dist/v1/utils/json-patch.test.js +28 -0
  96. package/dist/v1/utils/json-patch.test.js.map +1 -0
  97. package/dist/v1/utils/registry-conversion.d.ts +53 -0
  98. package/dist/v1/utils/registry-conversion.d.ts.map +1 -0
  99. package/dist/v1/utils/registry-conversion.js +114 -0
  100. package/dist/v1/utils/registry-conversion.js.map +1 -0
  101. package/dist/v1/utils/registry-conversion.test.d.ts +2 -0
  102. package/dist/v1/utils/registry-conversion.test.d.ts.map +1 -0
  103. package/dist/v1/utils/registry-conversion.test.js +179 -0
  104. package/dist/v1/utils/registry-conversion.test.js.map +1 -0
  105. package/dist/v1/utils/stream-handler.d.ts +45 -0
  106. package/dist/v1/utils/stream-handler.d.ts.map +1 -0
  107. package/dist/v1/utils/stream-handler.js +47 -0
  108. package/dist/v1/utils/stream-handler.js.map +1 -0
  109. package/dist/v1/utils/stream-handler.test.d.ts +2 -0
  110. package/dist/v1/utils/stream-handler.test.d.ts.map +1 -0
  111. package/dist/v1/utils/stream-handler.test.js +74 -0
  112. package/dist/v1/utils/stream-handler.test.js.map +1 -0
  113. package/dist/v1/utils/tool-call-tracker.d.ts +41 -0
  114. package/dist/v1/utils/tool-call-tracker.d.ts.map +1 -0
  115. package/dist/v1/utils/tool-call-tracker.js +90 -0
  116. package/dist/v1/utils/tool-call-tracker.js.map +1 -0
  117. package/dist/v1/utils/tool-executor.d.ts +33 -0
  118. package/dist/v1/utils/tool-executor.d.ts.map +1 -0
  119. package/dist/v1/utils/tool-executor.js +103 -0
  120. package/dist/v1/utils/tool-executor.js.map +1 -0
  121. package/dist/v1/utils/tool-executor.test.d.ts +2 -0
  122. package/dist/v1/utils/tool-executor.test.d.ts.map +1 -0
  123. package/dist/v1/utils/tool-executor.test.js +222 -0
  124. package/dist/v1/utils/tool-executor.test.js.map +1 -0
  125. package/esm/v1/hooks/use-tambo-v1-messages.d.ts +58 -0
  126. package/esm/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -0
  127. package/esm/v1/hooks/use-tambo-v1-messages.js +51 -0
  128. package/esm/v1/hooks/use-tambo-v1-messages.js.map +1 -0
  129. package/esm/v1/hooks/use-tambo-v1-messages.test.d.ts +2 -0
  130. package/esm/v1/hooks/use-tambo-v1-messages.test.d.ts.map +1 -0
  131. package/esm/v1/hooks/use-tambo-v1-messages.test.js +132 -0
  132. package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -0
  133. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +96 -0
  134. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -0
  135. package/esm/v1/hooks/use-tambo-v1-send-message.js +223 -0
  136. package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -0
  137. package/esm/v1/hooks/use-tambo-v1-send-message.test.d.ts +2 -0
  138. package/esm/v1/hooks/use-tambo-v1-send-message.test.d.ts.map +1 -0
  139. package/esm/v1/hooks/use-tambo-v1-send-message.test.js +822 -0
  140. package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -0
  141. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +61 -0
  142. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -0
  143. package/esm/v1/hooks/use-tambo-v1-thread-list.js +53 -0
  144. package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -0
  145. package/esm/v1/hooks/use-tambo-v1-thread-list.test.d.ts +2 -0
  146. package/esm/v1/hooks/use-tambo-v1-thread-list.test.d.ts.map +1 -0
  147. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +93 -0
  148. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -0
  149. package/esm/v1/hooks/use-tambo-v1-thread.d.ts +37 -0
  150. package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -0
  151. package/esm/v1/hooks/use-tambo-v1-thread.js +46 -0
  152. package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -0
  153. package/esm/v1/hooks/use-tambo-v1-thread.test.d.ts +2 -0
  154. package/esm/v1/hooks/use-tambo-v1-thread.test.d.ts.map +1 -0
  155. package/esm/v1/hooks/use-tambo-v1-thread.test.js +78 -0
  156. package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -0
  157. package/esm/v1/hooks/use-tambo-v1.d.ts +107 -0
  158. package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -0
  159. package/esm/v1/hooks/use-tambo-v1.js +84 -0
  160. package/esm/v1/hooks/use-tambo-v1.js.map +1 -0
  161. package/esm/v1/hooks/use-tambo-v1.test.d.ts +2 -0
  162. package/esm/v1/hooks/use-tambo-v1.test.d.ts.map +1 -0
  163. package/esm/v1/hooks/use-tambo-v1.test.js +145 -0
  164. package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -0
  165. package/esm/v1/index.d.ts +54 -16
  166. package/esm/v1/index.d.ts.map +1 -1
  167. package/esm/v1/index.js +64 -27
  168. package/esm/v1/index.js.map +1 -1
  169. package/esm/v1/providers/tambo-v1-provider.d.ts +91 -0
  170. package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -0
  171. package/esm/v1/providers/tambo-v1-provider.js +74 -0
  172. package/esm/v1/providers/tambo-v1-provider.js.map +1 -0
  173. package/esm/v1/providers/tambo-v1-provider.test.d.ts +2 -0
  174. package/esm/v1/providers/tambo-v1-provider.test.d.ts.map +1 -0
  175. package/esm/v1/providers/tambo-v1-provider.test.js +118 -0
  176. package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -0
  177. package/esm/v1/providers/tambo-v1-stream-context.d.ts +136 -0
  178. package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -0
  179. package/esm/v1/providers/tambo-v1-stream-context.js +191 -0
  180. package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -0
  181. package/esm/v1/providers/tambo-v1-stream-context.test.d.ts +2 -0
  182. package/esm/v1/providers/tambo-v1-stream-context.test.d.ts.map +1 -0
  183. package/esm/v1/providers/tambo-v1-stream-context.test.js +80 -0
  184. package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -0
  185. package/esm/v1/types/component.d.ts +5 -2
  186. package/esm/v1/types/component.d.ts.map +1 -1
  187. package/esm/v1/types/component.js +5 -2
  188. package/esm/v1/types/component.js.map +1 -1
  189. package/esm/v1/types/event.d.ts +21 -12
  190. package/esm/v1/types/event.d.ts.map +1 -1
  191. package/esm/v1/types/event.js +44 -2
  192. package/esm/v1/types/event.js.map +1 -1
  193. package/esm/v1/types/event.test.d.ts +2 -0
  194. package/esm/v1/types/event.test.d.ts.map +1 -0
  195. package/esm/v1/types/event.test.js +68 -0
  196. package/esm/v1/types/event.test.js.map +1 -0
  197. package/esm/v1/types/message.d.ts +4 -8
  198. package/esm/v1/types/message.d.ts.map +1 -1
  199. package/esm/v1/types/message.js +1 -1
  200. package/esm/v1/types/message.js.map +1 -1
  201. package/esm/v1/types/thread.d.ts +1 -3
  202. package/esm/v1/types/thread.d.ts.map +1 -1
  203. package/esm/v1/types/thread.js +1 -1
  204. package/esm/v1/types/thread.js.map +1 -1
  205. package/esm/v1/utils/event-accumulator.d.ts +100 -0
  206. package/esm/v1/utils/event-accumulator.d.ts.map +1 -0
  207. package/esm/v1/utils/event-accumulator.js +708 -0
  208. package/esm/v1/utils/event-accumulator.js.map +1 -0
  209. package/esm/v1/utils/event-accumulator.test.d.ts +2 -0
  210. package/esm/v1/utils/event-accumulator.test.d.ts.map +1 -0
  211. package/esm/v1/utils/event-accumulator.test.js +1008 -0
  212. package/esm/v1/utils/event-accumulator.test.js.map +1 -0
  213. package/esm/v1/utils/json-patch.d.ts +18 -0
  214. package/esm/v1/utils/json-patch.d.ts.map +1 -0
  215. package/esm/v1/utils/json-patch.js +32 -0
  216. package/esm/v1/utils/json-patch.js.map +1 -0
  217. package/esm/v1/utils/json-patch.test.d.ts +2 -0
  218. package/esm/v1/utils/json-patch.test.d.ts.map +1 -0
  219. package/esm/v1/utils/json-patch.test.js +26 -0
  220. package/esm/v1/utils/json-patch.test.js.map +1 -0
  221. package/esm/v1/utils/registry-conversion.d.ts +53 -0
  222. package/esm/v1/utils/registry-conversion.d.ts.map +1 -0
  223. package/esm/v1/utils/registry-conversion.js +108 -0
  224. package/esm/v1/utils/registry-conversion.js.map +1 -0
  225. package/esm/v1/utils/registry-conversion.test.d.ts +2 -0
  226. package/esm/v1/utils/registry-conversion.test.d.ts.map +1 -0
  227. package/esm/v1/utils/registry-conversion.test.js +177 -0
  228. package/esm/v1/utils/registry-conversion.test.js.map +1 -0
  229. package/esm/v1/utils/stream-handler.d.ts +45 -0
  230. package/esm/v1/utils/stream-handler.d.ts.map +1 -0
  231. package/esm/v1/utils/stream-handler.js +44 -0
  232. package/esm/v1/utils/stream-handler.js.map +1 -0
  233. package/esm/v1/utils/stream-handler.test.d.ts +2 -0
  234. package/esm/v1/utils/stream-handler.test.d.ts.map +1 -0
  235. package/esm/v1/utils/stream-handler.test.js +72 -0
  236. package/esm/v1/utils/stream-handler.test.js.map +1 -0
  237. package/esm/v1/utils/tool-call-tracker.d.ts +41 -0
  238. package/esm/v1/utils/tool-call-tracker.d.ts.map +1 -0
  239. package/esm/v1/utils/tool-call-tracker.js +86 -0
  240. package/esm/v1/utils/tool-call-tracker.js.map +1 -0
  241. package/esm/v1/utils/tool-executor.d.ts +33 -0
  242. package/esm/v1/utils/tool-executor.d.ts.map +1 -0
  243. package/esm/v1/utils/tool-executor.js +99 -0
  244. package/esm/v1/utils/tool-executor.js.map +1 -0
  245. package/esm/v1/utils/tool-executor.test.d.ts +2 -0
  246. package/esm/v1/utils/tool-executor.test.d.ts.map +1 -0
  247. package/esm/v1/utils/tool-executor.test.js +220 -0
  248. package/esm/v1/utils/tool-executor.test.js.map +1 -0
  249. package/package.json +7 -6
  250. package/dist/v1/types/tool.d.ts +0 -52
  251. package/dist/v1/types/tool.d.ts.map +0 -1
  252. package/dist/v1/types/tool.js +0 -11
  253. package/dist/v1/types/tool.js.map +0 -1
  254. package/esm/v1/types/tool.d.ts +0 -52
  255. package/esm/v1/types/tool.d.ts.map +0 -1
  256. package/esm/v1/types/tool.js +0 -10
  257. package/esm/v1/types/tool.js.map +0 -1
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /**
3
+ * Tool Executor for v1 API
4
+ *
5
+ * Handles automatic execution of client-side tools when the model
6
+ * requests them via `tambo.run.awaiting_input` events.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.executeClientTool = executeClientTool;
10
+ exports.executeAllPendingTools = executeAllPendingTools;
11
+ /**
12
+ * Execute a single client-side tool and return the result.
13
+ * @param tool - The tool definition from the registry
14
+ * @param toolCallId - The ID of the tool call to respond to
15
+ * @param args - The parsed arguments for the tool
16
+ * @returns ToolResultContent with the execution result or error
17
+ */
18
+ async function executeClientTool(tool, toolCallId, args) {
19
+ try {
20
+ const result = await tool.tool(args);
21
+ // Transform result to content if transformer provided
22
+ let content;
23
+ if (tool.transformToContent) {
24
+ // transformToContent may return content parts in beta format
25
+ // Convert to v1 format (TextContent | ResourceContent)
26
+ const transformed = await tool.transformToContent(result);
27
+ content = transformed.map((part) => {
28
+ if (part.type === "text" && "text" in part && part.text) {
29
+ return { type: "text", text: part.text };
30
+ }
31
+ // For other types, stringify as text
32
+ return {
33
+ type: "text",
34
+ text: JSON.stringify(part),
35
+ };
36
+ });
37
+ }
38
+ else {
39
+ // Default: stringify result as text
40
+ content = [
41
+ {
42
+ type: "text",
43
+ text: typeof result === "string" ? result : JSON.stringify(result),
44
+ },
45
+ ];
46
+ }
47
+ return {
48
+ type: "tool_result",
49
+ toolUseId: toolCallId,
50
+ content,
51
+ };
52
+ }
53
+ catch (error) {
54
+ return {
55
+ type: "tool_result",
56
+ toolUseId: toolCallId,
57
+ content: [
58
+ {
59
+ type: "text",
60
+ text: error instanceof Error ? error.message : "Tool execution failed",
61
+ },
62
+ ],
63
+ };
64
+ }
65
+ }
66
+ /**
67
+ * Execute all pending tool calls and return their results.
68
+ * Tools are executed sequentially to avoid race conditions when
69
+ * tools may have side effects that depend on each other.
70
+ * @param toolCalls - Map of tool call IDs to their call details
71
+ * @param registry - Registry of tool names to their definitions (Map or Record)
72
+ * @returns Array of ToolResultContent for all executed tools
73
+ */
74
+ async function executeAllPendingTools(toolCalls, registry) {
75
+ const results = [];
76
+ // Normalize registry to allow lookup regardless of Map or Record
77
+ const getTool = (name) => {
78
+ if (registry instanceof Map) {
79
+ return registry.get(name);
80
+ }
81
+ return registry[name];
82
+ };
83
+ for (const [toolCallId, { name, input }] of toolCalls) {
84
+ const tool = getTool(name);
85
+ if (!tool) {
86
+ results.push({
87
+ type: "tool_result",
88
+ toolUseId: toolCallId,
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: `Tool "${name}" not found in registry`,
93
+ },
94
+ ],
95
+ });
96
+ continue;
97
+ }
98
+ const result = await executeClientTool(tool, toolCallId, input);
99
+ results.push(result);
100
+ }
101
+ return results;
102
+ }
103
+ //# sourceMappingURL=tool-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-executor.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool Executor for v1 API\n *\n * Handles automatic execution of client-side tools when the model\n * requests them via `tambo.run.awaiting_input` events.\n */\n\nimport type { TamboTool } from \"../../model/component-metadata\";\nimport type {\n ToolResultContent,\n TextContent,\n ResourceContent,\n} from \"@tambo-ai/typescript-sdk/resources/threads/threads\";\n\n/**\n * Pending tool call from the stream accumulator\n */\nexport interface PendingToolCall {\n name: string;\n input: Record<string, unknown>;\n}\n\n/**\n * Execute a single client-side tool and return the result.\n * @param tool - The tool definition from the registry\n * @param toolCallId - The ID of the tool call to respond to\n * @param args - The parsed arguments for the tool\n * @returns ToolResultContent with the execution result or error\n */\nexport async function executeClientTool(\n tool: TamboTool,\n toolCallId: string,\n args: Record<string, unknown>,\n): Promise<ToolResultContent> {\n try {\n const result = await tool.tool(args);\n\n // Transform result to content if transformer provided\n let content: (TextContent | ResourceContent)[];\n if (tool.transformToContent) {\n // transformToContent may return content parts in beta format\n // Convert to v1 format (TextContent | ResourceContent)\n const transformed = await tool.transformToContent(result);\n content = transformed.map((part) => {\n if (part.type === \"text\" && \"text\" in part && part.text) {\n return { type: \"text\" as const, text: part.text };\n }\n // For other types, stringify as text\n return {\n type: \"text\" as const,\n text: JSON.stringify(part),\n };\n });\n } else {\n // Default: stringify result as text\n content = [\n {\n type: \"text\" as const,\n text: typeof result === \"string\" ? result : JSON.stringify(result),\n },\n ];\n }\n\n return {\n type: \"tool_result\",\n toolUseId: toolCallId,\n content,\n };\n } catch (error) {\n return {\n type: \"tool_result\",\n toolUseId: toolCallId,\n content: [\n {\n type: \"text\" as const,\n text:\n error instanceof Error ? error.message : \"Tool execution failed\",\n },\n ],\n };\n }\n}\n\n/**\n * Execute all pending tool calls and return their results.\n * Tools are executed sequentially to avoid race conditions when\n * tools may have side effects that depend on each other.\n * @param toolCalls - Map of tool call IDs to their call details\n * @param registry - Registry of tool names to their definitions (Map or Record)\n * @returns Array of ToolResultContent for all executed tools\n */\nexport async function executeAllPendingTools(\n toolCalls: Map<string, PendingToolCall>,\n registry: Map<string, TamboTool> | Record<string, TamboTool>,\n): Promise<ToolResultContent[]> {\n const results: ToolResultContent[] = [];\n\n // Normalize registry to allow lookup regardless of Map or Record\n const getTool = (name: string): TamboTool | undefined => {\n if (registry instanceof Map) {\n return registry.get(name);\n }\n return registry[name];\n };\n\n for (const [toolCallId, { name, input }] of toolCalls) {\n const tool = getTool(name);\n if (!tool) {\n results.push({\n type: \"tool_result\",\n toolUseId: toolCallId,\n content: [\n {\n type: \"text\" as const,\n text: `Tool \"${name}\" not found in registry`,\n },\n ],\n });\n continue;\n }\n\n const result = await executeClientTool(tool, toolCallId, input);\n results.push(result);\n }\n\n return results;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tool-executor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-executor.test.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const zod_1 = require("zod");
4
+ const tool_executor_1 = require("./tool-executor");
5
+ describe("tool-executor", () => {
6
+ describe("executeClientTool", () => {
7
+ it("executes a tool and returns text result", async () => {
8
+ const tool = {
9
+ name: "get_weather",
10
+ description: "Gets weather",
11
+ tool: async ({ city }) => `Weather in ${city} is sunny`,
12
+ inputSchema: zod_1.z.object({ city: zod_1.z.string() }),
13
+ outputSchema: zod_1.z.string(),
14
+ };
15
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-1", {
16
+ city: "Seattle",
17
+ });
18
+ expect(result).toEqual({
19
+ type: "tool_result",
20
+ toolUseId: "call-1",
21
+ content: [{ type: "text", text: "Weather in Seattle is sunny" }],
22
+ });
23
+ });
24
+ it("stringifies non-string results", async () => {
25
+ const tool = {
26
+ name: "get_data",
27
+ description: "Gets data",
28
+ tool: async () => ({ value: 42 }),
29
+ inputSchema: zod_1.z.object({}),
30
+ outputSchema: zod_1.z.object({ value: zod_1.z.number() }),
31
+ };
32
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-2", {});
33
+ expect(result).toEqual({
34
+ type: "tool_result",
35
+ toolUseId: "call-2",
36
+ content: [{ type: "text", text: '{"value":42}' }],
37
+ });
38
+ });
39
+ it("uses transformToContent when provided", async () => {
40
+ const tool = {
41
+ name: "custom_tool",
42
+ description: "Custom tool",
43
+ tool: async () => "custom result",
44
+ inputSchema: zod_1.z.object({}),
45
+ outputSchema: zod_1.z.string(),
46
+ transformToContent: (result) => [
47
+ { type: "text", text: `Transformed: ${result}` },
48
+ ],
49
+ };
50
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-3", {});
51
+ expect(result).toEqual({
52
+ type: "tool_result",
53
+ toolUseId: "call-3",
54
+ content: [{ type: "text", text: "Transformed: custom result" }],
55
+ });
56
+ });
57
+ it("handles transformToContent with non-text types by stringifying", async () => {
58
+ const tool = {
59
+ name: "image_tool",
60
+ description: "Image tool",
61
+ tool: async () => "image data",
62
+ inputSchema: zod_1.z.object({}),
63
+ outputSchema: zod_1.z.string(),
64
+ transformToContent: () => [
65
+ {
66
+ type: "image_url",
67
+ image_url: { url: "https://example.com/image.png" },
68
+ },
69
+ ],
70
+ };
71
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-4", {});
72
+ expect(result).toEqual({
73
+ type: "tool_result",
74
+ toolUseId: "call-4",
75
+ content: [
76
+ {
77
+ type: "text",
78
+ text: '{"type":"image_url","image_url":{"url":"https://example.com/image.png"}}',
79
+ },
80
+ ],
81
+ });
82
+ });
83
+ it("handles tool execution errors gracefully", async () => {
84
+ const tool = {
85
+ name: "failing_tool",
86
+ description: "A tool that fails",
87
+ tool: async () => {
88
+ throw new Error("Tool failed!");
89
+ },
90
+ inputSchema: zod_1.z.object({}),
91
+ outputSchema: zod_1.z.void(),
92
+ };
93
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-5", {});
94
+ expect(result).toEqual({
95
+ type: "tool_result",
96
+ toolUseId: "call-5",
97
+ content: [{ type: "text", text: "Tool failed!" }],
98
+ });
99
+ });
100
+ it("handles non-Error throws gracefully", async () => {
101
+ const tool = {
102
+ name: "throwing_tool",
103
+ description: "A tool that throws a string",
104
+ tool: async () => {
105
+ throw "string error";
106
+ },
107
+ inputSchema: zod_1.z.object({}),
108
+ outputSchema: zod_1.z.void(),
109
+ };
110
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-6", {});
111
+ expect(result).toEqual({
112
+ type: "tool_result",
113
+ toolUseId: "call-6",
114
+ content: [{ type: "text", text: "Tool execution failed" }],
115
+ });
116
+ });
117
+ });
118
+ describe("executeAllPendingTools", () => {
119
+ it("executes multiple tools with Map registry", async () => {
120
+ const registry = new Map([
121
+ [
122
+ "add",
123
+ {
124
+ name: "add",
125
+ description: "Adds numbers",
126
+ tool: async ({ a, b }) => a + b,
127
+ inputSchema: zod_1.z.object({ a: zod_1.z.number(), b: zod_1.z.number() }),
128
+ outputSchema: zod_1.z.number(),
129
+ },
130
+ ],
131
+ [
132
+ "multiply",
133
+ {
134
+ name: "multiply",
135
+ description: "Multiplies numbers",
136
+ tool: async ({ a, b }) => a * b,
137
+ inputSchema: zod_1.z.object({ a: zod_1.z.number(), b: zod_1.z.number() }),
138
+ outputSchema: zod_1.z.number(),
139
+ },
140
+ ],
141
+ ]);
142
+ const toolCalls = new Map([
143
+ ["call-1", { name: "add", input: { a: 2, b: 3 } }],
144
+ ["call-2", { name: "multiply", input: { a: 4, b: 5 } }],
145
+ ]);
146
+ const results = await (0, tool_executor_1.executeAllPendingTools)(toolCalls, registry);
147
+ expect(results).toHaveLength(2);
148
+ expect(results[0]).toEqual({
149
+ type: "tool_result",
150
+ toolUseId: "call-1",
151
+ content: [{ type: "text", text: "5" }],
152
+ });
153
+ expect(results[1]).toEqual({
154
+ type: "tool_result",
155
+ toolUseId: "call-2",
156
+ content: [{ type: "text", text: "20" }],
157
+ });
158
+ });
159
+ it("executes tools with Record registry", async () => {
160
+ const registry = {
161
+ greet: {
162
+ name: "greet",
163
+ description: "Greets user",
164
+ tool: async ({ name }) => `Hello, ${name}!`,
165
+ inputSchema: zod_1.z.object({ name: zod_1.z.string() }),
166
+ outputSchema: zod_1.z.string(),
167
+ },
168
+ };
169
+ const toolCalls = new Map([
170
+ ["call-1", { name: "greet", input: { name: "World" } }],
171
+ ]);
172
+ const results = await (0, tool_executor_1.executeAllPendingTools)(toolCalls, registry);
173
+ expect(results).toHaveLength(1);
174
+ expect(results[0]).toEqual({
175
+ type: "tool_result",
176
+ toolUseId: "call-1",
177
+ content: [{ type: "text", text: "Hello, World!" }],
178
+ });
179
+ });
180
+ it("returns error result for unknown tools", async () => {
181
+ const registry = new Map();
182
+ const toolCalls = new Map([
183
+ ["call-1", { name: "unknown_tool", input: {} }],
184
+ ]);
185
+ const results = await (0, tool_executor_1.executeAllPendingTools)(toolCalls, registry);
186
+ expect(results).toHaveLength(1);
187
+ expect(results[0]).toEqual({
188
+ type: "tool_result",
189
+ toolUseId: "call-1",
190
+ content: [
191
+ { type: "text", text: 'Tool "unknown_tool" not found in registry' },
192
+ ],
193
+ });
194
+ });
195
+ it("handles mixed known and unknown tools", async () => {
196
+ const registry = new Map([
197
+ [
198
+ "known",
199
+ {
200
+ name: "known",
201
+ description: "Known tool",
202
+ tool: async () => "success",
203
+ inputSchema: zod_1.z.object({}),
204
+ outputSchema: zod_1.z.string(),
205
+ },
206
+ ],
207
+ ]);
208
+ const toolCalls = new Map([
209
+ ["call-1", { name: "known", input: {} }],
210
+ ["call-2", { name: "unknown", input: {} }],
211
+ ]);
212
+ const results = await (0, tool_executor_1.executeAllPendingTools)(toolCalls, registry);
213
+ expect(results).toHaveLength(2);
214
+ expect(results[0].content[0]).toEqual({ type: "text", text: "success" });
215
+ expect(results[1].content[0]).toEqual({
216
+ type: "text",
217
+ text: 'Tool "unknown" not found in registry',
218
+ });
219
+ });
220
+ });
221
+ });
222
+ //# sourceMappingURL=tool-executor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-executor.test.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport type { TamboTool } from \"../../model/component-metadata\";\nimport {\n executeClientTool,\n executeAllPendingTools,\n type PendingToolCall,\n} from \"./tool-executor\";\n\ndescribe(\"tool-executor\", () => {\n describe(\"executeClientTool\", () => {\n it(\"executes a tool and returns text result\", async () => {\n const tool: TamboTool = {\n name: \"get_weather\",\n description: \"Gets weather\",\n tool: async ({ city }: { city: string }) =>\n `Weather in ${city} is sunny`,\n inputSchema: z.object({ city: z.string() }),\n outputSchema: z.string(),\n };\n\n const result = await executeClientTool(tool, \"call-1\", {\n city: \"Seattle\",\n });\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"Weather in Seattle is sunny\" }],\n });\n });\n\n it(\"stringifies non-string results\", async () => {\n const tool: TamboTool = {\n name: \"get_data\",\n description: \"Gets data\",\n tool: async () => ({ value: 42 }),\n inputSchema: z.object({}),\n outputSchema: z.object({ value: z.number() }),\n };\n\n const result = await executeClientTool(tool, \"call-2\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-2\",\n content: [{ type: \"text\", text: '{\"value\":42}' }],\n });\n });\n\n it(\"uses transformToContent when provided\", async () => {\n const tool: TamboTool = {\n name: \"custom_tool\",\n description: \"Custom tool\",\n tool: async () => \"custom result\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n transformToContent: (result) => [\n { type: \"text\", text: `Transformed: ${result}` },\n ],\n };\n\n const result = await executeClientTool(tool, \"call-3\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-3\",\n content: [{ type: \"text\", text: \"Transformed: custom result\" }],\n });\n });\n\n it(\"handles transformToContent with non-text types by stringifying\", async () => {\n const tool: TamboTool = {\n name: \"image_tool\",\n description: \"Image tool\",\n tool: async () => \"image data\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n transformToContent: () => [\n {\n type: \"image_url\",\n image_url: { url: \"https://example.com/image.png\" },\n },\n ],\n };\n\n const result = await executeClientTool(tool, \"call-4\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-4\",\n content: [\n {\n type: \"text\",\n text: '{\"type\":\"image_url\",\"image_url\":{\"url\":\"https://example.com/image.png\"}}',\n },\n ],\n });\n });\n\n it(\"handles tool execution errors gracefully\", async () => {\n const tool: TamboTool = {\n name: \"failing_tool\",\n description: \"A tool that fails\",\n tool: async () => {\n throw new Error(\"Tool failed!\");\n },\n inputSchema: z.object({}),\n outputSchema: z.void(),\n };\n\n const result = await executeClientTool(tool, \"call-5\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-5\",\n content: [{ type: \"text\", text: \"Tool failed!\" }],\n });\n });\n\n it(\"handles non-Error throws gracefully\", async () => {\n const tool: TamboTool = {\n name: \"throwing_tool\",\n description: \"A tool that throws a string\",\n tool: async () => {\n throw \"string error\";\n },\n inputSchema: z.object({}),\n outputSchema: z.void(),\n };\n\n const result = await executeClientTool(tool, \"call-6\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-6\",\n content: [{ type: \"text\", text: \"Tool execution failed\" }],\n });\n });\n });\n\n describe(\"executeAllPendingTools\", () => {\n it(\"executes multiple tools with Map registry\", async () => {\n const registry = new Map<string, TamboTool>([\n [\n \"add\",\n {\n name: \"add\",\n description: \"Adds numbers\",\n tool: async ({ a, b }: { a: number; b: number }) => a + b,\n inputSchema: z.object({ a: z.number(), b: z.number() }),\n outputSchema: z.number(),\n },\n ],\n [\n \"multiply\",\n {\n name: \"multiply\",\n description: \"Multiplies numbers\",\n tool: async ({ a, b }: { a: number; b: number }) => a * b,\n inputSchema: z.object({ a: z.number(), b: z.number() }),\n outputSchema: z.number(),\n },\n ],\n ]);\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"add\", input: { a: 2, b: 3 } }],\n [\"call-2\", { name: \"multiply\", input: { a: 4, b: 5 } }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(2);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"5\" }],\n });\n expect(results[1]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-2\",\n content: [{ type: \"text\", text: \"20\" }],\n });\n });\n\n it(\"executes tools with Record registry\", async () => {\n const registry: Record<string, TamboTool> = {\n greet: {\n name: \"greet\",\n description: \"Greets user\",\n tool: async ({ name }: { name: string }) => `Hello, ${name}!`,\n inputSchema: z.object({ name: z.string() }),\n outputSchema: z.string(),\n },\n };\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"greet\", input: { name: \"World\" } }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(1);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"Hello, World!\" }],\n });\n });\n\n it(\"returns error result for unknown tools\", async () => {\n const registry = new Map<string, TamboTool>();\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"unknown_tool\", input: {} }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(1);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [\n { type: \"text\", text: 'Tool \"unknown_tool\" not found in registry' },\n ],\n });\n });\n\n it(\"handles mixed known and unknown tools\", async () => {\n const registry = new Map<string, TamboTool>([\n [\n \"known\",\n {\n name: \"known\",\n description: \"Known tool\",\n tool: async () => \"success\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n },\n ],\n ]);\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"known\", input: {} }],\n [\"call-2\", { name: \"unknown\", input: {} }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(2);\n expect(results[0].content[0]).toEqual({ type: \"text\", text: \"success\" });\n expect(results[1].content[0]).toEqual({\n type: \"text\",\n text: 'Tool \"unknown\" not found in registry',\n });\n });\n });\n});\n"]}
@@ -0,0 +1,58 @@
1
+ import type { TamboV1Message } from "../types/message";
2
+ /**
3
+ * Return type for useTamboV1Messages hook
4
+ */
5
+ export interface UseTamboV1MessagesReturn {
6
+ /**
7
+ * All messages in the thread
8
+ */
9
+ messages: TamboV1Message[];
10
+ /**
11
+ * The most recent message (last in the list)
12
+ */
13
+ lastMessage: TamboV1Message | undefined;
14
+ /**
15
+ * User messages only
16
+ */
17
+ userMessages: TamboV1Message[];
18
+ /**
19
+ * Assistant messages only
20
+ */
21
+ assistantMessages: TamboV1Message[];
22
+ /**
23
+ * Whether there are any messages
24
+ */
25
+ hasMessages: boolean;
26
+ /**
27
+ * Total message count
28
+ */
29
+ messageCount: number;
30
+ }
31
+ /**
32
+ * Hook to access messages in a thread.
33
+ *
34
+ * Provides filtered views of messages (user-only, assistant-only)
35
+ * and metadata about the message list.
36
+ * @param threadId - Thread ID to get messages for
37
+ * @returns Message list and utilities
38
+ * @example
39
+ * ```tsx
40
+ * function MessageList({ threadId }: { threadId: string }) {
41
+ * const { messages, hasMessages, lastMessage } = useTamboV1Messages(threadId);
42
+ *
43
+ * if (!hasMessages) {
44
+ * return <EmptyState />;
45
+ * }
46
+ *
47
+ * return (
48
+ * <div>
49
+ * {messages.map(msg => (
50
+ * <Message key={msg.id} message={msg} />
51
+ * ))}
52
+ * </div>
53
+ * );
54
+ * }
55
+ * ```
56
+ */
57
+ export declare function useTamboV1Messages(threadId: string): UseTamboV1MessagesReturn;
58
+ //# sourceMappingURL=use-tambo-v1-messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-v1-messages.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-messages.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,QAAQ,EAAE,cAAc,EAAE,CAAC;IAE3B;;OAEG;IACH,WAAW,EAAE,cAAc,GAAG,SAAS,CAAC;IAExC;;OAEG;IACH,YAAY,EAAE,cAAc,EAAE,CAAC;IAE/B;;OAEG;IACH,iBAAiB,EAAE,cAAc,EAAE,CAAC;IAEpC;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,wBAAwB,CAgB7E"}
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ /**
3
+ * useTamboV1Messages - Messages Hook for v1 API
4
+ *
5
+ * Provides access to messages in a thread with streaming state awareness.
6
+ * Messages are accumulated from AG-UI events during streaming.
7
+ */
8
+ import { useMemo } from "react";
9
+ import { useStreamState } from "../providers/tambo-v1-stream-context";
10
+ /**
11
+ * Hook to access messages in a thread.
12
+ *
13
+ * Provides filtered views of messages (user-only, assistant-only)
14
+ * and metadata about the message list.
15
+ * @param threadId - Thread ID to get messages for
16
+ * @returns Message list and utilities
17
+ * @example
18
+ * ```tsx
19
+ * function MessageList({ threadId }: { threadId: string }) {
20
+ * const { messages, hasMessages, lastMessage } = useTamboV1Messages(threadId);
21
+ *
22
+ * if (!hasMessages) {
23
+ * return <EmptyState />;
24
+ * }
25
+ *
26
+ * return (
27
+ * <div>
28
+ * {messages.map(msg => (
29
+ * <Message key={msg.id} message={msg} />
30
+ * ))}
31
+ * </div>
32
+ * );
33
+ * }
34
+ * ```
35
+ */
36
+ export function useTamboV1Messages(threadId) {
37
+ const streamState = useStreamState();
38
+ const threadState = streamState.threadMap[threadId];
39
+ return useMemo(() => {
40
+ const messages = threadState?.thread.messages ?? [];
41
+ return {
42
+ messages,
43
+ lastMessage: messages[messages.length - 1],
44
+ userMessages: messages.filter((m) => m.role === "user"),
45
+ assistantMessages: messages.filter((m) => m.role === "assistant"),
46
+ hasMessages: messages.length > 0,
47
+ messageCount: messages.length,
48
+ };
49
+ }, [threadState?.thread.messages]);
50
+ }
51
+ //# sourceMappingURL=use-tambo-v1-messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-v1-messages.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-messages.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAsCtE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEpD,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,MAAM,QAAQ,GAAG,WAAW,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;QAEpD,OAAO;YACL,QAAQ;YACR,WAAW,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YAC1C,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;YACvD,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC;YACjE,WAAW,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC;YAChC,YAAY,EAAE,QAAQ,CAAC,MAAM;SAC9B,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AACrC,CAAC","sourcesContent":["\"use client\";\n\n/**\n * useTamboV1Messages - Messages Hook for v1 API\n *\n * Provides access to messages in a thread with streaming state awareness.\n * Messages are accumulated from AG-UI events during streaming.\n */\n\nimport { useMemo } from \"react\";\nimport { useStreamState } from \"../providers/tambo-v1-stream-context\";\nimport type { TamboV1Message } from \"../types/message\";\n\n/**\n * Return type for useTamboV1Messages hook\n */\nexport interface UseTamboV1MessagesReturn {\n /**\n * All messages in the thread\n */\n messages: TamboV1Message[];\n\n /**\n * The most recent message (last in the list)\n */\n lastMessage: TamboV1Message | undefined;\n\n /**\n * User messages only\n */\n userMessages: TamboV1Message[];\n\n /**\n * Assistant messages only\n */\n assistantMessages: TamboV1Message[];\n\n /**\n * Whether there are any messages\n */\n hasMessages: boolean;\n\n /**\n * Total message count\n */\n messageCount: number;\n}\n\n/**\n * Hook to access messages in a thread.\n *\n * Provides filtered views of messages (user-only, assistant-only)\n * and metadata about the message list.\n * @param threadId - Thread ID to get messages for\n * @returns Message list and utilities\n * @example\n * ```tsx\n * function MessageList({ threadId }: { threadId: string }) {\n * const { messages, hasMessages, lastMessage } = useTamboV1Messages(threadId);\n *\n * if (!hasMessages) {\n * return <EmptyState />;\n * }\n *\n * return (\n * <div>\n * {messages.map(msg => (\n * <Message key={msg.id} message={msg} />\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useTamboV1Messages(threadId: string): UseTamboV1MessagesReturn {\n const streamState = useStreamState();\n const threadState = streamState.threadMap[threadId];\n\n return useMemo(() => {\n const messages = threadState?.thread.messages ?? [];\n\n return {\n messages,\n lastMessage: messages[messages.length - 1],\n userMessages: messages.filter((m) => m.role === \"user\"),\n assistantMessages: messages.filter((m) => m.role === \"assistant\"),\n hasMessages: messages.length > 0,\n messageCount: messages.length,\n };\n }, [threadState?.thread.messages]);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-tambo-v1-messages.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-v1-messages.test.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-messages.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,132 @@
1
+ import { EventType, } from "@ag-ui/core";
2
+ import { renderHook, act } from "@testing-library/react";
3
+ import React from "react";
4
+ import { TamboV1StreamProvider, useStreamDispatch, } from "../providers/tambo-v1-stream-context";
5
+ import { useTamboV1Messages } from "./use-tambo-v1-messages";
6
+ describe("useTamboV1Messages", () => {
7
+ function TestWrapper({ children }) {
8
+ return (React.createElement(TamboV1StreamProvider, { threadId: "thread_123" }, children));
9
+ }
10
+ it("returns empty messages when thread has no messages", () => {
11
+ const { result } = renderHook(() => useTamboV1Messages("thread_123"), {
12
+ wrapper: TestWrapper,
13
+ });
14
+ expect(result.current.messages).toEqual([]);
15
+ expect(result.current.hasMessages).toBe(false);
16
+ expect(result.current.messageCount).toBe(0);
17
+ expect(result.current.lastMessage).toBeUndefined();
18
+ expect(result.current.userMessages).toEqual([]);
19
+ expect(result.current.assistantMessages).toEqual([]);
20
+ });
21
+ it("returns messages after events are dispatched", () => {
22
+ const { result } = renderHook(() => ({
23
+ messages: useTamboV1Messages("thread_123"),
24
+ dispatch: useStreamDispatch(),
25
+ }), { wrapper: TestWrapper });
26
+ // Simulate a text message being received
27
+ act(() => {
28
+ result.current.dispatch({
29
+ type: "EVENT",
30
+ event: {
31
+ type: EventType.TEXT_MESSAGE_START,
32
+ messageId: "msg_1",
33
+ role: "assistant",
34
+ },
35
+ threadId: "thread_123",
36
+ });
37
+ });
38
+ act(() => {
39
+ result.current.dispatch({
40
+ type: "EVENT",
41
+ event: {
42
+ type: EventType.TEXT_MESSAGE_CONTENT,
43
+ messageId: "msg_1",
44
+ delta: "Hello",
45
+ },
46
+ threadId: "thread_123",
47
+ });
48
+ });
49
+ act(() => {
50
+ result.current.dispatch({
51
+ type: "EVENT",
52
+ event: {
53
+ type: EventType.TEXT_MESSAGE_END,
54
+ messageId: "msg_1",
55
+ },
56
+ threadId: "thread_123",
57
+ });
58
+ });
59
+ expect(result.current.messages.messages.length).toBe(1);
60
+ expect(result.current.messages.hasMessages).toBe(true);
61
+ expect(result.current.messages.messageCount).toBe(1);
62
+ expect(result.current.messages.lastMessage?.id).toBe("msg_1");
63
+ expect(result.current.messages.lastMessage?.role).toBe("assistant");
64
+ expect(result.current.messages.assistantMessages.length).toBe(1);
65
+ expect(result.current.messages.userMessages.length).toBe(0);
66
+ });
67
+ it("filters user and assistant messages correctly", () => {
68
+ const { result } = renderHook(() => ({
69
+ messages: useTamboV1Messages("thread_123"),
70
+ dispatch: useStreamDispatch(),
71
+ }), { wrapper: TestWrapper });
72
+ // Add user message
73
+ act(() => {
74
+ result.current.dispatch({
75
+ type: "EVENT",
76
+ event: {
77
+ type: EventType.TEXT_MESSAGE_START,
78
+ messageId: "msg_user",
79
+ role: "user",
80
+ },
81
+ threadId: "thread_123",
82
+ });
83
+ });
84
+ act(() => {
85
+ result.current.dispatch({
86
+ type: "EVENT",
87
+ event: {
88
+ type: EventType.TEXT_MESSAGE_END,
89
+ messageId: "msg_user",
90
+ },
91
+ threadId: "thread_123",
92
+ });
93
+ });
94
+ // Add assistant message
95
+ act(() => {
96
+ result.current.dispatch({
97
+ type: "EVENT",
98
+ event: {
99
+ type: EventType.TEXT_MESSAGE_START,
100
+ messageId: "msg_assistant",
101
+ role: "assistant",
102
+ },
103
+ threadId: "thread_123",
104
+ });
105
+ });
106
+ act(() => {
107
+ result.current.dispatch({
108
+ type: "EVENT",
109
+ event: {
110
+ type: EventType.TEXT_MESSAGE_END,
111
+ messageId: "msg_assistant",
112
+ },
113
+ threadId: "thread_123",
114
+ });
115
+ });
116
+ expect(result.current.messages.messageCount).toBe(2);
117
+ expect(result.current.messages.userMessages.length).toBe(1);
118
+ expect(result.current.messages.userMessages[0].id).toBe("msg_user");
119
+ expect(result.current.messages.assistantMessages.length).toBe(1);
120
+ expect(result.current.messages.assistantMessages[0].id).toBe("msg_assistant");
121
+ expect(result.current.messages.lastMessage?.id).toBe("msg_assistant");
122
+ });
123
+ it("returns empty messages when threadId does not exist in threadMap", () => {
124
+ const { result } = renderHook(() => useTamboV1Messages("nonexistent_thread"), {
125
+ wrapper: TestWrapper,
126
+ });
127
+ expect(result.current.messages).toEqual([]);
128
+ expect(result.current.hasMessages).toBe(false);
129
+ expect(result.current.messageCount).toBe(0);
130
+ });
131
+ });
132
+ //# sourceMappingURL=use-tambo-v1-messages.test.js.map