@tambo-ai/react 0.74.0 → 0.75.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 (314) hide show
  1. package/README.md +46 -449
  2. package/dist/hoc/with-tambo-interactable.d.ts +8 -0
  3. package/dist/hoc/with-tambo-interactable.d.ts.map +1 -1
  4. package/dist/hoc/with-tambo-interactable.js +5 -2
  5. package/dist/hoc/with-tambo-interactable.js.map +1 -1
  6. package/dist/hoc/with-tambo-interactable.test.js +12 -0
  7. package/dist/hoc/with-tambo-interactable.test.js.map +1 -1
  8. package/dist/hooks/use-tambo-voice.test.js +3 -0
  9. package/dist/hooks/use-tambo-voice.test.js.map +1 -1
  10. package/dist/mcp/mcp-hooks.d.ts.map +1 -1
  11. package/dist/mcp/mcp-hooks.js +70 -16
  12. package/dist/mcp/mcp-hooks.js.map +1 -1
  13. package/dist/mcp/mcp-hooks.test.js +69 -0
  14. package/dist/mcp/mcp-hooks.test.js.map +1 -1
  15. package/dist/mcp/tambo-mcp-provider.test.js +24 -0
  16. package/dist/mcp/tambo-mcp-provider.test.js.map +1 -1
  17. package/dist/mcp/use-mcp-servers.test.js +9 -0
  18. package/dist/mcp/use-mcp-servers.test.js.map +1 -1
  19. package/dist/model/component-metadata.d.ts +4 -4
  20. package/dist/model/component-metadata.js.map +1 -1
  21. package/dist/providers/__tests__/thread-input-resource-resolution.test.js +2 -2
  22. package/dist/providers/__tests__/thread-input-resource-resolution.test.js.map +1 -1
  23. package/dist/providers/tambo-client-provider.d.ts +6 -0
  24. package/dist/providers/tambo-client-provider.d.ts.map +1 -1
  25. package/dist/providers/tambo-client-provider.js +4 -1
  26. package/dist/providers/tambo-client-provider.js.map +1 -1
  27. package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
  28. package/dist/providers/tambo-interactable-provider.js +8 -0
  29. package/dist/providers/tambo-interactable-provider.js.map +1 -1
  30. package/dist/providers/tambo-interactable-provider.test.js +47 -0
  31. package/dist/providers/tambo-interactable-provider.test.js.map +1 -1
  32. package/dist/providers/tambo-provider.d.ts.map +1 -1
  33. package/dist/providers/tambo-provider.js +4 -1
  34. package/dist/providers/tambo-provider.js.map +1 -1
  35. package/dist/providers/tambo-stubs.d.ts.map +1 -1
  36. package/dist/providers/tambo-stubs.js +3 -0
  37. package/dist/providers/tambo-stubs.js.map +1 -1
  38. package/dist/providers/tambo-thread-provider-initial-messages.test.js +3 -0
  39. package/dist/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
  40. package/dist/providers/tambo-thread-provider.test.js +3 -0
  41. package/dist/providers/tambo-thread-provider.test.js.map +1 -1
  42. package/dist/util/registry-validators.js +1 -1
  43. package/dist/util/registry-validators.js.map +1 -1
  44. package/dist/util/resource-content-resolver.test.js +1 -1
  45. package/dist/util/resource-content-resolver.test.js.map +1 -1
  46. package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts +11 -0
  47. package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -0
  48. package/dist/v1/hooks/use-tambo-v1-auth-state.js +48 -0
  49. package/dist/v1/hooks/use-tambo-v1-auth-state.js.map +1 -0
  50. package/dist/v1/hooks/use-tambo-v1-auth-state.test.d.ts +2 -0
  51. package/dist/v1/hooks/use-tambo-v1-auth-state.test.d.ts.map +1 -0
  52. package/dist/v1/hooks/use-tambo-v1-auth-state.test.js +105 -0
  53. package/dist/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -0
  54. package/dist/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
  55. package/dist/v1/hooks/use-tambo-v1-component-state.js +68 -21
  56. package/dist/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
  57. package/dist/v1/hooks/use-tambo-v1-component-state.test.js +100 -0
  58. package/dist/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
  59. package/dist/v1/hooks/use-tambo-v1-messages.test.js +8 -0
  60. package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  61. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +19 -1
  62. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  63. package/dist/v1/hooks/use-tambo-v1-send-message.js +86 -9
  64. package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  65. package/dist/v1/hooks/use-tambo-v1-send-message.test.js +273 -0
  66. package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  67. package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts +2 -2
  68. package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
  69. package/dist/v1/hooks/use-tambo-v1-stream-status.js +2 -2
  70. package/dist/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
  71. package/dist/v1/hooks/use-tambo-v1-stream-status.test.js +11 -11
  72. package/dist/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
  73. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +13 -0
  74. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  75. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  76. package/dist/v1/hooks/use-tambo-v1-thread-list.js +4 -0
  77. package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  78. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +6 -0
  79. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  80. package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
  81. package/dist/v1/hooks/use-tambo-v1-thread.js +4 -0
  82. package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -1
  83. package/dist/v1/hooks/use-tambo-v1-thread.test.js +6 -0
  84. package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
  85. package/dist/v1/hooks/use-tambo-v1.d.ts +11 -0
  86. package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -1
  87. package/dist/v1/hooks/use-tambo-v1.js +5 -0
  88. package/dist/v1/hooks/use-tambo-v1.js.map +1 -1
  89. package/dist/v1/hooks/use-tambo-v1.test.js +13 -0
  90. package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
  91. package/dist/v1/index.d.ts +4 -1
  92. package/dist/v1/index.d.ts.map +1 -1
  93. package/dist/v1/index.js +5 -2
  94. package/dist/v1/index.js.map +1 -1
  95. package/dist/v1/providers/tambo-v1-provider.d.ts +16 -1
  96. package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  97. package/dist/v1/providers/tambo-v1-provider.js +42 -5
  98. package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
  99. package/dist/v1/providers/tambo-v1-provider.test.js +19 -2
  100. package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
  101. package/dist/v1/providers/tambo-v1-stream-context.d.ts +6 -0
  102. package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  103. package/dist/v1/providers/tambo-v1-stream-context.js +50 -11
  104. package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
  105. package/dist/v1/providers/tambo-v1-stream-context.test.js +9 -0
  106. package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  107. package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
  108. package/dist/v1/providers/tambo-v1-stub-provider.js +4 -0
  109. package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -1
  110. package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +11 -0
  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 +10 -1
  113. package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
  114. package/dist/v1/types/auth.d.ts +24 -0
  115. package/dist/v1/types/auth.d.ts.map +1 -0
  116. package/dist/v1/types/auth.js +3 -0
  117. package/dist/v1/types/auth.js.map +1 -0
  118. package/dist/v1/types/message.d.ts +12 -0
  119. package/dist/v1/types/message.d.ts.map +1 -1
  120. package/dist/v1/types/message.js.map +1 -1
  121. package/dist/v1/types/tool-choice.d.ts +8 -0
  122. package/dist/v1/types/tool-choice.d.ts.map +1 -0
  123. package/dist/v1/types/tool-choice.js +3 -0
  124. package/dist/v1/types/tool-choice.js.map +1 -0
  125. package/dist/v1/utils/event-accumulator.d.ts +28 -2
  126. package/dist/v1/utils/event-accumulator.d.ts.map +1 -1
  127. package/dist/v1/utils/event-accumulator.js +67 -15
  128. package/dist/v1/utils/event-accumulator.js.map +1 -1
  129. package/dist/v1/utils/event-accumulator.test.js +106 -0
  130. package/dist/v1/utils/event-accumulator.test.js.map +1 -1
  131. package/dist/v1/utils/keyed-throttle.d.ts +42 -0
  132. package/dist/v1/utils/keyed-throttle.d.ts.map +1 -0
  133. package/dist/v1/utils/keyed-throttle.js +86 -0
  134. package/dist/v1/utils/keyed-throttle.js.map +1 -0
  135. package/dist/v1/utils/keyed-throttle.test.d.ts +2 -0
  136. package/dist/v1/utils/keyed-throttle.test.d.ts.map +1 -0
  137. package/dist/v1/utils/keyed-throttle.test.js +147 -0
  138. package/dist/v1/utils/keyed-throttle.test.js.map +1 -0
  139. package/dist/v1/utils/registry-conversion.d.ts.map +1 -1
  140. package/dist/v1/utils/registry-conversion.js +2 -0
  141. package/dist/v1/utils/registry-conversion.js.map +1 -1
  142. package/dist/v1/utils/registry-conversion.test.js +23 -0
  143. package/dist/v1/utils/registry-conversion.test.js.map +1 -1
  144. package/dist/v1/utils/tool-call-tracker.d.ts +10 -0
  145. package/dist/v1/utils/tool-call-tracker.d.ts.map +1 -1
  146. package/dist/v1/utils/tool-call-tracker.js +13 -0
  147. package/dist/v1/utils/tool-call-tracker.js.map +1 -1
  148. package/dist/v1/utils/tool-call-tracker.test.d.ts +2 -0
  149. package/dist/v1/utils/tool-call-tracker.test.d.ts.map +1 -0
  150. package/dist/v1/utils/tool-call-tracker.test.js +67 -0
  151. package/dist/v1/utils/tool-call-tracker.test.js.map +1 -0
  152. package/dist/v1/utils/tool-executor.d.ts +34 -0
  153. package/dist/v1/utils/tool-executor.d.ts.map +1 -1
  154. package/dist/v1/utils/tool-executor.js +55 -0
  155. package/dist/v1/utils/tool-executor.js.map +1 -1
  156. package/dist/v1/utils/tool-executor.test.js +211 -0
  157. package/dist/v1/utils/tool-executor.test.js.map +1 -1
  158. package/esm/hoc/with-tambo-interactable.d.ts +8 -0
  159. package/esm/hoc/with-tambo-interactable.d.ts.map +1 -1
  160. package/esm/hoc/with-tambo-interactable.js +5 -2
  161. package/esm/hoc/with-tambo-interactable.js.map +1 -1
  162. package/esm/hoc/with-tambo-interactable.test.js +12 -0
  163. package/esm/hoc/with-tambo-interactable.test.js.map +1 -1
  164. package/esm/hooks/use-tambo-voice.test.js +3 -0
  165. package/esm/hooks/use-tambo-voice.test.js.map +1 -1
  166. package/esm/mcp/mcp-hooks.d.ts.map +1 -1
  167. package/esm/mcp/mcp-hooks.js +70 -16
  168. package/esm/mcp/mcp-hooks.js.map +1 -1
  169. package/esm/mcp/mcp-hooks.test.js +69 -0
  170. package/esm/mcp/mcp-hooks.test.js.map +1 -1
  171. package/esm/mcp/tambo-mcp-provider.test.js +24 -0
  172. package/esm/mcp/tambo-mcp-provider.test.js.map +1 -1
  173. package/esm/mcp/use-mcp-servers.test.js +9 -0
  174. package/esm/mcp/use-mcp-servers.test.js.map +1 -1
  175. package/esm/model/component-metadata.d.ts +4 -4
  176. package/esm/model/component-metadata.js.map +1 -1
  177. package/esm/providers/__tests__/thread-input-resource-resolution.test.js +2 -2
  178. package/esm/providers/__tests__/thread-input-resource-resolution.test.js.map +1 -1
  179. package/esm/providers/tambo-client-provider.d.ts +6 -0
  180. package/esm/providers/tambo-client-provider.d.ts.map +1 -1
  181. package/esm/providers/tambo-client-provider.js +4 -1
  182. package/esm/providers/tambo-client-provider.js.map +1 -1
  183. package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
  184. package/esm/providers/tambo-interactable-provider.js +8 -0
  185. package/esm/providers/tambo-interactable-provider.js.map +1 -1
  186. package/esm/providers/tambo-interactable-provider.test.js +47 -0
  187. package/esm/providers/tambo-interactable-provider.test.js.map +1 -1
  188. package/esm/providers/tambo-provider.d.ts.map +1 -1
  189. package/esm/providers/tambo-provider.js +4 -1
  190. package/esm/providers/tambo-provider.js.map +1 -1
  191. package/esm/providers/tambo-stubs.d.ts.map +1 -1
  192. package/esm/providers/tambo-stubs.js +3 -0
  193. package/esm/providers/tambo-stubs.js.map +1 -1
  194. package/esm/providers/tambo-thread-provider-initial-messages.test.js +3 -0
  195. package/esm/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
  196. package/esm/providers/tambo-thread-provider.test.js +3 -0
  197. package/esm/providers/tambo-thread-provider.test.js.map +1 -1
  198. package/esm/util/registry-validators.js +1 -1
  199. package/esm/util/registry-validators.js.map +1 -1
  200. package/esm/util/resource-content-resolver.test.js +1 -1
  201. package/esm/util/resource-content-resolver.test.js.map +1 -1
  202. package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts +11 -0
  203. package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -0
  204. package/esm/v1/hooks/use-tambo-v1-auth-state.js +45 -0
  205. package/esm/v1/hooks/use-tambo-v1-auth-state.js.map +1 -0
  206. package/esm/v1/hooks/use-tambo-v1-auth-state.test.d.ts +2 -0
  207. package/esm/v1/hooks/use-tambo-v1-auth-state.test.d.ts.map +1 -0
  208. package/esm/v1/hooks/use-tambo-v1-auth-state.test.js +100 -0
  209. package/esm/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -0
  210. package/esm/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
  211. package/esm/v1/hooks/use-tambo-v1-component-state.js +68 -21
  212. package/esm/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
  213. package/esm/v1/hooks/use-tambo-v1-component-state.test.js +100 -0
  214. package/esm/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
  215. package/esm/v1/hooks/use-tambo-v1-messages.test.js +8 -0
  216. package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  217. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +19 -1
  218. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  219. package/esm/v1/hooks/use-tambo-v1-send-message.js +87 -10
  220. package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  221. package/esm/v1/hooks/use-tambo-v1-send-message.test.js +273 -0
  222. package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  223. package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts +2 -2
  224. package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
  225. package/esm/v1/hooks/use-tambo-v1-stream-status.js +2 -2
  226. package/esm/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
  227. package/esm/v1/hooks/use-tambo-v1-stream-status.test.js +11 -11
  228. package/esm/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
  229. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +13 -0
  230. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  231. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  232. package/esm/v1/hooks/use-tambo-v1-thread-list.js +4 -0
  233. package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  234. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +6 -0
  235. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  236. package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
  237. package/esm/v1/hooks/use-tambo-v1-thread.js +4 -0
  238. package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -1
  239. package/esm/v1/hooks/use-tambo-v1-thread.test.js +6 -0
  240. package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
  241. package/esm/v1/hooks/use-tambo-v1.d.ts +11 -0
  242. package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -1
  243. package/esm/v1/hooks/use-tambo-v1.js +5 -0
  244. package/esm/v1/hooks/use-tambo-v1.js.map +1 -1
  245. package/esm/v1/hooks/use-tambo-v1.test.js +13 -0
  246. package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
  247. package/esm/v1/index.d.ts +4 -1
  248. package/esm/v1/index.d.ts.map +1 -1
  249. package/esm/v1/index.js +3 -1
  250. package/esm/v1/index.js.map +1 -1
  251. package/esm/v1/providers/tambo-v1-provider.d.ts +16 -1
  252. package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  253. package/esm/v1/providers/tambo-v1-provider.js +43 -6
  254. package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
  255. package/esm/v1/providers/tambo-v1-provider.test.js +19 -2
  256. package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
  257. package/esm/v1/providers/tambo-v1-stream-context.d.ts +6 -0
  258. package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  259. package/esm/v1/providers/tambo-v1-stream-context.js +51 -12
  260. package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
  261. package/esm/v1/providers/tambo-v1-stream-context.test.js +9 -0
  262. package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  263. package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
  264. package/esm/v1/providers/tambo-v1-stub-provider.js +4 -0
  265. package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -1
  266. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +11 -0
  267. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
  268. package/esm/v1/providers/tambo-v1-thread-input-provider.js +10 -1
  269. package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
  270. package/esm/v1/types/auth.d.ts +24 -0
  271. package/esm/v1/types/auth.d.ts.map +1 -0
  272. package/esm/v1/types/auth.js +2 -0
  273. package/esm/v1/types/auth.js.map +1 -0
  274. package/esm/v1/types/message.d.ts +12 -0
  275. package/esm/v1/types/message.d.ts.map +1 -1
  276. package/esm/v1/types/message.js.map +1 -1
  277. package/esm/v1/types/tool-choice.d.ts +8 -0
  278. package/esm/v1/types/tool-choice.d.ts.map +1 -0
  279. package/esm/v1/types/tool-choice.js +2 -0
  280. package/esm/v1/types/tool-choice.js.map +1 -0
  281. package/esm/v1/utils/event-accumulator.d.ts +28 -2
  282. package/esm/v1/utils/event-accumulator.d.ts.map +1 -1
  283. package/esm/v1/utils/event-accumulator.js +66 -15
  284. package/esm/v1/utils/event-accumulator.js.map +1 -1
  285. package/esm/v1/utils/event-accumulator.test.js +106 -0
  286. package/esm/v1/utils/event-accumulator.test.js.map +1 -1
  287. package/esm/v1/utils/keyed-throttle.d.ts +42 -0
  288. package/esm/v1/utils/keyed-throttle.d.ts.map +1 -0
  289. package/esm/v1/utils/keyed-throttle.js +83 -0
  290. package/esm/v1/utils/keyed-throttle.js.map +1 -0
  291. package/esm/v1/utils/keyed-throttle.test.d.ts +2 -0
  292. package/esm/v1/utils/keyed-throttle.test.d.ts.map +1 -0
  293. package/esm/v1/utils/keyed-throttle.test.js +145 -0
  294. package/esm/v1/utils/keyed-throttle.test.js.map +1 -0
  295. package/esm/v1/utils/registry-conversion.d.ts.map +1 -1
  296. package/esm/v1/utils/registry-conversion.js +2 -0
  297. package/esm/v1/utils/registry-conversion.js.map +1 -1
  298. package/esm/v1/utils/registry-conversion.test.js +23 -0
  299. package/esm/v1/utils/registry-conversion.test.js.map +1 -1
  300. package/esm/v1/utils/tool-call-tracker.d.ts +10 -0
  301. package/esm/v1/utils/tool-call-tracker.d.ts.map +1 -1
  302. package/esm/v1/utils/tool-call-tracker.js +13 -0
  303. package/esm/v1/utils/tool-call-tracker.js.map +1 -1
  304. package/esm/v1/utils/tool-call-tracker.test.d.ts +2 -0
  305. package/esm/v1/utils/tool-call-tracker.test.d.ts.map +1 -0
  306. package/esm/v1/utils/tool-call-tracker.test.js +65 -0
  307. package/esm/v1/utils/tool-call-tracker.test.js.map +1 -0
  308. package/esm/v1/utils/tool-executor.d.ts +34 -0
  309. package/esm/v1/utils/tool-executor.d.ts.map +1 -1
  310. package/esm/v1/utils/tool-executor.js +53 -0
  311. package/esm/v1/utils/tool-executor.js.map +1 -1
  312. package/esm/v1/utils/tool-executor.test.js +212 -1
  313. package/esm/v1/utils/tool-executor.test.js.map +1 -1
  314. package/package.json +4 -4
