@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
@@ -0,0 +1,270 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const react_2 = require("@testing-library/react");
8
+ const zod_1 = require("zod");
9
+ const v1_component_renderer_1 = require("./v1-component-renderer");
10
+ const tambo_registry_provider_1 = require("../../providers/tambo-registry-provider");
11
+ // Simple test component
12
+ const TestComponent = ({ title, count, }) => (react_1.default.createElement("div", { "data-testid": "test-component" },
13
+ react_1.default.createElement("span", { "data-testid": "title" }, title),
14
+ count !== undefined && react_1.default.createElement("span", { "data-testid": "count" }, count)));
15
+ // Component with Zod schema for validation
16
+ const ValidatedComponent = ({ name, age, }) => (react_1.default.createElement("div", { "data-testid": "validated-component" },
17
+ react_1.default.createElement("span", { "data-testid": "name" }, name),
18
+ react_1.default.createElement("span", { "data-testid": "age" }, age)));
19
+ const validatedComponentSchema = zod_1.z.object({
20
+ name: zod_1.z.string(),
21
+ age: zod_1.z.number(),
22
+ });
23
+ // Create a mock registry
24
+ function createMockRegistry(componentList = {}) {
25
+ return {
26
+ componentList,
27
+ toolRegistry: {},
28
+ componentToolAssociations: {},
29
+ mcpServerInfos: [],
30
+ resources: [],
31
+ resourceSource: null,
32
+ registerComponent: jest.fn(),
33
+ registerTool: jest.fn(),
34
+ registerTools: jest.fn(),
35
+ addToolAssociation: jest.fn(),
36
+ registerMcpServer: jest.fn(),
37
+ registerMcpServers: jest.fn(),
38
+ registerResource: jest.fn(),
39
+ registerResources: jest.fn(),
40
+ registerResourceSource: jest.fn(),
41
+ };
42
+ }
43
+ describe("V1ComponentRenderer", () => {
44
+ function withMockedConsoleError(fn) {
45
+ const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
46
+ try {
47
+ return fn(consoleErrorSpy);
48
+ }
49
+ finally {
50
+ consoleErrorSpy.mockRestore();
51
+ }
52
+ }
53
+ const baseContent = {
54
+ type: "component",
55
+ id: "comp_123",
56
+ name: "TestComponent",
57
+ props: { title: "Hello World" },
58
+ streamingState: "done",
59
+ };
60
+ it("renders component from registry with props", () => {
61
+ const registry = createMockRegistry({
62
+ TestComponent: {
63
+ name: "TestComponent",
64
+ description: "A test component",
65
+ component: TestComponent,
66
+ props: { type: "object" },
67
+ contextTools: [],
68
+ },
69
+ });
70
+ (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
71
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: baseContent, threadId: "thread_123", messageId: "msg_456" })));
72
+ expect(react_2.screen.getByTestId("test-component")).toBeInTheDocument();
73
+ expect(react_2.screen.getByTestId("title")).toHaveTextContent("Hello World");
74
+ });
75
+ it("renders fallback when component not found in registry", () => {
76
+ const registry = createMockRegistry({});
77
+ withMockedConsoleError((consoleErrorSpy) => {
78
+ (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
79
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: baseContent, threadId: "thread_123", messageId: "msg_456", fallback: react_1.default.createElement("div", { "data-testid": "fallback" }, "Not found") })));
80
+ expect(react_2.screen.getByTestId("fallback")).toBeInTheDocument();
81
+ expect(react_2.screen.queryByTestId("test-component")).not.toBeInTheDocument();
82
+ expect(consoleErrorSpy).toHaveBeenCalledWith("[V1ComponentRenderer] Failed to render component", expect.objectContaining({
83
+ componentId: baseContent.id,
84
+ componentName: baseContent.name,
85
+ }));
86
+ });
87
+ });
88
+ it("renders nothing (null fallback) when component not found and no fallback provided", () => {
89
+ const registry = createMockRegistry({});
90
+ withMockedConsoleError((consoleErrorSpy) => {
91
+ const { container } = (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
92
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: baseContent, threadId: "thread_123", messageId: "msg_456" })));
93
+ expect(container.firstChild).toBeNull();
94
+ expect(consoleErrorSpy).toHaveBeenCalledWith("[V1ComponentRenderer] Failed to render component", expect.objectContaining({
95
+ componentId: baseContent.id,
96
+ componentName: baseContent.name,
97
+ }));
98
+ });
99
+ });
100
+ it("handles props with undefined values", () => {
101
+ const registry = createMockRegistry({
102
+ TestComponent: {
103
+ name: "TestComponent",
104
+ description: "A test component",
105
+ component: TestComponent,
106
+ props: { type: "object" },
107
+ contextTools: [],
108
+ },
109
+ });
110
+ const content = {
111
+ type: "component",
112
+ id: "comp_123",
113
+ name: "TestComponent",
114
+ props: { title: "Test", count: undefined },
115
+ streamingState: "done",
116
+ };
117
+ (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
118
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: content, threadId: "thread_123", messageId: "msg_456" })));
119
+ expect(react_2.screen.getByTestId("title")).toHaveTextContent("Test");
120
+ expect(react_2.screen.queryByTestId("count")).not.toBeInTheDocument();
121
+ });
122
+ it("handles null props", () => {
123
+ const registry = createMockRegistry({
124
+ TestComponent: {
125
+ name: "TestComponent",
126
+ description: "A test component",
127
+ component: TestComponent,
128
+ props: { type: "object" },
129
+ contextTools: [],
130
+ },
131
+ });
132
+ const content = {
133
+ type: "component",
134
+ id: "comp_123",
135
+ name: "TestComponent",
136
+ props: null,
137
+ streamingState: "done",
138
+ };
139
+ (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
140
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: content, threadId: "thread_123", messageId: "msg_456" })));
141
+ // Component should render with empty props
142
+ expect(react_2.screen.getByTestId("test-component")).toBeInTheDocument();
143
+ });
144
+ it("validates props with StandardSchema and uses validated values", () => {
145
+ const registry = createMockRegistry({
146
+ ValidatedComponent: {
147
+ name: "ValidatedComponent",
148
+ description: "A validated component",
149
+ component: ValidatedComponent,
150
+ // Cast as unknown to satisfy TypeScript while still providing a Zod schema
151
+ props: validatedComponentSchema,
152
+ contextTools: [],
153
+ },
154
+ });
155
+ const content = {
156
+ type: "component",
157
+ id: "comp_123",
158
+ name: "ValidatedComponent",
159
+ props: { name: "Alice", age: 30 },
160
+ streamingState: "done",
161
+ };
162
+ (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
163
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: content, threadId: "thread_123", messageId: "msg_456" })));
164
+ expect(react_2.screen.getByTestId("name")).toHaveTextContent("Alice");
165
+ expect(react_2.screen.getByTestId("age")).toHaveTextContent("30");
166
+ });
167
+ it("logs warning and renders with raw props when schema validation fails", () => {
168
+ const consoleSpy = jest.spyOn(console, "warn").mockImplementation();
169
+ const registry = createMockRegistry({
170
+ ValidatedComponent: {
171
+ name: "ValidatedComponent",
172
+ description: "A validated component",
173
+ component: ValidatedComponent,
174
+ // Cast as unknown to satisfy TypeScript while still providing a Zod schema
175
+ props: validatedComponentSchema,
176
+ contextTools: [],
177
+ },
178
+ });
179
+ const content = {
180
+ type: "component",
181
+ id: "comp_123",
182
+ name: "ValidatedComponent",
183
+ props: { name: "Bob", age: "not a number" }, // Invalid: age should be number
184
+ streamingState: "done",
185
+ };
186
+ (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
187
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: content, threadId: "thread_123", messageId: "msg_456" })));
188
+ // Should still render with raw props
189
+ expect(react_2.screen.getByTestId("name")).toHaveTextContent("Bob");
190
+ expect(react_2.screen.getByTestId("age")).toHaveTextContent("not a number");
191
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Props validation failed"), expect.any(String));
192
+ consoleSpy.mockRestore();
193
+ });
194
+ it("logs warning for async schema validation", () => {
195
+ const consoleSpy = jest.spyOn(console, "warn").mockImplementation();
196
+ // Create a mock async schema
197
+ const asyncSchema = {
198
+ "~standard": {
199
+ version: 1,
200
+ vendor: "test",
201
+ validate: async () => {
202
+ return await Promise.resolve({ value: {} });
203
+ },
204
+ },
205
+ };
206
+ const registry = createMockRegistry({
207
+ TestComponent: {
208
+ name: "TestComponent",
209
+ description: "A test component",
210
+ component: TestComponent,
211
+ props: asyncSchema,
212
+ contextTools: [],
213
+ },
214
+ });
215
+ (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
216
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: baseContent, threadId: "thread_123", messageId: "msg_456" })));
217
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Async schema validation not supported"));
218
+ consoleSpy.mockRestore();
219
+ });
220
+ it("handles partial JSON during streaming", () => {
221
+ const registry = createMockRegistry({
222
+ TestComponent: {
223
+ name: "TestComponent",
224
+ description: "A test component",
225
+ component: TestComponent,
226
+ props: { type: "object" },
227
+ contextTools: [],
228
+ },
229
+ });
230
+ // partial-json library handles incomplete JSON gracefully
231
+ const content = {
232
+ type: "component",
233
+ id: "comp_123",
234
+ name: "TestComponent",
235
+ props: { title: "Partial" },
236
+ streamingState: "streaming",
237
+ };
238
+ (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
239
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: content, threadId: "thread_123", messageId: "msg_456" })));
240
+ expect(react_2.screen.getByTestId("title")).toHaveTextContent("Partial");
241
+ });
242
+ it("provides component context to rendered components via V1ComponentContentProvider", () => {
243
+ // Create a component that uses the context
244
+ const ContextAwareComponent = () => {
245
+ // We can't directly test the context without importing useV1ComponentContent
246
+ // but we can verify the component renders which means the provider works
247
+ return react_1.default.createElement("div", { "data-testid": "context-aware" }, "Rendered");
248
+ };
249
+ const registry = createMockRegistry({
250
+ ContextAwareComponent: {
251
+ name: "ContextAwareComponent",
252
+ description: "A context aware component",
253
+ component: ContextAwareComponent,
254
+ props: { type: "object" },
255
+ contextTools: [],
256
+ },
257
+ });
258
+ const content = {
259
+ type: "component",
260
+ id: "comp_789",
261
+ name: "ContextAwareComponent",
262
+ props: {},
263
+ streamingState: "done",
264
+ };
265
+ (0, react_2.render)(react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: registry },
266
+ react_1.default.createElement(v1_component_renderer_1.V1ComponentRenderer, { content: content, threadId: "thread_abc", messageId: "msg_def" })));
267
+ expect(react_2.screen.getByTestId("context-aware")).toBeInTheDocument();
268
+ });
269
+ });
270
+ //# sourceMappingURL=v1-component-renderer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v1-component-renderer.test.js","sourceRoot":"","sources":["../../../src/v1/components/v1-component-renderer.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\nimport { render, screen } from \"@testing-library/react\";\nimport { z } from \"zod\";\nimport { V1ComponentRenderer } from \"./v1-component-renderer\";\nimport { TamboRegistryContext } from \"../../providers/tambo-registry-provider\";\nimport type { TamboRegistryContext as TamboRegistryContextType } from \"../../providers/tambo-registry-provider\";\nimport type { V1ComponentContent } from \"../types/message\";\n\n// Simple test component\nconst TestComponent: React.FC<{ title: string; count?: number }> = ({\n title,\n count,\n}) => (\n <div data-testid=\"test-component\">\n <span data-testid=\"title\">{title}</span>\n {count !== undefined && <span data-testid=\"count\">{count}</span>}\n </div>\n);\n\n// Component with Zod schema for validation\nconst ValidatedComponent: React.FC<{ name: string; age: number }> = ({\n name,\n age,\n}) => (\n <div data-testid=\"validated-component\">\n <span data-testid=\"name\">{name}</span>\n <span data-testid=\"age\">{age}</span>\n </div>\n);\n\nconst validatedComponentSchema = z.object({\n name: z.string(),\n age: z.number(),\n});\n\n// Create a mock registry\nfunction createMockRegistry(\n componentList: TamboRegistryContextType[\"componentList\"] = {},\n): TamboRegistryContextType {\n return {\n componentList,\n toolRegistry: {},\n componentToolAssociations: {},\n mcpServerInfos: [],\n resources: [],\n resourceSource: null,\n registerComponent: jest.fn(),\n registerTool: jest.fn(),\n registerTools: jest.fn(),\n addToolAssociation: jest.fn(),\n registerMcpServer: jest.fn(),\n registerMcpServers: jest.fn(),\n registerResource: jest.fn(),\n registerResources: jest.fn(),\n registerResourceSource: jest.fn(),\n };\n}\n\ndescribe(\"V1ComponentRenderer\", () => {\n function withMockedConsoleError<T>(\n fn: (consoleErrorSpy: jest.SpyInstance) => T,\n ): T {\n const consoleErrorSpy = jest.spyOn(console, \"error\").mockImplementation();\n try {\n return fn(consoleErrorSpy);\n } finally {\n consoleErrorSpy.mockRestore();\n }\n }\n\n const baseContent: V1ComponentContent = {\n type: \"component\",\n id: \"comp_123\",\n name: \"TestComponent\",\n props: { title: \"Hello World\" },\n streamingState: \"done\",\n };\n\n it(\"renders component from registry with props\", () => {\n const registry = createMockRegistry({\n TestComponent: {\n name: \"TestComponent\",\n description: \"A test component\",\n component: TestComponent,\n props: { type: \"object\" },\n contextTools: [],\n },\n });\n\n render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={baseContent}\n threadId=\"thread_123\"\n messageId=\"msg_456\"\n />\n </TamboRegistryContext.Provider>,\n );\n\n expect(screen.getByTestId(\"test-component\")).toBeInTheDocument();\n expect(screen.getByTestId(\"title\")).toHaveTextContent(\"Hello World\");\n });\n\n it(\"renders fallback when component not found in registry\", () => {\n const registry = createMockRegistry({});\n\n withMockedConsoleError((consoleErrorSpy) => {\n render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={baseContent}\n threadId=\"thread_123\"\n messageId=\"msg_456\"\n fallback={<div data-testid=\"fallback\">Not found</div>}\n />\n </TamboRegistryContext.Provider>,\n );\n\n expect(screen.getByTestId(\"fallback\")).toBeInTheDocument();\n expect(screen.queryByTestId(\"test-component\")).not.toBeInTheDocument();\n\n expect(consoleErrorSpy).toHaveBeenCalledWith(\n \"[V1ComponentRenderer] Failed to render component\",\n expect.objectContaining({\n componentId: baseContent.id,\n componentName: baseContent.name,\n }),\n );\n });\n });\n\n it(\"renders nothing (null fallback) when component not found and no fallback provided\", () => {\n const registry = createMockRegistry({});\n\n withMockedConsoleError((consoleErrorSpy) => {\n const { container } = render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={baseContent}\n threadId=\"thread_123\"\n messageId=\"msg_456\"\n />\n </TamboRegistryContext.Provider>,\n );\n\n expect(container.firstChild).toBeNull();\n\n expect(consoleErrorSpy).toHaveBeenCalledWith(\n \"[V1ComponentRenderer] Failed to render component\",\n expect.objectContaining({\n componentId: baseContent.id,\n componentName: baseContent.name,\n }),\n );\n });\n });\n\n it(\"handles props with undefined values\", () => {\n const registry = createMockRegistry({\n TestComponent: {\n name: \"TestComponent\",\n description: \"A test component\",\n component: TestComponent,\n props: { type: \"object\" },\n contextTools: [],\n },\n });\n\n const content: V1ComponentContent = {\n type: \"component\",\n id: \"comp_123\",\n name: \"TestComponent\",\n props: { title: \"Test\", count: undefined },\n streamingState: \"done\",\n };\n\n render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={content}\n threadId=\"thread_123\"\n messageId=\"msg_456\"\n />\n </TamboRegistryContext.Provider>,\n );\n\n expect(screen.getByTestId(\"title\")).toHaveTextContent(\"Test\");\n expect(screen.queryByTestId(\"count\")).not.toBeInTheDocument();\n });\n\n it(\"handles null props\", () => {\n const registry = createMockRegistry({\n TestComponent: {\n name: \"TestComponent\",\n description: \"A test component\",\n component: TestComponent,\n props: { type: \"object\" },\n contextTools: [],\n },\n });\n\n const content: V1ComponentContent = {\n type: \"component\",\n id: \"comp_123\",\n name: \"TestComponent\",\n props: null,\n streamingState: \"done\",\n };\n\n render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={content}\n threadId=\"thread_123\"\n messageId=\"msg_456\"\n />\n </TamboRegistryContext.Provider>,\n );\n\n // Component should render with empty props\n expect(screen.getByTestId(\"test-component\")).toBeInTheDocument();\n });\n\n it(\"validates props with StandardSchema and uses validated values\", () => {\n const registry = createMockRegistry({\n ValidatedComponent: {\n name: \"ValidatedComponent\",\n description: \"A validated component\",\n component: ValidatedComponent,\n // Cast as unknown to satisfy TypeScript while still providing a Zod schema\n props: validatedComponentSchema as unknown as Record<string, unknown>,\n contextTools: [],\n },\n });\n\n const content: V1ComponentContent = {\n type: \"component\",\n id: \"comp_123\",\n name: \"ValidatedComponent\",\n props: { name: \"Alice\", age: 30 },\n streamingState: \"done\",\n };\n\n render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={content}\n threadId=\"thread_123\"\n messageId=\"msg_456\"\n />\n </TamboRegistryContext.Provider>,\n );\n\n expect(screen.getByTestId(\"name\")).toHaveTextContent(\"Alice\");\n expect(screen.getByTestId(\"age\")).toHaveTextContent(\"30\");\n });\n\n it(\"logs warning and renders with raw props when schema validation fails\", () => {\n const consoleSpy = jest.spyOn(console, \"warn\").mockImplementation();\n\n const registry = createMockRegistry({\n ValidatedComponent: {\n name: \"ValidatedComponent\",\n description: \"A validated component\",\n component: ValidatedComponent,\n // Cast as unknown to satisfy TypeScript while still providing a Zod schema\n props: validatedComponentSchema as unknown as Record<string, unknown>,\n contextTools: [],\n },\n });\n\n const content: V1ComponentContent = {\n type: \"component\",\n id: \"comp_123\",\n name: \"ValidatedComponent\",\n props: { name: \"Bob\", age: \"not a number\" }, // Invalid: age should be number\n streamingState: \"done\",\n };\n\n render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={content}\n threadId=\"thread_123\"\n messageId=\"msg_456\"\n />\n </TamboRegistryContext.Provider>,\n );\n\n // Should still render with raw props\n expect(screen.getByTestId(\"name\")).toHaveTextContent(\"Bob\");\n expect(screen.getByTestId(\"age\")).toHaveTextContent(\"not a number\");\n\n expect(consoleSpy).toHaveBeenCalledWith(\n expect.stringContaining(\"Props validation failed\"),\n expect.any(String),\n );\n\n consoleSpy.mockRestore();\n });\n\n it(\"logs warning for async schema validation\", () => {\n const consoleSpy = jest.spyOn(console, \"warn\").mockImplementation();\n\n // Create a mock async schema\n const asyncSchema = {\n \"~standard\": {\n version: 1,\n vendor: \"test\",\n validate: async () => {\n return await Promise.resolve({ value: {} });\n },\n },\n };\n\n const registry = createMockRegistry({\n TestComponent: {\n name: \"TestComponent\",\n description: \"A test component\",\n component: TestComponent,\n props: asyncSchema,\n contextTools: [],\n },\n });\n\n render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={baseContent}\n threadId=\"thread_123\"\n messageId=\"msg_456\"\n />\n </TamboRegistryContext.Provider>,\n );\n\n expect(consoleSpy).toHaveBeenCalledWith(\n expect.stringContaining(\"Async schema validation not supported\"),\n );\n\n consoleSpy.mockRestore();\n });\n\n it(\"handles partial JSON during streaming\", () => {\n const registry = createMockRegistry({\n TestComponent: {\n name: \"TestComponent\",\n description: \"A test component\",\n component: TestComponent,\n props: { type: \"object\" },\n contextTools: [],\n },\n });\n\n // partial-json library handles incomplete JSON gracefully\n const content: V1ComponentContent = {\n type: \"component\",\n id: \"comp_123\",\n name: \"TestComponent\",\n props: { title: \"Partial\" },\n streamingState: \"streaming\",\n };\n\n render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={content}\n threadId=\"thread_123\"\n messageId=\"msg_456\"\n />\n </TamboRegistryContext.Provider>,\n );\n\n expect(screen.getByTestId(\"title\")).toHaveTextContent(\"Partial\");\n });\n\n it(\"provides component context to rendered components via V1ComponentContentProvider\", () => {\n // Create a component that uses the context\n const ContextAwareComponent: React.FC = () => {\n // We can't directly test the context without importing useV1ComponentContent\n // but we can verify the component renders which means the provider works\n return <div data-testid=\"context-aware\">Rendered</div>;\n };\n\n const registry = createMockRegistry({\n ContextAwareComponent: {\n name: \"ContextAwareComponent\",\n description: \"A context aware component\",\n component: ContextAwareComponent,\n props: { type: \"object\" },\n contextTools: [],\n },\n });\n\n const content: V1ComponentContent = {\n type: \"component\",\n id: \"comp_789\",\n name: \"ContextAwareComponent\",\n props: {},\n streamingState: \"done\",\n };\n\n render(\n <TamboRegistryContext.Provider value={registry}>\n <V1ComponentRenderer\n content={content}\n threadId=\"thread_abc\"\n messageId=\"msg_def\"\n />\n </TamboRegistryContext.Provider>,\n );\n\n expect(screen.getByTestId(\"context-aware\")).toBeInTheDocument();\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-tambo-v1-component-state.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,MAAM,MAAM,8BAA8B,CAAC,CAAC,IAAI;IAC9C,YAAY,EAAE,CAAC;IACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI;IAClD,IAAI,EAAE;QACJ,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,MAAM,IAAI,CAAC;KACnB;CACF,CAAC;AAgCF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,GAAG,SAAS,EACpD,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,CAAC,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,8BAA8B,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AACjD,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,8BAA8B,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"use-tambo-v1-component-state.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,MAAM,MAAM,8BAA8B,CAAC,CAAC,IAAI;IAC9C,YAAY,EAAE,CAAC;IACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI;IAClD,IAAI,EAAE;QACJ,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,MAAM,IAAI,CAAC;KACnB;CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,GAAG,SAAS,EACpD,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,CAAC,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,8BAA8B,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AACjD,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,8BAA8B,CAAC,CAAC,CAAC,CAAC"}
@@ -17,36 +17,13 @@ const fast_equals_1 = require("fast-equals");
17
17
  const tambo_client_provider_1 = require("../../providers/tambo-client-provider");
