@tambo-ai/react 0.69.1 → 0.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/README.md +7 -7
  2. package/dist/hooks/use-tambo-threads.test.js.map +1 -1
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/mcp/index.d.ts +4 -5
  7. package/dist/mcp/index.d.ts.map +1 -1
  8. package/dist/mcp/index.js +4 -5
  9. package/dist/mcp/index.js.map +1 -1
  10. package/dist/model/component-metadata.d.ts +88 -241
  11. package/dist/model/component-metadata.d.ts.map +1 -1
  12. package/dist/model/component-metadata.js.map +1 -1
  13. package/dist/model/mcp-server-info.d.ts +3 -3
  14. package/dist/model/mcp-server-info.js.map +1 -1
  15. package/dist/providers/hooks/use-tambo-session-token.test.js.map +1 -1
  16. package/dist/providers/tambo-component-provider.d.ts +2 -2
  17. package/dist/providers/tambo-component-provider.d.ts.map +1 -1
  18. package/dist/providers/tambo-component-provider.js.map +1 -1
  19. package/dist/providers/tambo-interactable-provider.d.ts +1 -1
  20. package/dist/providers/tambo-registry-provider.d.ts +4 -4
  21. package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
  22. package/dist/providers/tambo-registry-provider.js +11 -8
  23. package/dist/providers/tambo-registry-provider.js.map +1 -1
  24. package/dist/providers/tambo-registry-provider.test.js +31 -0
  25. package/dist/providers/tambo-registry-provider.test.js.map +1 -1
  26. package/dist/providers/tambo-registry-schema-compat.test.js +42 -52
  27. package/dist/providers/tambo-registry-schema-compat.test.js.map +1 -1
  28. package/dist/providers/tambo-stubs.d.ts +2 -2
  29. package/dist/providers/tambo-stubs.d.ts.map +1 -1
  30. package/dist/providers/tambo-stubs.js.map +1 -1
  31. package/dist/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
  32. package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
  33. package/dist/providers/tambo-thread-provider.js +107 -141
  34. package/dist/providers/tambo-thread-provider.js.map +1 -1
  35. package/dist/providers/tambo-thread-provider.test.js +274 -445
  36. package/dist/providers/tambo-thread-provider.test.js.map +1 -1
  37. package/dist/schema/index.d.ts +1 -2
  38. package/dist/schema/index.d.ts.map +1 -1
  39. package/dist/schema/index.js +1 -5
  40. package/dist/schema/index.js.map +1 -1
  41. package/dist/schema/schema.d.ts +7 -24
  42. package/dist/schema/schema.d.ts.map +1 -1
  43. package/dist/schema/schema.js +34 -105
  44. package/dist/schema/schema.js.map +1 -1
  45. package/dist/schema/schema.test.js +26 -124
  46. package/dist/schema/schema.test.js.map +1 -1
  47. package/dist/testing/tools.d.ts +2 -12
  48. package/dist/testing/tools.d.ts.map +1 -1
  49. package/dist/testing/tools.js +1 -20
  50. package/dist/testing/tools.js.map +1 -1
  51. package/dist/testing/types.d.ts +2 -2
  52. package/dist/testing/types.d.ts.map +1 -1
  53. package/dist/testing/types.js.map +1 -1
  54. package/dist/util/registry-validators.d.ts +2 -2
  55. package/dist/util/registry-validators.d.ts.map +1 -1
  56. package/dist/util/registry-validators.js +37 -17
  57. package/dist/util/registry-validators.js.map +1 -1
  58. package/dist/util/registry-validators.test.js +64 -25
  59. package/dist/util/registry-validators.test.js.map +1 -1
  60. package/dist/util/registry.d.ts +4 -10
  61. package/dist/util/registry.d.ts.map +1 -1
  62. package/dist/util/registry.js +6 -22
  63. package/dist/util/registry.js.map +1 -1
  64. package/dist/util/registry.test.js +1 -47
  65. package/dist/util/registry.test.js.map +1 -1
  66. package/dist/util/tool-caller.d.ts +2 -2
  67. package/dist/util/tool-caller.d.ts.map +1 -1
  68. package/dist/util/tool-caller.js +5 -12
  69. package/dist/util/tool-caller.js.map +1 -1
  70. package/dist/v1/hooks/use-tambo-v1-messages.d.ts +58 -0
  71. package/dist/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -0
  72. package/dist/v1/hooks/use-tambo-v1-messages.js +54 -0
  73. package/dist/v1/hooks/use-tambo-v1-messages.js.map +1 -0
  74. package/dist/v1/hooks/use-tambo-v1-messages.test.d.ts +2 -0
  75. package/dist/v1/hooks/use-tambo-v1-messages.test.d.ts.map +1 -0
  76. package/dist/v1/hooks/use-tambo-v1-messages.test.js +137 -0
  77. package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -0
  78. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +96 -0
  79. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -0
  80. package/dist/v1/hooks/use-tambo-v1-send-message.js +227 -0
  81. package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -0
  82. package/dist/v1/hooks/use-tambo-v1-send-message.test.d.ts +2 -0
  83. package/dist/v1/hooks/use-tambo-v1-send-message.test.d.ts.map +1 -0
  84. package/dist/v1/hooks/use-tambo-v1-send-message.test.js +827 -0
  85. package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -0
  86. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +61 -0
  87. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -0
  88. package/dist/v1/hooks/use-tambo-v1-thread-list.js +56 -0
  89. package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -0
  90. package/dist/v1/hooks/use-tambo-v1-thread-list.test.d.ts +2 -0
  91. package/dist/v1/hooks/use-tambo-v1-thread-list.test.d.ts.map +1 -0
  92. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +98 -0
  93. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -0
  94. package/dist/v1/hooks/use-tambo-v1-thread.d.ts +37 -0
  95. package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -0
  96. package/dist/v1/hooks/use-tambo-v1-thread.js +49 -0
  97. package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -0
  98. package/dist/v1/hooks/use-tambo-v1-thread.test.d.ts +2 -0
  99. package/dist/v1/hooks/use-tambo-v1-thread.test.d.ts.map +1 -0
  100. package/dist/v1/hooks/use-tambo-v1-thread.test.js +83 -0
  101. package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -0
  102. package/dist/v1/hooks/use-tambo-v1.d.ts +107 -0
  103. package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -0
  104. package/dist/v1/hooks/use-tambo-v1.js +87 -0
  105. package/dist/v1/hooks/use-tambo-v1.js.map +1 -0
  106. package/dist/v1/hooks/use-tambo-v1.test.d.ts +2 -0
  107. package/dist/v1/hooks/use-tambo-v1.test.d.ts.map +1 -0
  108. package/dist/v1/hooks/use-tambo-v1.test.js +150 -0
  109. package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -0
  110. package/dist/v1/index.d.ts +73 -0
  111. package/dist/v1/index.d.ts.map +1 -0
  112. package/dist/v1/index.js +106 -0
  113. package/dist/v1/index.js.map +1 -0
  114. package/dist/v1/providers/tambo-v1-provider.d.ts +91 -0
  115. package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -0
  116. package/dist/v1/providers/tambo-v1-provider.js +110 -0
  117. package/dist/v1/providers/tambo-v1-provider.js.map +1 -0
  118. package/dist/v1/providers/tambo-v1-provider.test.d.ts +2 -0
  119. package/dist/v1/providers/tambo-v1-provider.test.d.ts.map +1 -0
  120. package/dist/v1/providers/tambo-v1-provider.test.js +123 -0
  121. package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -0
  122. package/dist/v1/providers/tambo-v1-stream-context.d.ts +136 -0
  123. package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -0
  124. package/dist/v1/providers/tambo-v1-stream-context.js +230 -0
  125. package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -0
  126. package/dist/v1/providers/tambo-v1-stream-context.test.d.ts +2 -0
  127. package/dist/v1/providers/tambo-v1-stream-context.test.d.ts.map +1 -0
  128. package/dist/v1/providers/tambo-v1-stream-context.test.js +85 -0
  129. package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -0
  130. package/dist/v1/types/component.d.ts +50 -0
  131. package/dist/v1/types/component.d.ts.map +1 -0
  132. package/dist/v1/types/component.js +14 -0
  133. package/dist/v1/types/component.js.map +1 -0
  134. package/dist/v1/types/event.d.ts +72 -0
  135. package/dist/v1/types/event.d.ts.map +1 -0
  136. package/dist/v1/types/event.js +54 -0
  137. package/dist/v1/types/event.js.map +1 -0
  138. package/dist/v1/types/event.test.d.ts +2 -0
  139. package/dist/v1/types/event.test.d.ts.map +1 -0
  140. package/dist/v1/types/event.test.js +70 -0
  141. package/dist/v1/types/event.test.js.map +1 -0
  142. package/dist/v1/types/message.d.ts +35 -0
  143. package/dist/v1/types/message.d.ts.map +1 -0
  144. package/dist/v1/types/message.js +10 -0
  145. package/dist/v1/types/message.js.map +1 -0
  146. package/dist/v1/types/thread.d.ts +52 -0
  147. package/dist/v1/types/thread.d.ts.map +1 -0
  148. package/dist/v1/types/thread.js +9 -0
  149. package/dist/v1/types/thread.js.map +1 -0
  150. package/dist/v1/utils/event-accumulator.d.ts +100 -0
  151. package/dist/v1/utils/event-accumulator.d.ts.map +1 -0
  152. package/dist/v1/utils/event-accumulator.js +715 -0
  153. package/dist/v1/utils/event-accumulator.js.map +1 -0
  154. package/dist/v1/utils/event-accumulator.test.d.ts +2 -0
  155. package/dist/v1/utils/event-accumulator.test.d.ts.map +1 -0
  156. package/dist/v1/utils/event-accumulator.test.js +1010 -0
  157. package/dist/v1/utils/event-accumulator.test.js.map +1 -0
  158. package/dist/v1/utils/json-patch.d.ts +18 -0
  159. package/dist/v1/utils/json-patch.d.ts.map +1 -0
  160. package/dist/v1/utils/json-patch.js +35 -0
  161. package/dist/v1/utils/json-patch.js.map +1 -0
  162. package/dist/v1/utils/json-patch.test.d.ts +2 -0
  163. package/dist/v1/utils/json-patch.test.d.ts.map +1 -0
  164. package/dist/v1/utils/json-patch.test.js +28 -0
  165. package/dist/v1/utils/json-patch.test.js.map +1 -0
  166. package/dist/v1/utils/registry-conversion.d.ts +53 -0
  167. package/dist/v1/utils/registry-conversion.d.ts.map +1 -0
  168. package/dist/v1/utils/registry-conversion.js +114 -0
  169. package/dist/v1/utils/registry-conversion.js.map +1 -0
  170. package/dist/v1/utils/registry-conversion.test.d.ts +2 -0
  171. package/dist/v1/utils/registry-conversion.test.d.ts.map +1 -0
  172. package/dist/v1/utils/registry-conversion.test.js +179 -0
  173. package/dist/v1/utils/registry-conversion.test.js.map +1 -0
  174. package/dist/v1/utils/stream-handler.d.ts +45 -0
  175. package/dist/v1/utils/stream-handler.d.ts.map +1 -0
  176. package/dist/v1/utils/stream-handler.js +47 -0
  177. package/dist/v1/utils/stream-handler.js.map +1 -0
  178. package/dist/v1/utils/stream-handler.test.d.ts +2 -0
  179. package/dist/v1/utils/stream-handler.test.d.ts.map +1 -0
  180. package/dist/v1/utils/stream-handler.test.js +74 -0
  181. package/dist/v1/utils/stream-handler.test.js.map +1 -0
  182. package/dist/v1/utils/tool-call-tracker.d.ts +41 -0
  183. package/dist/v1/utils/tool-call-tracker.d.ts.map +1 -0
  184. package/dist/v1/utils/tool-call-tracker.js +90 -0
  185. package/dist/v1/utils/tool-call-tracker.js.map +1 -0
  186. package/dist/v1/utils/tool-executor.d.ts +33 -0
  187. package/dist/v1/utils/tool-executor.d.ts.map +1 -0
  188. package/dist/v1/utils/tool-executor.js +103 -0
  189. package/dist/v1/utils/tool-executor.js.map +1 -0
  190. package/dist/v1/utils/tool-executor.test.d.ts +2 -0
  191. package/dist/v1/utils/tool-executor.test.d.ts.map +1 -0
  192. package/dist/v1/utils/tool-executor.test.js +222 -0
  193. package/dist/v1/utils/tool-executor.test.js.map +1 -0
  194. package/esm/hooks/use-tambo-threads.test.js.map +1 -1
  195. package/esm/index.d.ts +1 -1
  196. package/esm/index.d.ts.map +1 -1
  197. package/esm/index.js.map +1 -1
  198. package/esm/mcp/index.d.ts +4 -5
  199. package/esm/mcp/index.d.ts.map +1 -1
  200. package/esm/mcp/index.js +4 -5
  201. package/esm/mcp/index.js.map +1 -1
  202. package/esm/model/component-metadata.d.ts +88 -241
  203. package/esm/model/component-metadata.d.ts.map +1 -1
  204. package/esm/model/component-metadata.js.map +1 -1
  205. package/esm/model/mcp-server-info.d.ts +3 -3
  206. package/esm/model/mcp-server-info.js.map +1 -1
  207. package/esm/providers/hooks/use-tambo-session-token.test.js.map +1 -1
  208. package/esm/providers/tambo-component-provider.d.ts +2 -2
  209. package/esm/providers/tambo-component-provider.d.ts.map +1 -1
  210. package/esm/providers/tambo-component-provider.js.map +1 -1
  211. package/esm/providers/tambo-interactable-provider.d.ts +1 -1
  212. package/esm/providers/tambo-registry-provider.d.ts +4 -4
  213. package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
  214. package/esm/providers/tambo-registry-provider.js +11 -8
  215. package/esm/providers/tambo-registry-provider.js.map +1 -1
  216. package/esm/providers/tambo-registry-provider.test.js +31 -0
  217. package/esm/providers/tambo-registry-provider.test.js.map +1 -1
  218. package/esm/providers/tambo-registry-schema-compat.test.js +42 -52
  219. package/esm/providers/tambo-registry-schema-compat.test.js.map +1 -1
  220. package/esm/providers/tambo-stubs.d.ts +2 -2
  221. package/esm/providers/tambo-stubs.d.ts.map +1 -1
  222. package/esm/providers/tambo-stubs.js.map +1 -1
  223. package/esm/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
  224. package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
  225. package/esm/providers/tambo-thread-provider.js +107 -141
  226. package/esm/providers/tambo-thread-provider.js.map +1 -1
  227. package/esm/providers/tambo-thread-provider.test.js +241 -445
  228. package/esm/providers/tambo-thread-provider.test.js.map +1 -1
  229. package/esm/schema/index.d.ts +1 -2
  230. package/esm/schema/index.d.ts.map +1 -1
  231. package/esm/schema/index.js +1 -2
  232. package/esm/schema/index.js.map +1 -1
  233. package/esm/schema/schema.d.ts +7 -24
  234. package/esm/schema/schema.d.ts.map +1 -1
  235. package/esm/schema/schema.js +34 -103
  236. package/esm/schema/schema.js.map +1 -1
  237. package/esm/schema/schema.test.js +27 -125
  238. package/esm/schema/schema.test.js.map +1 -1
  239. package/esm/testing/tools.d.ts +2 -12
  240. package/esm/testing/tools.d.ts.map +1 -1
  241. package/esm/testing/tools.js +2 -20
  242. package/esm/testing/tools.js.map +1 -1
  243. package/esm/testing/types.d.ts +2 -2
  244. package/esm/testing/types.d.ts.map +1 -1
  245. package/esm/testing/types.js.map +1 -1
  246. package/esm/util/registry-validators.d.ts +2 -2
  247. package/esm/util/registry-validators.d.ts.map +1 -1
  248. package/esm/util/registry-validators.js +38 -18
  249. package/esm/util/registry-validators.js.map +1 -1
  250. package/esm/util/registry-validators.test.js +64 -25
  251. package/esm/util/registry-validators.test.js.map +1 -1
  252. package/esm/util/registry.d.ts +4 -10
  253. package/esm/util/registry.d.ts.map +1 -1
  254. package/esm/util/registry.js +7 -22
  255. package/esm/util/registry.js.map +1 -1
  256. package/esm/util/registry.test.js +3 -49
  257. package/esm/util/registry.test.js.map +1 -1
  258. package/esm/util/tool-caller.d.ts +2 -2
  259. package/esm/util/tool-caller.d.ts.map +1 -1
  260. package/esm/util/tool-caller.js +5 -12
  261. package/esm/util/tool-caller.js.map +1 -1
  262. package/esm/v1/hooks/use-tambo-v1-messages.d.ts +58 -0
  263. package/esm/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -0
  264. package/esm/v1/hooks/use-tambo-v1-messages.js +51 -0
  265. package/esm/v1/hooks/use-tambo-v1-messages.js.map +1 -0
  266. package/esm/v1/hooks/use-tambo-v1-messages.test.d.ts +2 -0
  267. package/esm/v1/hooks/use-tambo-v1-messages.test.d.ts.map +1 -0
  268. package/esm/v1/hooks/use-tambo-v1-messages.test.js +132 -0
  269. package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -0
  270. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +96 -0
  271. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -0
  272. package/esm/v1/hooks/use-tambo-v1-send-message.js +223 -0
  273. package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -0
  274. package/esm/v1/hooks/use-tambo-v1-send-message.test.d.ts +2 -0
  275. package/esm/v1/hooks/use-tambo-v1-send-message.test.d.ts.map +1 -0
  276. package/esm/v1/hooks/use-tambo-v1-send-message.test.js +822 -0
  277. package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -0
  278. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +61 -0
  279. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -0
  280. package/esm/v1/hooks/use-tambo-v1-thread-list.js +53 -0
  281. package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -0
  282. package/esm/v1/hooks/use-tambo-v1-thread-list.test.d.ts +2 -0
  283. package/esm/v1/hooks/use-tambo-v1-thread-list.test.d.ts.map +1 -0
  284. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +93 -0
  285. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -0
  286. package/esm/v1/hooks/use-tambo-v1-thread.d.ts +37 -0
  287. package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -0
  288. package/esm/v1/hooks/use-tambo-v1-thread.js +46 -0
  289. package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -0
  290. package/esm/v1/hooks/use-tambo-v1-thread.test.d.ts +2 -0
  291. package/esm/v1/hooks/use-tambo-v1-thread.test.d.ts.map +1 -0
  292. package/esm/v1/hooks/use-tambo-v1-thread.test.js +78 -0
  293. package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -0
  294. package/esm/v1/hooks/use-tambo-v1.d.ts +107 -0
  295. package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -0
  296. package/esm/v1/hooks/use-tambo-v1.js +84 -0
  297. package/esm/v1/hooks/use-tambo-v1.js.map +1 -0
  298. package/esm/v1/hooks/use-tambo-v1.test.d.ts +2 -0
  299. package/esm/v1/hooks/use-tambo-v1.test.d.ts.map +1 -0
  300. package/esm/v1/hooks/use-tambo-v1.test.js +145 -0
  301. package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -0
  302. package/esm/v1/index.d.ts +73 -0
  303. package/esm/v1/index.d.ts.map +1 -0
  304. package/esm/v1/index.js +83 -0
  305. package/esm/v1/index.js.map +1 -0
  306. package/esm/v1/providers/tambo-v1-provider.d.ts +91 -0
  307. package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -0
  308. package/esm/v1/providers/tambo-v1-provider.js +74 -0
  309. package/esm/v1/providers/tambo-v1-provider.js.map +1 -0
  310. package/esm/v1/providers/tambo-v1-provider.test.d.ts +2 -0
  311. package/esm/v1/providers/tambo-v1-provider.test.d.ts.map +1 -0
  312. package/esm/v1/providers/tambo-v1-provider.test.js +118 -0
  313. package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -0
  314. package/esm/v1/providers/tambo-v1-stream-context.d.ts +136 -0
  315. package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -0
  316. package/esm/v1/providers/tambo-v1-stream-context.js +191 -0
  317. package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -0
  318. package/esm/v1/providers/tambo-v1-stream-context.test.d.ts +2 -0
  319. package/esm/v1/providers/tambo-v1-stream-context.test.d.ts.map +1 -0
  320. package/esm/v1/providers/tambo-v1-stream-context.test.js +80 -0
  321. package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -0
  322. package/esm/v1/types/component.d.ts +50 -0
  323. package/esm/v1/types/component.d.ts.map +1 -0
  324. package/esm/v1/types/component.js +13 -0
  325. package/esm/v1/types/component.js.map +1 -0
  326. package/esm/v1/types/event.d.ts +72 -0
  327. package/esm/v1/types/event.d.ts.map +1 -0
  328. package/esm/v1/types/event.js +50 -0
  329. package/esm/v1/types/event.js.map +1 -0
  330. package/esm/v1/types/event.test.d.ts +2 -0
  331. package/esm/v1/types/event.test.d.ts.map +1 -0
  332. package/esm/v1/types/event.test.js +68 -0
  333. package/esm/v1/types/event.test.js.map +1 -0
  334. package/esm/v1/types/message.d.ts +35 -0
  335. package/esm/v1/types/message.d.ts.map +1 -0
  336. package/esm/v1/types/message.js +9 -0
  337. package/esm/v1/types/message.js.map +1 -0
  338. package/esm/v1/types/thread.d.ts +52 -0
  339. package/esm/v1/types/thread.d.ts.map +1 -0
  340. package/esm/v1/types/thread.js +8 -0
  341. package/esm/v1/types/thread.js.map +1 -0
  342. package/esm/v1/utils/event-accumulator.d.ts +100 -0
  343. package/esm/v1/utils/event-accumulator.d.ts.map +1 -0
  344. package/esm/v1/utils/event-accumulator.js +708 -0
  345. package/esm/v1/utils/event-accumulator.js.map +1 -0
  346. package/esm/v1/utils/event-accumulator.test.d.ts +2 -0
  347. package/esm/v1/utils/event-accumulator.test.d.ts.map +1 -0
  348. package/esm/v1/utils/event-accumulator.test.js +1008 -0
  349. package/esm/v1/utils/event-accumulator.test.js.map +1 -0
  350. package/esm/v1/utils/json-patch.d.ts +18 -0
  351. package/esm/v1/utils/json-patch.d.ts.map +1 -0
  352. package/esm/v1/utils/json-patch.js +32 -0
  353. package/esm/v1/utils/json-patch.js.map +1 -0
  354. package/esm/v1/utils/json-patch.test.d.ts +2 -0
  355. package/esm/v1/utils/json-patch.test.d.ts.map +1 -0
  356. package/esm/v1/utils/json-patch.test.js +26 -0
  357. package/esm/v1/utils/json-patch.test.js.map +1 -0
  358. package/esm/v1/utils/registry-conversion.d.ts +53 -0
  359. package/esm/v1/utils/registry-conversion.d.ts.map +1 -0
  360. package/esm/v1/utils/registry-conversion.js +108 -0
  361. package/esm/v1/utils/registry-conversion.js.map +1 -0
  362. package/esm/v1/utils/registry-conversion.test.d.ts +2 -0
  363. package/esm/v1/utils/registry-conversion.test.d.ts.map +1 -0
  364. package/esm/v1/utils/registry-conversion.test.js +177 -0
  365. package/esm/v1/utils/registry-conversion.test.js.map +1 -0
  366. package/esm/v1/utils/stream-handler.d.ts +45 -0
  367. package/esm/v1/utils/stream-handler.d.ts.map +1 -0
  368. package/esm/v1/utils/stream-handler.js +44 -0
  369. package/esm/v1/utils/stream-handler.js.map +1 -0
  370. package/esm/v1/utils/stream-handler.test.d.ts +2 -0
  371. package/esm/v1/utils/stream-handler.test.d.ts.map +1 -0
  372. package/esm/v1/utils/stream-handler.test.js +72 -0
  373. package/esm/v1/utils/stream-handler.test.js.map +1 -0
  374. package/esm/v1/utils/tool-call-tracker.d.ts +41 -0
  375. package/esm/v1/utils/tool-call-tracker.d.ts.map +1 -0
  376. package/esm/v1/utils/tool-call-tracker.js +86 -0
  377. package/esm/v1/utils/tool-call-tracker.js.map +1 -0
  378. package/esm/v1/utils/tool-executor.d.ts +33 -0
  379. package/esm/v1/utils/tool-executor.d.ts.map +1 -0
  380. package/esm/v1/utils/tool-executor.js +99 -0
  381. package/esm/v1/utils/tool-executor.js.map +1 -0
  382. package/esm/v1/utils/tool-executor.test.d.ts +2 -0
  383. package/esm/v1/utils/tool-executor.test.d.ts.map +1 -0
  384. package/esm/v1/utils/tool-executor.test.js +220 -0
  385. package/esm/v1/utils/tool-executor.test.js.map +1 -0
  386. package/package.json +20 -9
  387. package/dist/schema/zod.d.ts +0 -57
  388. package/dist/schema/zod.d.ts.map +0 -1
  389. package/dist/schema/zod.js +0 -191
  390. package/dist/schema/zod.js.map +0 -1
  391. package/dist/schema/zod.test.d.ts +0 -2
  392. package/dist/schema/zod.test.d.ts.map +0 -1
  393. package/dist/schema/zod.test.js +0 -663
  394. package/dist/schema/zod.test.js.map +0 -1
  395. package/esm/schema/zod.d.ts +0 -57
  396. package/esm/schema/zod.d.ts.map +0 -1
  397. package/esm/schema/zod.js +0 -180
  398. package/esm/schema/zod.js.map +0 -1
  399. package/esm/schema/zod.test.d.ts +0 -2
  400. package/esm/schema/zod.test.d.ts.map +0 -1
  401. package/esm/schema/zod.test.js +0 -628
  402. package/esm/schema/zod.test.js.map +0 -1