@@ -12,6 +12,23 @@ jest.mock("../providers/tambo-v1-stream-context", () => ({
12
12
  jest.mock("../utils/component-renderer", () => ({
13
13
  useV1ComponentContent: jest.fn(),
14
14
  }));
15
+ const mockSetInteractableState = jest.fn();
16
+ const mockGetInteractableComponentState = jest.fn(() => undefined);
17
+ jest.mock("../../providers/tambo-interactable-provider", () => ({
18
+ useTamboInteractable: () => ({
19
+ interactableComponents: [],
20
+ addInteractableComponent: jest.fn(),
21
+ removeInteractableComponent: jest.fn(),
22
+ updateInteractableComponentProps: jest.fn(),
23
+ getInteractableComponent: jest.fn(),
24
+ getInteractableComponentsByName: jest.fn(),
25
+ clearAllInteractableComponents: jest.fn(),
26
+ setInteractableState: mockSetInteractableState,
27
+ getInteractableComponentState: mockGetInteractableComponentState,
28
+ setInteractableSelected: jest.fn(),
29
+ clearInteractableSelections: jest.fn(),
30
+ }),
31
+ }));
15
32
  // Create a mock debounced function with flush method
16
33
  const createMockDebouncedFunction = (fn) => {
17
34
  const debouncedFn = jest.fn((...args) => fn(...args));
@@ -89,6 +106,10 @@ describe("useTamboV1ComponentState", () => {
89
106
  jest
90
107
  .mocked(use_debounce_1.useDebouncedCallback)
91
108
  .mockImplementation((fn) => createMockDebouncedFunction(fn));
109
+ // Reset interactable mocks to default (no interactable state)
110
+ mockSetInteractableState.mockClear();
111
+ mockGetInteractableComponentState.mockReset();
112
+ mockGetInteractableComponentState.mockReturnValue(undefined);
92
113
  });
93
114
  afterEach(() => {
94
115
  jest.restoreAllMocks();
@@ -289,5 +310,84 @@ describe("useTamboV1ComponentState", () => {
289
310
  }).toThrow("useV1ComponentContent must be used within a rendered component");
290
311
  });
291
312
  });
313
+ describe("Interactable Component Support", () => {
314
+ const interactableComponentId = "MyWidget-abc";
315
+ beforeEach(() => {
316
+ // Simulate interactable context: threadId="" signals interactable
317
+ jest.mocked(component_renderer_1.useV1ComponentContent).mockReturnValue({
318
+ componentId: interactableComponentId,
319
+ threadId: "",
320
+ messageId: "",
321
+ componentName: "MyWidget",
322
+ });
323
+ // Empty stream state - interactable components don't use it
324
+ jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue({
325
+ threadMap: {},
326
+ currentThreadId: "",
327
+ });
328
+ });
329
+ it("should initialize with initialValue when no interactable state exists", () => {
330
+ mockGetInteractableComponentState.mockReturnValue(undefined);
331
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("count", 42));
332
+ expect(result.current[0]).toBe(42);
333
+ });
334
+ it("should initialize from interactable state when it exists", () => {
335
+ mockGetInteractableComponentState.mockReturnValue({ count: 99 });
336
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("count", 0));
337
+ expect(result.current[0]).toBe(99);
338
+ });
339
+ it("should call setInteractableState when setState is called", () => {
340
+ mockGetInteractableComponentState.mockReturnValue(undefined);
341
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("count", 0));
342
+ (0, react_1.act)(() => {
343
+ result.current[1](10);
344
+ });
345
+ expect(mockSetInteractableState).toHaveBeenCalledWith(interactableComponentId, "count", 10);
346
+ });
347
+ it("should NOT call client.threads.state.updateState for interactable components", () => {
348
+ mockGetInteractableComponentState.mockReturnValue(undefined);
349
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("count", 0));
350
+ (0, react_1.act)(() => {
351
+ result.current[1](10);
352
+ });
353
+ expect(mockUpdateState).not.toHaveBeenCalled();
354
+ });
355
+ it("should sync from interactable provider when state changes externally", () => {
356
+ mockGetInteractableComponentState.mockReturnValue({ count: 0 });
357
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("count", 0));
358
+ expect(result.current[0]).toBe(0);
359
+ // Simulate external state change (e.g., AI tool call)
360
+ mockGetInteractableComponentState.mockReturnValue({ count: 77 });
361
+ rerender();
362
+ expect(result.current[0]).toBe(77);
363
+ });
364
+ it("should have isPending as false in interactable context", () => {
365
+ mockGetInteractableComponentState.mockReturnValue(undefined);
366
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("count", 0));
367
+ expect(result.current[2].isPending).toBe(false);
368
+ expect(result.current[2].error).toBeNull();
369
+ });
370
+ it("should set initial value in interactable state on mount when no existing state", () => {
371
+ mockGetInteractableComponentState.mockReturnValue(undefined);
372
+ (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("count", 42));
373
+ expect(mockSetInteractableState).toHaveBeenCalledWith(interactableComponentId, "count", 42);
374
+ });
375
+ it("should NOT set initial value in interactable state when state already exists", () => {
376
+ mockGetInteractableComponentState.mockReturnValue({ count: 99 });
377
+ (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("count", 42));
378
+ // Should not be called because state already exists
379
+ expect(mockSetInteractableState).not.toHaveBeenCalled();
380
+ });
381
+ it("should not flush on unmount for interactable components", () => {
382
+ const mockFlush = jest.fn();
383
+ const mockDebouncedFn = createMockDebouncedFunction(jest.fn());
384
+ mockDebouncedFn.flush = mockFlush;
385
+ jest.mocked(use_debounce_1.useDebouncedCallback).mockReturnValue(mockDebouncedFn);
386
+ mockGetInteractableComponentState.mockReturnValue(undefined);
387
+ const { unmount } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("count", 0));
388
+ unmount();
389
+ expect(mockFlush).not.toHaveBeenCalled();
390
+ });
391
+ });
292
392
  });
