@tambo-ai/react 0.73.0 → 0.74.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. package/README.md +12 -12
  2. package/dist/hooks/use-component-state.d.ts +1 -1
  3. package/dist/hooks/use-component-state.js.map +1 -1
  4. package/dist/hooks/use-streaming-props.d.ts +1 -1
  5. package/dist/hooks/use-streaming-props.js +1 -1
  6. package/dist/hooks/use-streaming-props.js.map +1 -1
  7. package/dist/hooks/use-tambo-stream-status.d.ts +1 -1
  8. package/dist/hooks/use-tambo-stream-status.js +1 -1
  9. package/dist/hooks/use-tambo-stream-status.js.map +1 -1
  10. package/dist/mcp/mcp-hooks.d.ts +4 -0
  11. package/dist/mcp/mcp-hooks.d.ts.map +1 -1
  12. package/dist/mcp/mcp-hooks.js +4 -0
  13. package/dist/mcp/mcp-hooks.js.map +1 -1
  14. package/dist/providers/tambo-interactable-provider-partial-updates.test.js +3 -3
  15. package/dist/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
  16. package/dist/providers/tambo-interactable-provider.js +2 -2
  17. package/dist/providers/tambo-interactable-provider.js.map +1 -1
  18. package/dist/providers/tambo-interactable-provider.test.js +3 -3
  19. package/dist/providers/tambo-interactable-provider.test.js.map +1 -1
  20. package/dist/providers/tambo-provider.d.ts +3 -0
  21. package/dist/providers/tambo-provider.d.ts.map +1 -1
  22. package/dist/providers/tambo-provider.js +3 -0
  23. package/dist/providers/tambo-provider.js.map +1 -1
  24. package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
  25. package/dist/providers/tambo-thread-input-provider.js +1 -0
  26. package/dist/providers/tambo-thread-input-provider.js.map +1 -1
  27. package/dist/util/resource-content-resolver.d.ts.map +1 -1
  28. package/dist/util/resource-content-resolver.js +2 -0
  29. package/dist/util/resource-content-resolver.js.map +1 -1
  30. package/dist/v1/__tests__/v1-interactables.test.d.ts +2 -0
  31. package/dist/v1/__tests__/v1-interactables.test.d.ts.map +1 -0
  32. package/dist/v1/__tests__/v1-interactables.test.js +135 -0
  33. package/dist/v1/__tests__/v1-interactables.test.js.map +1 -0
  34. package/dist/v1/components/v1-component-renderer.d.ts +48 -0
  35. package/dist/v1/components/v1-component-renderer.d.ts.map +1 -0
  36. package/dist/v1/components/v1-component-renderer.js +137 -0
  37. package/dist/v1/components/v1-component-renderer.js.map +1 -0
  38. package/dist/v1/components/v1-component-renderer.test.d.ts +2 -0
  39. package/dist/v1/components/v1-component-renderer.test.d.ts.map +1 -0
  40. package/dist/v1/components/v1-component-renderer.test.js +270 -0
  41. package/dist/v1/components/v1-component-renderer.test.js.map +1 -0
  42. package/dist/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
  43. package/dist/v1/hooks/use-tambo-v1-component-state.js +2 -25
  44. package/dist/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
  45. package/dist/v1/hooks/use-tambo-v1-component-state.test.js +2 -1
  46. package/dist/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
  47. package/dist/v1/hooks/use-tambo-v1-messages.test.js +25 -1
  48. package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  49. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +18 -0
  50. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  51. package/dist/v1/hooks/use-tambo-v1-send-message.js +204 -17
  52. package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  53. package/dist/v1/hooks/use-tambo-v1-send-message.test.js +261 -7
  54. package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  55. package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts +90 -0
  56. package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -0
  57. package/dist/v1/hooks/use-tambo-v1-stream-status.js +179 -0
  58. package/dist/v1/hooks/use-tambo-v1-stream-status.js.map +1 -0
  59. package/dist/v1/hooks/use-tambo-v1-stream-status.test.d.ts +2 -0
  60. package/dist/v1/hooks/use-tambo-v1-stream-status.test.d.ts.map +1 -0
  61. package/dist/v1/hooks/use-tambo-v1-stream-status.test.js +371 -0
  62. package/dist/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -0
  63. package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts +78 -54
  64. package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
  65. package/dist/v1/hooks/use-tambo-v1-suggestions.js +153 -87
  66. package/dist/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
  67. package/dist/v1/hooks/use-tambo-v1-suggestions.test.js +213 -134
  68. package/dist/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
  69. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +148 -13
  70. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  71. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +8 -21
  72. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  73. package/dist/v1/hooks/use-tambo-v1-thread-list.js +11 -10
  74. package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  75. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +37 -2
  76. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  77. package/dist/v1/hooks/use-tambo-v1-thread.d.ts +1 -1
  78. package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
  79. package/dist/v1/hooks/use-tambo-v1-thread.js +2 -7
  80. package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -1
  81. package/dist/v1/hooks/use-tambo-v1-thread.test.js +2 -0
  82. package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
  83. package/dist/v1/hooks/use-tambo-v1.d.ts +12 -28
  84. package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -1
  85. package/dist/v1/hooks/use-tambo-v1.js +164 -31
  86. package/dist/v1/hooks/use-tambo-v1.js.map +1 -1
  87. package/dist/v1/hooks/use-tambo-v1.test.js +891 -18
  88. package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
  89. package/dist/v1/index.d.ts +7 -1
  90. package/dist/v1/index.d.ts.map +1 -1
  91. package/dist/v1/index.js +18 -1
  92. package/dist/v1/index.js.map +1 -1
  93. package/dist/v1/providers/tambo-v1-provider.d.ts +16 -6
  94. package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  95. package/dist/v1/providers/tambo-v1-provider.js +14 -19
  96. package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
  97. package/dist/v1/providers/tambo-v1-provider.test.js +34 -20
  98. package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
  99. package/dist/v1/providers/tambo-v1-stream-context.d.ts +3 -3
  100. package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  101. package/dist/v1/providers/tambo-v1-stream-context.js +60 -12
  102. package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
  103. package/dist/v1/providers/tambo-v1-stream-context.test.js +49 -20
  104. package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  105. package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
  106. package/dist/v1/providers/tambo-v1-stub-provider.js +2 -0
  107. package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -1
  108. package/dist/v1/providers/tambo-v1-stub-provider.test.js +7 -6
  109. package/dist/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
  110. package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +1 -6
  111. package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
  112. package/dist/v1/providers/tambo-v1-thread-input-provider.js +14 -12
  113. package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
  114. package/dist/v1/types/event.d.ts +9 -1
  115. package/dist/v1/types/event.d.ts.map +1 -1
  116. package/dist/v1/types/event.js.map +1 -1
  117. package/dist/v1/types/event.test.js +5 -1
  118. package/dist/v1/types/event.test.js.map +1 -1
  119. package/dist/v1/types/message.d.ts +65 -7
  120. package/dist/v1/types/message.d.ts.map +1 -1
  121. package/dist/v1/types/message.js.map +1 -1
  122. package/dist/v1/types/thread.d.ts +4 -0
  123. package/dist/v1/types/thread.d.ts.map +1 -1
  124. package/dist/v1/types/thread.js.map +1 -1
  125. package/dist/v1/utils/event-accumulator.d.ts +40 -4
  126. package/dist/v1/utils/event-accumulator.d.ts.map +1 -1
  127. package/dist/v1/utils/event-accumulator.js +444 -35
  128. package/dist/v1/utils/event-accumulator.js.map +1 -1
  129. package/dist/v1/utils/event-accumulator.test.js +1041 -28
  130. package/dist/v1/utils/event-accumulator.test.js.map +1 -1
  131. package/dist/v1/utils/registry-conversion.d.ts +9 -9
  132. package/dist/v1/utils/registry-conversion.d.ts.map +1 -1
  133. package/dist/v1/utils/registry-conversion.js +10 -11
  134. package/dist/v1/utils/registry-conversion.js.map +1 -1
  135. package/dist/v1/utils/registry-conversion.test.js +39 -11
  136. package/dist/v1/utils/registry-conversion.test.js.map +1 -1
  137. package/dist/v1/utils/thread-utils.d.ts +16 -0
  138. package/dist/v1/utils/thread-utils.d.ts.map +1 -0
  139. package/dist/v1/utils/thread-utils.js +34 -0
  140. package/dist/v1/utils/thread-utils.js.map +1 -0
  141. package/dist/v1/utils/tool-executor.d.ts.map +1 -1
  142. package/dist/v1/utils/tool-executor.js +2 -0
  143. package/dist/v1/utils/tool-executor.js.map +1 -1
  144. package/dist/v1/utils/tool-executor.test.js +5 -0
  145. package/dist/v1/utils/tool-executor.test.js.map +1 -1
  146. package/esm/context-helpers/context-helpers-provider.test.js +2 -2
  147. package/esm/context-helpers/context-helpers.test.js +1 -1
  148. package/esm/context-helpers/current-interactables-context-helper.d.ts +1 -1
  149. package/esm/context-helpers/current-page-context-helper.d.ts +1 -1
  150. package/esm/context-helpers/current-time-context-helper.d.ts +1 -1
  151. package/esm/context-helpers/index.d.ts +4 -4
  152. package/esm/context-helpers/index.js +4 -4
  153. package/esm/hoc/with-tambo-interactable.d.ts +1 -1
  154. package/esm/hoc/with-tambo-interactable.js +2 -2
  155. package/esm/hoc/with-tambo-interactable.test.js +3 -3
  156. package/esm/hooks/index.d.ts +8 -8
  157. package/esm/hooks/index.js +8 -8
  158. package/esm/hooks/react-query-hooks.js +1 -1
  159. package/esm/hooks/use-component-state.d.ts +1 -1
  160. package/esm/hooks/use-component-state.js +3 -3
  161. package/esm/hooks/use-component-state.js.map +1 -1
  162. package/esm/hooks/use-component-state.test.js +5 -5
  163. package/esm/hooks/use-current-message.d.ts +1 -1
  164. package/esm/hooks/use-current-message.test.js +1 -1
  165. package/esm/hooks/use-message-images.test.js +1 -1
  166. package/esm/hooks/use-streaming-props.d.ts +1 -1
  167. package/esm/hooks/use-streaming-props.js +1 -1
  168. package/esm/hooks/use-streaming-props.js.map +1 -1
  169. package/esm/hooks/use-suggestions.d.ts +2 -2
  170. package/esm/hooks/use-suggestions.js +10 -10
  171. package/esm/hooks/use-suggestions.test.js +7 -7
  172. package/esm/hooks/use-tambo-stream-status.d.ts +1 -1
  173. package/esm/hooks/use-tambo-stream-status.js +4 -4
  174. package/esm/hooks/use-tambo-stream-status.js.map +1 -1
  175. package/esm/hooks/use-tambo-stream-status.test.js +4 -4
  176. package/esm/hooks/use-tambo-threads.js +3 -3
  177. package/esm/hooks/use-tambo-threads.test.js +3 -3
  178. package/esm/hooks/use-tambo-voice.js +2 -2
  179. package/esm/hooks/use-tambo-voice.test.js +3 -3
  180. package/esm/index.d.ts +22 -22
  181. package/esm/index.js +15 -15
  182. package/esm/mcp/elicitation.d.ts +1 -1
  183. package/esm/mcp/elicitation.test.js +1 -1
  184. package/esm/mcp/index.d.ts +7 -7
  185. package/esm/mcp/index.js +3 -3
  186. package/esm/mcp/mcp-client.d.ts +1 -1
  187. package/esm/mcp/mcp-client.js +1 -1
  188. package/esm/mcp/mcp-client.test.js +1 -1
  189. package/esm/mcp/mcp-hooks.d.ts +5 -1
  190. package/esm/mcp/mcp-hooks.d.ts.map +1 -1
  191. package/esm/mcp/mcp-hooks.js +8 -4
  192. package/esm/mcp/mcp-hooks.js.map +1 -1
  193. package/esm/mcp/mcp-hooks.test.js +6 -6
  194. package/esm/mcp/tambo-mcp-provider.d.ts +4 -4
  195. package/esm/mcp/tambo-mcp-provider.js +7 -7
  196. package/esm/mcp/tambo-mcp-provider.test.js +5 -5
  197. package/esm/mcp/use-mcp-servers.test.js +4 -4
  198. package/esm/model/generate-component-response.d.ts +1 -1
  199. package/esm/model/tambo-interactable.d.ts +1 -1
  200. package/esm/model/tambo-thread.d.ts +1 -1
  201. package/esm/providers/__tests__/thread-input-resource-resolution.test.js +3 -3
  202. package/esm/providers/hooks/use-tambo-session-token.test.js +1 -1
  203. package/esm/providers/index.d.ts +12 -12
  204. package/esm/providers/index.js +10 -10
  205. package/esm/providers/tambo-client-provider.js +1 -1
  206. package/esm/providers/tambo-client-provider.test.js +2 -2
  207. package/esm/providers/tambo-component-provider.d.ts +1 -1
  208. package/esm/providers/tambo-component-provider.js +2 -2
  209. package/esm/providers/tambo-context-attachment-provider.js +1 -1
  210. package/esm/providers/tambo-context-attachment-provider.test.js +2 -2
  211. package/esm/providers/tambo-context-helpers-provider.d.ts +1 -1
  212. package/esm/providers/tambo-context-helpers-provider.js +1 -1
  213. package/esm/providers/tambo-context-helpers-provider.test.js +2 -2
  214. package/esm/providers/tambo-interactable-provider-partial-updates.test.js +4 -4
  215. package/esm/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
  216. package/esm/providers/tambo-interactable-provider.d.ts +5 -5
  217. package/esm/providers/tambo-interactable-provider.js +6 -6
  218. package/esm/providers/tambo-interactable-provider.js.map +1 -1
  219. package/esm/providers/tambo-interactable-provider.test.js +4 -4
  220. package/esm/providers/tambo-interactable-provider.test.js.map +1 -1
  221. package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js +4 -4
  222. package/esm/providers/tambo-interactables-additional-context.test.js +4 -4
  223. package/esm/providers/tambo-mcp-token-provider.js +2 -2
  224. package/esm/providers/tambo-prop-stream-provider/index.d.ts +8 -8
  225. package/esm/providers/tambo-prop-stream-provider/index.js +9 -9
  226. package/esm/providers/tambo-prop-stream-provider/pending.d.ts +1 -1
  227. package/esm/providers/tambo-prop-stream-provider/pending.js +2 -2
  228. package/esm/providers/tambo-prop-stream-provider/provider.d.ts +1 -1
  229. package/esm/providers/tambo-prop-stream-provider/provider.js +2 -2
  230. package/esm/providers/tambo-prop-stream-provider/streaming.d.ts +1 -1
  231. package/esm/providers/tambo-prop-stream-provider/streaming.js +2 -2
  232. package/esm/providers/tambo-prop-stream-provider/success.d.ts +1 -1
  233. package/esm/providers/tambo-prop-stream-provider/success.js +2 -2
  234. package/esm/providers/tambo-prop-stream-provider/types.d.ts +1 -1
  235. package/esm/providers/tambo-prop-stream-provider.test.js +4 -4
  236. package/esm/providers/tambo-provider.d.ts +10 -7
  237. package/esm/providers/tambo-provider.d.ts.map +1 -1
  238. package/esm/providers/tambo-provider.js +13 -10
  239. package/esm/providers/tambo-provider.js.map +1 -1
  240. package/esm/providers/tambo-registry-provider.d.ts +3 -3
  241. package/esm/providers/tambo-registry-provider.js +3 -3
  242. package/esm/providers/tambo-registry-provider.test.js +2 -2
  243. package/esm/providers/tambo-registry-schema-compat.test.js +2 -2
  244. package/esm/providers/tambo-stubs.d.ts +4 -4
  245. package/esm/providers/tambo-stubs.js +9 -9
  246. package/esm/providers/tambo-stubs.test.js +2 -2
  247. package/esm/providers/tambo-thread-input-provider.d.ts +2 -2
  248. package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
  249. package/esm/providers/tambo-thread-input-provider.js +11 -10
  250. package/esm/providers/tambo-thread-input-provider.js.map +1 -1
  251. package/esm/providers/tambo-thread-provider-initial-messages.test.js +6 -6
  252. package/esm/providers/tambo-thread-provider.d.ts +2 -2
  253. package/esm/providers/tambo-thread-provider.js +8 -8
  254. package/esm/providers/tambo-thread-provider.test.js +7 -7
  255. package/esm/schema/index.d.ts +4 -4
  256. package/esm/schema/index.js +4 -4
  257. package/esm/schema/json-schema.test.js +1 -1
  258. package/esm/schema/schema.d.ts +1 -1
  259. package/esm/schema/schema.js +2 -2
  260. package/esm/schema/schema.test.js +3 -3
  261. package/esm/schema/standard-schema.test.js +1 -1
  262. package/esm/schema/validate.js +2 -2
  263. package/esm/schema/validate.test.js +1 -1
  264. package/esm/testing/tools.d.ts +3 -3
  265. package/esm/testing/tools.js +2 -2
  266. package/esm/util/content-parts.test.js +1 -1
  267. package/esm/util/generate-component.d.ts +2 -2
  268. package/esm/util/generate-component.js +4 -4
  269. package/esm/util/generate-component.test.js +2 -2
  270. package/esm/util/is-promise.test.js +1 -1
  271. package/esm/util/mcp-server-utils.d.ts +1 -1
  272. package/esm/util/mcp-server-utils.js +1 -1
  273. package/esm/util/mcp-server-utils.test.js +2 -2
  274. package/esm/util/message-builder.d.ts +1 -1
  275. package/esm/util/message-builder.test.js +1 -1
  276. package/esm/util/query-utils.test.js +1 -1
  277. package/esm/util/registry-validators.d.ts +1 -1
  278. package/esm/util/registry-validators.js +2 -2
  279. package/esm/util/registry-validators.test.js +1 -1
  280. package/esm/util/registry.d.ts +1 -1
  281. package/esm/util/registry.js +1 -1
  282. package/esm/util/registry.test.js +2 -2
  283. package/esm/util/resource-content-resolver.d.ts +2 -2
  284. package/esm/util/resource-content-resolver.d.ts.map +1 -1
  285. package/esm/util/resource-content-resolver.js +3 -1
  286. package/esm/util/resource-content-resolver.js.map +1 -1
  287. package/esm/util/resource-content-resolver.test.js +3 -3
  288. package/esm/util/resource-validators.d.ts +1 -1
  289. package/esm/util/resource-validators.test.js +1 -1
  290. package/esm/util/tool-caller.d.ts +1 -1
  291. package/esm/util/tool-caller.js +1 -1
  292. package/esm/util/validate-component-name.test.js +1 -1
  293. package/esm/v1/__tests__/v1-interactables.test.d.ts +2 -0
  294. package/esm/v1/__tests__/v1-interactables.test.d.ts.map +1 -0
  295. package/esm/v1/__tests__/v1-interactables.test.js +130 -0
  296. package/esm/v1/__tests__/v1-interactables.test.js.map +1 -0
  297. package/esm/v1/components/v1-component-renderer.d.ts +48 -0
  298. package/esm/v1/components/v1-component-renderer.d.ts.map +1 -0
  299. package/esm/v1/components/v1-component-renderer.js +100 -0
  300. package/esm/v1/components/v1-component-renderer.js.map +1 -0
  301. package/esm/v1/components/v1-component-renderer.test.d.ts +2 -0
  302. package/esm/v1/components/v1-component-renderer.test.d.ts.map +1 -0
  303. package/esm/v1/components/v1-component-renderer.test.js +265 -0
  304. package/esm/v1/components/v1-component-renderer.test.js.map +1 -0
  305. package/esm/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
  306. package/esm/v1/hooks/use-tambo-v1-component-state.js +4 -27
  307. package/esm/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
  308. package/esm/v1/hooks/use-tambo-v1-component-state.test.js +6 -5
  309. package/esm/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
  310. package/esm/v1/hooks/use-tambo-v1-messages.d.ts +1 -1
  311. package/esm/v1/hooks/use-tambo-v1-messages.js +1 -1
  312. package/esm/v1/hooks/use-tambo-v1-messages.test.js +27 -3
  313. package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  314. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +20 -2
  315. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  316. package/esm/v1/hooks/use-tambo-v1-send-message.js +213 -26
  317. package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  318. package/esm/v1/hooks/use-tambo-v1-send-message.test.js +266 -12
  319. package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  320. package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts +90 -0
  321. package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -0
  322. package/esm/v1/hooks/use-tambo-v1-stream-status.js +176 -0
  323. package/esm/v1/hooks/use-tambo-v1-stream-status.js.map +1 -0
  324. package/esm/v1/hooks/use-tambo-v1-stream-status.test.d.ts +2 -0
  325. package/esm/v1/hooks/use-tambo-v1-stream-status.test.d.ts.map +1 -0
  326. package/esm/v1/hooks/use-tambo-v1-stream-status.test.js +369 -0
  327. package/esm/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -0
  328. package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts +78 -54
  329. package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
  330. package/esm/v1/hooks/use-tambo-v1-suggestions.js +157 -91
  331. package/esm/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
  332. package/esm/v1/hooks/use-tambo-v1-suggestions.test.js +218 -139
  333. package/esm/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
  334. package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts +1 -1
  335. package/esm/v1/hooks/use-tambo-v1-thread-input.js +1 -1
  336. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +151 -16
  337. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  338. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +8 -21
  339. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  340. package/esm/v1/hooks/use-tambo-v1-thread-list.js +12 -11
  341. package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  342. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +39 -4
  343. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  344. package/esm/v1/hooks/use-tambo-v1-thread.d.ts +1 -1
  345. package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
  346. package/esm/v1/hooks/use-tambo-v1-thread.js +3 -8
  347. package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -1
  348. package/esm/v1/hooks/use-tambo-v1-thread.test.js +4 -2
  349. package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
  350. package/esm/v1/hooks/use-tambo-v1.d.ts +15 -31
  351. package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -1
  352. package/esm/v1/hooks/use-tambo-v1.js +134 -34
  353. package/esm/v1/hooks/use-tambo-v1.js.map +1 -1
  354. package/esm/v1/hooks/use-tambo-v1.test.js +862 -19
  355. package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
  356. package/esm/v1/index.d.ts +28 -22
  357. package/esm/v1/index.d.ts.map +1 -1
  358. package/esm/v1/index.js +30 -18
  359. package/esm/v1/index.js.map +1 -1
  360. package/esm/v1/providers/tambo-v1-provider.d.ts +21 -11
  361. package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  362. package/esm/v1/providers/tambo-v1-provider.js +20 -25
  363. package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
  364. package/esm/v1/providers/tambo-v1-provider.test.js +40 -26
  365. package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
  366. package/esm/v1/providers/tambo-v1-stream-context.d.ts +4 -4
  367. package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  368. package/esm/v1/providers/tambo-v1-stream-context.js +62 -14
  369. package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
  370. package/esm/v1/providers/tambo-v1-stream-context.test.js +50 -21
  371. package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  372. package/esm/v1/providers/tambo-v1-stub-provider.d.ts +3 -3
  373. package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
  374. package/esm/v1/providers/tambo-v1-stub-provider.js +7 -5
  375. package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -1
  376. package/esm/v1/providers/tambo-v1-stub-provider.test.js +12 -11
  377. package/esm/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
  378. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +3 -8
  379. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
  380. package/esm/v1/providers/tambo-v1-thread-input-provider.js +18 -16
  381. package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
  382. package/esm/v1/types/event.d.ts +9 -1
  383. package/esm/v1/types/event.d.ts.map +1 -1
  384. package/esm/v1/types/event.js.map +1 -1
  385. package/esm/v1/types/event.test.js +6 -2
  386. package/esm/v1/types/event.test.js.map +1 -1
  387. package/esm/v1/types/message.d.ts +65 -7
  388. package/esm/v1/types/message.d.ts.map +1 -1
  389. package/esm/v1/types/message.js.map +1 -1
  390. package/esm/v1/types/thread.d.ts +5 -1
  391. package/esm/v1/types/thread.d.ts.map +1 -1
  392. package/esm/v1/types/thread.js.map +1 -1
  393. package/esm/v1/utils/component-renderer.test.js +1 -1
  394. package/esm/v1/utils/event-accumulator.d.ts +41 -5
  395. package/esm/v1/utils/event-accumulator.d.ts.map +1 -1
  396. package/esm/v1/utils/event-accumulator.js +444 -36
  397. package/esm/v1/utils/event-accumulator.js.map +1 -1
  398. package/esm/v1/utils/event-accumulator.test.js +1042 -29
  399. package/esm/v1/utils/event-accumulator.test.js.map +1 -1
  400. package/esm/v1/utils/json-patch.test.js +1 -1
  401. package/esm/v1/utils/registry-conversion.d.ts +9 -9
  402. package/esm/v1/utils/registry-conversion.d.ts.map +1 -1
  403. package/esm/v1/utils/registry-conversion.js +11 -12
  404. package/esm/v1/utils/registry-conversion.js.map +1 -1
  405. package/esm/v1/utils/registry-conversion.test.js +40 -12
  406. package/esm/v1/utils/registry-conversion.test.js.map +1 -1
  407. package/esm/v1/utils/stream-handler.test.js +1 -1
  408. package/esm/v1/utils/thread-utils.d.ts +16 -0
  409. package/esm/v1/utils/thread-utils.d.ts.map +1 -0
  410. package/esm/v1/utils/thread-utils.js +31 -0
  411. package/esm/v1/utils/thread-utils.js.map +1 -0
  412. package/esm/v1/utils/tool-call-tracker.d.ts +1 -1
  413. package/esm/v1/utils/tool-executor.d.ts +1 -1
  414. package/esm/v1/utils/tool-executor.d.ts.map +1 -1
  415. package/esm/v1/utils/tool-executor.js +2 -0
  416. package/esm/v1/utils/tool-executor.js.map +1 -1
  417. package/esm/v1/utils/tool-executor.test.js +6 -1
  418. package/esm/v1/utils/tool-executor.test.js.map +1 -1
  419. package/package.json +11 -10
