@tambo-ai/react 0.73.0 → 0.74.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 (419) hide show
  1. package/README.md +12 -12
  2. package/dist/hooks/use-component-state.d.ts +1 -1
  3. package/dist/hooks/use-component-state.js.map +1 -1
  4. package/dist/hooks/use-streaming-props.d.ts +1 -1
  5. package/dist/hooks/use-streaming-props.js +1 -1
  6. package/dist/hooks/use-streaming-props.js.map +1 -1
  7. package/dist/hooks/use-tambo-stream-status.d.ts +1 -1
  8. package/dist/hooks/use-tambo-stream-status.js +1 -1
  9. package/dist/hooks/use-tambo-stream-status.js.map +1 -1
  10. package/dist/mcp/mcp-hooks.d.ts +4 -0
  11. package/dist/mcp/mcp-hooks.d.ts.map +1 -1
  12. package/dist/mcp/mcp-hooks.js +4 -0
  13. package/dist/mcp/mcp-hooks.js.map +1 -1
  14. package/dist/providers/tambo-interactable-provider-partial-updates.test.js +3 -3
  15. package/dist/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
  16. package/dist/providers/tambo-interactable-provider.js +2 -2
  17. package/dist/providers/tambo-interactable-provider.js.map +1 -1
  18. package/dist/providers/tambo-interactable-provider.test.js +3 -3
  19. package/dist/providers/tambo-interactable-provider.test.js.map +1 -1
  20. package/dist/providers/tambo-provider.d.ts +3 -0
  21. package/dist/providers/tambo-provider.d.ts.map +1 -1
  22. package/dist/providers/tambo-provider.js +3 -0
  23. package/dist/providers/tambo-provider.js.map +1 -1
  24. package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
  25. package/dist/providers/tambo-thread-input-provider.js +1 -0
  26. package/dist/providers/tambo-thread-input-provider.js.map +1 -1
  27. package/dist/util/resource-content-resolver.d.ts.map +1 -1
  28. package/dist/util/resource-content-resolver.js +2 -0
  29. package/dist/util/resource-content-resolver.js.map +1 -1
  30. package/dist/v1/__tests__/v1-interactables.test.d.ts +2 -0
  31. package/dist/v1/__tests__/v1-interactables.test.d.ts.map +1 -0
  32. package/dist/v1/__tests__/v1-interactables.test.js +135 -0
  33. package/dist/v1/__tests__/v1-interactables.test.js.map +1 -0
  34. package/dist/v1/components/v1-component-renderer.d.ts +48 -0
  35. package/dist/v1/components/v1-component-renderer.d.ts.map +1 -0
  36. package/dist/v1/components/v1-component-renderer.js +137 -0
  37. package/dist/v1/components/v1-component-renderer.js.map +1 -0
  38. package/dist/v1/components/v1-component-renderer.test.d.ts +2 -0
  39. package/dist/v1/components/v1-component-renderer.test.d.ts.map +1 -0
  40. package/dist/v1/components/v1-component-renderer.test.js +270 -0
  41. package/dist/v1/components/v1-component-renderer.test.js.map +1 -0
  42. package/dist/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
  43. package/dist/v1/hooks/use-tambo-v1-component-state.js +2 -25
  44. package/dist/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
  45. package/dist/v1/hooks/use-tambo-v1-component-state.test.js +2 -1
  46. package/dist/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
  47. package/dist/v1/hooks/use-tambo-v1-messages.test.js +25 -1
  48. package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  49. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +18 -0
  50. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  51. package/dist/v1/hooks/use-tambo-v1-send-message.js +204 -17
  52. package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  53. package/dist/v1/hooks/use-tambo-v1-send-message.test.js +261 -7
  54. package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  55. package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts +90 -0
  56. package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -0
  57. package/dist/v1/hooks/use-tambo-v1-stream-status.js +179 -0
  58. package/dist/v1/hooks/use-tambo-v1-stream-status.js.map +1 -0
  59. package/dist/v1/hooks/use-tambo-v1-stream-status.test.d.ts +2 -0
  60. package/dist/v1/hooks/use-tambo-v1-stream-status.test.d.ts.map +1 -0
  61. package/dist/v1/hooks/use-tambo-v1-stream-status.test.js +371 -0
  62. package/dist/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -0
  63. package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts +78 -54
  64. package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
  65. package/dist/v1/hooks/use-tambo-v1-suggestions.js +153 -87
  66. package/dist/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
  67. package/dist/v1/hooks/use-tambo-v1-suggestions.test.js +213 -134
  68. package/dist/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
  69. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +148 -13
  70. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  71. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +8 -21
  72. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  73. package/dist/v1/hooks/use-tambo-v1-thread-list.js +11 -10
  74. package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  75. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +37 -2
  76. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  77. package/dist/v1/hooks/use-tambo-v1-thread.d.ts +1 -1
  78. package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
  79. package/dist/v1/hooks/use-tambo-v1-thread.js +2 -7
  80. package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -1
  81. package/dist/v1/hooks/use-tambo-v1-thread.test.js +2 -0
  82. package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
  83. package/dist/v1/hooks/use-tambo-v1.d.ts +12 -28
  84. package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -1
  85. package/dist/v1/hooks/use-tambo-v1.js +164 -31
  86. package/dist/v1/hooks/use-tambo-v1.js.map +1 -1
  87. package/dist/v1/hooks/use-tambo-v1.test.js +891 -18
  88. package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
  89. package/dist/v1/index.d.ts +7 -1
  90. package/dist/v1/index.d.ts.map +1 -1
  91. package/dist/v1/index.js +18 -1
  92. package/dist/v1/index.js.map +1 -1
  93. package/dist/v1/providers/tambo-v1-provider.d.ts +16 -6
  94. package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  95. package/dist/v1/providers/tambo-v1-provider.js +14 -19
  96. package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
  97. package/dist/v1/providers/tambo-v1-provider.test.js +34 -20
  98. package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
  99. package/dist/v1/providers/tambo-v1-stream-context.d.ts +3 -3
  100. package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  101. package/dist/v1/providers/tambo-v1-stream-context.js +60 -12
  102. package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
  103. package/dist/v1/providers/tambo-v1-stream-context.test.js +49 -20
  104. package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  105. package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
  106. package/dist/v1/providers/tambo-v1-stub-provider.js +2 -0
  107. package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -1
  108. package/dist/v1/providers/tambo-v1-stub-provider.test.js +7 -6
  109. package/dist/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
  110. package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +1 -6
  111. package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
  112. package/dist/v1/providers/tambo-v1-thread-input-provider.js +14 -12
  113. package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
  114. package/dist/v1/types/event.d.ts +9 -1
  115. package/dist/v1/types/event.d.ts.map +1 -1
  116. package/dist/v1/types/event.js.map +1 -1
  117. package/dist/v1/types/event.test.js +5 -1
  118. package/dist/v1/types/event.test.js.map +1 -1
  119. package/dist/v1/types/message.d.ts +65 -7
  120. package/dist/v1/types/message.d.ts.map +1 -1
  121. package/dist/v1/types/message.js.map +1 -1
  122. package/dist/v1/types/thread.d.ts +4 -0
  123. package/dist/v1/types/thread.d.ts.map +1 -1
  124. package/dist/v1/types/thread.js.map +1 -1
  125. package/dist/v1/utils/event-accumulator.d.ts +40 -4
  126. package/dist/v1/utils/event-accumulator.d.ts.map +1 -1
  127. package/dist/v1/utils/event-accumulator.js +444 -35
  128. package/dist/v1/utils/event-accumulator.js.map +1 -1
  129. package/dist/v1/utils/event-accumulator.test.js +1041 -28
  130. package/dist/v1/utils/event-accumulator.test.js.map +1 -1
  131. package/dist/v1/utils/registry-conversion.d.ts +9 -9
  132. package/dist/v1/utils/registry-conversion.d.ts.map +1 -1
  133. package/dist/v1/utils/registry-conversion.js +10 -11
  134. package/dist/v1/utils/registry-conversion.js.map +1 -1
  135. package/dist/v1/utils/registry-conversion.test.js +39 -11
  136. package/dist/v1/utils/registry-conversion.test.js.map +1 -1
  137. package/dist/v1/utils/thread-utils.d.ts +16 -0
  138. package/dist/v1/utils/thread-utils.d.ts.map +1 -0
  139. package/dist/v1/utils/thread-utils.js +34 -0
  140. package/dist/v1/utils/thread-utils.js.map +1 -0
  141. package/dist/v1/utils/tool-executor.d.ts.map +1 -1
  142. package/dist/v1/utils/tool-executor.js +2 -0
  143. package/dist/v1/utils/tool-executor.js.map +1 -1
  144. package/dist/v1/utils/tool-executor.test.js +5 -0
  145. package/dist/v1/utils/tool-executor.test.js.map +1 -1
  146. package/esm/context-helpers/context-helpers-provider.test.js +2 -2
  147. package/esm/context-helpers/context-helpers.test.js +1 -1
  148. package/esm/context-helpers/current-interactables-context-helper.d.ts +1 -1
  149. package/esm/context-helpers/current-page-context-helper.d.ts +1 -1
  150. package/esm/context-helpers/current-time-context-helper.d.ts +1 -1
  151. package/esm/context-helpers/index.d.ts +4 -4
  152. package/esm/context-helpers/index.js +4 -4
  153. package/esm/hoc/with-tambo-interactable.d.ts +1 -1
  154. package/esm/hoc/with-tambo-interactable.js +2 -2
  155. package/esm/hoc/with-tambo-interactable.test.js +3 -3
  156. package/esm/hooks/index.d.ts +8 -8
  157. package/esm/hooks/index.js +8 -8
  158. package/esm/hooks/react-query-hooks.js +1 -1
  159. package/esm/hooks/use-component-state.d.ts +1 -1
  160. package/esm/hooks/use-component-state.js +3 -3
  161. package/esm/hooks/use-component-state.js.map +1 -1
  162. package/esm/hooks/use-component-state.test.js +5 -5
  163. package/esm/hooks/use-current-message.d.ts +1 -1
  164. package/esm/hooks/use-current-message.test.js +1 -1
  165. package/esm/hooks/use-message-images.test.js +1 -1
  166. package/esm/hooks/use-streaming-props.d.ts +1 -1
  167. package/esm/hooks/use-streaming-props.js +1 -1
  168. package/esm/hooks/use-streaming-props.js.map +1 -1
  169. package/esm/hooks/use-suggestions.d.ts +2 -2
  170. package/esm/hooks/use-suggestions.js +10 -10
  171. package/esm/hooks/use-suggestions.test.js +7 -7
  172. package/esm/hooks/use-tambo-stream-status.d.ts +1 -1
  173. package/esm/hooks/use-tambo-stream-status.js +4 -4
  174. package/esm/hooks/use-tambo-stream-status.js.map +1 -1
  175. package/esm/hooks/use-tambo-stream-status.test.js +4 -4
  176. package/esm/hooks/use-tambo-threads.js +3 -3
  177. package/esm/hooks/use-tambo-threads.test.js +3 -3
  178. package/esm/hooks/use-tambo-voice.js +2 -2
  179. package/esm/hooks/use-tambo-voice.test.js +3 -3
  180. package/esm/index.d.ts +22 -22
  181. package/esm/index.js +15 -15
  182. package/esm/mcp/elicitation.d.ts +1 -1
  183. package/esm/mcp/elicitation.test.js +1 -1
  184. package/esm/mcp/index.d.ts +7 -7
  185. package/esm/mcp/index.js +3 -3
  186. package/esm/mcp/mcp-client.d.ts +1 -1
  187. package/esm/mcp/mcp-client.js +1 -1
  188. package/esm/mcp/mcp-client.test.js +1 -1
  189. package/esm/mcp/mcp-hooks.d.ts +5 -1
  190. package/esm/mcp/mcp-hooks.d.ts.map +1 -1
  191. package/esm/mcp/mcp-hooks.js +8 -4
  192. package/esm/mcp/mcp-hooks.js.map +1 -1
  193. package/esm/mcp/mcp-hooks.test.js +6 -6
  194. package/esm/mcp/tambo-mcp-provider.d.ts +4 -4
  195. package/esm/mcp/tambo-mcp-provider.js +7 -7
  196. package/esm/mcp/tambo-mcp-provider.test.js +5 -5
  197. package/esm/mcp/use-mcp-servers.test.js +4 -4
  198. package/esm/model/generate-component-response.d.ts +1 -1
  199. package/esm/model/tambo-interactable.d.ts +1 -1
  200. package/esm/model/tambo-thread.d.ts +1 -1
  201. package/esm/providers/__tests__/thread-input-resource-resolution.test.js +3 -3
  202. package/esm/providers/hooks/use-tambo-session-token.test.js +1 -1
  203. package/esm/providers/index.d.ts +12 -12
  204. package/esm/providers/index.js +10 -10
  205. package/esm/providers/tambo-client-provider.js +1 -1
  206. package/esm/providers/tambo-client-provider.test.js +2 -2
  207. package/esm/providers/tambo-component-provider.d.ts +1 -1
  208. package/esm/providers/tambo-component-provider.js +2 -2
  209. package/esm/providers/tambo-context-attachment-provider.js +1 -1
  210. package/esm/providers/tambo-context-attachment-provider.test.js +2 -2
  211. package/esm/providers/tambo-context-helpers-provider.d.ts +1 -1
  212. package/esm/providers/tambo-context-helpers-provider.js +1 -1
  213. package/esm/providers/tambo-context-helpers-provider.test.js +2 -2
  214. package/esm/providers/tambo-interactable-provider-partial-updates.test.js +4 -4
  215. package/esm/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
  216. package/esm/providers/tambo-interactable-provider.d.ts +5 -5
  217. package/esm/providers/tambo-interactable-provider.js +6 -6
  218. package/esm/providers/tambo-interactable-provider.js.map +1 -1
  219. package/esm/providers/tambo-interactable-provider.test.js +4 -4
  220. package/esm/providers/tambo-interactable-provider.test.js.map +1 -1
  221. package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js +4 -4
  222. package/esm/providers/tambo-interactables-additional-context.test.js +4 -4
  223. package/esm/providers/tambo-mcp-token-provider.js +2 -2
  224. package/esm/providers/tambo-prop-stream-provider/index.d.ts +8 -8
  225. package/esm/providers/tambo-prop-stream-provider/index.js +9 -9
  226. package/esm/providers/tambo-prop-stream-provider/pending.d.ts +1 -1
  227. package/esm/providers/tambo-prop-stream-provider/pending.js +2 -2
  228. package/esm/providers/tambo-prop-stream-provider/provider.d.ts +1 -1
  229. package/esm/providers/tambo-prop-stream-provider/provider.js +2 -2
  230. package/esm/providers/tambo-prop-stream-provider/streaming.d.ts +1 -1
  231. package/esm/providers/tambo-prop-stream-provider/streaming.js +2 -2
  232. package/esm/providers/tambo-prop-stream-provider/success.d.ts +1 -1
  233. package/esm/providers/tambo-prop-stream-provider/success.js +2 -2
  234. package/esm/providers/tambo-prop-stream-provider/types.d.ts +1 -1
  235. package/esm/providers/tambo-prop-stream-provider.test.js +4 -4
  236. package/esm/providers/tambo-provider.d.ts +10 -7
  237. package/esm/providers/tambo-provider.d.ts.map +1 -1
  238. package/esm/providers/tambo-provider.js +13 -10
  239. package/esm/providers/tambo-provider.js.map +1 -1
  240. package/esm/providers/tambo-registry-provider.d.ts +3 -3
  241. package/esm/providers/tambo-registry-provider.js +3 -3
  242. package/esm/providers/tambo-registry-provider.test.js +2 -2
  243. package/esm/providers/tambo-registry-schema-compat.test.js +2 -2
  244. package/esm/providers/tambo-stubs.d.ts +4 -4
  245. package/esm/providers/tambo-stubs.js +9 -9
  246. package/esm/providers/tambo-stubs.test.js +2 -2
  247. package/esm/providers/tambo-thread-input-provider.d.ts +2 -2
  248. package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
  249. package/esm/providers/tambo-thread-input-provider.js +11 -10
  250. package/esm/providers/tambo-thread-input-provider.js.map +1 -1
  251. package/esm/providers/tambo-thread-provider-initial-messages.test.js +6 -6
  252. package/esm/providers/tambo-thread-provider.d.ts +2 -2
  253. package/esm/providers/tambo-thread-provider.js +8 -8
  254. package/esm/providers/tambo-thread-provider.test.js +7 -7
  255. package/esm/schema/index.d.ts +4 -4
  256. package/esm/schema/index.js +4 -4
  257. package/esm/schema/json-schema.test.js +1 -1
  258. package/esm/schema/schema.d.ts +1 -1
  259. package/esm/schema/schema.js +2 -2
  260. package/esm/schema/schema.test.js +3 -3
  261. package/esm/schema/standard-schema.test.js +1 -1
  262. package/esm/schema/validate.js +2 -2
  263. package/esm/schema/validate.test.js +1 -1
  264. package/esm/testing/tools.d.ts +3 -3
  265. package/esm/testing/tools.js +2 -2
  266. package/esm/util/content-parts.test.js +1 -1
  267. package/esm/util/generate-component.d.ts +2 -2
  268. package/esm/util/generate-component.js +4 -4
  269. package/esm/util/generate-component.test.js +2 -2
  270. package/esm/util/is-promise.test.js +1 -1
  271. package/esm/util/mcp-server-utils.d.ts +1 -1
  272. package/esm/util/mcp-server-utils.js +1 -1
  273. package/esm/util/mcp-server-utils.test.js +2 -2
  274. package/esm/util/message-builder.d.ts +1 -1
  275. package/esm/util/message-builder.test.js +1 -1
  276. package/esm/util/query-utils.test.js +1 -1
  277. package/esm/util/registry-validators.d.ts +1 -1
  278. package/esm/util/registry-validators.js +2 -2
  279. package/esm/util/registry-validators.test.js +1 -1
  280. package/esm/util/registry.d.ts +1 -1
  281. package/esm/util/registry.js +1 -1
  282. package/esm/util/registry.test.js +2 -2
  283. package/esm/util/resource-content-resolver.d.ts +2 -2
  284. package/esm/util/resource-content-resolver.d.ts.map +1 -1
  285. package/esm/util/resource-content-resolver.js +3 -1
  286. package/esm/util/resource-content-resolver.js.map +1 -1
  287. package/esm/util/resource-content-resolver.test.js +3 -3
  288. package/esm/util/resource-validators.d.ts +1 -1
  289. package/esm/util/resource-validators.test.js +1 -1
  290. package/esm/util/tool-caller.d.ts +1 -1
  291. package/esm/util/tool-caller.js +1 -1
  292. package/esm/util/validate-component-name.test.js +1 -1
  293. package/esm/v1/__tests__/v1-interactables.test.d.ts +2 -0
  294. package/esm/v1/__tests__/v1-interactables.test.d.ts.map +1 -0
  295. package/esm/v1/__tests__/v1-interactables.test.js +130 -0
  296. package/esm/v1/__tests__/v1-interactables.test.js.map +1 -0
  297. package/esm/v1/components/v1-component-renderer.d.ts +48 -0
  298. package/esm/v1/components/v1-component-renderer.d.ts.map +1 -0
  299. package/esm/v1/components/v1-component-renderer.js +100 -0
  300. package/esm/v1/components/v1-component-renderer.js.map +1 -0
  301. package/esm/v1/components/v1-component-renderer.test.d.ts +2 -0
  302. package/esm/v1/components/v1-component-renderer.test.d.ts.map +1 -0
  303. package/esm/v1/components/v1-component-renderer.test.js +265 -0
  304. package/esm/v1/components/v1-component-renderer.test.js.map +1 -0
  305. package/esm/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
  306. package/esm/v1/hooks/use-tambo-v1-component-state.js +4 -27
  307. package/esm/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
  308. package/esm/v1/hooks/use-tambo-v1-component-state.test.js +6 -5
  309. package/esm/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
  310. package/esm/v1/hooks/use-tambo-v1-messages.d.ts +1 -1
  311. package/esm/v1/hooks/use-tambo-v1-messages.js +1 -1
  312. package/esm/v1/hooks/use-tambo-v1-messages.test.js +27 -3
  313. package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  314. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +20 -2
  315. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  316. package/esm/v1/hooks/use-tambo-v1-send-message.js +213 -26
  317. package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  318. package/esm/v1/hooks/use-tambo-v1-send-message.test.js +266 -12
  319. package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  320. package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts +90 -0
  321. package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -0
  322. package/esm/v1/hooks/use-tambo-v1-stream-status.js +176 -0
  323. package/esm/v1/hooks/use-tambo-v1-stream-status.js.map +1 -0
  324. package/esm/v1/hooks/use-tambo-v1-stream-status.test.d.ts +2 -0
  325. package/esm/v1/hooks/use-tambo-v1-stream-status.test.d.ts.map +1 -0
  326. package/esm/v1/hooks/use-tambo-v1-stream-status.test.js +369 -0
  327. package/esm/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -0
  328. package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts +78 -54
  329. package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
  330. package/esm/v1/hooks/use-tambo-v1-suggestions.js +157 -91
  331. package/esm/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
  332. package/esm/v1/hooks/use-tambo-v1-suggestions.test.js +218 -139
  333. package/esm/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
  334. package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts +1 -1
  335. package/esm/v1/hooks/use-tambo-v1-thread-input.js +1 -1
  336. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +151 -16
  337. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  338. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +8 -21
  339. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  340. package/esm/v1/hooks/use-tambo-v1-thread-list.js +12 -11
  341. package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  342. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +39 -4
  343. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  344. package/esm/v1/hooks/use-tambo-v1-thread.d.ts +1 -1
  345. package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
  346. package/esm/v1/hooks/use-tambo-v1-thread.js +3 -8
  347. package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -1
  348. package/esm/v1/hooks/use-tambo-v1-thread.test.js +4 -2
  349. package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
  350. package/esm/v1/hooks/use-tambo-v1.d.ts +15 -31
  351. package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -1
  352. package/esm/v1/hooks/use-tambo-v1.js +134 -34
  353. package/esm/v1/hooks/use-tambo-v1.js.map +1 -1
  354. package/esm/v1/hooks/use-tambo-v1.test.js +862 -19
  355. package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
  356. package/esm/v1/index.d.ts +28 -22
  357. package/esm/v1/index.d.ts.map +1 -1
  358. package/esm/v1/index.js +30 -18
  359. package/esm/v1/index.js.map +1 -1
  360. package/esm/v1/providers/tambo-v1-provider.d.ts +21 -11
  361. package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  362. package/esm/v1/providers/tambo-v1-provider.js +20 -25
  363. package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
  364. package/esm/v1/providers/tambo-v1-provider.test.js +40 -26
  365. package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
  366. package/esm/v1/providers/tambo-v1-stream-context.d.ts +4 -4
  367. package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  368. package/esm/v1/providers/tambo-v1-stream-context.js +62 -14
  369. package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
  370. package/esm/v1/providers/tambo-v1-stream-context.test.js +50 -21
  371. package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  372. package/esm/v1/providers/tambo-v1-stub-provider.d.ts +3 -3
  373. package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
  374. package/esm/v1/providers/tambo-v1-stub-provider.js +7 -5
  375. package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -1
  376. package/esm/v1/providers/tambo-v1-stub-provider.test.js +12 -11
  377. package/esm/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
  378. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +3 -8
  379. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
  380. package/esm/v1/providers/tambo-v1-thread-input-provider.js +18 -16
  381. package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
  382. package/esm/v1/types/event.d.ts +9 -1
  383. package/esm/v1/types/event.d.ts.map +1 -1
  384. package/esm/v1/types/event.js.map +1 -1
  385. package/esm/v1/types/event.test.js +6 -2
  386. package/esm/v1/types/event.test.js.map +1 -1
  387. package/esm/v1/types/message.d.ts +65 -7
  388. package/esm/v1/types/message.d.ts.map +1 -1
  389. package/esm/v1/types/message.js.map +1 -1
  390. package/esm/v1/types/thread.d.ts +5 -1
  391. package/esm/v1/types/thread.d.ts.map +1 -1
  392. package/esm/v1/types/thread.js.map +1 -1
  393. package/esm/v1/utils/component-renderer.test.js +1 -1
  394. package/esm/v1/utils/event-accumulator.d.ts +41 -5
  395. package/esm/v1/utils/event-accumulator.d.ts.map +1 -1
  396. package/esm/v1/utils/event-accumulator.js +444 -36
  397. package/esm/v1/utils/event-accumulator.js.map +1 -1
  398. package/esm/v1/utils/event-accumulator.test.js +1042 -29
  399. package/esm/v1/utils/event-accumulator.test.js.map +1 -1
  400. package/esm/v1/utils/json-patch.test.js +1 -1
  401. package/esm/v1/utils/registry-conversion.d.ts +9 -9
  402. package/esm/v1/utils/registry-conversion.d.ts.map +1 -1
  403. package/esm/v1/utils/registry-conversion.js +11 -12
  404. package/esm/v1/utils/registry-conversion.js.map +1 -1
  405. package/esm/v1/utils/registry-conversion.test.js +40 -12
  406. package/esm/v1/utils/registry-conversion.test.js.map +1 -1
  407. package/esm/v1/utils/stream-handler.test.js +1 -1
  408. package/esm/v1/utils/thread-utils.d.ts +16 -0
  409. package/esm/v1/utils/thread-utils.d.ts.map +1 -0
  410. package/esm/v1/utils/thread-utils.js +31 -0
  411. package/esm/v1/utils/thread-utils.js.map +1 -0
  412. package/esm/v1/utils/tool-call-tracker.d.ts +1 -1
  413. package/esm/v1/utils/tool-executor.d.ts +1 -1
  414. package/esm/v1/utils/tool-executor.d.ts.map +1 -1
  415. package/esm/v1/utils/tool-executor.js +2 -0
  416. package/esm/v1/utils/tool-executor.js.map +1 -1
  417. package/esm/v1/utils/tool-executor.test.js +6 -1
  418. package/esm/v1/utils/tool-executor.test.js.map +1 -1
  419. package/package.json +11 -10