293
393
  //# sourceMappingURL=use-tambo-v1-component-state.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-tambo-v1-component-state.test.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { act, renderHook } from \"@testing-library/react\";\nimport { useTamboV1ComponentState } from \"./use-tambo-v1-component-state\";\n\n// Mock the required modules\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(),\n}));\n\njest.mock(\"../providers/tambo-v1-stream-context\", () => ({\n useStreamState: jest.fn(),\n}));\n\njest.mock(\"../utils/component-renderer\", () => ({\n useV1ComponentContent: jest.fn(),\n}));\n\n// Create a mock debounced function with flush method\nconst createMockDebouncedFunction = (fn: (...args: unknown[]) => unknown) => {\n const debouncedFn = jest.fn((...args: unknown[]) =>\n fn(...args),\n ) as jest.Mock & {\n flush: jest.Mock;\n cancel: jest.Mock;\n isPending: () => boolean;\n };\n debouncedFn.flush = jest.fn();\n debouncedFn.cancel = jest.fn();\n debouncedFn.isPending = jest.fn(() => false);\n return debouncedFn;\n};\n\n// Mock use-debounce\njest.mock(\"use-debounce\", () => ({\n useDebouncedCallback: jest.fn(),\n}));\n\n// Import the mocked modules\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useStreamState } from \"../providers/tambo-v1-stream-context\";\nimport { useV1ComponentContent } from \"../utils/component-renderer\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport type { StreamState } from \"../utils/event-accumulator\";\nimport type { V1ComponentContent } from \"../types/message\";\n\ndescribe(\"useTamboV1ComponentState\", () => {\n const mockUpdateState = jest.fn();\n const mockComponentId = \"comp_test123\";\n const mockThreadId = \"thread_abc\";\n const mockMessageId = \"msg_xyz\";\n\n // Helper to create mock stream state\n const createMockStreamState = (\n componentState?: Record<string, unknown>,\n ): StreamState => ({\n threadMap: {\n [mockThreadId]: {\n thread: {\n id: mockThreadId,\n messages: [\n {\n id: mockMessageId,\n role: \"assistant\",\n content: [\n {\n type: \"component\",\n id: mockComponentId,\n name: \"TestComponent\",\n props: {},\n state: componentState,\n streamingState: \"done\",\n } as V1ComponentContent,\n ],\n createdAt: new Date().toISOString(),\n },\n ],\n status: \"idle\",\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n lastRunCancelled: false,\n },\n streaming: { status: \"idle\" },\n accumulatingToolArgs: new Map(),\n },\n },\n currentThreadId: mockThreadId,\n });\n\n beforeEach(() => {\n jest.clearAllMocks();\n\n // Setup default mocks\n jest.mocked(useTamboClient).mockReturnValue({\n threads: {\n state: {\n updateState: mockUpdateState,\n },\n },\n } as unknown as ReturnType<typeof useTamboClient>);\n\n jest.mocked(useV1ComponentContent).mockReturnValue({\n componentId: mockComponentId,\n threadId: mockThreadId,\n messageId: mockMessageId,\n componentName: \"TestComponent\",\n });\n\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState());\n\n // Setup default mock for useDebouncedCallback\n jest\n .mocked(useDebouncedCallback)\n .mockImplementation((fn) => createMockDebouncedFunction(fn));\n });\n\n afterEach(() => {\n jest.restoreAllMocks();\n });\n\n describe(\"Initial State Management\", () => {\n it(\"should initialize with initialValue when no server state exists\", () => {\n const initialValue = \"test-initial\";\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", initialValue),\n );\n\n expect(result.current[0]).toBe(initialValue);\n });\n\n it(\"should use server state over initialValue\", () => {\n const initialValue = \"initial\";\n const serverValue = \"server-value\";\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ testKey: serverValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", initialValue),\n );\n\n expect(result.current[0]).toBe(serverValue);\n });\n\n it(\"should handle undefined initialValue gracefully\", () => {\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { result } = renderHook(() => useTamboV1ComponentState(\"testKey\"));\n\n expect(result.current[0]).toBeUndefined();\n });\n\n it(\"should handle different data types correctly\", () => {\n const testCases = [\n { value: \"string\" },\n { value: 42 },\n { value: true },\n { value: { name: \"test\" } },\n { value: [1, 2, 3] },\n ];\n\n testCases.forEach(({ value }) => {\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ testKey: value }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", value),\n );\n\n expect(result.current[0]).toEqual(value);\n });\n });\n });\n\n describe(\"State Updates\", () => {\n it(\"should update local state immediately when setState is called\", () => {\n const initialValue = \"initial\";\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ testKey: initialValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", initialValue),\n );\n\n const newValue = \"updated\";\n act(() => {\n result.current[1](newValue);\n });\n\n expect(result.current[0]).toBe(newValue);\n });\n\n it(\"should support functional updates\", () => {\n const initialValue = 5;\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ counter: initialValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"counter\", initialValue),\n );\n\n act(() => {\n result.current[1]((prev) => (prev ?? 0) + 1);\n });\n\n expect(result.current[0]).toBe(6);\n });\n\n it(\"should trigger debounced API call when setState is called\", () => {\n const initialValue = \"initial\";\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ testKey: initialValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", initialValue),\n );\n\n const newValue = \"updated\";\n act(() => {\n result.current[1](newValue);\n });\n\n // The debounced function should be called\n expect(mockUpdateState).toHaveBeenCalledWith(mockComponentId, {\n threadId: mockThreadId,\n state: { testKey: newValue },\n });\n });\n\n it(\"should work with complex objects\", () => {\n const initialValue = { name: \"test\", items: [1, 2, 3] };\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ data: initialValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"data\", initialValue),\n );\n\n const newValue = { name: \"updated\", items: [4, 5, 6] };\n act(() => {\n result.current[1](newValue);\n });\n\n expect(result.current[0]).toEqual(newValue);\n });\n });\n\n describe(\"Metadata\", () => {\n it(\"should return isPending and error in meta\", () => {\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n expect(result.current[2]).toEqual({\n isPending: false,\n error: null,\n flush: expect.any(Function),\n });\n });\n\n it(\"should provide a flush function\", () => {\n const mockFlush = jest.fn();\n const mockDebouncedFn = createMockDebouncedFunction(jest.fn());\n mockDebouncedFn.flush = mockFlush;\n jest.mocked(useDebouncedCallback).mockReturnValue(mockDebouncedFn);\n\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n act(() => {\n result.current[2].flush();\n });\n\n expect(mockFlush).toHaveBeenCalled();\n });\n });\n\n describe(\"Debouncing Behavior\", () => {\n it(\"should use default debounce time of 500ms\", () => {\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n renderHook(() => useTamboV1ComponentState(\"testKey\", \"initial\"));\n\n expect(useDebouncedCallback).toHaveBeenCalledWith(\n expect.any(Function),\n 500,\n );\n });\n\n it(\"should use custom debounce time when provided\", () => {\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n const customDebounceTime = 1000;\n\n renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\", customDebounceTime),\n );\n\n expect(useDebouncedCallback).toHaveBeenCalledWith(\n expect.any(Function),\n customDebounceTime,\n );\n });\n\n it(\"should flush debounced callback on unmount\", () => {\n const mockFlush = jest.fn();\n const mockDebouncedFn = createMockDebouncedFunction(jest.fn());\n mockDebouncedFn.flush = mockFlush;\n jest.mocked(useDebouncedCallback).mockReturnValue(mockDebouncedFn);\n\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { unmount } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n unmount();\n\n expect(mockFlush).toHaveBeenCalled();\n });\n });\n\n describe(\"Server State Sync\", () => {\n it(\"should sync with server state changes from streaming\", () => {\n const streamState = createMockStreamState({ testKey: \"initial\" });\n jest.mocked(useStreamState).mockReturnValue(streamState);\n\n const { result, rerender } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n expect(result.current[0]).toBe(\"initial\");\n\n // Simulate server state change from streaming\n const updatedStreamState = createMockStreamState({\n testKey: \"updated-from-server\",\n });\n jest.mocked(useStreamState).mockReturnValue(updatedStreamState);\n\n rerender();\n\n expect(result.current[0]).toBe(\"updated-from-server\");\n });\n\n it(\"should handle component not found in stream state\", () => {\n // Empty stream state (no matching component)\n jest.mocked(useStreamState).mockReturnValue({\n threadMap: {},\n currentThreadId: \"placeholder\",\n });\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"default\"),\n );\n\n expect(result.current[0]).toBe(\"default\");\n });\n });\n\n describe(\"Error Handling\", () => {\n it(\"should handle API errors gracefully\", async () => {\n const mockError = new Error(\"API Error\");\n mockUpdateState.mockRejectedValue(mockError);\n\n // Create a sync mock that calls the function immediately\n jest.mocked(useDebouncedCallback).mockImplementation((fn) => {\n const debouncedFn = Object.assign(\n async (...args: unknown[]) => fn(...args),\n {\n flush: jest.fn(),\n cancel: jest.fn(),\n isPending: () => false,\n },\n ) as unknown as ReturnType<typeof useDebouncedCallback>;\n return debouncedFn;\n });\n\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n await act(async () => {\n result.current[1](\"new-value\");\n // Wait for async operations\n await new Promise((resolve) => setTimeout(resolve, 0));\n });\n\n expect(consoleSpy).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to sync state\"),\n mockError,\n );\n\n consoleSpy.mockRestore();\n });\n });\n\n describe(\"Context Requirements\", () => {\n it(\"should throw when used outside component content context\", () => {\n jest.mocked(useV1ComponentContent).mockImplementation(() => {\n throw new Error(\n \"useV1ComponentContent must be used within a rendered component\",\n );\n });\n\n expect(() => {\n renderHook(() => useTamboV1ComponentState(\"testKey\", \"initial\"));\n }).toThrow(\n \"useV1ComponentContent must be used within a rendered component\",\n );\n });\n });\n});\n"]}