@@ -1,9 +1,42 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const typescript_sdk_1 = require("@tambo-ai/typescript-sdk");
39
+ const typescript_sdk_1 = __importStar(require("@tambo-ai/typescript-sdk"));
7
40
  const react_1 = require("@testing-library/react");
8
41
  const react_2 = __importDefault(require("react"));
9
42
  const v4_1 = require("zod/v4");
@@ -28,9 +61,14 @@ jest.mock("./tambo-client-provider", () => {
28
61
  TamboClientContext: react_2.default.createContext(undefined),
29
62
  };
30
63
  });
31
- jest.mock("@tambo-ai/typescript-sdk", () => ({
32
- advanceStream: jest.fn(),
33
- }));
64
+ jest.mock("@tambo-ai/typescript-sdk", () => {
65
+ const actual = jest.requireActual("@tambo-ai/typescript-sdk");
66
+ return {
67
+ __esModule: true,
68
+ ...actual,
69
+ advanceStream: jest.fn(),
70
+ };
71
+ });
34
72
  // Mock the getCustomContext
35
73
  jest.mock("../util/registry", () => ({
36
74
  ...jest.requireActual("../util/registry"),
@@ -73,26 +111,9 @@ const createMockAdvanceResponse = (overrides = {}) => ({
73
111
  });
74
112
  describe("TamboThreadProvider", () => {
75
113
  const mockThread = createMockThread();
76
- const mockThreadsApi = {
77
- messages: {
78
- create: jest.fn(),
79
- },
80
- retrieve: jest.fn(),
81
- advance: jest.fn(),
82
- advanceByID: jest.fn(),
83
- generateName: jest.fn(),
84
- };
85
- const mockProjectsApi = {
86
- getCurrent: jest.fn(),
87
- };
88
- const mockBeta = {
89
- threads: mockThreadsApi,
90
- projects: mockProjectsApi,
91
- };
92
- const mockTamboAI = {
93
- apiKey: "",
94
- beta: mockBeta,
95
- };
114
+ let mockTamboAI;
115
+ let mockThreadsApi;
116
+ let mockProjectsApi;
96
117
  let mockQueryClient;
97
118
  const mockRegistry = [
98
119
  {
@@ -144,8 +165,19 @@ describe("TamboThreadProvider", () => {
144
165
  };
145
166
  // Default wrapper for most tests
146
167
  const Wrapper = createWrapper();
168
+ afterEach(() => {
169
+ jest.restoreAllMocks();
170
+ });
147
171
  beforeEach(() => {
148
172
  jest.clearAllMocks();
173
+ mockTamboAI = new typescript_sdk_1.default({
174
+ apiKey: "",
175
+ fetch: () => {
176
+ throw new Error("Unexpected network call in test");
177
+ },
178
+ });
179
+ mockThreadsApi = mockTamboAI.beta.threads;
180
+ mockProjectsApi = mockTamboAI.beta.projects;
149
181
  // Setup mock query client
150
182
  mockQueryClient = {
151
183
  invalidateQueries: jest.fn().mockResolvedValue(undefined),
@@ -154,21 +186,22 @@ describe("TamboThreadProvider", () => {
154
186
  jest
155
187
  .mocked(tambo_client_provider_1.useTamboQueryClient)
156
188
  .mockReturnValue(mockQueryClient);
157
- jest.mocked(mockThreadsApi.retrieve).mockResolvedValue(mockThread);
189
+ jest.spyOn(mockThreadsApi, "retrieve").mockResolvedValue(mockThread);
158
190
  jest
159
- .mocked(mockThreadsApi.messages.create)
191
+ .spyOn(mockThreadsApi.messages, "create")
160
192
  .mockResolvedValue(createMockMessage());
161
193
  jest
162
- .mocked(mockThreadsApi.advance)
194
+ .spyOn(mockThreadsApi, "advance")
163
195
  .mockResolvedValue(createMockAdvanceResponse());
164
196
  jest
165
- .mocked(mockThreadsApi.advanceByID)
197
+ .spyOn(mockThreadsApi, "advanceByID")
166
198
  .mockResolvedValue(createMockAdvanceResponse());
167
- jest.mocked(mockThreadsApi.generateName).mockResolvedValue({
199
+ jest.spyOn(mockThreadsApi, "generateName").mockResolvedValue({
168
200
  ...mockThread,
169
201
  name: "Generated Thread Name",
170
202
  });
171
- jest.mocked(mockProjectsApi.getCurrent).mockResolvedValue({
203
+ jest.spyOn(mockThreadsApi, "update").mockResolvedValue({});
204
+ jest.spyOn(mockProjectsApi, "getCurrent").mockResolvedValue({
172
205
  id: "test-project-id",
173
206
  name: "Test Project",
174
207
  isTokenRequired: false,
@@ -236,7 +269,7 @@ describe("TamboThreadProvider", () => {
236
269
  });
237
270
  });
238
271
  it("should send a message and update thread state", async () => {
239
- const mockAdvanceResponse = {
272
+ const mockStreamResponse = {
240
273
  responseMessageDto: {
241
274
  id: "response-1",
242
275
  content: [{ type: "text", text: "Response" }],
@@ -249,14 +282,17 @@ describe("TamboThreadProvider", () => {
249
282
  generationStage: generate_component_response_1.GenerationStage.COMPLETE,
250
283
  mcpAccessToken: "test-mcp-access-token",
251
284
  };
252
- jest
253
- .mocked(mockThreadsApi.advanceByID)
254
- .mockResolvedValue(mockAdvanceResponse);
285
+ const mockAsyncIterator = {
286
+ [Symbol.asyncIterator]: async function* () {
287
+ yield mockStreamResponse;
288
+ },
289
+ };
290
+ jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
255
291
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), { wrapper: Wrapper });
256
292
  await (0, react_1.act)(async () => {
257
293
  await result.current.sendThreadMessage("Hello", {
258
294
  threadId: "test-thread-1",
259
- streamResponse: false,
295
+ streamResponse: true,
260
296
  additionalContext: {
261
297
  custom: {
262
298
  message: "additional instructions",
@@ -264,7 +300,7 @@ describe("TamboThreadProvider", () => {
264
300
  },
265
301
  });
266
302
  });
267
- expect(mockThreadsApi.advanceByID).toHaveBeenCalledWith("test-thread-1", {
303
+ expect(typescript_sdk_1.advanceStream).toHaveBeenCalledWith(expect.anything(), {
268
304
  messageToAppend: {
269
305
  content: [{ type: "text", text: "Hello" }],
270
306
  role: "user",
@@ -278,7 +314,7 @@ describe("TamboThreadProvider", () => {
278
314
  contextKey: undefined,
279
315
  clientTools: [],
280
316
  toolCallCounts: {},
281
- });
317
+ }, "test-thread-1");
282
318
  expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
283
319
  });
284
320
  it("should handle streaming responses", async () => {
@@ -313,7 +349,7 @@ describe("TamboThreadProvider", () => {
313
349
  expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
314
350
  });
315
351
  it("should handle tool calls during message processing.", async () => {
316
- const mockToolCallResponse = {
352
+ const mockToolCallChunk = {
317
353
  responseMessageDto: {
318
354
  id: "tool-call-1",
319
355
  content: [{ type: "text", text: "Tool response" }],
@@ -329,10 +365,7 @@ describe("TamboThreadProvider", () => {
329
365
  generationStage: generate_component_response_1.GenerationStage.COMPLETE,
330
366
  mcpAccessToken: "test-mcp-access-token",
331
367
  };
332
- jest
333
- .mocked(mockThreadsApi.advanceByID)
334
- .mockResolvedValueOnce(mockToolCallResponse)
335
- .mockResolvedValueOnce({
368
+ const mockFinalChunk = {
336
369
  responseMessageDto: {
337
370
  id: "advance-response2",
338
371
  content: [{ type: "text", text: "response 2" }],
@@ -343,12 +376,26 @@ describe("TamboThreadProvider", () => {
343
376
  },
344
377
  generationStage: generate_component_response_1.GenerationStage.COMPLETE,
345
378
  mcpAccessToken: "test-mcp-access-token",
346
- });
379
+ };
380
+ const mockAsyncIterator = {
381
+ [Symbol.asyncIterator]: async function* () {
382
+ yield mockToolCallChunk;
383
+ },
384
+ };
385
+ const mockAsyncIterator2 = {
386
+ [Symbol.asyncIterator]: async function* () {
387
+ yield mockFinalChunk;
388
+ },
389
+ };
390
+ jest
391
+ .mocked(typescript_sdk_1.advanceStream)
392
+ .mockResolvedValueOnce(mockAsyncIterator)
393
+ .mockResolvedValueOnce(mockAsyncIterator2);
347
394
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), { wrapper: Wrapper });
348
395
  await (0, react_1.act)(async () => {
349
396
  await result.current.sendThreadMessage("Use tool", {
350
397
  threadId: "test-thread-1",
351
- streamResponse: false,
398
+ streamResponse: true,
352
399
  });
353
400
  });
354
401
  expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
@@ -361,7 +408,7 @@ describe("TamboThreadProvider", () => {
361
408
  const mockOnCallUnregisteredTool = jest
362
409
  .fn()
363
410
  .mockResolvedValue("unregistered-tool-result");
364
- const mockUnregisteredToolCallResponse = {
411
+ const mockUnregisteredToolCallChunk = {
365
412
  responseMessageDto: {
366
413
  id: "unregistered-tool-call-1",
367
414
  content: [{ type: "text", text: "Unregistered tool response" }],
@@ -379,10 +426,7 @@ describe("TamboThreadProvider", () => {
379
426
  generationStage: generate_component_response_1.GenerationStage.COMPLETE,
380
427
  mcpAccessToken: "test-mcp-access-token",
381
428
  };
382
- jest
383
- .mocked(mockThreadsApi.advanceByID)
384
- .mockResolvedValueOnce(mockUnregisteredToolCallResponse)
385
- .mockResolvedValueOnce({
429
+ const mockFinalChunk = {
386
430
  responseMessageDto: {
387
431
  id: "advance-response2",
388
432
  content: [{ type: "text", text: "response 2" }],
@@ -393,7 +437,21 @@ describe("TamboThreadProvider", () => {
393
437
  },
394
438
  generationStage: generate_component_response_1.GenerationStage.COMPLETE,
395
439
  mcpAccessToken: "test-mcp-access-token",
396
- });
440
+ };
441
+ const mockAsyncIterator = {
442
+ [Symbol.asyncIterator]: async function* () {
443
+ yield mockUnregisteredToolCallChunk;
444
+ },
445
+ };
446
+ const mockAsyncIterator2 = {
447
+ [Symbol.asyncIterator]: async function* () {
448
+ yield mockFinalChunk;
449
+ },
450
+ };
451
+ jest
452
+ .mocked(typescript_sdk_1.advanceStream)
453
+ .mockResolvedValueOnce(mockAsyncIterator)
454
+ .mockResolvedValueOnce(mockAsyncIterator2);
397
455
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
398
456
  wrapper: createWrapper({
399
457
  onCallUnregisteredTool: mockOnCallUnregisteredTool,
@@ -402,14 +460,14 @@ describe("TamboThreadProvider", () => {
402
460
  await (0, react_1.act)(async () => {
403
461
  await result.current.sendThreadMessage("Use unregistered tool", {
404
462
  threadId: "test-thread-1",
405
- streamResponse: false,
463
+ streamResponse: true,
406
464
  });
407
465
  });
408
466
  expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
409
467
  expect(mockOnCallUnregisteredTool).toHaveBeenCalledWith("unregistered-tool", [{ parameterName: "input", parameterValue: "test-input" }]);
410
468
  });
411
469
  it("should handle unregistered tool calls without onCallUnregisteredTool", async () => {
412
- const mockUnregisteredToolCallResponse = {
470
+ const mockUnregisteredToolCallChunk = {
413
471
  responseMessageDto: {
414
472
  id: "unregistered-tool-call-1",
415
473
  content: [{ type: "text", text: "Unregistered tool response" }],
@@ -427,10 +485,7 @@ describe("TamboThreadProvider", () => {
427
485
  generationStage: generate_component_response_1.GenerationStage.COMPLETE,
428
486
  mcpAccessToken: "test-mcp-access-token",
429
487
  };
430
- jest
431
- .mocked(mockThreadsApi.advanceByID)
432
- .mockResolvedValueOnce(mockUnregisteredToolCallResponse)
433
- .mockResolvedValueOnce({
488
+ const mockFinalChunk = {
434
489
  responseMessageDto: {
435
490
  id: "advance-response2",
436
491
  content: [{ type: "text", text: "response 2" }],
@@ -441,12 +496,26 @@ describe("TamboThreadProvider", () => {
441
496
  },
442
497
  generationStage: generate_component_response_1.GenerationStage.COMPLETE,
443
498
  mcpAccessToken: "test-mcp-access-token",
444
- });
499
+ };
500
+ const mockAsyncIterator = {
501
+ [Symbol.asyncIterator]: async function* () {
502
+ yield mockUnregisteredToolCallChunk;
503
+ },
504
+ };
505
+ const mockAsyncIterator2 = {
506
+ [Symbol.asyncIterator]: async function* () {
507
+ yield mockFinalChunk;
508
+ },
509
+ };
510
+ jest
511
+ .mocked(typescript_sdk_1.advanceStream)
512
+ .mockResolvedValueOnce(mockAsyncIterator)
513
+ .mockResolvedValueOnce(mockAsyncIterator2);
445
514
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), { wrapper: Wrapper });
446
515
  await (0, react_1.act)(async () => {
447
516
  await result.current.sendThreadMessage("Use unregistered tool", {
448
517
  threadId: "test-thread-1",
449
- streamResponse: false,
518
+ streamResponse: true,
450
519
  });
451
520
  });
452
521
  expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
@@ -507,77 +576,16 @@ describe("TamboThreadProvider", () => {
507
576
  expect(mockThreadsApi.advance).not.toHaveBeenCalled();
508
577
  expect(mockThreadsApi.advanceByID).not.toHaveBeenCalled();
509
578
  });
510
- it("should call advanceById when streamResponse=false for existing thread", async () => {
511
- // Use wrapper with streaming=true to show that explicit streamResponse=false overrides provider setting
579
+ it("should throw error when streamResponse=false (non-streaming not supported)", async () => {
512
580
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
513
581
  wrapper: createWrapper({ streaming: true }),
514
582
  });
515
583
  await (0, react_1.act)(async () => {
516
- await result.current.sendThreadMessage("Hello non-streaming", {
584
+ await expect(result.current.sendThreadMessage("Hello non-streaming", {
517
585
  threadId: "test-thread-1",
518
586
  streamResponse: false,
519
- additionalContext: {
520
- custom: {
521
- message: "additional instructions",
522
- },
523
- },
524
- });
525
- });
526
- expect(mockThreadsApi.advanceByID).toHaveBeenCalledWith("test-thread-1", {
527
- messageToAppend: {
528
- content: [{ type: "text", text: "Hello non-streaming" }],
529
- role: "user",
530
- additionalContext: {
531
- custom: {
532
- message: "additional instructions",
533
- },
534
- },
535
- },
536
- availableComponents: (0, tools_1.serializeRegistry)(mockRegistry),
537
- contextKey: undefined,
538
- clientTools: [],
539
- forceToolChoice: undefined,
540
- toolCallCounts: {},
541
- });
542
- // Should not call advance or advanceStream
543
- expect(mockThreadsApi.advance).not.toHaveBeenCalled();
544
- expect(typescript_sdk_1.advanceStream).not.toHaveBeenCalled();
545
- });
546
- it("should call advanceById when streamResponse is undefined and provider streaming=false", async () => {
547
- // Use wrapper with streaming=false to test that undefined streamResponse respects provider setting
548
- const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
549
- wrapper: createWrapper({ streaming: false }),
550
- });
551
- await (0, react_1.act)(async () => {
552
- await result.current.sendThreadMessage("Hello default", {
553
- threadId: "test-thread-1",
554
- // streamResponse is undefined, should use provider's streaming=false
555
- additionalContext: {
556
- custom: {
557
- message: "additional instructions",
558
- },
559
- },
560
- });
561
- });
562
- expect(mockThreadsApi.advanceByID).toHaveBeenCalledWith("test-thread-1", {
563
- messageToAppend: {
564
- content: [{ type: "text", text: "Hello default" }],
565
- role: "user",
566
- additionalContext: {
567
- custom: {
568
- message: "additional instructions",
569
- },
570
- },
571
- },
572
- availableComponents: (0, tools_1.serializeRegistry)(mockRegistry),
573
- contextKey: undefined,
574
- clientTools: [],
575
- forceToolChoice: undefined,
576
- toolCallCounts: {},
587
+ })).rejects.toThrow();
577
588
  });
578
- // Should not call advance or advanceStream
579
- expect(mockThreadsApi.advance).not.toHaveBeenCalled();
580
- expect(typescript_sdk_1.advanceStream).not.toHaveBeenCalled();
581
589
  });
582
590
  it("should call advanceStream when streamResponse is undefined and provider streaming=true (default)", async () => {
583
591
  const mockStreamResponse = {
@@ -633,44 +641,6 @@ describe("TamboThreadProvider", () => {
633
641
  expect(mockThreadsApi.advance).not.toHaveBeenCalled();
634
642
  expect(mockThreadsApi.advanceByID).not.toHaveBeenCalled();
635
643
  });
636
- it("should call advance when streamResponse=false for placeholder thread", async () => {
637
- // Use wrapper with streaming=true to show that explicit streamResponse=false overrides provider setting
638
- const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
639
- wrapper: createWrapper({ streaming: true }),
640
- });
641
- // Start with placeholder thread (which is the default state)
642
- expect(result.current.thread.id).toBe("placeholder");
643
- await (0, react_1.act)(async () => {
644
- await result.current.sendThreadMessage("Hello new thread", {
645
- threadId: "placeholder",
646
- streamResponse: false,
647
- additionalContext: {
648
- custom: {
649
- message: "additional instructions",
650
- },
651
- },
652
- });
653
- });
654
- expect(mockThreadsApi.advance).toHaveBeenCalledWith({
655
- messageToAppend: {
656
- content: [{ type: "text", text: "Hello new thread" }],
657
- role: "user",
658
- additionalContext: {
659
- custom: {
660
- message: "additional instructions",
661
- },
662
- },
663
- },
664
- availableComponents: (0, tools_1.serializeRegistry)(mockRegistry),
665
- contextKey: undefined,
666
- clientTools: [],
667
- forceToolChoice: undefined,
668
- toolCallCounts: {},
669
- });
670
- // Should not call advanceById or advanceStream
671
- expect(mockThreadsApi.advanceByID).not.toHaveBeenCalled();
672
- expect(typescript_sdk_1.advanceStream).not.toHaveBeenCalled();
673
- });
674
644
  it("should call advanceStream when streamResponse=true for placeholder thread", async () => {
675
645
  const mockStreamResponse = {
676
646
  responseMessageDto: {
@@ -817,10 +787,10 @@ describe("TamboThreadProvider", () => {
817
787
  });
818
788
  });
819
789
  describe("error handling", () => {
820
- it("should set generation stage to ERROR when non-streaming sendThreadMessage fails", async () => {
821
- const testError = new Error("API call failed");
822
- // Mock advanceById to throw an error
823
- jest.mocked(mockThreadsApi.advanceByID).mockRejectedValue(testError);
790
+ it("should set generation stage to ERROR when streaming sendThreadMessage fails", async () => {
791
+ const testError = new Error("Streaming API call failed");
792
+ // Mock advanceStream to throw an error
793
+ jest.mocked(typescript_sdk_1.advanceStream).mockRejectedValue(testError);
824
794
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
825
795
  wrapper: Wrapper,
826
796
  });
@@ -829,48 +799,91 @@ describe("TamboThreadProvider", () => {
829
799
  await result.current.switchCurrentThread("test-thread-1");
830
800
  await expect(result.current.sendThreadMessage("Hello", {
831
801
  threadId: "test-thread-1",
832
- streamResponse: false,
833
- })).rejects.toThrow("API call failed");
802
+ streamResponse: true,
803
+ })).rejects.toThrow("Streaming API call failed");
834
804
  });
835
805
  // Verify generation stage is set to ERROR
836
806
  expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.ERROR);
837
807
  });
838
- it("should set generation stage to ERROR when streaming sendThreadMessage fails", async () => {
839
- const testError = new Error("Streaming API call failed");
840
- // Mock advanceStream to throw an error
808
+ it("should rollback optimistic user message when sendThreadMessage fails", async () => {
809
+ const testError = new Error("API call failed");
841
810
  jest.mocked(typescript_sdk_1.advanceStream).mockRejectedValue(testError);
842
811
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
843
812
  wrapper: Wrapper,
844
813
  });
845
- // Expect the error to be thrown
846
814
  await (0, react_1.act)(async () => {
847
815
  await result.current.switchCurrentThread("test-thread-1");
816
+ });
817
+ const initialMessageCount = result.current.thread.messages.length;
818
+ await (0, react_1.act)(async () => {
848
819
  await expect(result.current.sendThreadMessage("Hello", {
849
820
  threadId: "test-thread-1",
850
821
  streamResponse: true,
851
- })).rejects.toThrow("Streaming API call failed");
822
+ })).rejects.toThrow("API call failed");
852
823
  });
853
- // Verify generation stage is set to ERROR
854
- expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.ERROR);
824
+ // Verify user message was rolled back
825
+ expect(result.current.thread.messages.length).toBe(initialMessageCount);
855
826
  });
856
- it("should set generation stage to ERROR when advance API call fails for placeholder thread", async () => {
857
- const testError = new Error("Advance API call failed");
858
- // Mock advance to throw an error
859
- jest.mocked(mockThreadsApi.advance).mockRejectedValue(testError);
827
+ it("should rollback optimistic message when addThreadMessage fails", async () => {
828
+ const testError = new Error("Create message failed");
829
+ jest.mocked(mockThreadsApi.messages.create).mockRejectedValue(testError);
860
830
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
861
831
  wrapper: Wrapper,
862
832
  });
863
- // Start with placeholder thread (which is the default state)
864
- expect(result.current.thread.id).toBe("placeholder");
865
- // Expect the error to be thrown
866
833
  await (0, react_1.act)(async () => {
867
- await expect(result.current.sendThreadMessage("Hello", {
868
- threadId: "placeholder",
869
- streamResponse: false,
870
- })).rejects.toThrow("Advance API call failed");
834
+ await result.current.switchCurrentThread("test-thread-1");
871
835
  });
872
- // Verify generation stage is set to ERROR
873
- expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.ERROR);
836
+ const initialMessageCount = result.current.thread.messages.length;
837
+ const newMessage = createMockMessage({ threadId: "test-thread-1" });
838
+ await (0, react_1.act)(async () => {
839
+ await expect(result.current.addThreadMessage(newMessage, true)).rejects.toThrow("Create message failed");
840
+ });
841
+ // Verify message was rolled back
842
+ expect(result.current.thread.messages.length).toBe(initialMessageCount);
843
+ });
844
+ it("should rollback optimistic update when updateThreadMessage fails", async () => {
845
+ const testError = new Error("Update message failed");
846
+ jest.mocked(mockThreadsApi.messages.create).mockRejectedValue(testError);
847
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
848
+ wrapper: Wrapper,
849
+ });
850
+ await (0, react_1.act)(async () => {
851
+ await result.current.switchCurrentThread("test-thread-1");
852
+ });
853
+ const existingMessage = createMockMessage({
854
+ id: "existing-msg",
855
+ threadId: "test-thread-1",
856
+ content: [{ type: "text", text: "Old content" }],
857
+ });
858
+ await (0, react_1.act)(async () => {
859
+ await result.current.addThreadMessage(existingMessage, false);
860
+ });
861
+ const initialMessageCount = result.current.thread.messages.length;
862
+ await (0, react_1.act)(async () => {
863
+ await expect(result.current.updateThreadMessage("existing-msg", {
864
+ threadId: "test-thread-1",
865
+ content: [{ type: "text", text: "New content" }],
866
+ role: "assistant",
867
+ }, true)).rejects.toThrow("Update message failed");
868
+ });
869
+ // Verify message was rolled back
870
+ expect(result.current.thread.messages.length).toBe(initialMessageCount - 1);
871
+ });
872
+ it("should rollback optimistic name update when updateThreadName fails", async () => {
873
+ const testError = new Error("Update name failed");
874
+ jest.mocked(mockThreadsApi.update).mockRejectedValue(testError);
875
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
876
+ wrapper: Wrapper,
877
+ });
878
+ await (0, react_1.act)(async () => {
879
+ await result.current.switchCurrentThread("test-thread-1");
880
+ });
881
+ const initialName = result.current.thread.name;
882
+ await (0, react_1.act)(async () => {
883
+ await expect(result.current.updateThreadName("New Name", "test-thread-1")).rejects.toThrow("Update name failed");
884
+ });
885
+ // Verify name was rolled back
886
+ expect(result.current.thread.name).toBe(initialName);
874
887
  });
875
888
  });
876
889
  describe("refetch threads list behavior", () => {
@@ -878,8 +891,8 @@ describe("TamboThreadProvider", () => {
878
891
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
879
892
  wrapper: Wrapper,
880
893
  });
881
- // Mock the advance response to return a new thread ID
882
- const mockAdvanceResponse = {
894
+ // Mock the stream response to return a new thread ID
895
+ const mockStreamResponse = {
883
896
  responseMessageDto: {
884
897
  id: "response-1",
885
898
  content: [{ type: "text", text: "Response" }],
@@ -892,16 +905,19 @@ describe("TamboThreadProvider", () => {
892
905
  generationStage: generate_component_response_1.GenerationStage.COMPLETE,
893
906
  mcpAccessToken: "test-mcp-access-token",
894
907
  };
895
- jest
896
- .mocked(mockThreadsApi.advance)
897
- .mockResolvedValue(mockAdvanceResponse);
908
+ const mockAsyncIterator = {
909
+ [Symbol.asyncIterator]: async function* () {
910
+ yield mockStreamResponse;
911
+ },
912
+ };
913
+ jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
898
914
  // Start with placeholder thread
899
915
  expect(result.current.thread.id).toBe("placeholder");
900
916
  // Send a message which will create a new thread with contextKey
901
917
  await (0, react_1.act)(async () => {
902
918
  await result.current.sendThreadMessage("Hello", {
903
919
  threadId: "placeholder",
904
- streamResponse: false,
920
+ streamResponse: true,
905
921
  contextKey: "test-context-key",
906
922
  });
907
923
  });
@@ -939,93 +955,6 @@ describe("TamboThreadProvider", () => {
939
955
  });
940
956
  });
941
957
  describe("transformToContent", () => {
942
- it("should use custom transformToContent when provided (non-streaming)", async () => {
943
- const mockTransformToContent = jest.fn().mockReturnValue([
944
- { type: "text", text: "Custom transformed content" },
945
- {
946
- type: "image_url",
947
- image_url: { url: "https://example.com/image.png" },
948
- },
949
- ]);
950
- const customToolRegistry = [
951
- {
952
- name: "TestComponent",
953
- component: () => react_2.default.createElement("div", null, "Test"),
954
- description: "Test",
955
- propsSchema: v4_1.z.object({ test: v4_1.z.string() }),
956
- associatedTools: [
957
- {
958
- name: "custom-tool",
959
- tool: jest.fn().mockResolvedValue({ data: "tool result" }),
960
- description: "Tool with custom transform",
961
- inputSchema: v4_1.z.object({ input: v4_1.z.string() }),
962
- outputSchema: v4_1.z.object({ data: v4_1.z.string() }),
963
- transformToContent: mockTransformToContent,
964
- },
965
- ],
966
- },
967
- ];
968
- const mockToolCallResponse = {
969
- responseMessageDto: {
970
- id: "tool-call-1",
971
- content: [{ type: "text", text: "Tool response" }],
972
- role: "tool",
973
- threadId: "test-thread-1",
974
- toolCallRequest: {
975
- toolName: "custom-tool",
976
- parameters: [{ parameterName: "input", parameterValue: "test" }],
977
- },
978
- componentState: {},
979
- createdAt: new Date().toISOString(),
980
- },
981
- generationStage: generate_component_response_1.GenerationStage.COMPLETE,
982
- mcpAccessToken: "test-mcp-access-token",
983
- };
984
- jest
985
- .mocked(mockThreadsApi.advanceByID)
986
- .mockResolvedValueOnce(mockToolCallResponse)
987
- .mockResolvedValueOnce({
988
- responseMessageDto: {
989
- id: "final-response",
990
- content: [{ type: "text", text: "Final response" }],
991
- role: "assistant",
992
- threadId: "test-thread-1",
993
- componentState: {},
994
- createdAt: new Date().toISOString(),
995
- },
996
- generationStage: generate_component_response_1.GenerationStage.COMPLETE,
997
- mcpAccessToken: "test-mcp-access-token",
998
- });
999
- const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
1000
- wrapper: createWrapper({ components: customToolRegistry }),
1001
- });
1002
- await (0, react_1.act)(async () => {
1003
- await result.current.sendThreadMessage("Use custom tool", {
1004
- threadId: "test-thread-1",
1005
- streamResponse: false,
1006
- });
1007
- });
1008
- // Verify the tool was called with single object arg (new inputSchema interface)
1009
- expect(customToolRegistry[0]?.associatedTools?.[0]?.tool).toHaveBeenCalledWith({ input: "test" });
1010
- // Verify transformToContent was called with the tool result
1011
- expect(mockTransformToContent).toHaveBeenCalledWith({
1012
- data: "tool result",
1013
- });
1014
- // Verify the second advance call included the transformed content
1015
- expect(mockThreadsApi.advanceByID).toHaveBeenCalledTimes(2);
1016
- expect(mockThreadsApi.advanceByID).toHaveBeenLastCalledWith("test-thread-1", expect.objectContaining({
1017
- messageToAppend: expect.objectContaining({
1018
- content: [
1019
- { type: "text", text: "Custom transformed content" },
1020
- {
1021
- type: "image_url",
1022
- image_url: { url: "https://example.com/image.png" },
1023
- },
1024
- ],
1025
- role: "tool",
1026
- }),
1027
- }));
1028
- });
1029
958
  it("should use custom async transformToContent when provided (streaming)", async () => {
1030
959
  const mockTransformToContent = jest
1031
960
  .fn()
@@ -1122,169 +1051,6 @@ describe("TamboThreadProvider", () => {
1122
1051
  }),
1123
1052
  }), "test-thread-1");
1124
1053
  });
1125
- it("should fallback to stringified text when transformToContent is not provided", async () => {
1126
- const toolWithoutTransform = [
1127
- {
1128
- name: "TestComponent",
1129
- component: () => react_2.default.createElement("div", null, "Test"),
1130
- description: "Test",
1131
- propsSchema: v4_1.z.object({ test: v4_1.z.string() }),
1132
- associatedTools: [
1133
- {
1134
- name: "no-transform-tool",
1135
- tool: jest
1136
- .fn()
1137
- .mockResolvedValue({ complex: "data", nested: { value: 42 } }),
1138
- description: "Tool without custom transform",
1139
- inputSchema: v4_1.z.object({ input: v4_1.z.string() }),
1140
- outputSchema: v4_1.z.object({
1141
- complex: v4_1.z.string(),
1142
- nested: v4_1.z.object({ value: v4_1.z.number() }),
1143
- }),
1144
- // No transformToContent provided
1145
- },
1146
- ],
1147
- },
1148
- ];
1149
- const mockToolCallResponse = {
1150
- responseMessageDto: {
1151
- id: "tool-call-1",
1152
- content: [{ type: "text", text: "Tool call" }],
1153
- role: "tool",
1154
- threadId: "test-thread-1",
1155
- toolCallRequest: {
1156
- toolName: "no-transform-tool",
1157
- parameters: [{ parameterName: "input", parameterValue: "test" }],
1158
- },
1159
- componentState: {},
1160
- createdAt: new Date().toISOString(),
1161
- },
1162
- generationStage: generate_component_response_1.GenerationStage.COMPLETE,
1163
- mcpAccessToken: "test-mcp-access-token",
1164
- };
1165
- jest
1166
- .mocked(mockThreadsApi.advanceByID)
1167
- .mockResolvedValueOnce(mockToolCallResponse)
1168
- .mockResolvedValueOnce({
1169
- responseMessageDto: {
1170
- id: "final-response",
1171
- content: [{ type: "text", text: "Final response" }],
1172
- role: "assistant",
1173
- threadId: "test-thread-1",
1174
- componentState: {},
1175
- createdAt: new Date().toISOString(),
1176
- },
1177
- generationStage: generate_component_response_1.GenerationStage.COMPLETE,
1178
- mcpAccessToken: "test-mcp-access-token",
1179
- });
1180
- const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
1181
- wrapper: createWrapper({ components: toolWithoutTransform }),
1182
- });
1183
- await (0, react_1.act)(async () => {
1184
- await result.current.sendThreadMessage("Use tool without transform", {
1185
- threadId: "test-thread-1",
1186
- streamResponse: false,
1187
- });
1188
- });
1189
- // Verify the tool was called with single object arg (new inputSchema interface)
1190
- expect(toolWithoutTransform[0]?.associatedTools?.[0]?.tool).toHaveBeenCalledWith({ input: "test" });
1191
- // Verify the second advance call used stringified content
1192
- expect(mockThreadsApi.advanceByID).toHaveBeenLastCalledWith("test-thread-1", expect.objectContaining({
1193
- messageToAppend: expect.objectContaining({
1194
- content: [
1195
- {
1196
- type: "text",
1197
- text: '{"complex":"data","nested":{"value":42}}',
1198
- },
1199
- ],
1200
- role: "tool",
1201
- }),
1202
- }));
1203
- });
1204
- it("should always return text for error responses even with transformToContent", async () => {
1205
- const mockTransformToContent = jest.fn().mockReturnValue([
1206
- {
1207
- type: "image_url",
1208
- image_url: { url: "https://example.com/error.png" },
1209
- },
1210
- ]);
1211
- const toolWithTransform = [
1212
- {
1213
- name: "TestComponent",
1214
- component: () => react_2.default.createElement("div", null, "Test"),
1215
- description: "Test",
1216
- propsSchema: v4_1.z.object({ test: v4_1.z.string() }),
1217
- associatedTools: [
1218
- {
1219
- name: "error-tool",
1220
- tool: jest
1221
- .fn()
1222
- .mockRejectedValue(new Error("Tool execution failed")),
1223
- description: "Tool that errors",
1224
- inputSchema: v4_1.z.object({ input: v4_1.z.string() }),
1225
- outputSchema: v4_1.z.string(),
1226
- transformToContent: mockTransformToContent,
1227
- },
1228
- ],
1229
- },
1230
- ];
1231
- const mockToolCallResponse = {
1232
- responseMessageDto: {
1233
- id: "tool-call-1",
1234
- content: [{ type: "text", text: "Tool call" }],
1235
- role: "tool",
1236
- threadId: "test-thread-1",
1237
- toolCallRequest: {
1238
- toolName: "error-tool",
1239
- parameters: [{ parameterName: "input", parameterValue: "test" }],
1240
- },
1241
- componentState: {},
1242
- createdAt: new Date().toISOString(),
1243
- },
1244
- generationStage: generate_component_response_1.GenerationStage.COMPLETE,
1245
- mcpAccessToken: "test-mcp-access-token",
1246
- };
1247
- jest
1248
- .mocked(mockThreadsApi.advanceByID)
1249
- .mockResolvedValueOnce(mockToolCallResponse)
1250
- .mockResolvedValueOnce({
1251
- responseMessageDto: {
1252
- id: "final-response",
1253
- content: [{ type: "text", text: "Final response" }],
1254
- role: "assistant",
1255
- threadId: "test-thread-1",
1256
- componentState: {},
1257
- createdAt: new Date().toISOString(),
1258
- },
1259
- generationStage: generate_component_response_1.GenerationStage.COMPLETE,
1260
- mcpAccessToken: "test-mcp-access-token",
1261
- });
1262
- const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
1263
- wrapper: createWrapper({ components: toolWithTransform }),
1264
- });
1265
- await (0, react_1.act)(async () => {
1266
- await result.current.sendThreadMessage("Use error tool", {
1267
- threadId: "test-thread-1",
1268
- streamResponse: false,
1269
- });
1270
- });
1271
- // Verify the tool was called with single object arg (new inputSchema interface)
1272
- expect(toolWithTransform[0]?.associatedTools?.[0]?.tool).toHaveBeenCalledWith({ input: "test" });
1273
- // Verify transformToContent was NOT called for error responses
1274
- expect(mockTransformToContent).not.toHaveBeenCalled();
1275
- // Verify the second advance call used text content with the error message
1276
- expect(mockThreadsApi.advanceByID).toHaveBeenLastCalledWith("test-thread-1", expect.objectContaining({
1277
- messageToAppend: expect.objectContaining({
1278
- content: [
1279
- expect.objectContaining({
1280
- type: "text",
1281
- // Error message should be in text format
1282
- }),
1283
- ],
1284
- role: "tool",
1285
- }),
1286
- }));
1287
- });
1288
1054
  });
1289
1055
  describe("tamboStreamableHint streaming behavior", () => {
1290
1056
  it("should call streamable tool during streaming when tamboStreamableHint is true", async () => {
@@ -1617,6 +1383,25 @@ describe("TamboThreadProvider", () => {
1617
1383
  });
1618
1384
  describe("auto-generate thread name", () => {
1619
1385
  it("should auto-generate thread name after reaching threshold", async () => {
1386
+ const mockStreamResponse = {
1387
+ responseMessageDto: {
1388
+ id: "response-1",
1389
+ content: [{ type: "text", text: "Response" }],
1390
+ role: "assistant",
1391
+ threadId: "test-thread-1",
1392
+ component: undefined,
1393
+ componentState: {},
1394
+ createdAt: new Date().toISOString(),
1395
+ },
1396
+ generationStage: generate_component_response_1.GenerationStage.COMPLETE,
1397
+ mcpAccessToken: "test-mcp-access-token",
1398
+ };
1399
+ const mockAsyncIterator = {
1400
+ [Symbol.asyncIterator]: async function* () {
1401
+ yield mockStreamResponse;
1402
+ },
1403
+ };
1404
+ jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
1620
1405
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
1621
1406
  wrapper: createWrapper({ autoGenerateNameThreshold: 2 }),
1622
1407
  });
@@ -1648,13 +1433,34 @@ describe("TamboThreadProvider", () => {
1648
1433
  }), false);
1649
1434
  });
1650
1435
  await (0, react_1.act)(async () => {
1651
- await result.current.sendThreadMessage("Test message");
1436
+ await result.current.sendThreadMessage("Test message", {
1437
+ streamResponse: true,
1438
+ });
1652
1439
  });
1653
1440
  expect(mockThreadsApi.generateName).toHaveBeenCalledWith("test-thread-1");
1654
1441
  expect(result.current.thread.name).toBe("Generated Thread Name");
1655
1442
  expect(mockQueryClient.setQueryData).toHaveBeenCalledWith(["threads", "test-project-id", undefined], expect.any(Function));
1656
1443
  });
1657
1444
  it("should NOT auto-generate when autoGenerateThreadName is false", async () => {
1445
+ const mockStreamResponse = {
1446
+ responseMessageDto: {
1447
+ id: "response-1",
1448
+ content: [{ type: "text", text: "Response" }],
1449
+ role: "assistant",
1450
+ threadId: "test-thread-1",
1451
+ component: undefined,
1452
+ componentState: {},
1453
+ createdAt: new Date().toISOString(),
1454
+ },
1455
+ generationStage: generate_component_response_1.GenerationStage.COMPLETE,
1456
+ mcpAccessToken: "test-mcp-access-token",
1457
+ };
1458
+ const mockAsyncIterator = {
1459
+ [Symbol.asyncIterator]: async function* () {
1460
+ yield mockStreamResponse;
1461
+ },
1462
+ };
1463
+ jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
1658
1464
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
1659
1465
  wrapper: createWrapper({
1660
1466
  autoGenerateThreadName: false,
@@ -1686,12 +1492,33 @@ describe("TamboThreadProvider", () => {
1686
1492
  }), false);
1687
1493
  });
1688
1494
  await (0, react_1.act)(async () => {
1689
- await result.current.sendThreadMessage("Test message");
1495
+ await result.current.sendThreadMessage("Test message", {
1496
+ streamResponse: true,
1497
+ });
1690
1498
  });
1691
1499
  // Should NOT generate name because feature is disabled
1692
1500
  expect(mockThreadsApi.generateName).not.toHaveBeenCalled();
1693
1501
  });
1694
1502
  it("should NOT auto-generate when thread already has a name", async () => {
1503
+ const mockStreamResponse = {
1504
+ responseMessageDto: {
1505
+ id: "response-1",
1506
+ content: [{ type: "text", text: "Response" }],
1507
+ role: "assistant",
1508
+ threadId: "test-thread-1",
1509
+ component: undefined,
1510
+ componentState: {},
1511
+ createdAt: new Date().toISOString(),
1512
+ },
1513
+ generationStage: generate_component_response_1.GenerationStage.COMPLETE,
1514
+ mcpAccessToken: "test-mcp-access-token",
1515
+ };
1516
+ const mockAsyncIterator = {
1517
+ [Symbol.asyncIterator]: async function* () {
1518
+ yield mockStreamResponse;
1519
+ },
1520
+ };
1521
+ jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
1695
1522
  const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
1696
1523
  wrapper: createWrapper({ autoGenerateNameThreshold: 2 }),
1697
1524
  });
@@ -1725,7 +1552,9 @@ describe("TamboThreadProvider", () => {
1725
1552
  expect(result.current.thread.messages).toHaveLength(2);
1726
1553
  // Send another message to reach threshold (3 messages total)
1727
1554
  await (0, react_1.act)(async () => {
1728
- await result.current.sendThreadMessage("Test message");
1555
+ await result.current.sendThreadMessage("Test message", {
1556
+ streamResponse: true,
1557
+ });
1729
1558
  });
1730
1559
  // Should NOT generate name because thread already has one
1731
1560
  expect(mockThreadsApi.generateName).not.toHaveBeenCalled();