@@ -1,21 +1,63 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
5
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ const react_query_1 = require("@tanstack/react-query");
6
37
  const react_1 = require("@testing-library/react");
7
- const react_2 = __importDefault(require("react"));
38
+ const react_2 = __importStar(require("react"));
8
39
  const tambo_client_provider_1 = require("../../providers/tambo-client-provider");
9
40
  const tambo_registry_provider_1 = require("../../providers/tambo-registry-provider");
10
41
  const tambo_v1_stream_context_1 = require("../providers/tambo-v1-stream-context");
42
+ const event_accumulator_1 = require("../utils/event-accumulator");
11
43
  const use_tambo_v1_1 = require("./use-tambo-v1");
12
44
  jest.mock("../../providers/tambo-client-provider", () => ({
13
45
  useTamboClient: jest.fn(),
46
+ useTamboQueryClient: jest.fn(),
14
47
  }));
48
+ const tambo_client_provider_2 = require("../../providers/tambo-client-provider");
15
49
  describe("useTamboV1", () => {
50
+ let queryClient;
16
51
  const mockTamboClient = {
17
52
  apiKey: "",
18
- threads: {},
53
+ threads: {
54
+ messages: {
55
+ list: jest.fn().mockResolvedValue({ messages: [], hasMore: false }),
56
+ },
57
+ runs: {
58
+ delete: jest.fn().mockResolvedValue({}),
59
+ },
60
+ },
19
61
  };
20
62
  const mockRegistry = {
21
63
  componentList: {},
@@ -35,11 +77,35 @@ describe("useTamboV1", () => {
35
77
  registerResourceSource: jest.fn(),
36
78
  };
37
79
  function TestWrapper({ children }) {
38
- return (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: mockRegistry },
39
- react_2.default.createElement(tambo_v1_stream_context_1.TamboV1StreamProvider, null, children)));
80
+ return (react_2.default.createElement(react_query_1.QueryClientProvider, { client: queryClient },
81
+ react_2.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: mockRegistry },
82
+ react_2.default.createElement(tambo_v1_stream_context_1.TamboV1StreamProvider, null, children))));
83
+ }
84
+ function createWrapperWithState(state, registry = mockRegistry) {
85
+ const noopDispatch = () => { };
86
+ return function WrapperWithState({ children, }) {
87
+ return (react_2.default.createElement(react_query_1.QueryClientProvider, { client: queryClient },
88
+ react_2.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
89
+ react_2.default.createElement(tambo_v1_stream_context_1.TamboV1StreamProvider, { state: state, dispatch: noopDispatch }, children))));
90
+ };
91
+ }
92
+ // Wrapper that uses the real reducer so state updates properly
93
+ function createWrapperWithRealReducer(initialState) {
94
+ return function WrapperWithRealReducer({ children, }) {
95
+ const [state, dispatch] = (0, react_2.useReducer)(event_accumulator_1.streamReducer, initialState);
96
+ return (react_2.default.createElement(react_query_1.QueryClientProvider, { client: queryClient },
97
+ react_2.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: mockRegistry },
98
+ react_2.default.createElement(tambo_v1_stream_context_1.TamboV1StreamProvider, { state: state, dispatch: dispatch }, children))));
99
+ };
40
100
  }