1
+ {"version":3,"file":"use-tambo-v1-component-state.test.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { act, renderHook } from \"@testing-library/react\";\nimport { useTamboV1ComponentState } from \"./use-tambo-v1-component-state\";\n\n// Mock the required modules\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(),\n}));\n\njest.mock(\"../providers/tambo-v1-stream-context\", () => ({\n useStreamState: jest.fn(),\n}));\n\njest.mock(\"../utils/component-renderer\", () => ({\n useV1ComponentContent: jest.fn(),\n}));\n\nconst mockSetInteractableState = jest.fn();\nconst mockGetInteractableComponentState = jest.fn<\n Record<string, unknown> | undefined,\n [string]\n>(() => undefined);\n\njest.mock(\"../../providers/tambo-interactable-provider\", () => ({\n useTamboInteractable: () => ({\n interactableComponents: [],\n addInteractableComponent: jest.fn(),\n removeInteractableComponent: jest.fn(),\n updateInteractableComponentProps: jest.fn(),\n getInteractableComponent: jest.fn(),\n getInteractableComponentsByName: jest.fn(),\n clearAllInteractableComponents: jest.fn(),\n setInteractableState: mockSetInteractableState,\n getInteractableComponentState: mockGetInteractableComponentState,\n setInteractableSelected: jest.fn(),\n clearInteractableSelections: jest.fn(),\n }),\n}));\n\n// Create a mock debounced function with flush method\nconst createMockDebouncedFunction = (fn: (...args: unknown[]) => unknown) => {\n const debouncedFn = jest.fn((...args: unknown[]) =>\n fn(...args),\n ) as jest.Mock & {\n flush: jest.Mock;\n cancel: jest.Mock;\n isPending: () => boolean;\n };\n debouncedFn.flush = jest.fn();\n debouncedFn.cancel = jest.fn();\n debouncedFn.isPending = jest.fn(() => false);\n return debouncedFn;\n};\n\n// Mock use-debounce\njest.mock(\"use-debounce\", () => ({\n useDebouncedCallback: jest.fn(),\n}));\n\n// Import the mocked modules\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useStreamState } from \"../providers/tambo-v1-stream-context\";\nimport { useV1ComponentContent } from \"../utils/component-renderer\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport type { StreamState } from \"../utils/event-accumulator\";\nimport type { V1ComponentContent } from \"../types/message\";\n\ndescribe(\"useTamboV1ComponentState\", () => {\n const mockUpdateState = jest.fn();\n const mockComponentId = \"comp_test123\";\n const mockThreadId = \"thread_abc\";\n const mockMessageId = \"msg_xyz\";\n\n // Helper to create mock stream state\n const createMockStreamState = (\n componentState?: Record<string, unknown>,\n ): StreamState => ({\n threadMap: {\n [mockThreadId]: {\n thread: {\n id: mockThreadId,\n messages: [\n {\n id: mockMessageId,\n role: \"assistant\",\n content: [\n {\n type: \"component\",\n id: mockComponentId,\n name: \"TestComponent\",\n props: {},\n state: componentState,\n streamingState: \"done\",\n } as V1ComponentContent,\n ],\n createdAt: new Date().toISOString(),\n },\n ],\n status: \"idle\",\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n lastRunCancelled: false,\n },\n streaming: { status: \"idle\" },\n accumulatingToolArgs: new Map(),\n },\n },\n currentThreadId: mockThreadId,\n });\n\n beforeEach(() => {\n jest.clearAllMocks();\n\n // Setup default mocks\n jest.mocked(useTamboClient).mockReturnValue({\n threads: {\n state: {\n updateState: mockUpdateState,\n },\n },\n } as unknown as ReturnType<typeof useTamboClient>);\n\n jest.mocked(useV1ComponentContent).mockReturnValue({\n componentId: mockComponentId,\n threadId: mockThreadId,\n messageId: mockMessageId,\n componentName: \"TestComponent\",\n });\n\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState());\n\n // Setup default mock for useDebouncedCallback\n jest\n .mocked(useDebouncedCallback)\n .mockImplementation((fn) => createMockDebouncedFunction(fn));\n\n // Reset interactable mocks to default (no interactable state)\n mockSetInteractableState.mockClear();\n mockGetInteractableComponentState.mockReset();\n mockGetInteractableComponentState.mockReturnValue(undefined);\n });\n\n afterEach(() => {\n jest.restoreAllMocks();\n });\n\n describe(\"Initial State Management\", () => {\n it(\"should initialize with initialValue when no server state exists\", () => {\n const initialValue = \"test-initial\";\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", initialValue),\n );\n\n expect(result.current[0]).toBe(initialValue);\n });\n\n it(\"should use server state over initialValue\", () => {\n const initialValue = \"initial\";\n const serverValue = \"server-value\";\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ testKey: serverValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", initialValue),\n );\n\n expect(result.current[0]).toBe(serverValue);\n });\n\n it(\"should handle undefined initialValue gracefully\", () => {\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { result } = renderHook(() => useTamboV1ComponentState(\"testKey\"));\n\n expect(result.current[0]).toBeUndefined();\n });\n\n it(\"should handle different data types correctly\", () => {\n const testCases = [\n { value: \"string\" },\n { value: 42 },\n { value: true },\n { value: { name: \"test\" } },\n { value: [1, 2, 3] },\n ];\n\n testCases.forEach(({ value }) => {\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ testKey: value }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", value),\n );\n\n expect(result.current[0]).toEqual(value);\n });\n });\n });\n\n describe(\"State Updates\", () => {\n it(\"should update local state immediately when setState is called\", () => {\n const initialValue = \"initial\";\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ testKey: initialValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", initialValue),\n );\n\n const newValue = \"updated\";\n act(() => {\n result.current[1](newValue);\n });\n\n expect(result.current[0]).toBe(newValue);\n });\n\n it(\"should support functional updates\", () => {\n const initialValue = 5;\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ counter: initialValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"counter\", initialValue),\n );\n\n act(() => {\n result.current[1]((prev) => (prev ?? 0) + 1);\n });\n\n expect(result.current[0]).toBe(6);\n });\n\n it(\"should trigger debounced API call when setState is called\", () => {\n const initialValue = \"initial\";\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ testKey: initialValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", initialValue),\n );\n\n const newValue = \"updated\";\n act(() => {\n result.current[1](newValue);\n });\n\n // The debounced function should be called\n expect(mockUpdateState).toHaveBeenCalledWith(mockComponentId, {\n threadId: mockThreadId,\n state: { testKey: newValue },\n });\n });\n\n it(\"should work with complex objects\", () => {\n const initialValue = { name: \"test\", items: [1, 2, 3] };\n jest\n .mocked(useStreamState)\n .mockReturnValue(createMockStreamState({ data: initialValue }));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"data\", initialValue),\n );\n\n const newValue = { name: \"updated\", items: [4, 5, 6] };\n act(() => {\n result.current[1](newValue);\n });\n\n expect(result.current[0]).toEqual(newValue);\n });\n });\n\n describe(\"Metadata\", () => {\n it(\"should return isPending and error in meta\", () => {\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n expect(result.current[2]).toEqual({\n isPending: false,\n error: null,\n flush: expect.any(Function),\n });\n });\n\n it(\"should provide a flush function\", () => {\n const mockFlush = jest.fn();\n const mockDebouncedFn = createMockDebouncedFunction(jest.fn());\n mockDebouncedFn.flush = mockFlush;\n jest.mocked(useDebouncedCallback).mockReturnValue(mockDebouncedFn);\n\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n act(() => {\n result.current[2].flush();\n });\n\n expect(mockFlush).toHaveBeenCalled();\n });\n });\n\n describe(\"Debouncing Behavior\", () => {\n it(\"should use default debounce time of 500ms\", () => {\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n renderHook(() => useTamboV1ComponentState(\"testKey\", \"initial\"));\n\n expect(useDebouncedCallback).toHaveBeenCalledWith(\n expect.any(Function),\n 500,\n );\n });\n\n it(\"should use custom debounce time when provided\", () => {\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n const customDebounceTime = 1000;\n\n renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\", customDebounceTime),\n );\n\n expect(useDebouncedCallback).toHaveBeenCalledWith(\n expect.any(Function),\n customDebounceTime,\n );\n });\n\n it(\"should flush debounced callback on unmount\", () => {\n const mockFlush = jest.fn();\n const mockDebouncedFn = createMockDebouncedFunction(jest.fn());\n mockDebouncedFn.flush = mockFlush;\n jest.mocked(useDebouncedCallback).mockReturnValue(mockDebouncedFn);\n\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const { unmount } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n unmount();\n\n expect(mockFlush).toHaveBeenCalled();\n });\n });\n\n describe(\"Server State Sync\", () => {\n it(\"should sync with server state changes from streaming\", () => {\n const streamState = createMockStreamState({ testKey: \"initial\" });\n jest.mocked(useStreamState).mockReturnValue(streamState);\n\n const { result, rerender } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n expect(result.current[0]).toBe(\"initial\");\n\n // Simulate server state change from streaming\n const updatedStreamState = createMockStreamState({\n testKey: \"updated-from-server\",\n });\n jest.mocked(useStreamState).mockReturnValue(updatedStreamState);\n\n rerender();\n\n expect(result.current[0]).toBe(\"updated-from-server\");\n });\n\n it(\"should handle component not found in stream state\", () => {\n // Empty stream state (no matching component)\n jest.mocked(useStreamState).mockReturnValue({\n threadMap: {},\n currentThreadId: \"placeholder\",\n });\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"default\"),\n );\n\n expect(result.current[0]).toBe(\"default\");\n });\n });\n\n describe(\"Error Handling\", () => {\n it(\"should handle API errors gracefully\", async () => {\n const mockError = new Error(\"API Error\");\n mockUpdateState.mockRejectedValue(mockError);\n\n // Create a sync mock that calls the function immediately\n jest.mocked(useDebouncedCallback).mockImplementation((fn) => {\n const debouncedFn = Object.assign(\n async (...args: unknown[]) => fn(...args),\n {\n flush: jest.fn(),\n cancel: jest.fn(),\n isPending: () => false,\n },\n ) as unknown as ReturnType<typeof useDebouncedCallback>;\n return debouncedFn;\n });\n\n jest.mocked(useStreamState).mockReturnValue(createMockStreamState({}));\n\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"testKey\", \"initial\"),\n );\n\n await act(async () => {\n result.current[1](\"new-value\");\n // Wait for async operations\n await new Promise((resolve) => setTimeout(resolve, 0));\n });\n\n expect(consoleSpy).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to sync state\"),\n mockError,\n );\n\n consoleSpy.mockRestore();\n });\n });\n\n describe(\"Context Requirements\", () => {\n it(\"should throw when used outside component content context\", () => {\n jest.mocked(useV1ComponentContent).mockImplementation(() => {\n throw new Error(\n \"useV1ComponentContent must be used within a rendered component\",\n );\n });\n\n expect(() => {\n renderHook(() => useTamboV1ComponentState(\"testKey\", \"initial\"));\n }).toThrow(\n \"useV1ComponentContent must be used within a rendered component\",\n );\n });\n });\n\n describe(\"Interactable Component Support\", () => {\n const interactableComponentId = \"MyWidget-abc\";\n\n beforeEach(() => {\n // Simulate interactable context: threadId=\"\" signals interactable\n jest.mocked(useV1ComponentContent).mockReturnValue({\n componentId: interactableComponentId,\n threadId: \"\",\n messageId: \"\",\n componentName: \"MyWidget\",\n });\n\n // Empty stream state - interactable components don't use it\n jest.mocked(useStreamState).mockReturnValue({\n threadMap: {},\n currentThreadId: \"\",\n });\n });\n\n it(\"should initialize with initialValue when no interactable state exists\", () => {\n mockGetInteractableComponentState.mockReturnValue(undefined);\n\n const { result } = renderHook(() =>\n useTamboV1ComponentState(\"count\", 42),\n );\n\n expect(result.current[0]).toBe(42);\n });\n\n it(\"should initialize from interactable state when it exists\", () => {\n mockGetInteractableComponentState.mockReturnValue({ count: 99 });\n\n const { result } = renderHook(() => useTamboV1ComponentState(\"count\", 0));\n\n expect(result.current[0]).toBe(99);\n });\n\n it(\"should call setInteractableState when setState is called\", () => {\n mockGetInteractableComponentState.mockReturnValue(undefined);\n\n const { result } = renderHook(() => useTamboV1ComponentState(\"count\", 0));\n\n act(() => {\n result.current[1](10);\n });\n\n expect(mockSetInteractableState).toHaveBeenCalledWith(\n interactableComponentId,\n \"count\",\n 10,\n );\n });\n\n it(\"should NOT call client.threads.state.updateState for interactable components\", () => {\n mockGetInteractableComponentState.mockReturnValue(undefined);\n\n const { result } = renderHook(() => useTamboV1ComponentState(\"count\", 0));\n\n act(() => {\n result.current[1](10);\n });\n\n expect(mockUpdateState).not.toHaveBeenCalled();\n });\n\n it(\"should sync from interactable provider when state changes externally\", () => {\n mockGetInteractableComponentState.mockReturnValue({ count: 0 });\n\n const { result, rerender } = renderHook(() =>\n useTamboV1ComponentState(\"count\", 0),\n );\n\n expect(result.current[0]).toBe(0);\n\n // Simulate external state change (e.g., AI tool call)\n mockGetInteractableComponentState.mockReturnValue({ count: 77 });\n\n rerender();\n\n expect(result.current[0]).toBe(77);\n });\n\n it(\"should have isPending as false in interactable context\", () => {\n mockGetInteractableComponentState.mockReturnValue(undefined);\n\n const { result } = renderHook(() => useTamboV1ComponentState(\"count\", 0));\n\n expect(result.current[2].isPending).toBe(false);\n expect(result.current[2].error).toBeNull();\n });\n\n it(\"should set initial value in interactable state on mount when no existing state\", () => {\n mockGetInteractableComponentState.mockReturnValue(undefined);\n\n renderHook(() => useTamboV1ComponentState(\"count\", 42));\n\n expect(mockSetInteractableState).toHaveBeenCalledWith(\n interactableComponentId,\n \"count\",\n 42,\n );\n });\n\n it(\"should NOT set initial value in interactable state when state already exists\", () => {\n mockGetInteractableComponentState.mockReturnValue({ count: 99 });\n\n renderHook(() => useTamboV1ComponentState(\"count\", 42));\n\n // Should not be called because state already exists\n expect(mockSetInteractableState).not.toHaveBeenCalled();\n });\n\n it(\"should not flush on unmount for interactable components\", () => {\n const mockFlush = jest.fn();\n const mockDebouncedFn = createMockDebouncedFunction(jest.fn());\n mockDebouncedFn.flush = mockFlush;\n jest.mocked(useDebouncedCallback).mockReturnValue(mockDebouncedFn);\n\n mockGetInteractableComponentState.mockReturnValue(undefined);\n\n const { unmount } = renderHook(() =>\n useTamboV1ComponentState(\"count\", 0),\n );\n\n unmount();\n\n expect(mockFlush).not.toHaveBeenCalled();\n });\n });\n});\n"]}
@@ -16,10 +16,18 @@ jest.mock("../../providers/tambo-client-provider", () => ({
16
16
  messages: {
17
17
  list: jest.fn().mockResolvedValue({ messages: [], hasMore: false }),
18
18
  },
19
+ retrieve: jest.fn().mockResolvedValue({}),
19
20
  },
20
21
  })),