@@ -1,11 +1,12 @@
1
1
  import { renderHook, act, waitFor } from "@testing-library/react";
2
2
  import React from "react";
3
3
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
- import { useTamboV1Suggestions } from "./use-tambo-v1-suggestions";
5
- import { useTamboV1ThreadInput } from "./use-tambo-v1-thread-input";
6
- import { useTamboV1 } from "./use-tambo-v1";
7
- import { useTamboClient } from "../../providers/tambo-client-provider";
8
- import { useTamboRegistry } from "../../providers/tambo-registry-provider";
4
+ import { useTamboV1Suggestions } from "./use-tambo-v1-suggestions.js";
5
+ import { useTamboV1ThreadInput } from "./use-tambo-v1-thread-input.js";
6
+ import { useTamboV1 } from "./use-tambo-v1.js";
7
+ import { useTamboClient, useTamboQueryClient, } from "../../providers/tambo-client-provider.js";
8
+ import { useTamboRegistry } from "../../providers/tambo-registry-provider.js";
9
+ import { useTamboV1Config } from "../providers/tambo-v1-provider.js";
9
10
  // Mock dependencies
10
11
  jest.mock("./use-tambo-v1-thread-input", () => ({
11
12
  useTamboV1ThreadInput: jest.fn(),
@@ -20,11 +21,34 @@ jest.mock("../../providers/tambo-client-provider", () => ({
20
21
  jest.mock("../../providers/tambo-registry-provider", () => ({
21
22
  useTamboRegistry: jest.fn(),
22
23
  }));
24
+ jest.mock("../providers/tambo-v1-provider", () => ({
25
+ useTamboV1Config: jest.fn(),
26
+ }));
23
27
  describe("useTamboV1Suggestions", () => {
24
28
  let queryClient;
25
29
  const mockSetValue = jest.fn();
26
30
  const mockSubmit = jest.fn();
27
- const mockGenerateSuggestions = jest.fn();
31
+ const mockListSuggestions = jest.fn();
32
+ const mockCreateSuggestions = jest.fn();
33
+ const mockSuggestions = [
34
+ {
35
+ id: "suggestion_1",
36
+ messageId: "msg_1",
37
+ title: "What's the weather?",
38
+ detailedSuggestion: "What's the weather like today?",
39
+ },
40
+ {
41
+ id: "suggestion_2",
42
+ messageId: "msg_1",
43
+ title: "Tell me a joke",
44
+ detailedSuggestion: "Can you tell me a funny joke?",
45
+ },
46
+ ];
47
+ const mockSuggestionsResponse = {
48
+ suggestions: mockSuggestions,
49
+ hasMore: false,
50
+ nextCursor: undefined,
51
+ };
28
52
  function createWrapper() {
29
53
  return function Wrapper({ children }) {
30
54
  return (React.createElement(QueryClientProvider, { client: queryClient }, children));
@@ -38,21 +62,20 @@ describe("useTamboV1Suggestions", () => {
38
62
  mutations: { retry: false },
39
63
  },
40
64
  });
65
+ // Mock useTamboQueryClient to return the test's queryClient
66
+ jest.mocked(useTamboQueryClient).mockReturnValue(queryClient);
67
+ // Default mock for v1 config
68
+ jest.mocked(useTamboV1Config).mockReturnValue({ userKey: "user_123" });
41
69
  // Default mock for thread input
42
70
  jest.mocked(useTamboV1ThreadInput).mockReturnValue({
43
71
  value: "",
44
72
  setValue: mockSetValue,
45
73
  submit: mockSubmit,
46
- threadId: "thread_123",
47
- setThreadId: jest.fn(),
48
- images: [],
49
- addImage: jest.fn(),
50
- addImages: jest.fn(),
51
- removeImage: jest.fn(),
52
- clearImages: jest.fn(),
53
74
  isPending: false,
54
75
  isError: false,
55
- error: undefined,
76
+ error: null,
77
+ isSuccess: false,
78
+ reset: jest.fn(),
56
79
  });
57
80
  // Default mock for useTamboV1
58
81
  jest.mocked(useTamboV1).mockReturnValue({
@@ -60,6 +83,7 @@ describe("useTamboV1Suggestions", () => {
60
83
  thread: undefined,
61
84
  isIdle: true,
62
85
  isStreaming: false,
86
+ currentThreadId: "thread_123",
63
87
  startNewThread: jest.fn(),
64
88
  switchThread: jest.fn(),
65
89
  initThread: jest.fn(),
@@ -86,30 +110,39 @@ describe("useTamboV1Suggestions", () => {
86
110
  unregisterResource: jest.fn(),
87
111
  setResourceSource: jest.fn(),
88
112
  });
89
- // Default mock for client
90
- mockGenerateSuggestions.mockResolvedValue([
91
- {
92
- id: "suggestion_1",
93
- suggestion: "What's the weather?",
94
- detailedSuggestion: "What's the weather like today?",
95
- },
96
- {
97
- id: "suggestion_2",
98
- suggestion: "Tell me a joke",
99
- detailedSuggestion: "Can you tell me a funny joke?",
100
- },
101
- ]);
113
+ // Default mock for client - using v1 API structure
114
+ mockListSuggestions.mockResolvedValue({ suggestions: [], hasMore: false });
115
+ mockCreateSuggestions.mockResolvedValue(mockSuggestionsResponse);
102
116
  jest.mocked(useTamboClient).mockReturnValue({
103
- beta: {
104
- threads: {
105
- suggestions: {
106
- generate: mockGenerateSuggestions,
107
- },
117
+ threads: {
118
+ suggestions: {
119
+ list: mockListSuggestions,
120
+ create: mockCreateSuggestions,
108
121
  },
109
122
  },
110
123
  });
111
124
  });
112
125
  describe("Initial State", () => {
126
+ it("returns empty suggestions when thread has placeholder ID", () => {
127
+ // Mock useTamboV1 to return placeholder thread ID
128
+ jest.mocked(useTamboV1).mockReturnValue({
129
+ messages: [],
130
+ thread: undefined,
131
+ isIdle: true,
132
+ isStreaming: false,
133
+ currentThreadId: "placeholder",
134
+ startNewThread: jest.fn(),
135
+ switchThread: jest.fn(),
136
+ initThread: jest.fn(),
137
+ streamingState: { status: "idle" },
138
+ });
139
+ const { result } = renderHook(() => useTamboV1Suggestions(), {
140
+ wrapper: createWrapper(),
141
+ });
142
+ expect(result.current.suggestions).toEqual([]);
143
+ expect(result.current.selectedSuggestionId).toBeNull();
144
+ expect(result.current.isLoading).toBe(false);
145
+ });
113
146
  it("returns empty suggestions when no messages", () => {
114
147
  const { result } = renderHook(() => useTamboV1Suggestions(), {
115
148
  wrapper: createWrapper(),
@@ -130,12 +163,11 @@ describe("useTamboV1Suggestions", () => {
130
163
  thread: undefined,
131
164
  isIdle: true,
132
165
  isStreaming: false,
166
+ currentThreadId: "thread_123",
133
167
  startNewThread: jest.fn(),
134
168
  switchThread: jest.fn(),
135
169
  initThread: jest.fn(),
136
- streamingState: {
137
- status: "idle",
138
- },
170
+ streamingState: { status: "idle" },
139
171
  });
140
172
  const { result } = renderHook(() => useTamboV1Suggestions(), {
141
173
  wrapper: createWrapper(),
@@ -157,12 +189,11 @@ describe("useTamboV1Suggestions", () => {
157
189
  thread: undefined,
158
190
  isIdle: true,
159
191
  isStreaming: false,
192
+ currentThreadId: "thread_123",
160
193
  startNewThread: jest.fn(),
161
194
  switchThread: jest.fn(),
162
195
  initThread: jest.fn(),
163
- streamingState: {
164
- status: "idle",
165
- },
196
+ streamingState: { status: "idle" },
166
197
  });
167
198
  const { result } = renderHook(() => useTamboV1Suggestions(), {
168
199
  wrapper: createWrapper(),
@@ -170,11 +201,46 @@ describe("useTamboV1Suggestions", () => {
170
201
  await waitFor(() => {
171
202
  expect(result.current.suggestions).toHaveLength(2);
172
203
  });
173
- expect(mockGenerateSuggestions).toHaveBeenCalledWith("msg_1", expect.objectContaining({
174
- id: "thread_123",
204
+ // Should first call list, then create since list returns empty
205
+ expect(mockListSuggestions).toHaveBeenCalledWith("msg_1", {
206
+ threadId: "thread_123",
207
+ userKey: "user_123",
208
+ });
209
+ expect(mockCreateSuggestions).toHaveBeenCalledWith("msg_1", expect.objectContaining({
210
+ threadId: "thread_123",
175
211
  maxSuggestions: 3,
212
+ userKey: "user_123",
176
213
  }));
177
214
  });
215
+ it("returns existing suggestions from list without calling create", async () => {
216
+ mockListSuggestions.mockResolvedValue(mockSuggestionsResponse);
217
+ jest.mocked(useTamboV1).mockReturnValue({
218
+ messages: [
219
+ {
220
+ id: "msg_1",
221
+ role: "assistant",
222
+ content: [],
223
+ createdAt: "2024-01-01T00:00:00Z",
224
+ },
225
+ ],
226
+ thread: undefined,
227
+ isIdle: true,
228
+ isStreaming: false,
229
+ currentThreadId: "thread_123",
230
+ startNewThread: jest.fn(),
231
+ switchThread: jest.fn(),
232
+ initThread: jest.fn(),
233
+ streamingState: { status: "idle" },
234
+ });
235
+ const { result } = renderHook(() => useTamboV1Suggestions(), {
236
+ wrapper: createWrapper(),
237
+ });
238
+ await waitFor(() => {
239
+ expect(result.current.suggestions).toHaveLength(2);
240
+ });
241
+ expect(mockListSuggestions).toHaveBeenCalled();
242
+ expect(mockCreateSuggestions).not.toHaveBeenCalled();
243
+ });
178
244
  it("does not generate suggestions when thread is streaming", () => {
179
245
  jest.mocked(useTamboV1).mockReturnValue({
180
246
  messages: [
@@ -188,35 +254,19 @@ describe("useTamboV1Suggestions", () => {
188
254
  thread: undefined,
189
255
  isIdle: false,
190
256
  isStreaming: true,
257
+ currentThreadId: "thread_123",
191
258
  startNewThread: jest.fn(),
192
259
  switchThread: jest.fn(),
193
260
  initThread: jest.fn(),
194
- streamingState: {
195
- status: "streaming",
196
- runId: "run_1",
197
- },
261
+ streamingState: { status: "streaming", runId: "run_1" },
198
262
  });
199
263
  renderHook(() => useTamboV1Suggestions(), {
200
264
  wrapper: createWrapper(),
201
265
  });
202
- expect(mockGenerateSuggestions).not.toHaveBeenCalled();
266
+ expect(mockListSuggestions).not.toHaveBeenCalled();
267
+ expect(mockCreateSuggestions).not.toHaveBeenCalled();
203
268
  });
204
- it("does not generate suggestions when no threadId", () => {
205
- jest.mocked(useTamboV1ThreadInput).mockReturnValue({
206
- value: "",
207
- setValue: mockSetValue,
208
- submit: mockSubmit,
209
- threadId: undefined,
210
- setThreadId: jest.fn(),
211
- images: [],
212
- addImage: jest.fn(),
213
- addImages: jest.fn(),
214
- removeImage: jest.fn(),
215
- clearImages: jest.fn(),
216
- isPending: false,
217
- isError: false,
218
- error: undefined,
219
- });
269
+ it("does not generate suggestions when autoGenerate is false", () => {
220
270
  jest.mocked(useTamboV1).mockReturnValue({
221
271
  messages: [
222
272
  {
@@ -229,17 +279,17 @@ describe("useTamboV1Suggestions", () => {
229
279
  thread: undefined,
230
280
  isIdle: true,
231
281
  isStreaming: false,
282
+ currentThreadId: "thread_123",
232
283
  startNewThread: jest.fn(),
233
284
  switchThread: jest.fn(),
234
285
  initThread: jest.fn(),
235
- streamingState: {
236
- status: "idle",
237
- },
286
+ streamingState: { status: "idle" },
238
287
  });
239
- renderHook(() => useTamboV1Suggestions(), {
288
+ renderHook(() => useTamboV1Suggestions({ autoGenerate: false }), {
240
289
  wrapper: createWrapper(),
241
290
  });
242
- expect(mockGenerateSuggestions).not.toHaveBeenCalled();
291
+ expect(mockListSuggestions).not.toHaveBeenCalled();
292
+ expect(mockCreateSuggestions).not.toHaveBeenCalled();
243
293
  });
244
294
  it("uses custom maxSuggestions option", async () => {
245
295
  jest.mocked(useTamboV1).mockReturnValue({
@@ -254,24 +304,21 @@ describe("useTamboV1Suggestions", () => {
254
304
  thread: undefined,
255
305
  isIdle: true,
256
306
  isStreaming: false,
307
+ currentThreadId: "thread_123",
257
308
  startNewThread: jest.fn(),
258
309
  switchThread: jest.fn(),
259
310
  initThread: jest.fn(),
260
- streamingState: {
261
- status: "idle",
262
- },
311
+ streamingState: { status: "idle" },
263
312
  });
264
313
  const { result } = renderHook(() => useTamboV1Suggestions({ maxSuggestions: 5 }), { wrapper: createWrapper() });
265
314
  await waitFor(() => {
266
315
  expect(result.current.suggestions).toHaveLength(2);
267
316
  });
268
- expect(mockGenerateSuggestions).toHaveBeenCalledWith("msg_1", expect.objectContaining({
269
- maxSuggestions: 5,
270
- }));
317
+ expect(mockCreateSuggestions).toHaveBeenCalledWith("msg_1", expect.objectContaining({ maxSuggestions: 5 }));
271
318
  });
272
319
  });
273
320
  describe("Accepting Suggestions", () => {
274
- it("updates shared input value when accepting without submit", async () => {
321
+ it("updates input value when accepting without submit", async () => {
275
322
  jest.mocked(useTamboV1).mockReturnValue({
276
323
  messages: [
277
324
  {
@@ -284,12 +331,11 @@ describe("useTamboV1Suggestions", () => {
284
331
  thread: undefined,
285
332
  isIdle: true,
286
333
  isStreaming: false,
334
+ currentThreadId: "thread_123",
287
335
  startNewThread: jest.fn(),
288
336
  switchThread: jest.fn(),
289
337
  initThread: jest.fn(),
290
- streamingState: {
291
- status: "idle",
292
- },
338
+ streamingState: { status: "idle" },
293
339
  });
294
340
  const { result } = renderHook(() => useTamboV1Suggestions(), {
295
341
  wrapper: createWrapper(),
@@ -319,12 +365,11 @@ describe("useTamboV1Suggestions", () => {
319
365
  thread: undefined,
320
366
  isIdle: true,
321
367
  isStreaming: false,
368
+ currentThreadId: "thread_123",
322
369
  startNewThread: jest.fn(),
323
370
  switchThread: jest.fn(),
324
371
  initThread: jest.fn(),
325
- streamingState: {
326
- status: "idle",
327
- },
372
+ streamingState: { status: "idle" },
328
373
  });
329
374
  const { result } = renderHook(() => useTamboV1Suggestions(), {
330
375
  wrapper: createWrapper(),
@@ -339,65 +384,40 @@ describe("useTamboV1Suggestions", () => {
339
384
  expect(mockSetValue).toHaveBeenCalledWith("What's the weather like today?");
340
385
  expect(mockSubmit).toHaveBeenCalled();
341
386
  });
342
- it("throws error when suggestion has no detailed content", async () => {
343
- jest.mocked(useTamboV1).mockReturnValue({
344
- messages: [
345
- {
346
- id: "msg_1",
347
- role: "assistant",
348
- content: [],
349
- createdAt: "2024-01-01T00:00:00Z",
350
- },
351
- ],
352
- thread: undefined,
353
- isIdle: true,
354
- isStreaming: false,
355
- startNewThread: jest.fn(),
356
- switchThread: jest.fn(),
357
- initThread: jest.fn(),
358
- streamingState: {
359
- status: "idle",
360
- },
361
- });
387
+ it("throws error when suggestion has no content", async () => {
362
388
  const { result } = renderHook(() => useTamboV1Suggestions(), {
363
389
  wrapper: createWrapper(),
364
390
  });
365
391
  const emptySuggestion = {
366
392
  id: "empty_suggestion",
367
- suggestion: "Empty",
393
+ messageId: "msg_1",
394
+ title: "Empty",
368
395
  detailedSuggestion: "",
369
396
  };
370
- await expect(result.current.accept({ suggestion: emptySuggestion })).rejects.toThrow("Suggestion has no detailed content");
397
+ await expect(result.current.accept({ suggestion: emptySuggestion })).rejects.toThrow("Suggestion has no content");
371
398
  });
372
399
  it("throws error when detailedSuggestion is only whitespace", async () => {
373
- jest.mocked(useTamboV1).mockReturnValue({
374
- messages: [
375
- {
376
- id: "msg_1",
377
- role: "assistant",
378
- content: [],
379
- createdAt: "2024-01-01T00:00:00Z",
380
- },
381
- ],
382
- thread: undefined,
383
- isIdle: true,
384
- isStreaming: false,
385
- startNewThread: jest.fn(),
386
- switchThread: jest.fn(),
387
- initThread: jest.fn(),
388
- streamingState: {
389
- status: "idle",
390
- },
391
- });
392
400
  const { result } = renderHook(() => useTamboV1Suggestions(), {
393
401
  wrapper: createWrapper(),
394
402
  });
395
403
  const whitespaceSuggestion = {
396
404
  id: "whitespace_suggestion",
397
- suggestion: "Whitespace",
405
+ messageId: "msg_1",
406
+ title: "Whitespace",
398
407
  detailedSuggestion: " ",
399
408
  };
400
- await expect(result.current.accept({ suggestion: whitespaceSuggestion })).rejects.toThrow("Suggestion has no detailed content");
409
+ await expect(result.current.accept({ suggestion: whitespaceSuggestion })).rejects.toThrow("Suggestion has no content");
410
+ });
411
+ it("throws error when detailedSuggestion is undefined", async () => {
412
+ const { result } = renderHook(() => useTamboV1Suggestions(), {
413
+ wrapper: createWrapper(),
414
+ });
415
+ const undefinedSuggestion = {
416
+ id: "undefined_suggestion",
417
+ messageId: "msg_1",
418
+ title: "Undefined",
419
+ };
420
+ await expect(result.current.accept({ suggestion: undefinedSuggestion })).rejects.toThrow("Suggestion has no content");
401
421
  });
402
422
  });
403
423
  describe("State Management", () => {
@@ -415,12 +435,11 @@ describe("useTamboV1Suggestions", () => {
415
435
  thread: undefined,
416
436
  isIdle: true,
417
437
  isStreaming: false,
438
+ currentThreadId: "thread_123",
418
439
  startNewThread: jest.fn(),
419
440
  switchThread: jest.fn(),
420
441
  initThread: jest.fn(),
421
- streamingState: {
422
- status: "idle",
423
- },
442
+ streamingState: { status: "idle" },
424
443
  });
425
444
  const { result, rerender } = renderHook(() => useTamboV1Suggestions(), {
426
445
  wrapper: createWrapper(),
@@ -454,19 +473,23 @@ describe("useTamboV1Suggestions", () => {
454
473
  thread: undefined,
455
474
  isIdle: true,
456
475
  isStreaming: false,
476
+ currentThreadId: "thread_123",
457
477
  startNewThread: jest.fn(),
458
478
  switchThread: jest.fn(),
459
479
  initThread: jest.fn(),
460
- streamingState: {
461
- status: "idle",
462
- },
480
+ streamingState: { status: "idle" },
463
481
  });
464
482
  rerender();
465
483
  await waitFor(() => {
466
484
  expect(result.current.selectedSuggestionId).toBeNull();
467
485
  });
468
486
  });
469
- it("exposes mutation and query results", async () => {
487
+ it("includes pagination info on raw data", async () => {
488
+ mockListSuggestions.mockResolvedValue({
489
+ suggestions: mockSuggestions,
490
+ hasMore: true,
491
+ nextCursor: "cursor_abc",
492
+ });
470
493
  jest.mocked(useTamboV1).mockReturnValue({
471
494
  messages: [
472
495
  {
@@ -479,27 +502,83 @@ describe("useTamboV1Suggestions", () => {
479
502
  thread: undefined,
480
503
  isIdle: true,
481
504
  isStreaming: false,
505
+ currentThreadId: "thread_123",
482
506
  startNewThread: jest.fn(),
483
507
  switchThread: jest.fn(),
484
508
  initThread: jest.fn(),
485
- streamingState: {
486
- status: "idle",
487
- },
509
+ streamingState: { status: "idle" },
510
+ });
511
+ const { result } = renderHook(() => useTamboV1Suggestions(), {
512
+ wrapper: createWrapper(),
513
+ });
514
+ await waitFor(() => {
515
+ expect(result.current.data?.hasMore).toBe(true);
516
+ expect(result.current.data?.nextCursor).toBe("cursor_abc");
488
517
  });
518
+ });
519
+ it("exposes loading and error states", () => {
489
520
  const { result } = renderHook(() => useTamboV1Suggestions(), {
490
521
  wrapper: createWrapper(),
491
522
  });
492
- expect(result.current.acceptResult).toBeDefined();
493
- expect(result.current.generateResult).toBeDefined();
494
- expect(result.current.suggestionsResult).toBeDefined();
523
+ expect(result.current.isLoading).toBeDefined();
524
+ expect(result.current.isSuccess).toBeDefined();
525
+ expect(result.current.isError).toBeDefined();
526
+ expect(result.current.error).toBeDefined();
527
+ expect(result.current.isAccepting).toBe(false);
528
+ expect(result.current.isGenerating).toBe(false);
495
529
  });
496
- it("exposes combined mutation results (isPending, isError, error)", () => {
530
+ });
531
+ describe("Manual Generation", () => {
532
+ it("allows manual generation via generate function", async () => {
533
+ jest.mocked(useTamboV1).mockReturnValue({
534
+ messages: [
535
+ {
536
+ id: "msg_1",
537
+ role: "assistant",
538
+ content: [],
539
+ createdAt: "2024-01-01T00:00:00Z",
540
+ },
541
+ ],
542
+ thread: undefined,
543
+ isIdle: true,
544
+ isStreaming: false,
545
+ currentThreadId: "thread_123",
546
+ startNewThread: jest.fn(),
547
+ switchThread: jest.fn(),
548
+ initThread: jest.fn(),
549
+ streamingState: { status: "idle" },
550
+ });
551
+ const { result } = renderHook(() => useTamboV1Suggestions({ autoGenerate: false }), { wrapper: createWrapper() });
552
+ // No auto-generation
553
+ expect(mockCreateSuggestions).not.toHaveBeenCalled();
554
+ // Manual generation
555
+ await act(async () => {
556
+ await result.current.generate();
557
+ });
558
+ expect(mockCreateSuggestions).toHaveBeenCalledWith("msg_1", expect.objectContaining({
559
+ threadId: "thread_123",
560
+ }));
561
+ });
562
+ it("returns undefined from generate when no assistant message", async () => {
563
+ jest.mocked(useTamboV1).mockReturnValue({
564
+ messages: [],
565
+ thread: undefined,
566
+ isIdle: true,
567
+ isStreaming: false,
568
+ currentThreadId: "thread_123",
569
+ startNewThread: jest.fn(),
570
+ switchThread: jest.fn(),
571
+ initThread: jest.fn(),
572
+ streamingState: { status: "idle" },
573
+ });
497
574
  const { result } = renderHook(() => useTamboV1Suggestions(), {
498
575
  wrapper: createWrapper(),
499
576
  });
500
- expect(result.current.isPending).toBe(false);
501
- expect(result.current.isError).toBe(false);
502
- expect(result.current.error).toBeNull();
577
+ let generateResult;
578
+ await act(async () => {
579
+ generateResult = await result.current.generate();
580
+ });
581
+ expect(generateResult).toBeUndefined();
503
582
  });
504
583
  });
505
584
  });