41
101
  beforeEach(() => {
102
+ queryClient = new react_query_1.QueryClient({
103
+ defaultOptions: {
104
+ queries: { retry: false },
105
+ },
106
+ });
42
107
  jest.mocked(tambo_client_provider_1.useTamboClient).mockReturnValue(mockTamboClient);
108
+ jest.mocked(tambo_client_provider_2.useTamboQueryClient).mockReturnValue(queryClient);
43
109
  jest.clearAllMocks();
44
110
  });
45
111
  it("returns client from useTamboClient", () => {
@@ -58,20 +124,23 @@ describe("useTamboV1", () => {
58
124
  expect(result.current.componentList).toBe(mockRegistry.componentList);
59
125
  expect(result.current.toolRegistry).toBe(mockRegistry.toolRegistry);
60
126
  });
61
- it("returns undefined thread when no threadId provided", () => {
127
+ it("returns placeholder thread when no threadId provided", () => {
62
128
  const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
63
129
  wrapper: TestWrapper,
64
130
  });
65
- expect(result.current.thread).toBeUndefined();
131
+ // Default state has placeholder thread for optimistic UI
132
+ expect(result.current.thread).toBeDefined();
133
+ expect(result.current.thread?.thread.id).toBe("placeholder");
66
134
  expect(result.current.messages).toEqual([]);
67
135
  });
68
- it("returns thread state when threadId provided", () => {
69
- const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)("thread_123"), {
136
+ it("returns thread state when switched to a thread", () => {
137
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
70
138
  wrapper: TestWrapper,
71
139
  });
72
- // Initialize thread first
140
+ // Initialize and switch to thread
73
141
  (0, react_1.act)(() => {
74
142
  result.current.initThread("thread_123");
143
+ result.current.switchThread("thread_123");
75
144
  });
76
145
  expect(result.current.thread).toBeDefined();
77
146
  expect(result.current.thread?.thread.id).toBe("thread_123");
@@ -87,12 +156,13 @@ describe("useTamboV1", () => {
87
156
  expect(result.current.isWaiting).toBe(false);
88
157
  });
89
158
  it("returns thread streaming state when thread loaded", () => {
90
- const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)("thread_123"), {
159
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
91
160
  wrapper: TestWrapper,
92
161
  });
93
- // Initialize thread first
162
+ // Initialize and switch to thread
94
163
  (0, react_1.act)(() => {
95
164
  result.current.initThread("thread_123");
165
+ result.current.switchThread("thread_123");
96
166
  });
97
167
  expect(result.current.streamingState.status).toBe("idle");
98
168
  expect(result.current.isIdle).toBe(true);
@@ -117,9 +187,10 @@ describe("useTamboV1", () => {
117
187
  const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
118
188
  wrapper: TestWrapper,
119
189
  });
120
- // Initially no current thread
121
- expect(result.current.currentThreadId).toBeNull();
122
- expect(result.current.thread).toBeUndefined();
190
+ // Initially has placeholder thread for optimistic UI
191
+ expect(result.current.currentThreadId).toBe("placeholder");
192
+ expect(result.current.thread).toBeDefined();
193
+ expect(result.current.thread?.thread.id).toBe("placeholder");
123
194
  // Initialize a new thread
124
195
  (0, react_1.act)(() => {
125
196
  result.current.initThread("new_thread_1");
@@ -138,7 +209,7 @@ describe("useTamboV1", () => {
138
209
  (0, react_1.act)(() => {
139
210
  newThreadId = result.current.startNewThread();
140
211
  });
141
- expect(newThreadId).toMatch(/^temp_/);
212
+ expect(newThreadId).toBe("placeholder");
142
213
  expect(result.current.currentThreadId).toBe(newThreadId);
143
214
  expect(result.current.thread).toBeDefined();
144
215
  });
@@ -155,5 +226,807 @@ describe("useTamboV1", () => {
155
226
  expect(result.current.currentThreadId).toBe("thread_123");
156
227
  expect(result.current.thread?.thread.id).toBe("thread_123");
157
228
  });
229
+ describe("component content transformation", () => {
230
+ const createComponentContent = (id, name, props) => ({
231
+ type: "component",
232
+ id,
233
+ name,
234
+ props,
235
+ streamingState: "done",
236
+ });
237
+ it("adds renderedComponent to component content blocks", () => {
238
+ const state = {
239
+ threadMap: {
240
+ thread_123: {
241
+ thread: {
242
+ id: "thread_123",
243
+ messages: [
244
+ {
245
+ id: "msg_1",
246
+ role: "assistant",
247
+ content: [
248
+ createComponentContent("comp_1", "TestComponent", {
249
+ title: "Hello",
250
+ }),
251
+ ],
252
+ createdAt: new Date().toISOString(),
253
+ },
254
+ ],
255
+ status: "idle",
256
+ createdAt: new Date().toISOString(),
257
+ updatedAt: new Date().toISOString(),
258
+ lastRunCancelled: false,
259
+ },
260
+ streaming: { status: "idle" },
261
+ accumulatingToolArgs: new Map(),
262
+ },
263
+ },
264
+ currentThreadId: "thread_123",
265
+ };
266
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
267
+ wrapper: createWrapperWithState(state),
268
+ });
269
+ expect(result.current.messages).toHaveLength(1);
270
+ const content = result.current.messages[0].content[0];
271
+ expect(content.type).toBe("component");
272
+ expect(content.renderedComponent).toBeDefined();
273
+ });
274
+ it("preserves non-component content blocks unchanged", () => {
275
+ const state = {
276
+ threadMap: {
277
+ thread_123: {
278
+ thread: {
279
+ id: "thread_123",
280
+ messages: [
281
+ {
282
+ id: "msg_1",
283
+ role: "assistant",
284
+ content: [
285
+ { type: "text", text: "Hello world" },
286
+ createComponentContent("comp_1", "TestComponent", {
287
+ title: "Hi",
288
+ }),
289
+ ],
290
+ createdAt: new Date().toISOString(),
291
+ },
292
+ ],
293
+ status: "idle",
294
+ createdAt: new Date().toISOString(),
295
+ updatedAt: new Date().toISOString(),
296
+ lastRunCancelled: false,
297
+ },
298
+ streaming: { status: "idle" },
299
+ accumulatingToolArgs: new Map(),
300
+ },
301
+ },
302
+ currentThreadId: "thread_123",
303
+ };
304
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
305
+ wrapper: createWrapperWithState(state),
306
+ });
307
+ expect(result.current.messages).toHaveLength(1);
308
+ const textContent = result.current.messages[0].content[0];
309
+ expect(textContent.type).toBe("text");
310
+ expect(textContent).toEqual({ type: "text", text: "Hello world" });
311
+ const componentContent = result.current.messages[0].content[1];
312
+ expect(componentContent.type).toBe("component");
313
+ expect(componentContent.renderedComponent).toBeDefined();
314
+ });
315
+ it("caches rendered components and returns same reference when props unchanged", () => {
316
+ const state = {
317
+ threadMap: {
318
+ thread_123: {
319
+ thread: {
320
+ id: "thread_123",
321
+ messages: [
322
+ {
323
+ id: "msg_1",
324
+ role: "assistant",
325
+ content: [
326
+ createComponentContent("comp_1", "TestComponent", {
327
+ title: "Hello",
328
+ }),
329
+ ],
330
+ createdAt: new Date().toISOString(),
331
+ },
332
+ ],
333
+ status: "idle",
334
+ createdAt: new Date().toISOString(),
335
+ updatedAt: new Date().toISOString(),
336
+ lastRunCancelled: false,
337
+ },
338
+ streaming: { status: "idle" },
339
+ accumulatingToolArgs: new Map(),
340
+ },
341
+ },
342
+ currentThreadId: "thread_123",
343
+ };
344
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
345
+ wrapper: createWrapperWithState(state),
346
+ });
347
+ const firstRender = result.current.messages[0].content[0].renderedComponent;
348
+ // Re-render with same state
349
+ rerender();
350
+ const secondRender = result.current.messages[0].content[0].renderedComponent;
351
+ // Should return the same cached element reference
352
+ expect(secondRender).toBe(firstRender);
353
+ });
354
+ it("handles empty props on components", () => {
355
+ const state = {
356
+ threadMap: {
357
+ thread_123: {
358
+ thread: {
359
+ id: "thread_123",
360
+ messages: [
361
+ {
362
+ id: "msg_1",
363
+ role: "assistant",
364
+ content: [
365
+ createComponentContent("comp_1", "TestComponent", {}),
366
+ ],
367
+ createdAt: new Date().toISOString(),
368
+ },
369
+ ],
370
+ status: "idle",
371
+ createdAt: new Date().toISOString(),
372
+ updatedAt: new Date().toISOString(),
373
+ lastRunCancelled: false,
374
+ },
375
+ streaming: { status: "idle" },
376
+ accumulatingToolArgs: new Map(),
377
+ },
378
+ },
379
+ currentThreadId: "thread_123",
380
+ };
381
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
382
+ wrapper: createWrapperWithState(state),
383
+ });
384
+ const content = result.current.messages[0].content[0];
385
+ expect(content.type).toBe("component");
386
+ expect(content.renderedComponent).toBeDefined();
387
+ });
388
+ it("handles undefined props on components", () => {
389
+ const state = {
390
+ threadMap: {
391
+ thread_123: {
392
+ thread: {
393
+ id: "thread_123",
394
+ messages: [
395
+ {
396
+ id: "msg_1",
397
+ role: "assistant",
398
+ content: [
399
+ {
400
+ type: "component",
401
+ id: "comp_1",
402
+ name: "TestComponent",
403
+ props: undefined,
404
+ streamingState: "done",
405
+ },
406
+ ],
407
+ createdAt: new Date().toISOString(),
408
+ },
409
+ ],
410
+ status: "idle",
411
+ createdAt: new Date().toISOString(),
412
+ updatedAt: new Date().toISOString(),
413
+ lastRunCancelled: false,
414
+ },
415
+ streaming: { status: "idle" },
416
+ accumulatingToolArgs: new Map(),
417
+ },
418
+ },
419
+ currentThreadId: "thread_123",
420
+ };
421
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
422
+ wrapper: createWrapperWithState(state),
423
+ });
424
+ const content = result.current.messages[0].content[0];
425
+ expect(content.type).toBe("component");
426
+ expect(content.renderedComponent).toBeDefined();
427
+ });
428
+ it("handles multiple component content blocks in same message", () => {
429
+ const state = {
430
+ threadMap: {
431
+ thread_123: {
432
+ thread: {
433
+ id: "thread_123",
434
+ messages: [
435
+ {
436
+ id: "msg_1",
437
+ role: "assistant",
438
+ content: [
439
+ createComponentContent("comp_1", "ComponentA", {
440
+ value: 1,
441
+ }),
442
+ createComponentContent("comp_2", "ComponentB", {
443
+ value: 2,
444
+ }),
445
+ createComponentContent("comp_3", "ComponentC", {
446
+ value: 3,
447
+ }),
448
+ ],
449
+ createdAt: new Date().toISOString(),
450
+ },
451
+ ],
452
+ status: "idle",
453
+ createdAt: new Date().toISOString(),
454
+ updatedAt: new Date().toISOString(),
455
+ lastRunCancelled: false,
456
+ },
457
+ streaming: { status: "idle" },
458
+ accumulatingToolArgs: new Map(),
459
+ },
460
+ },
461
+ currentThreadId: "thread_123",
462
+ };
463
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
464
+ wrapper: createWrapperWithState(state),
465
+ });
466
+ expect(result.current.messages[0].content).toHaveLength(3);
467
+ result.current.messages[0].content.forEach((content) => {
468
+ expect(content.type).toBe("component");
469
+ expect(content.renderedComponent).toBeDefined();
470
+ });
471
+ });
472
+ it("uses currentThreadId from stream state", () => {
473
+ const state = {
474
+ threadMap: {
475
+ placeholder: {
476
+ thread: {
477
+ id: "placeholder",
478
+ messages: [
479
+ {
480
+ id: "msg_1",
481
+ role: "assistant",
482
+ content: [
483
+ createComponentContent("comp_1", "TestComponent", {
484
+ title: "Hello",
485
+ }),
486
+ ],
487
+ createdAt: new Date().toISOString(),
488
+ },
489
+ ],
490
+ status: "idle",
491
+ createdAt: new Date().toISOString(),
492
+ updatedAt: new Date().toISOString(),
493
+ lastRunCancelled: false,
494
+ },
495
+ streaming: { status: "idle" },
496
+ accumulatingToolArgs: new Map(),
497
+ },
498
+ },
499
+ currentThreadId: "placeholder",
500
+ };
501
+ // No explicit threadId - uses currentThreadId from state
502
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
503
+ wrapper: createWrapperWithState(state),
504
+ });
505
+ // Component should render using the placeholder thread
506
+ const content = result.current.messages[0].content[0];
507
+ expect(content.type).toBe("component");
508
+ expect(content.renderedComponent).toBeDefined();
509
+ });
510
+ });
511
+ describe("tool_use content transformation", () => {
512
+ it("adds computed properties to tool_use content", () => {
513
+ const state = {
514
+ threadMap: {
515
+ thread_123: {
516
+ thread: {
517
+ id: "thread_123",
518
+ messages: [
519
+ {
520
+ id: "msg_1",
521
+ role: "assistant",
522
+ content: [
523
+ {
524
+ type: "tool_use",
525
+ id: "tool_1",
526
+ name: "getWeather",
527
+ input: { location: "NYC" },
528
+ },
529
+ ],
530
+ createdAt: new Date().toISOString(),
531
+ },
532
+ ],
533
+ status: "idle",
534
+ createdAt: new Date().toISOString(),
535
+ updatedAt: new Date().toISOString(),
536
+ lastRunCancelled: false,
537
+ },
538
+ streaming: { status: "idle" },
539
+ accumulatingToolArgs: new Map(),
540
+ },
541
+ },
542
+ currentThreadId: "thread_123",
543
+ };
544
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
545
+ wrapper: createWrapperWithState(state),
546
+ });
547
+ const content = result.current.messages[0].content[0];
548
+ expect(content.type).toBe("tool_use");
549
+ expect(content.hasCompleted).toBe(false);
550
+ expect(content.statusMessage).toBe("Calling getWeather");
551
+ expect(content.tamboDisplayProps).toBeDefined();
552
+ });
553
+ it("sets hasCompleted to true when matching tool_result exists", () => {
554
+ const state = {
555
+ threadMap: {
556
+ thread_123: {
557
+ thread: {
558
+ id: "thread_123",
559
+ messages: [
560
+ {
561
+ id: "msg_1",
562
+ role: "assistant",
563
+ content: [
564
+ {
565
+ type: "tool_use",
566
+ id: "tool_1",
567
+ name: "getWeather",
568
+ input: { location: "NYC" },
569
+ },
570
+ ],
571
+ createdAt: new Date().toISOString(),
572
+ },
573
+ {
574
+ id: "msg_2",
575
+ role: "user",
576
+ content: [
577
+ {
578
+ type: "tool_result",
579
+ toolUseId: "tool_1",
580
+ content: [{ type: "text", text: "Sunny" }],
581
+ },
582
+ ],
583
+ createdAt: new Date().toISOString(),
584
+ },
585
+ ],
586
+ status: "idle",
587
+ createdAt: new Date().toISOString(),
588
+ updatedAt: new Date().toISOString(),
589
+ lastRunCancelled: false,
590
+ },
591
+ streaming: { status: "idle" },
592
+ accumulatingToolArgs: new Map(),
593
+ },
594
+ },
595
+ currentThreadId: "thread_123",
596
+ };
597
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
598
+ wrapper: createWrapperWithState(state),
599
+ });
600
+ const content = result.current.messages[0].content[0];
601
+ expect(content.hasCompleted).toBe(true);
602
+ expect(content.statusMessage).toBe("Called getWeather");
603
+ });
604
+ it("uses _tambo_statusMessage when tool is in progress", () => {
605
+ const state = {
606
+ threadMap: {
607
+ thread_123: {
608
+ thread: {
609
+ id: "thread_123",
610
+ messages: [
611
+ {
612
+ id: "msg_1",
613
+ role: "assistant",
614
+ content: [
615
+ {
616
+ type: "tool_use",
617
+ id: "tool_1",
618
+ name: "getWeather",
619
+ input: {
620
+ location: "NYC",
621
+ _tambo_statusMessage: "Fetching weather for NYC...",
622
+ },
623
+ },
624
+ ],
625
+ createdAt: new Date().toISOString(),
626
+ },
627
+ ],
628
+ status: "idle",
629
+ createdAt: new Date().toISOString(),
630
+ updatedAt: new Date().toISOString(),
631
+ lastRunCancelled: false,
632
+ },
633
+ streaming: { status: "idle" },
634
+ accumulatingToolArgs: new Map(),
635
+ },
636
+ },
637
+ currentThreadId: "thread_123",
638
+ };
639
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
640
+ wrapper: createWrapperWithState(state),
641
+ });
642
+ const content = result.current.messages[0].content[0];
643
+ expect(content.statusMessage).toBe("Fetching weather for NYC...");
644
+ expect(content.tamboDisplayProps?._tambo_statusMessage).toBe("Fetching weather for NYC...");
645
+ });
646
+ it("uses _tambo_completionStatusMessage when tool is completed", () => {
647
+ const state = {
648
+ threadMap: {
649
+ thread_123: {
650
+ thread: {
651
+ id: "thread_123",
652
+ messages: [
653
+ {
654
+ id: "msg_1",
655
+ role: "assistant",
656
+ content: [
657
+ {
658
+ type: "tool_use",
659
+ id: "tool_1",
660
+ name: "getWeather",
661
+ input: {
662
+ location: "NYC",
663
+ _tambo_statusMessage: "Fetching weather...",
664
+ _tambo_completionStatusMessage: "Got weather for NYC",
665
+ },
666
+ },
667
+ ],
668
+ createdAt: new Date().toISOString(),
669
+ },
670
+ {
671
+ id: "msg_2",
672
+ role: "user",
673
+ content: [
674
+ {
675
+ type: "tool_result",
676
+ toolUseId: "tool_1",
677
+ content: [{ type: "text", text: "Sunny" }],
678
+ },
679
+ ],
680
+ createdAt: new Date().toISOString(),
681
+ },
682
+ ],
683
+ status: "idle",
684
+ createdAt: new Date().toISOString(),
685
+ updatedAt: new Date().toISOString(),
686
+ lastRunCancelled: false,
687
+ },
688
+ streaming: { status: "idle" },
689
+ accumulatingToolArgs: new Map(),
690
+ },
691
+ },
692
+ currentThreadId: "thread_123",
693
+ };
694
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
695
+ wrapper: createWrapperWithState(state),
696
+ });
697
+ const content = result.current.messages[0].content[0];
698
+ expect(content.hasCompleted).toBe(true);
699
+ expect(content.statusMessage).toBe("Got weather for NYC");
700
+ });
701
+ it("filters _tambo_* properties from input", () => {
702
+ const state = {
703
+ threadMap: {
704
+ thread_123: {
705
+ thread: {
706
+ id: "thread_123",
707
+ messages: [
708
+ {
709
+ id: "msg_1",
710
+ role: "assistant",
711
+ content: [
712
+ {
713
+ type: "tool_use",
714
+ id: "tool_1",
715
+ name: "getWeather",
716
+ input: {
717
+ location: "NYC",
718
+ units: "celsius",
719
+ _tambo_statusMessage: "Fetching...",
720
+ _tambo_completionStatusMessage: "Done",
721
+ _tambo_displayMessage: "Weather lookup",
722
+ },
723
+ },
724
+ ],
725
+ createdAt: new Date().toISOString(),
726
+ },
727
+ ],
728
+ status: "idle",
729
+ createdAt: new Date().toISOString(),
730
+ updatedAt: new Date().toISOString(),
731
+ lastRunCancelled: false,
732
+ },
733
+ streaming: { status: "idle" },
734
+ accumulatingToolArgs: new Map(),
735
+ },
736
+ },
737
+ currentThreadId: "thread_123",
738
+ };
739
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
740
+ wrapper: createWrapperWithState(state),
741
+ });
742
+ const content = result.current.messages[0].content[0];
743
+ // Input should only have non-_tambo_ properties
744
+ expect(content.input).toEqual({ location: "NYC", units: "celsius" });
745
+ expect(content.input._tambo_statusMessage).toBeUndefined();
746
+ expect(content.input._tambo_completionStatusMessage).toBeUndefined();
747
+ expect(content.input._tambo_displayMessage).toBeUndefined();
748
+ });
749
+ it("handles tool_use with empty input", () => {
750
+ const state = {
751
+ threadMap: {
752
+ thread_123: {
753
+ thread: {
754
+ id: "thread_123",
755
+ messages: [
756
+ {
757
+ id: "msg_1",
758
+ role: "assistant",
759
+ content: [
760
+ {
761
+ type: "tool_use",
762
+ id: "tool_1",
763
+ name: "getCurrentTime",
764
+ input: {},
765
+ },
766
+ ],
767
+ createdAt: new Date().toISOString(),
768
+ },
769
+ ],
770
+ status: "idle",
771
+ createdAt: new Date().toISOString(),
772
+ updatedAt: new Date().toISOString(),
773
+ lastRunCancelled: false,
774
+ },
775
+ streaming: { status: "idle" },
776
+ accumulatingToolArgs: new Map(),
777
+ },
778
+ },
779
+ currentThreadId: "thread_123",
780
+ };
781
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
782
+ wrapper: createWrapperWithState(state),
783
+ });
784
+ const content = result.current.messages[0].content[0];
785
+ expect(content.input).toEqual({});
786
+ expect(content.hasCompleted).toBe(false);
787
+ expect(content.statusMessage).toBe("Calling getCurrentTime");
788
+ });
789
+ it("handles tool_use with undefined input", () => {
790
+ const state = {
791
+ threadMap: {
792
+ thread_123: {
793
+ thread: {
794
+ id: "thread_123",
795
+ messages: [
796
+ {
797
+ id: "msg_1",
798
+ role: "assistant",
799
+ content: [
800
+ {
801
+ type: "tool_use",
802
+ id: "tool_1",
803
+ name: "getCurrentTime",
804
+ input: undefined,
805
+ },
806
+ ],
807
+ createdAt: new Date().toISOString(),
808
+ },
809
+ ],
810
+ status: "idle",
811
+ createdAt: new Date().toISOString(),
812
+ updatedAt: new Date().toISOString(),
813
+ lastRunCancelled: false,
814
+ },
815
+ streaming: { status: "idle" },
816
+ accumulatingToolArgs: new Map(),
817
+ },
818
+ },
819
+ currentThreadId: "thread_123",
820
+ };
821
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
822
+ wrapper: createWrapperWithState(state),
823
+ });
824
+ const content = result.current.messages[0].content[0];
825
+ expect(content.input).toEqual({});
826
+ expect(content.hasCompleted).toBe(false);
827
+ });
828
+ it("handles multiple tool_use blocks with different completion states", () => {
829
+ const state = {
830
+ threadMap: {
831
+ thread_123: {
832
+ thread: {
833
+ id: "thread_123",
834
+ messages: [
835
+ {
836
+ id: "msg_1",
837
+ role: "assistant",
838
+ content: [
839
+ {
840
+ type: "tool_use",
841
+ id: "tool_1",
842
+ name: "getWeather",
843
+ input: { location: "NYC" },
844
+ },
845
+ {
846
+ type: "tool_use",
847
+ id: "tool_2",
848
+ name: "getTime",
849
+ input: { timezone: "EST" },
850
+ },
851
+ ],
852
+ createdAt: new Date().toISOString(),
853
+ },
854
+ {
855
+ id: "msg_2",
856
+ role: "user",
857
+ content: [
858
+ {
859
+ type: "tool_result",
860
+ toolUseId: "tool_1",
861
+ content: [{ type: "text", text: "Sunny" }],
862
+ },
863
+ // tool_2 has no result yet
864
+ ],
865
+ createdAt: new Date().toISOString(),
866
+ },
867
+ ],
868
+ status: "idle",
869
+ createdAt: new Date().toISOString(),
870
+ updatedAt: new Date().toISOString(),
871
+ lastRunCancelled: false,
872
+ },
873
+ streaming: { status: "idle" },
874
+ accumulatingToolArgs: new Map(),
875
+ },
876
+ },
877
+ currentThreadId: "thread_123",
878
+ };
879
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
880
+ wrapper: createWrapperWithState(state),
881
+ });
882
+ const tool1 = result.current.messages[0].content[0];
883
+ const tool2 = result.current.messages[0].content[1];
884
+ expect(tool1.hasCompleted).toBe(true);
885
+ expect(tool1.statusMessage).toBe("Called getWeather");
886
+ expect(tool2.hasCompleted).toBe(false);
887
+ expect(tool2.statusMessage).toBe("Calling getTime");
888
+ });
889
+ });
890
+ describe("cancelRun", () => {
891
+ it("sets thread to idle and lastRunCancelled to true when cancelled", async () => {
892
+ const initialState = {
893
+ threadMap: {
894
+ thread_123: {
895
+ thread: {
896
+ id: "thread_123",
897
+ messages: [],
898
+ status: "streaming",
899
+ createdAt: new Date().toISOString(),
900
+ updatedAt: new Date().toISOString(),
901
+ lastRunCancelled: false,
902
+ },
903
+ streaming: { status: "streaming", runId: "run_456" },
904
+ accumulatingToolArgs: new Map(),
905
+ },
906
+ },
907
+ currentThreadId: "thread_123",
908
+ };
909
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
910
+ wrapper: createWrapperWithRealReducer(initialState),
911
+ });
912
+ // Before cancel: streaming and lastRunCancelled is false
913
+ expect(result.current.isStreaming).toBe(true);
914
+ expect(result.current.isIdle).toBe(false);
915
+ expect(result.current.thread?.thread.lastRunCancelled).toBe(false);
916
+ await (0, react_1.act)(async () => {
917
+ await result.current.cancelRun();
918
+ });
919
+ // After cancel: idle and lastRunCancelled is true
920
+ expect(result.current.isStreaming).toBe(false);
921
+ expect(result.current.isIdle).toBe(true);
922
+ expect(result.current.thread?.thread.lastRunCancelled).toBe(true);
923
+ // Verify API was called to cancel the run
924
+ expect(mockTamboClient.threads.runs.delete).toHaveBeenCalledWith("run_456", { threadId: "thread_123" });
925
+ });
926
+ it("is a no-op when there is no active run", async () => {
927
+ const initialState = {
928
+ threadMap: {
929
+ thread_123: {
930
+ thread: {
931
+ id: "thread_123",
932
+ messages: [],
933
+ status: "idle",
934
+ createdAt: new Date().toISOString(),
935
+ updatedAt: new Date().toISOString(),
936
+ lastRunCancelled: false,
937
+ },
938
+ streaming: { status: "idle" }, // No runId
939
+ accumulatingToolArgs: new Map(),
940
+ },
941
+ },
942
+ currentThreadId: "thread_123",
943
+ };
944
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
945
+ wrapper: createWrapperWithRealReducer(initialState),
946
+ });
947
+ // Idle before
948
+ expect(result.current.isIdle).toBe(true);
949
+ expect(result.current.thread?.thread.lastRunCancelled).toBe(false);
950
+ await (0, react_1.act)(async () => {
951
+ await result.current.cancelRun();
952
+ });
953
+ // Still idle, lastRunCancelled unchanged
954
+ expect(result.current.isIdle).toBe(true);
955
+ expect(result.current.thread?.thread.lastRunCancelled).toBe(false);
956
+ // API should not have been called
957
+ expect(mockTamboClient.threads.runs.delete).not.toHaveBeenCalled();
958
+ });
959
+ it("is a no-op when on a placeholder thread", async () => {
960
+ const initialState = {
961
+ threadMap: {
962
+ placeholder: {
963
+ thread: {
964
+ id: "placeholder",
965
+ messages: [],
966
+ status: "streaming",
967
+ createdAt: new Date().toISOString(),
968
+ updatedAt: new Date().toISOString(),
969
+ lastRunCancelled: false,
970
+ },
971
+ streaming: { status: "streaming", runId: "run_123" },
972
+ accumulatingToolArgs: new Map(),
973
+ },
974
+ },
975
+ currentThreadId: "placeholder",
976
+ };
977
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
978
+ wrapper: createWrapperWithRealReducer(initialState),
979
+ });
980
+ // Before: streaming on placeholder
981
+ expect(result.current.isStreaming).toBe(true);
982
+ expect(result.current.thread?.thread.lastRunCancelled).toBe(false);
983
+ await (0, react_1.act)(async () => {
984
+ await result.current.cancelRun();
985
+ });
986
+ // After: state should be unchanged (placeholder threads are skipped)
987
+ expect(result.current.isStreaming).toBe(true);
988
+ expect(result.current.thread?.thread.lastRunCancelled).toBe(false);
989
+ // API should not have been called for placeholder threads
990
+ expect(mockTamboClient.threads.runs.delete).not.toHaveBeenCalled();
991
+ });
992
+ it("still updates local state even if API call fails", async () => {
993
+ const consoleWarnSpy = jest
994
+ .spyOn(console, "warn")
995
+ .mockImplementation(() => { });
996
+ // Make the API call fail
997
+ jest
998
+ .mocked(mockTamboClient.threads.runs.delete)
999
+ .mockRejectedValueOnce(new Error("Network error"));
1000
+ const initialState = {
1001
+ threadMap: {
1002
+ thread_123: {
1003
+ thread: {
1004
+ id: "thread_123",
1005
+ messages: [],
1006
+ status: "streaming",
1007
+ createdAt: new Date().toISOString(),
1008
+ updatedAt: new Date().toISOString(),
1009
+ lastRunCancelled: false,
1010
+ },
1011
+ streaming: { status: "streaming", runId: "run_456" },
1012
+ accumulatingToolArgs: new Map(),
1013
+ },
1014
+ },
1015
+ currentThreadId: "thread_123",
1016
+ };
1017
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_1.useTamboV1)(), {
1018
+ wrapper: createWrapperWithRealReducer(initialState),
1019
+ });
1020
+ await (0, react_1.act)(async () => {
1021
+ await result.current.cancelRun();
1022
+ });
1023
+ // Local state should still be updated (optimistic update)
1024
+ expect(result.current.isIdle).toBe(true);
1025
+ expect(result.current.thread?.thread.lastRunCancelled).toBe(true);
1026
+ // Warning should have been logged
1027
+ expect(consoleWarnSpy).toHaveBeenCalledWith("Failed to cancel run on server:", expect.any(Error));
1028
+ consoleWarnSpy.mockRestore();
1029
+ });
1030
+ });
158
1031
  });
159
1032
  //# sourceMappingURL=use-tambo-v1.test.js.map