21
22
  useTamboQueryClient: jest.fn(),
22
23
  }));
24
+ jest.mock("../providers/tambo-v1-provider", () => {
25
+ const actual = jest.requireActual("../providers/tambo-v1-provider");
26
+ return {
27
+ ...actual,
28
+ useTamboV1Config: () => ({ userKey: undefined }),
29
+ };
30
+ });
23
31
  const tambo_client_provider_1 = require("../../providers/tambo-client-provider");
24
32
  describe("useTamboV1Messages", () => {
25
33
  let queryClient;
@@ -1 +1 @@
1
- {"version":3,"file":"use-tambo-v1-messages.test.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-messages.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n EventType,\n type TextMessageStartEvent,\n type TextMessageContentEvent,\n type TextMessageEndEvent,\n} from \"@ag-ui/core\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { renderHook, act } from \"@testing-library/react\";\nimport React from \"react\";\nimport {\n TamboV1StreamProvider,\n useStreamDispatch,\n} from \"../providers/tambo-v1-stream-context\";\nimport { useTamboV1Messages } from \"./use-tambo-v1-messages\";\n\n// Mock useTamboClient and useTamboQueryClient to avoid TamboClientProvider dependency\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(() => ({\n threads: {\n messages: {\n list: jest.fn().mockResolvedValue({ messages: [], hasMore: false }),\n },\n },\n })),\n useTamboQueryClient: jest.fn(),\n}));\n\nimport { useTamboQueryClient } from \"../../providers/tambo-client-provider\";\n\ndescribe(\"useTamboV1Messages\", () => {\n let queryClient: QueryClient;\n\n beforeEach(() => {\n queryClient = new QueryClient({\n defaultOptions: {\n queries: { retry: false },\n },\n });\n // Configure mock to return the test's queryClient\n jest.mocked(useTamboQueryClient).mockReturnValue(queryClient);\n });\n\n function TestWrapper({ children }: { children: React.ReactNode }) {\n return (\n <QueryClientProvider client={queryClient}>\n <TamboV1StreamProvider>{children}</TamboV1StreamProvider>\n </QueryClientProvider>\n );\n }\n\n it(\"returns empty messages when thread has no messages\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboV1Messages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n expect(result.current.messages.messages).toEqual([]);\n expect(result.current.messages.hasMessages).toBe(false);\n expect(result.current.messages.messageCount).toBe(0);\n expect(result.current.messages.lastMessage).toBeUndefined();\n expect(result.current.messages.userMessages).toEqual([]);\n expect(result.current.messages.assistantMessages).toEqual([]);\n });\n\n it(\"returns messages after events are dispatched\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboV1Messages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n // Simulate a text message being received\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_1\",\n role: \"assistant\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId: \"msg_1\",\n delta: \"Hello\",\n } as TextMessageContentEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_1\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n expect(result.current.messages.messages.length).toBe(1);\n expect(result.current.messages.hasMessages).toBe(true);\n expect(result.current.messages.messageCount).toBe(1);\n expect(result.current.messages.lastMessage?.id).toBe(\"msg_1\");\n expect(result.current.messages.lastMessage?.role).toBe(\"assistant\");\n expect(result.current.messages.assistantMessages.length).toBe(1);\n expect(result.current.messages.userMessages.length).toBe(0);\n });\n\n it(\"filters user and assistant messages correctly\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboV1Messages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n // Add user message\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_user\",\n role: \"user\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_user\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n // Add assistant message\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_assistant\",\n role: \"assistant\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_assistant\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n expect(result.current.messages.messageCount).toBe(2);\n expect(result.current.messages.userMessages.length).toBe(1);\n expect(result.current.messages.userMessages[0].id).toBe(\"msg_user\");\n expect(result.current.messages.assistantMessages.length).toBe(1);\n expect(result.current.messages.assistantMessages[0].id).toBe(\n \"msg_assistant\",\n );\n expect(result.current.messages.lastMessage?.id).toBe(\"msg_assistant\");\n });\n\n it(\"returns empty messages when threadId does not exist in threadMap\", () => {\n const { result } = renderHook(\n () => useTamboV1Messages(\"nonexistent_thread\"),\n {\n wrapper: TestWrapper,\n },\n );\n\n expect(result.current.messages).toEqual([]);\n expect(result.current.hasMessages).toBe(false);\n expect(result.current.messageCount).toBe(0);\n });\n});\n"]}
1
+ {"version":3,"file":"use-tambo-v1-messages.test.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-messages.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n EventType,\n type TextMessageStartEvent,\n type TextMessageContentEvent,\n type TextMessageEndEvent,\n} from \"@ag-ui/core\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { renderHook, act } from \"@testing-library/react\";\nimport React from \"react\";\nimport {\n TamboV1StreamProvider,\n useStreamDispatch,\n} from \"../providers/tambo-v1-stream-context\";\nimport { useTamboV1Messages } from \"./use-tambo-v1-messages\";\n\n// Mock useTamboClient and useTamboQueryClient to avoid TamboClientProvider dependency\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(() => ({\n threads: {\n messages: {\n list: jest.fn().mockResolvedValue({ messages: [], hasMore: false }),\n },\n retrieve: jest.fn().mockResolvedValue({}),\n },\n })),\n useTamboQueryClient: jest.fn(),\n}));\n\njest.mock(\"../providers/tambo-v1-provider\", () => {\n const actual = jest.requireActual(\"../providers/tambo-v1-provider\");\n return {\n ...actual,\n useTamboV1Config: () => ({ userKey: undefined }),\n };\n});\n\nimport { useTamboQueryClient } from \"../../providers/tambo-client-provider\";\n\ndescribe(\"useTamboV1Messages\", () => {\n let queryClient: QueryClient;\n\n beforeEach(() => {\n queryClient = new QueryClient({\n defaultOptions: {\n queries: { retry: false },\n },\n });\n // Configure mock to return the test's queryClient\n jest.mocked(useTamboQueryClient).mockReturnValue(queryClient);\n });\n\n function TestWrapper({ children }: { children: React.ReactNode }) {\n return (\n <QueryClientProvider client={queryClient}>\n <TamboV1StreamProvider>{children}</TamboV1StreamProvider>\n </QueryClientProvider>\n );\n }\n\n it(\"returns empty messages when thread has no messages\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboV1Messages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n expect(result.current.messages.messages).toEqual([]);\n expect(result.current.messages.hasMessages).toBe(false);\n expect(result.current.messages.messageCount).toBe(0);\n expect(result.current.messages.lastMessage).toBeUndefined();\n expect(result.current.messages.userMessages).toEqual([]);\n expect(result.current.messages.assistantMessages).toEqual([]);\n });\n\n it(\"returns messages after events are dispatched\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboV1Messages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n // Simulate a text message being received\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_1\",\n role: \"assistant\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId: \"msg_1\",\n delta: \"Hello\",\n } as TextMessageContentEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_1\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n expect(result.current.messages.messages.length).toBe(1);\n expect(result.current.messages.hasMessages).toBe(true);\n expect(result.current.messages.messageCount).toBe(1);\n expect(result.current.messages.lastMessage?.id).toBe(\"msg_1\");\n expect(result.current.messages.lastMessage?.role).toBe(\"assistant\");\n expect(result.current.messages.assistantMessages.length).toBe(1);\n expect(result.current.messages.userMessages.length).toBe(0);\n });\n\n it(\"filters user and assistant messages correctly\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboV1Messages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n // Add user message\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_user\",\n role: \"user\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_user\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n // Add assistant message\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_assistant\",\n role: \"assistant\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_assistant\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n expect(result.current.messages.messageCount).toBe(2);\n expect(result.current.messages.userMessages.length).toBe(1);\n expect(result.current.messages.userMessages[0].id).toBe(\"msg_user\");\n expect(result.current.messages.assistantMessages.length).toBe(1);\n expect(result.current.messages.assistantMessages[0].id).toBe(\n \"msg_assistant\",\n );\n expect(result.current.messages.lastMessage?.id).toBe(\"msg_assistant\");\n });\n\n it(\"returns empty messages when threadId does not exist in threadMap\", () => {\n const { result } = renderHook(\n () => useTamboV1Messages(\"nonexistent_thread\"),\n {\n wrapper: TestWrapper,\n },\n );\n\n expect(result.current.messages).toEqual([]);\n expect(result.current.hasMessages).toBe(false);\n expect(result.current.messageCount).toBe(0);\n });\n});\n"]}
@@ -1,7 +1,8 @@
1
1
  import type TamboAI from "@tambo-ai/typescript-sdk";