18
18
  const component_renderer_1 = require("../utils/component-renderer");
19
19
  const tambo_v1_stream_context_1 = require("../providers/tambo-v1-stream-context");
20
- /**
21
- * Find a component content block by ID in a specific thread.
22
- * Only searches the specified thread to prevent cross-thread data access
23
- * and improve performance (O(m*k) instead of O(n*m*k)).
24
- * @param streamState - The current stream state
25
- * @param threadId - The thread ID to search in
26
- * @param componentId - The component ID to find
27
- * @returns The component content block, or undefined if not found
28
- */
29
- function findComponentContent(streamState, threadId, componentId) {
30
- // Only search the specified thread (not all threads)
31
- const threadState = streamState.threadMap[threadId];
32
- if (!threadState) {
33
- return undefined;
34
- }
35
- for (const message of threadState.thread.messages) {
36
- for (const content of message.content) {
37
- if (content.type === "component" && content.id === componentId) {
38
- return content;
39
- }
40
- }
41
- }
42
- return undefined;
43
- }
20
+ const thread_utils_1 = require("../utils/thread-utils");
44
21
  function useTamboV1ComponentState(keyName, initialValue, debounceTime = 500) {
45
22
  const client = (0, tambo_client_provider_1.useTamboClient)();
46
23
  const { componentId, threadId } = (0, component_renderer_1.useV1ComponentContent)();
47
24
  const streamState = (0, tambo_v1_stream_context_1.useStreamState)();
48
25
  // Find the component content to get server state (only search current thread)
49
- const componentContent = findComponentContent(streamState, threadId, componentId);
26
+ const componentContent = (0, thread_utils_1.findComponentContent)(streamState, threadId, componentId);
50
27
  const serverState = componentContent?.state;
51
28
  const serverValue = serverState?.[keyName];
52
29
  // Local state - initialized from server state or initial value
@@ -1 +1 @@
1
- {"version":3,"file":"use-tambo-v1-component-state.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * useTamboV1ComponentState - Component State Hook for v1 API\n *\n * Provides bidirectional state synchronization between React components\n * and the Tambo backend. State changes are debounced before syncing to\n * the server, and server state updates are reflected in the component.\n *\n * Must be used within a component rendered via the component renderer.\n */\n\nimport { useCallback, useEffect, useState, useRef } from \"react\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { deepEqual } from \"fast-equals\";\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useV1ComponentContent } from \"../utils/component-renderer\";\nimport { useStreamState } from \"../providers/tambo-v1-stream-context\";\nimport type { V1ComponentContent } from \"../types/message\";\n\n/**\n * Return type for useTamboV1ComponentState hook.\n * Similar to useState but with additional metadata.\n */\nexport type UseTamboV1ComponentStateReturn<S> = [\n currentState: S,\n setState: (newState: S | ((prev: S) => S)) => void,\n meta: {\n isPending: boolean;\n error: Error | null;\n flush: () => void;\n },\n];\n\n/**\n * Find a component content block by ID in a specific thread.\n * Only searches the specified thread to prevent cross-thread data access\n * and improve performance (O(m*k) instead of O(n*m*k)).\n * @param streamState - The current stream state\n * @param threadId - The thread ID to search in\n * @param componentId - The component ID to find\n * @returns The component content block, or undefined if not found\n */\nfunction findComponentContent(\n streamState: ReturnType<typeof useStreamState>,\n threadId: string,\n componentId: string,\n): V1ComponentContent | undefined {\n // Only search the specified thread (not all threads)\n const threadState = streamState.threadMap[threadId];\n if (!threadState) {\n return undefined;\n }\n\n for (const message of threadState.thread.messages) {\n for (const content of message.content) {\n if (content.type === \"component\" && content.id === componentId) {\n return content;\n }\n }\n }\n return undefined;\n}\n\n/**\n * Hook for managing component state with bidirectional server sync.\n *\n * This hook acts like useState but automatically syncs state changes\n * to the Tambo backend. Server-side state updates are also reflected\n * in the component.\n *\n * Must be used within a component rendered via the component renderer.\n * @param keyName - The unique key to identify this state value within the component's state\n * @param initialValue - Initial value for the state (used if no server state exists)\n * @param debounceTime - Debounce time in milliseconds (default: 500ms)\n * @returns Tuple of [currentState, setState, meta]\n * @example\n * ```tsx\n * function Counter() {\n * const [count, setCount, { isPending }] = useTamboV1ComponentState('count', 0);\n *\n * return (\n * <div>\n * <span>{count}</span>\n * <button onClick={() => setCount(c => c + 1)} disabled={isPending}>\n * Increment\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useTamboV1ComponentState<S = undefined>(\n keyName: string,\n initialValue?: S,\n debounceTime?: number,\n): UseTamboV1ComponentStateReturn<S | undefined>;\nexport function useTamboV1ComponentState<S>(\n keyName: string,\n initialValue: S,\n debounceTime?: number,\n): UseTamboV1ComponentStateReturn<S>;\nexport function useTamboV1ComponentState<S>(\n keyName: string,\n initialValue?: S,\n debounceTime = 500,\n): UseTamboV1ComponentStateReturn<S> {\n const client = useTamboClient();\n const { componentId, threadId } = useV1ComponentContent();\n const streamState = useStreamState();\n\n // Find the component content to get server state (only search current thread)\n const componentContent = findComponentContent(\n streamState,\n threadId,\n componentId,\n );\n const serverState = componentContent?.state as\n | Record<string, unknown>\n | undefined;\n const serverValue = serverState?.[keyName] as S | undefined;\n\n // Local state - initialized from server state or initial value\n const [localState, setLocalState] = useState<S>(\n () => serverValue ?? (initialValue as S),\n );\n\n // Track pending state and errors\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track the last value we sent to avoid overwriting with stale server state\n const lastSentValueRef = useRef<S | undefined>(undefined);\n\n // Track whether there's a pending local change that hasn't synced yet\n const hasPendingLocalChangeRef = useRef(false);\n\n // Track in-flight sync requests to avoid stale completions clearing pending state\n const syncSeqRef = useRef(0);\n\n // Debounced function to sync state to server\n const syncToServer = useDebouncedCallback(async (newState: S) => {\n const seq = ++syncSeqRef.current;\n setIsPending(true);\n setError(null);\n lastSentValueRef.current = newState;\n\n try {\n await client.threads.state.updateState(componentId, {\n threadId,\n state: { [keyName]: newState },\n });\n // Clear pending flag after successful sync\n hasPendingLocalChangeRef.current = false;\n } catch (err) {\n // Clear pending flag on error to allow server reconciliation\n hasPendingLocalChangeRef.current = false;\n const syncError = err instanceof Error ? err : new Error(String(err));\n setError(syncError);\n console.error(\n `[useTamboV1ComponentState] Failed to sync state for ${componentId}:`,\n syncError,\n );\n } finally {\n // Only clear isPending if this is the most recent request\n if (seq === syncSeqRef.current) {\n setIsPending(false);\n }\n }\n }, debounceTime);\n\n // setState function that updates local state and triggers debounced sync\n const setState = useCallback(\n (newState: S | ((prev: S) => S)) => {\n setLocalState((prev) => {\n const nextState =\n typeof newState === \"function\"\n ? (newState as (prev: S) => S)(prev)\n : newState;\n\n // Mark that we have a pending local change\n hasPendingLocalChangeRef.current = true;\n\n // Trigger debounced sync to server\n void syncToServer(nextState);\n\n return nextState;\n });\n },\n [syncToServer],\n );\n\n // Sync from server state when it changes (e.g., from streaming events)\n useEffect(() => {\n if (serverValue === undefined) {\n return;\n }\n\n // Don't overwrite local changes that haven't synced yet\n if (hasPendingLocalChangeRef.current) {\n return;\n }\n\n // Only sync if the server value is different from what we last sent\n // This prevents overwriting local state with stale server values\n if (\n lastSentValueRef.current !== undefined &&\n deepEqual(serverValue, lastSentValueRef.current)\n ) {\n return;\n }\n\n // Use functional update to avoid localState in deps\n setLocalState((prev) =>\n deepEqual(serverValue, prev) ? prev : serverValue,\n );\n }, [serverValue]);\n\n // Flush pending updates on unmount\n useEffect(() => {\n return () => {\n void syncToServer.flush();\n };\n }, [syncToServer]);\n\n // Flush function for immediate sync\n const flush = useCallback(() => {\n void syncToServer.flush();\n }, [syncToServer]);\n\n return [localState, setState, { isPending, error, flush }];\n}\n"]}
1
+ {"version":3,"file":"use-tambo-v1-component-state.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * useTamboV1ComponentState - Component State Hook for v1 API\n *\n * Provides bidirectional state synchronization between React components\n * and the Tambo backend. State changes are debounced before syncing to\n * the server, and server state updates are reflected in the component.\n *\n * Must be used within a component rendered via the component renderer.\n */\n\nimport { useCallback, useEffect, useState, useRef } from \"react\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { deepEqual } from \"fast-equals\";\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useV1ComponentContent } from \"../utils/component-renderer\";\nimport { useStreamState } from \"../providers/tambo-v1-stream-context\";\nimport { findComponentContent } from \"../utils/thread-utils\";\n\n/**\n * Return type for useTamboV1ComponentState hook.\n * Similar to useState but with additional metadata.\n */\nexport type UseTamboV1ComponentStateReturn<S> = [\n currentState: S,\n setState: (newState: S | ((prev: S) => S)) => void,\n meta: {\n isPending: boolean;\n error: Error | null;\n flush: () => void;\n },\n];\n\n/**\n * Hook for managing component state with bidirectional server sync.\n *\n * This hook acts like useState but automatically syncs state changes\n * to the Tambo backend. Server-side state updates are also reflected\n * in the component.\n *\n * Must be used within a component rendered via the component renderer.\n * @param keyName - The unique key to identify this state value within the component's state\n * @param initialValue - Initial value for the state (used if no server state exists)\n * @param debounceTime - Debounce time in milliseconds (default: 500ms)\n * @returns Tuple of [currentState, setState, meta]\n * @example\n * ```tsx\n * function Counter() {\n * const [count, setCount, { isPending }] = useTamboV1ComponentState('count', 0);\n *\n * return (\n * <div>\n * <span>{count}</span>\n * <button onClick={() => setCount(c => c + 1)} disabled={isPending}>\n * Increment\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useTamboV1ComponentState<S = undefined>(\n keyName: string,\n initialValue?: S,\n debounceTime?: number,\n): UseTamboV1ComponentStateReturn<S | undefined>;\nexport function useTamboV1ComponentState<S>(\n keyName: string,\n initialValue: S,\n debounceTime?: number,\n): UseTamboV1ComponentStateReturn<S>;\nexport function useTamboV1ComponentState<S>(\n keyName: string,\n initialValue?: S,\n debounceTime = 500,\n): UseTamboV1ComponentStateReturn<S> {\n const client = useTamboClient();\n const { componentId, threadId } = useV1ComponentContent();\n const streamState = useStreamState();\n\n // Find the component content to get server state (only search current thread)\n const componentContent = findComponentContent(\n streamState,\n threadId,\n componentId,\n );\n const serverState = componentContent?.state as\n | Record<string, unknown>\n | undefined;\n const serverValue = serverState?.[keyName] as S | undefined;\n\n // Local state - initialized from server state or initial value\n const [localState, setLocalState] = useState<S>(\n () => serverValue ?? (initialValue as S),\n );\n\n // Track pending state and errors\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track the last value we sent to avoid overwriting with stale server state\n const lastSentValueRef = useRef<S | undefined>(undefined);\n\n // Track whether there's a pending local change that hasn't synced yet\n const hasPendingLocalChangeRef = useRef(false);\n\n // Track in-flight sync requests to avoid stale completions clearing pending state\n const syncSeqRef = useRef(0);\n\n // Debounced function to sync state to server\n const syncToServer = useDebouncedCallback(async (newState: S) => {\n const seq = ++syncSeqRef.current;\n setIsPending(true);\n setError(null);\n lastSentValueRef.current = newState;\n\n try {\n await client.threads.state.updateState(componentId, {\n threadId,\n state: { [keyName]: newState },\n });\n // Clear pending flag after successful sync\n hasPendingLocalChangeRef.current = false;\n } catch (err) {\n // Clear pending flag on error to allow server reconciliation\n hasPendingLocalChangeRef.current = false;\n const syncError = err instanceof Error ? err : new Error(String(err));\n setError(syncError);\n console.error(\n `[useTamboV1ComponentState] Failed to sync state for ${componentId}:`,\n syncError,\n );\n } finally {\n // Only clear isPending if this is the most recent request\n if (seq === syncSeqRef.current) {\n setIsPending(false);\n }\n }\n }, debounceTime);\n\n // setState function that updates local state and triggers debounced sync\n const setState = useCallback(\n (newState: S | ((prev: S) => S)) => {\n setLocalState((prev) => {\n const nextState =\n typeof newState === \"function\"\n ? (newState as (prev: S) => S)(prev)\n : newState;\n\n // Mark that we have a pending local change\n hasPendingLocalChangeRef.current = true;\n\n // Trigger debounced sync to server\n void syncToServer(nextState);\n\n return nextState;\n });\n },\n [syncToServer],\n );\n\n // Sync from server state when it changes (e.g., from streaming events)\n useEffect(() => {\n if (serverValue === undefined) {\n return;\n }\n\n // Don't overwrite local changes that haven't synced yet\n if (hasPendingLocalChangeRef.current) {\n return;\n }\n\n // Only sync if the server value is different from what we last sent\n // This prevents overwriting local state with stale server values\n if (\n lastSentValueRef.current !== undefined &&\n deepEqual(serverValue, lastSentValueRef.current)\n ) {\n return;\n }\n\n // Use functional update to avoid localState in deps\n setLocalState((prev) =>\n deepEqual(serverValue, prev) ? prev : serverValue,\n );\n }, [serverValue]);\n\n // Flush pending updates on unmount\n useEffect(() => {\n return () => {\n void syncToServer.flush();\n };\n }, [syncToServer]);\n\n // Flush function for immediate sync\n const flush = useCallback(() => {\n void syncToServer.flush();\n }, [syncToServer]);\n\n return [localState, setState, { isPending, error, flush }];\n}\n"]}
@@ -60,6 +60,7 @@ describe("useTamboV1ComponentState", () => {
60
60
  status: "idle",
61
61
  createdAt: new Date().toISOString(),
62
62
  updatedAt: new Date().toISOString(),
63
+ lastRunCancelled: false,
63
64
  },
64
65
  streaming: { status: "idle" },
65
66
  accumulatingToolArgs: new Map(),
@@ -247,7 +248,7 @@ describe("useTamboV1ComponentState", () => {
247
248
  // Empty stream state (no matching component)
248
249
  jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue({
249
250
  threadMap: {},
250
- currentThreadId: null,
251
+ currentThreadId: "placeholder",
251
252
  });
252
253
  const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboV1ComponentState)("testKey", "default"));
253
254
  expect(result.current[0]).toBe("default");
@@ -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 },\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: null,\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\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"]}
@@ -4,13 +4,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const core_1 = require("@ag-ui/core");
7
+ const react_query_1 = require("@tanstack/react-query");
7
8
  const react_1 = require("@testing-library/react");