2
2
  import type { Stream } from "@tambo-ai/typescript-sdk/core/streaming";
3
3
  import { type TamboRegistryContext as TamboRegistry } from "../../providers/tambo-registry-provider";
4
- import type { InputMessage } from "../types/message";
4
+ import type { InitialInputMessage, InputMessage } from "../types/message";
5
+ import type { ToolChoice } from "../types/tool-choice";
5
6
  /**
6
7
  * Options for sending a message
7
8
  */
@@ -20,6 +21,14 @@ export interface SendMessageOptions {
20
21
  * Enable debug logging for the stream
21
22
  */
22
23
  debug?: boolean;
24
+ /**
25
+ * How the model should use tools. Defaults to "auto".
26
+ * - "auto": Model decides whether to use tools
27
+ * - "required": Model must use at least one tool
28
+ * - "none": Model cannot use tools
29
+ * - { name: "toolName" }: Model must use the specified tool
30
+ */
31
+ toolChoice?: ToolChoice;
23
32
  }
24
33
  /**
25
34
  * Parameters for creating a run stream
@@ -40,6 +49,15 @@ export interface CreateRunStreamParams {
40
49
  * Merged into the message's additionalContext before sending.
41
50
  */
42
51
  additionalContext?: Record<string, unknown>;
52
+ /**
53
+ * How the model should use tools.
54
+ */
55
+ toolChoice?: ToolChoice;
56
+ /**
57
+ * Initial messages to seed the thread with when creating a new thread.
58
+ * Only used when threadId is undefined (new thread creation).
59
+ */
60
+ initialMessages?: InitialInputMessage[];
43
61
  }
44
62
  /**
45
63
  * Stream types from the SDK
@@ -1 +1 @@
1
- {"version":3,"file":"use-tambo-v1-send-message.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-send-message.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AAMtE,OAAO,EAEL,KAAK,oBAAoB,IAAI,aAAa,EAC3C,MAAM,yCAAyC,CAAC;AAOjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAwKrD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B;;;OAGG;IACH,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C;AAED;;GAEG;AACH,KAAK,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAC7D,KAAK,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,SAAS,GAAG,YAAY,CAAC;IACjC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AA6ED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CAgDhC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,CAAC,EAAE,MAAM;;;;uCA4MtD"}
1
+ {"version":3,"file":"use-tambo-v1-send-message.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-send-message.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AAMtE,OAAO,EAEL,KAAK,oBAAoB,IAAI,aAAa,EAC3C,MAAM,yCAAyC,CAAC;AAQjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AA4MvD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B;;;OAGG;IACH,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C;;OAEG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACzC;AAED;;GAEG;AACH,KAAK,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAC7D,KAAK,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,SAAS,GAAG,YAAY,CAAC;IACjC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAgFD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CA+DhC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,CAAC,EAAE,MAAM;;;;uCA+PtD"}
@@ -16,12 +16,14 @@ const react_query_hooks_1 = require("../../hooks/react-query-hooks");
16
16
  const tambo_registry_provider_1 = require("../../providers/tambo-registry-provider");
17
17
  const tambo_v1_stream_context_1 = require("../providers/tambo-v1-stream-context");
18
18
  const tambo_v1_provider_1 = require("../providers/tambo-v1-provider");
19
+ const use_tambo_v1_auth_state_1 = require("./use-tambo-v1-auth-state");
19
20
  const tambo_context_helpers_provider_1 = require("../../providers/tambo-context-helpers-provider");
20
21
  const event_accumulator_1 = require("../utils/event-accumulator");
21
22
  const registry_conversion_1 = require("../utils/registry-conversion");
22
23
  const stream_handler_1 = require("../utils/stream-handler");
23
24
  const tool_executor_1 = require("../utils/tool-executor");
24
25
  const tool_call_tracker_1 = require("../utils/tool-call-tracker");
26
+ const partial_json_1 = require("partial-json");
25
27
  /**
26
28
  * Dispatches synthetic AG-UI events to show a user message in the thread.
27
29
  * @param dispatch - Stream state dispatcher
@@ -117,6 +119,33 @@ function shouldGenerateThreadName(threadId, threadAlreadyHasTitle, preMutationMe
117
119
  // +2 accounts for the user message and assistant response just added
118
120
  preMutationMessageCount + 2 >= autoGenerateNameThreshold);
119
121
  }
122
+ /**
123
+ * Attempts to parse partial JSON from accumulated tool call args.
124
+ *
125
+ * Returns a parsed object if the accumulated args are parseable as
126
+ * a JSON object, or undefined if parsing fails or the result is not
127
+ * a plain object (e.g. array or primitive).
128
+ * @param toolTracker - Tracker holding pending tool call state
129
+ * @param toolCallId - The tool call ID to parse args for
130
+ * @returns Parsed args object, or undefined if not parseable yet
131
+ */
132
+ function parseToolCallArgs(toolTracker, toolCallId) {
133
+ const accToolCall = toolTracker.getAccumulatingToolCall(toolCallId);
134
+ if (!accToolCall)
135
+ return undefined;
136
+ try {
137
+ const parsed = (0, partial_json_1.parse)(accToolCall.accumulatedArgs);
138
+ if (typeof parsed === "object" &&
139
+ parsed !== null &&
140
+ !Array.isArray(parsed)) {
141
+ return parsed;
142
+ }
143
+ }
144
+ catch {
145
+ /* not parseable yet */
146
+ }
147
+ return undefined;
148
+ }
120
149
  /**
121
150
  * Generates a thread name via the beta API, dispatches the title update,
122
151
  * and invalidates the thread list cache. Errors are logged, never thrown.
@@ -153,7 +182,7 @@ async function generateThreadName(client, dispatch, queryClient, threadId) {
153
182
  * @returns The continuation stream and tool results for optimistic local state updates
154
183
  */