8
9
  const react_2 = __importDefault(require("react"));
9
10
  const tambo_v1_stream_context_1 = require("../providers/tambo-v1-stream-context");
10
11
  const use_tambo_v1_messages_1 = require("./use-tambo-v1-messages");
12
+ // Mock useTamboClient and useTamboQueryClient to avoid TamboClientProvider dependency
13
+ jest.mock("../../providers/tambo-client-provider", () => ({
14
+ useTamboClient: jest.fn(() => ({
15
+ threads: {
16
+ messages: {
17
+ list: jest.fn().mockResolvedValue({ messages: [], hasMore: false }),
18
+ },
19
+ },
20
+ })),
21
+ useTamboQueryClient: jest.fn(),
22
+ }));
23
+ const tambo_client_provider_1 = require("../../providers/tambo-client-provider");
11
24
  describe("useTamboV1Messages", () => {
25
+ let queryClient;
26
+ beforeEach(() => {
27
+ queryClient = new react_query_1.QueryClient({
28
+ defaultOptions: {
29
+ queries: { retry: false },
30
+ },
31
+ });
32
+ // Configure mock to return the test's queryClient
33
+ jest.mocked(tambo_client_provider_1.useTamboQueryClient).mockReturnValue(queryClient);
34
+ });
12
35
  function TestWrapper({ children }) {
13
- return react_2.default.createElement(tambo_v1_stream_context_1.TamboV1StreamProvider, null, children);
36
+ return (react_2.default.createElement(react_query_1.QueryClientProvider, { client: queryClient },
37
+ react_2.default.createElement(tambo_v1_stream_context_1.TamboV1StreamProvider, null, children)));
14
38
  }
15
39
  it("returns empty messages when thread has no messages", () => {
16
40
  const { result } = (0, react_1.renderHook)(() => ({