155
184
  async function executeToolsAndContinue(params) {
156
- const { event, toolTracker, registry, client, threadId, runId, userKey, additionalContext, } = params;
185
+ const { event, toolTracker, registry, client, threadId, runId, userKey, additionalContext, toolChoice, } = params;
157
186
  const pendingToolCallIds = event.value.pendingToolCalls.map((tc) => tc.toolCallId);
158
187
  const toolCallsToExecute = toolTracker.getToolCallsById(pendingToolCallIds);
159
188
  // Execute tools
@@ -171,6 +200,7 @@ async function executeToolsAndContinue(params) {
171
200
  availableComponents: (0, registry_conversion_1.toAvailableComponents)(registry.componentList),
172
201
  tools: (0, registry_conversion_1.toAvailableTools)(registry.toolRegistry),
173
202
  userKey,
203
+ toolChoice,
174
204
  });
175
205
  return { stream, toolResults };
176
206
  }
@@ -183,7 +213,7 @@ async function executeToolsAndContinue(params) {
183
213
  * @returns The stream and initial thread ID (undefined if creating new thread)
184
214
  */
185
215
  async function createRunStream(params) {
186
- const { client, threadId, message, registry, userKey, previousRunId, additionalContext, } = params;
216
+ const { client, threadId, message, registry, userKey, previousRunId, additionalContext, toolChoice, initialMessages, } = params;
187
217
  // Merge helper context with any caller-provided additionalContext on the message
188
218
  const mergedContext = additionalContext || message.additionalContext
189
219
  ? {
@@ -205,16 +235,27 @@ async function createRunStream(params) {
205
235
  tools: availableTools,
206
236
  userKey,
207
237
  previousRunId,
238
+ toolChoice,
208
239
  });
209
240
  return { stream, initialThreadId: threadId };
210
241
  }
211
242
  else {
212
- // Create new thread
243
+ // Create new thread - include initialMessages if provided
244
+ // Cast to InputMessage[] at the SDK boundary: the V1 API accepts system/assistant roles
245
+ // but the TS SDK type constrains role to 'user'. Remove cast when typescript-sdk is regenerated.
246
+ const threadConfig = {};
247
+ if (userKey) {
248
+ threadConfig.userKey = userKey;
249
+ }
250
+ if (initialMessages?.length) {
251
+ threadConfig.initialMessages = initialMessages;
252
+ }
213
253
  const stream = await client.threads.runs.create({
214
254
  message: messageWithContext,
215
255
  availableComponents,
216
256
  tools: availableTools,
217
- thread: userKey ? { userKey } : undefined,
257
+ thread: Object.keys(threadConfig).length > 0 ? threadConfig : undefined,
258
+ toolChoice,
218
259
  });
219
260
  // threadId will be extracted from first event (RUN_STARTED)
220
261
  return { stream, initialThreadId: undefined };
@@ -268,29 +309,46 @@ function useTamboV1SendMessage(threadId) {
268
309
  const client = (0, tambo_client_provider_1.useTamboClient)();
269
310
  const dispatch = (0, tambo_v1_stream_context_1.useStreamDispatch)();
270
311
  const streamState = (0, tambo_v1_stream_context_1.useStreamState)();
271
- const { userKey, autoGenerateThreadName = true, autoGenerateNameThreshold = 3, } = (0, tambo_v1_provider_1.useTamboV1Config)();
312
+ const { userKey, autoGenerateThreadName = true, autoGenerateNameThreshold = 3, initialMessages, } = (0, tambo_v1_provider_1.useTamboV1Config)();
272
313
  const registry = (0, react_1.useContext)(tambo_registry_provider_1.TamboRegistryContext);
273
314
  const queryClient = (0, tambo_client_provider_1.useTamboQueryClient)();
274
315
  const { getAdditionalContext } = (0, tambo_context_helpers_provider_1.useTamboContextHelpers)();
316
+ const authState = (0, use_tambo_v1_auth_state_1.useTamboV1AuthState)();
275
317
  if (!registry) {
276
318
  throw new Error("useTamboV1SendMessage must be used within TamboRegistryProvider");
277
319
  }
278
320
  // Placeholder ID isn't a valid API thread ID - treat as new thread creation
279
321
  const isNewThread = (0, event_accumulator_1.isPlaceholderThreadId)(threadId);
280
322
  const apiThreadId = isNewThread ? undefined : threadId;
281
- // Get previousRunId from the thread's streaming state (if thread exists and has messages)
323
+ // Get previousRunId from the thread's streaming state (active run) or
324
+ // lastCompletedRunId (persisted after run finishes / loaded from API).
325
+ // The latter is essential after page reload when streaming state is gone.
282
326
  const threadState = apiThreadId
283
327
  ? streamState.threadMap[apiThreadId]
284
328
  : undefined;
285
- const previousRunId = threadState?.streaming.runId;
329
+ const previousRunId = threadState?.streaming.runId ?? threadState?.lastCompletedRunId;
286
330
  return (0, react_query_hooks_1.useTamboMutation)({
287
331
  mutationFn: async (options) => {
288
- const { message, userMessageText, debug = false } = options;
332
+ if (authState.status !== "identified") {
333
+ const messages = {
334
+ unauthenticated: "Cannot send message: no userKey or userToken provided. " +
335
+ "Configure authentication in TamboV1Provider.",
336
+ exchanging: "Cannot send message: token exchange is still in progress. " +
337
+ "Wait for authentication to complete.",
338
+ error: "Cannot send message: token exchange failed. " +
339
+ "Check your userToken configuration.",
340
+ invalid: "Cannot send message: both userKey and userToken were provided. " +
341
+ "You must provide one or the other, not both.",
342
+ };
343
+ throw new Error(messages[authState.status]);
344
+ }
345
+ const { message, userMessageText, debug = false, toolChoice } = options;
289
346
  // Capture pre-mutation state for auto thread name generation
290
347
  const existingThread = streamState.threadMap[apiThreadId ?? ""];
291
348
  const preMutationMessageCount = existingThread?.thread.messages.length ?? 0;
292
349
  const threadAlreadyHasTitle = !!existingThread?.thread.title;
293
350
  const toolTracker = new tool_call_tracker_1.ToolCallTracker();
351
+ const throttledStreamable = (0, tool_executor_1.createThrottledStreamableExecutor)(toolTracker, registry.toolRegistry);
294
352
  // Generate a stable message ID for the user message
295
353
  const userMessageId = userMessageText
296
354
  ? `user_msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`
@@ -311,6 +369,7 @@ function useTamboV1SendMessage(threadId) {
311
369
  additionalContext[helperContext.name] = helperContext.context;
312
370
  }
313
371
  // Create the run stream
372
+ // Include initialMessages only on first send (new thread creation)
314
373
  const { stream, initialThreadId } = await createRunStream({
315
374
  client,
316
375
  threadId: apiThreadId,
@@ -319,6 +378,8 @@ function useTamboV1SendMessage(threadId) {
319
378
  userKey,
320
379
  previousRunId,
321
380
  additionalContext,
381
+ toolChoice,
382
+ initialMessages: isNewThread ? initialMessages : undefined,
322
383
  });
323
384
  let actualThreadId = initialThreadId;
324
385
  let runId;
@@ -348,7 +409,20 @@ function useTamboV1SendMessage(threadId) {
348
409
  throw new Error(`Expected first event to be RUN_STARTED with threadId, got: ${event.type}`);
349
410
  }
350
411
  toolTracker.handleEvent(event);
351
- dispatch({ type: "EVENT", event, threadId: actualThreadId });
412
+ // Parse partial JSON once for TOOL_CALL_ARGS — reused by both dispatch and streamable execution
413
+ const parsedToolArgs = event.type === core_1.EventType.TOOL_CALL_ARGS
414
+ ? parseToolCallArgs(toolTracker, event.toolCallId)
415
+ : undefined;
416
+ dispatch({
417
+ type: "EVENT",
418
+ event,
419
+ threadId: actualThreadId,
420
+ parsedToolArgs,
421
+ });
422
+ // Schedule debounced streamable tool execution with the same pre-parsed args
423
+ if (parsedToolArgs && event.type === core_1.EventType.TOOL_CALL_ARGS) {
424
+ throttledStreamable.schedule(event.toolCallId, parsedToolArgs);
425
+ }
352
426
  // Check for awaiting_input - if found, break to execute tools
353
427
  if (event.type === core_1.EventType.CUSTOM) {
354
428
  const customEvent = (0, event_1.asTamboCustomEvent)(event);
@@ -358,6 +432,8 @@ function useTamboV1SendMessage(threadId) {
358
432
  }
359
433
  }
360
434
  }
435
+ // Flush any pending debounced streamable calls before continuing
436
+ throttledStreamable.flush();
361
437
  // If stream finished without awaiting_input, we're done
362
438
  if (!pendingAwaitingInput) {
363
439
  break;
@@ -376,6 +452,7 @@ function useTamboV1SendMessage(threadId) {
376
452
  runId,
377
453
  userKey,
378
454
  additionalContext,
455
+ toolChoice,
379
456
  });
380
457
  dispatchToolResults(dispatch, actualThreadId, toolResults);
381
458
  currentStream = continuationStream;