@tambo-ai/react 0.70.0 → 0.72.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 (305) hide show
  1. package/dist/v1/hooks/use-tambo-v1-component-state.d.ts +44 -0
  2. package/dist/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -0
  3. package/dist/v1/hooks/use-tambo-v1-component-state.js +134 -0
  4. package/dist/v1/hooks/use-tambo-v1-component-state.js.map +1 -0
  5. package/dist/v1/hooks/use-tambo-v1-component-state.test.d.ts +2 -0
  6. package/dist/v1/hooks/use-tambo-v1-component-state.test.d.ts.map +1 -0
  7. package/dist/v1/hooks/use-tambo-v1-component-state.test.js +292 -0
  8. package/dist/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -0
  9. package/dist/v1/hooks/use-tambo-v1-messages.d.ts +58 -0
  10. package/dist/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -0
  11. package/dist/v1/hooks/use-tambo-v1-messages.js +54 -0
  12. package/dist/v1/hooks/use-tambo-v1-messages.js.map +1 -0
  13. package/dist/v1/hooks/use-tambo-v1-messages.test.d.ts +2 -0
  14. package/dist/v1/hooks/use-tambo-v1-messages.test.d.ts.map +1 -0
  15. package/dist/v1/hooks/use-tambo-v1-messages.test.js +137 -0
  16. package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -0
  17. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +96 -0
  18. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -0
  19. package/dist/v1/hooks/use-tambo-v1-send-message.js +227 -0
  20. package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -0
  21. package/dist/v1/hooks/use-tambo-v1-send-message.test.d.ts +2 -0
  22. package/dist/v1/hooks/use-tambo-v1-send-message.test.d.ts.map +1 -0
  23. package/dist/v1/hooks/use-tambo-v1-send-message.test.js +827 -0
  24. package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -0
  25. package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts +62 -0
  26. package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -0
  27. package/dist/v1/hooks/use-tambo-v1-thread-input.js +76 -0
  28. package/dist/v1/hooks/use-tambo-v1-thread-input.js.map +1 -0
  29. package/dist/v1/hooks/use-tambo-v1-thread-input.test.d.ts +2 -0
  30. package/dist/v1/hooks/use-tambo-v1-thread-input.test.d.ts.map +1 -0
  31. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +168 -0
  32. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -0
  33. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +61 -0
  34. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -0
  35. package/dist/v1/hooks/use-tambo-v1-thread-list.js +56 -0
  36. package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -0
  37. package/dist/v1/hooks/use-tambo-v1-thread-list.test.d.ts +2 -0
  38. package/dist/v1/hooks/use-tambo-v1-thread-list.test.d.ts.map +1 -0
  39. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +98 -0
  40. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -0
  41. package/dist/v1/hooks/use-tambo-v1-thread.d.ts +37 -0
  42. package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -0
  43. package/dist/v1/hooks/use-tambo-v1-thread.js +49 -0
  44. package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -0
  45. package/dist/v1/hooks/use-tambo-v1-thread.test.d.ts +2 -0
  46. package/dist/v1/hooks/use-tambo-v1-thread.test.d.ts.map +1 -0
  47. package/dist/v1/hooks/use-tambo-v1-thread.test.js +83 -0
  48. package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -0
  49. package/dist/v1/hooks/use-tambo-v1.d.ts +107 -0
  50. package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -0
  51. package/dist/v1/hooks/use-tambo-v1.js +87 -0
  52. package/dist/v1/hooks/use-tambo-v1.js.map +1 -0
  53. package/dist/v1/hooks/use-tambo-v1.test.d.ts +2 -0
  54. package/dist/v1/hooks/use-tambo-v1.test.d.ts.map +1 -0
  55. package/dist/v1/hooks/use-tambo-v1.test.js +150 -0
  56. package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -0
  57. package/dist/v1/index.d.ts +65 -16
  58. package/dist/v1/index.d.ts.map +1 -1
  59. package/dist/v1/index.js +119 -26
  60. package/dist/v1/index.js.map +1 -1
  61. package/dist/v1/providers/tambo-v1-provider.d.ts +133 -0
  62. package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -0
  63. package/dist/v1/providers/tambo-v1-provider.js +131 -0
  64. package/dist/v1/providers/tambo-v1-provider.js.map +1 -0
  65. package/dist/v1/providers/tambo-v1-provider.test.d.ts +2 -0
  66. package/dist/v1/providers/tambo-v1-provider.test.d.ts.map +1 -0
  67. package/dist/v1/providers/tambo-v1-provider.test.js +181 -0
  68. package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -0
  69. package/dist/v1/providers/tambo-v1-stream-context.d.ts +136 -0
  70. package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -0
  71. package/dist/v1/providers/tambo-v1-stream-context.js +230 -0
  72. package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -0
  73. package/dist/v1/providers/tambo-v1-stream-context.test.d.ts +2 -0
  74. package/dist/v1/providers/tambo-v1-stream-context.test.d.ts.map +1 -0
  75. package/dist/v1/providers/tambo-v1-stream-context.test.js +85 -0
  76. package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -0
  77. package/dist/v1/types/component.d.ts +5 -2
  78. package/dist/v1/types/component.d.ts.map +1 -1
  79. package/dist/v1/types/component.js +5 -2
  80. package/dist/v1/types/component.js.map +1 -1
  81. package/dist/v1/types/event.d.ts +21 -12
  82. package/dist/v1/types/event.d.ts.map +1 -1
  83. package/dist/v1/types/event.js +46 -1
  84. package/dist/v1/types/event.js.map +1 -1
  85. package/dist/v1/types/event.test.d.ts +2 -0
  86. package/dist/v1/types/event.test.d.ts.map +1 -0
  87. package/dist/v1/types/event.test.js +70 -0
  88. package/dist/v1/types/event.test.js.map +1 -0
  89. package/dist/v1/types/message.d.ts +30 -9
  90. package/dist/v1/types/message.d.ts.map +1 -1
  91. package/dist/v1/types/message.js +1 -1
  92. package/dist/v1/types/message.js.map +1 -1
  93. package/dist/v1/types/thread.d.ts +1 -3
  94. package/dist/v1/types/thread.d.ts.map +1 -1
  95. package/dist/v1/types/thread.js +1 -1
  96. package/dist/v1/types/thread.js.map +1 -1
  97. package/dist/v1/utils/component-renderer.d.ts +89 -0
  98. package/dist/v1/utils/component-renderer.d.ts.map +1 -0
  99. package/dist/v1/utils/component-renderer.js +216 -0
  100. package/dist/v1/utils/component-renderer.js.map +1 -0
  101. package/dist/v1/utils/component-renderer.test.d.ts +2 -0
  102. package/dist/v1/utils/component-renderer.test.d.ts.map +1 -0
  103. package/dist/v1/utils/component-renderer.test.js +380 -0
  104. package/dist/v1/utils/component-renderer.test.js.map +1 -0
  105. package/dist/v1/utils/event-accumulator.d.ts +100 -0
  106. package/dist/v1/utils/event-accumulator.d.ts.map +1 -0
  107. package/dist/v1/utils/event-accumulator.js +735 -0
  108. package/dist/v1/utils/event-accumulator.js.map +1 -0
  109. package/dist/v1/utils/event-accumulator.test.d.ts +2 -0
  110. package/dist/v1/utils/event-accumulator.test.d.ts.map +1 -0
  111. package/dist/v1/utils/event-accumulator.test.js +1205 -0
  112. package/dist/v1/utils/event-accumulator.test.js.map +1 -0
  113. package/dist/v1/utils/json-patch.d.ts +18 -0
  114. package/dist/v1/utils/json-patch.d.ts.map +1 -0
  115. package/dist/v1/utils/json-patch.js +35 -0
  116. package/dist/v1/utils/json-patch.js.map +1 -0
  117. package/dist/v1/utils/json-patch.test.d.ts +2 -0
  118. package/dist/v1/utils/json-patch.test.d.ts.map +1 -0
  119. package/dist/v1/utils/json-patch.test.js +28 -0
  120. package/dist/v1/utils/json-patch.test.js.map +1 -0
  121. package/dist/v1/utils/registry-conversion.d.ts +53 -0
  122. package/dist/v1/utils/registry-conversion.d.ts.map +1 -0
  123. package/dist/v1/utils/registry-conversion.js +114 -0
  124. package/dist/v1/utils/registry-conversion.js.map +1 -0
  125. package/dist/v1/utils/registry-conversion.test.d.ts +2 -0
  126. package/dist/v1/utils/registry-conversion.test.d.ts.map +1 -0
  127. package/dist/v1/utils/registry-conversion.test.js +179 -0
  128. package/dist/v1/utils/registry-conversion.test.js.map +1 -0
  129. package/dist/v1/utils/stream-handler.d.ts +45 -0
  130. package/dist/v1/utils/stream-handler.d.ts.map +1 -0
  131. package/dist/v1/utils/stream-handler.js +47 -0
  132. package/dist/v1/utils/stream-handler.js.map +1 -0
  133. package/dist/v1/utils/stream-handler.test.d.ts +2 -0
  134. package/dist/v1/utils/stream-handler.test.d.ts.map +1 -0
  135. package/dist/v1/utils/stream-handler.test.js +74 -0
  136. package/dist/v1/utils/stream-handler.test.js.map +1 -0
  137. package/dist/v1/utils/tool-call-tracker.d.ts +41 -0
  138. package/dist/v1/utils/tool-call-tracker.d.ts.map +1 -0
  139. package/dist/v1/utils/tool-call-tracker.js +90 -0
  140. package/dist/v1/utils/tool-call-tracker.js.map +1 -0
  141. package/dist/v1/utils/tool-executor.d.ts +33 -0
  142. package/dist/v1/utils/tool-executor.d.ts.map +1 -0
  143. package/dist/v1/utils/tool-executor.js +103 -0
  144. package/dist/v1/utils/tool-executor.js.map +1 -0
  145. package/dist/v1/utils/tool-executor.test.d.ts +2 -0
  146. package/dist/v1/utils/tool-executor.test.d.ts.map +1 -0
  147. package/dist/v1/utils/tool-executor.test.js +222 -0
  148. package/dist/v1/utils/tool-executor.test.js.map +1 -0
  149. package/esm/v1/hooks/use-tambo-v1-component-state.d.ts +44 -0
  150. package/esm/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -0
  151. package/esm/v1/hooks/use-tambo-v1-component-state.js +131 -0
  152. package/esm/v1/hooks/use-tambo-v1-component-state.js.map +1 -0
  153. package/esm/v1/hooks/use-tambo-v1-component-state.test.d.ts +2 -0
  154. package/esm/v1/hooks/use-tambo-v1-component-state.test.d.ts.map +1 -0
  155. package/esm/v1/hooks/use-tambo-v1-component-state.test.js +290 -0
  156. package/esm/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -0
  157. package/esm/v1/hooks/use-tambo-v1-messages.d.ts +58 -0
  158. package/esm/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -0
  159. package/esm/v1/hooks/use-tambo-v1-messages.js +51 -0
  160. package/esm/v1/hooks/use-tambo-v1-messages.js.map +1 -0
  161. package/esm/v1/hooks/use-tambo-v1-messages.test.d.ts +2 -0
  162. package/esm/v1/hooks/use-tambo-v1-messages.test.d.ts.map +1 -0
  163. package/esm/v1/hooks/use-tambo-v1-messages.test.js +132 -0
  164. package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -0
  165. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +96 -0
  166. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -0
  167. package/esm/v1/hooks/use-tambo-v1-send-message.js +223 -0
  168. package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -0
  169. package/esm/v1/hooks/use-tambo-v1-send-message.test.d.ts +2 -0
  170. package/esm/v1/hooks/use-tambo-v1-send-message.test.d.ts.map +1 -0
  171. package/esm/v1/hooks/use-tambo-v1-send-message.test.js +822 -0
  172. package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -0
  173. package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts +62 -0
  174. package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -0
  175. package/esm/v1/hooks/use-tambo-v1-thread-input.js +73 -0
  176. package/esm/v1/hooks/use-tambo-v1-thread-input.js.map +1 -0
  177. package/esm/v1/hooks/use-tambo-v1-thread-input.test.d.ts +2 -0
  178. package/esm/v1/hooks/use-tambo-v1-thread-input.test.d.ts.map +1 -0
  179. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +166 -0
  180. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -0
  181. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +61 -0
  182. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -0
  183. package/esm/v1/hooks/use-tambo-v1-thread-list.js +53 -0
  184. package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -0
  185. package/esm/v1/hooks/use-tambo-v1-thread-list.test.d.ts +2 -0
  186. package/esm/v1/hooks/use-tambo-v1-thread-list.test.d.ts.map +1 -0
  187. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +93 -0
  188. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -0
  189. package/esm/v1/hooks/use-tambo-v1-thread.d.ts +37 -0
  190. package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -0
  191. package/esm/v1/hooks/use-tambo-v1-thread.js +46 -0
  192. package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -0
  193. package/esm/v1/hooks/use-tambo-v1-thread.test.d.ts +2 -0
  194. package/esm/v1/hooks/use-tambo-v1-thread.test.d.ts.map +1 -0
  195. package/esm/v1/hooks/use-tambo-v1-thread.test.js +78 -0
  196. package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -0
  197. package/esm/v1/hooks/use-tambo-v1.d.ts +107 -0
  198. package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -0
  199. package/esm/v1/hooks/use-tambo-v1.js +84 -0
  200. package/esm/v1/hooks/use-tambo-v1.js.map +1 -0
  201. package/esm/v1/hooks/use-tambo-v1.test.d.ts +2 -0
  202. package/esm/v1/hooks/use-tambo-v1.test.d.ts.map +1 -0
  203. package/esm/v1/hooks/use-tambo-v1.test.js +145 -0
  204. package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -0
  205. package/esm/v1/index.d.ts +65 -16
  206. package/esm/v1/index.d.ts.map +1 -1
  207. package/esm/v1/index.js +83 -27
  208. package/esm/v1/index.js.map +1 -1
  209. package/esm/v1/providers/tambo-v1-provider.d.ts +133 -0
  210. package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -0
  211. package/esm/v1/providers/tambo-v1-provider.js +94 -0
  212. package/esm/v1/providers/tambo-v1-provider.js.map +1 -0
  213. package/esm/v1/providers/tambo-v1-provider.test.d.ts +2 -0
  214. package/esm/v1/providers/tambo-v1-provider.test.d.ts.map +1 -0
  215. package/esm/v1/providers/tambo-v1-provider.test.js +176 -0
  216. package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -0
  217. package/esm/v1/providers/tambo-v1-stream-context.d.ts +136 -0
  218. package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -0
  219. package/esm/v1/providers/tambo-v1-stream-context.js +191 -0
  220. package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -0
  221. package/esm/v1/providers/tambo-v1-stream-context.test.d.ts +2 -0
  222. package/esm/v1/providers/tambo-v1-stream-context.test.d.ts.map +1 -0
  223. package/esm/v1/providers/tambo-v1-stream-context.test.js +80 -0
  224. package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -0
  225. package/esm/v1/types/component.d.ts +5 -2
  226. package/esm/v1/types/component.d.ts.map +1 -1
  227. package/esm/v1/types/component.js +5 -2
  228. package/esm/v1/types/component.js.map +1 -1
  229. package/esm/v1/types/event.d.ts +21 -12
  230. package/esm/v1/types/event.d.ts.map +1 -1
  231. package/esm/v1/types/event.js +44 -2
  232. package/esm/v1/types/event.js.map +1 -1
  233. package/esm/v1/types/event.test.d.ts +2 -0
  234. package/esm/v1/types/event.test.d.ts.map +1 -0
  235. package/esm/v1/types/event.test.js +68 -0
  236. package/esm/v1/types/event.test.js.map +1 -0
  237. package/esm/v1/types/message.d.ts +30 -9
  238. package/esm/v1/types/message.d.ts.map +1 -1
  239. package/esm/v1/types/message.js +1 -1
  240. package/esm/v1/types/message.js.map +1 -1
  241. package/esm/v1/types/thread.d.ts +1 -3
  242. package/esm/v1/types/thread.d.ts.map +1 -1
  243. package/esm/v1/types/thread.js +1 -1
  244. package/esm/v1/types/thread.js.map +1 -1
  245. package/esm/v1/utils/component-renderer.d.ts +89 -0
  246. package/esm/v1/utils/component-renderer.d.ts.map +1 -0
  247. package/esm/v1/utils/component-renderer.js +175 -0
  248. package/esm/v1/utils/component-renderer.js.map +1 -0
  249. package/esm/v1/utils/component-renderer.test.d.ts +2 -0
  250. package/esm/v1/utils/component-renderer.test.d.ts.map +1 -0
  251. package/esm/v1/utils/component-renderer.test.js +375 -0
  252. package/esm/v1/utils/component-renderer.test.js.map +1 -0
  253. package/esm/v1/utils/event-accumulator.d.ts +100 -0
  254. package/esm/v1/utils/event-accumulator.d.ts.map +1 -0
  255. package/esm/v1/utils/event-accumulator.js +728 -0
  256. package/esm/v1/utils/event-accumulator.js.map +1 -0
  257. package/esm/v1/utils/event-accumulator.test.d.ts +2 -0
  258. package/esm/v1/utils/event-accumulator.test.d.ts.map +1 -0
  259. package/esm/v1/utils/event-accumulator.test.js +1203 -0
  260. package/esm/v1/utils/event-accumulator.test.js.map +1 -0
  261. package/esm/v1/utils/json-patch.d.ts +18 -0
  262. package/esm/v1/utils/json-patch.d.ts.map +1 -0
  263. package/esm/v1/utils/json-patch.js +32 -0
  264. package/esm/v1/utils/json-patch.js.map +1 -0
  265. package/esm/v1/utils/json-patch.test.d.ts +2 -0
  266. package/esm/v1/utils/json-patch.test.d.ts.map +1 -0
  267. package/esm/v1/utils/json-patch.test.js +26 -0
  268. package/esm/v1/utils/json-patch.test.js.map +1 -0
  269. package/esm/v1/utils/registry-conversion.d.ts +53 -0
  270. package/esm/v1/utils/registry-conversion.d.ts.map +1 -0
  271. package/esm/v1/utils/registry-conversion.js +108 -0
  272. package/esm/v1/utils/registry-conversion.js.map +1 -0
  273. package/esm/v1/utils/registry-conversion.test.d.ts +2 -0
  274. package/esm/v1/utils/registry-conversion.test.d.ts.map +1 -0
  275. package/esm/v1/utils/registry-conversion.test.js +177 -0
  276. package/esm/v1/utils/registry-conversion.test.js.map +1 -0
  277. package/esm/v1/utils/stream-handler.d.ts +45 -0
  278. package/esm/v1/utils/stream-handler.d.ts.map +1 -0
  279. package/esm/v1/utils/stream-handler.js +44 -0
  280. package/esm/v1/utils/stream-handler.js.map +1 -0
  281. package/esm/v1/utils/stream-handler.test.d.ts +2 -0
  282. package/esm/v1/utils/stream-handler.test.d.ts.map +1 -0
  283. package/esm/v1/utils/stream-handler.test.js +72 -0
  284. package/esm/v1/utils/stream-handler.test.js.map +1 -0
  285. package/esm/v1/utils/tool-call-tracker.d.ts +41 -0
  286. package/esm/v1/utils/tool-call-tracker.d.ts.map +1 -0
  287. package/esm/v1/utils/tool-call-tracker.js +86 -0
  288. package/esm/v1/utils/tool-call-tracker.js.map +1 -0
  289. package/esm/v1/utils/tool-executor.d.ts +33 -0
  290. package/esm/v1/utils/tool-executor.d.ts.map +1 -0
  291. package/esm/v1/utils/tool-executor.js +99 -0
  292. package/esm/v1/utils/tool-executor.js.map +1 -0
  293. package/esm/v1/utils/tool-executor.test.d.ts +2 -0
  294. package/esm/v1/utils/tool-executor.test.d.ts.map +1 -0
  295. package/esm/v1/utils/tool-executor.test.js +220 -0
  296. package/esm/v1/utils/tool-executor.test.js.map +1 -0
  297. package/package.json +7 -6
  298. package/dist/v1/types/tool.d.ts +0 -52
  299. package/dist/v1/types/tool.d.ts.map +0 -1
  300. package/dist/v1/types/tool.js +0 -11
  301. package/dist/v1/types/tool.js.map +0 -1
  302. package/esm/v1/types/tool.d.ts +0 -52
  303. package/esm/v1/types/tool.d.ts.map +0 -1
  304. package/esm/v1/types/tool.js +0 -10
  305. package/esm/v1/types/tool.js.map +0 -1
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /**
3
+ * Tool Executor for v1 API
4
+ *
5
+ * Handles automatic execution of client-side tools when the model
6
+ * requests them via `tambo.run.awaiting_input` events.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.executeClientTool = executeClientTool;
10
+ exports.executeAllPendingTools = executeAllPendingTools;
11
+ /**
12
+ * Execute a single client-side tool and return the result.
13
+ * @param tool - The tool definition from the registry
14
+ * @param toolCallId - The ID of the tool call to respond to
15
+ * @param args - The parsed arguments for the tool
16
+ * @returns ToolResultContent with the execution result or error
17
+ */
18
+ async function executeClientTool(tool, toolCallId, args) {
19
+ try {
20
+ const result = await tool.tool(args);
21
+ // Transform result to content if transformer provided
22
+ let content;
23
+ if (tool.transformToContent) {
24
+ // transformToContent may return content parts in beta format
25
+ // Convert to v1 format (TextContent | ResourceContent)
26
+ const transformed = await tool.transformToContent(result);
27
+ content = transformed.map((part) => {
28
+ if (part.type === "text" && "text" in part && part.text) {
29
+ return { type: "text", text: part.text };
30
+ }
31
+ // For other types, stringify as text
32
+ return {
33
+ type: "text",
34
+ text: JSON.stringify(part),
35
+ };
36
+ });
37
+ }
38
+ else {
39
+ // Default: stringify result as text
40
+ content = [
41
+ {
42
+ type: "text",
43
+ text: typeof result === "string" ? result : JSON.stringify(result),
44
+ },
45
+ ];
46
+ }
47
+ return {
48
+ type: "tool_result",
49
+ toolUseId: toolCallId,
50
+ content,
51
+ };
52
+ }
53
+ catch (error) {
54
+ return {
55
+ type: "tool_result",
56
+ toolUseId: toolCallId,
57
+ content: [
58
+ {
59
+ type: "text",
60
+ text: error instanceof Error ? error.message : "Tool execution failed",
61
+ },
62
+ ],
63
+ };
64
+ }
65
+ }
66
+ /**
67
+ * Execute all pending tool calls and return their results.
68
+ * Tools are executed sequentially to avoid race conditions when
69
+ * tools may have side effects that depend on each other.
70
+ * @param toolCalls - Map of tool call IDs to their call details
71
+ * @param registry - Registry of tool names to their definitions (Map or Record)
72
+ * @returns Array of ToolResultContent for all executed tools
73
+ */
74
+ async function executeAllPendingTools(toolCalls, registry) {
75
+ const results = [];
76
+ // Normalize registry to allow lookup regardless of Map or Record
77
+ const getTool = (name) => {
78
+ if (registry instanceof Map) {
79
+ return registry.get(name);
80
+ }
81
+ return registry[name];
82
+ };
83
+ for (const [toolCallId, { name, input }] of toolCalls) {
84
+ const tool = getTool(name);
85
+ if (!tool) {
86
+ results.push({
87
+ type: "tool_result",
88
+ toolUseId: toolCallId,
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: `Tool "${name}" not found in registry`,
93
+ },
94
+ ],
95
+ });
96
+ continue;
97
+ }
98
+ const result = await executeClientTool(tool, toolCallId, input);
99
+ results.push(result);
100
+ }
101
+ return results;
102
+ }
103
+ //# sourceMappingURL=tool-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-executor.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool Executor for v1 API\n *\n * Handles automatic execution of client-side tools when the model\n * requests them via `tambo.run.awaiting_input` events.\n */\n\nimport type { TamboTool } from \"../../model/component-metadata\";\nimport type {\n ToolResultContent,\n TextContent,\n ResourceContent,\n} from \"@tambo-ai/typescript-sdk/resources/threads/threads\";\n\n/**\n * Pending tool call from the stream accumulator\n */\nexport interface PendingToolCall {\n name: string;\n input: Record<string, unknown>;\n}\n\n/**\n * Execute a single client-side tool and return the result.\n * @param tool - The tool definition from the registry\n * @param toolCallId - The ID of the tool call to respond to\n * @param args - The parsed arguments for the tool\n * @returns ToolResultContent with the execution result or error\n */\nexport async function executeClientTool(\n tool: TamboTool,\n toolCallId: string,\n args: Record<string, unknown>,\n): Promise<ToolResultContent> {\n try {\n const result = await tool.tool(args);\n\n // Transform result to content if transformer provided\n let content: (TextContent | ResourceContent)[];\n if (tool.transformToContent) {\n // transformToContent may return content parts in beta format\n // Convert to v1 format (TextContent | ResourceContent)\n const transformed = await tool.transformToContent(result);\n content = transformed.map((part) => {\n if (part.type === \"text\" && \"text\" in part && part.text) {\n return { type: \"text\" as const, text: part.text };\n }\n // For other types, stringify as text\n return {\n type: \"text\" as const,\n text: JSON.stringify(part),\n };\n });\n } else {\n // Default: stringify result as text\n content = [\n {\n type: \"text\" as const,\n text: typeof result === \"string\" ? result : JSON.stringify(result),\n },\n ];\n }\n\n return {\n type: \"tool_result\",\n toolUseId: toolCallId,\n content,\n };\n } catch (error) {\n return {\n type: \"tool_result\",\n toolUseId: toolCallId,\n content: [\n {\n type: \"text\" as const,\n text:\n error instanceof Error ? error.message : \"Tool execution failed\",\n },\n ],\n };\n }\n}\n\n/**\n * Execute all pending tool calls and return their results.\n * Tools are executed sequentially to avoid race conditions when\n * tools may have side effects that depend on each other.\n * @param toolCalls - Map of tool call IDs to their call details\n * @param registry - Registry of tool names to their definitions (Map or Record)\n * @returns Array of ToolResultContent for all executed tools\n */\nexport async function executeAllPendingTools(\n toolCalls: Map<string, PendingToolCall>,\n registry: Map<string, TamboTool> | Record<string, TamboTool>,\n): Promise<ToolResultContent[]> {\n const results: ToolResultContent[] = [];\n\n // Normalize registry to allow lookup regardless of Map or Record\n const getTool = (name: string): TamboTool | undefined => {\n if (registry instanceof Map) {\n return registry.get(name);\n }\n return registry[name];\n };\n\n for (const [toolCallId, { name, input }] of toolCalls) {\n const tool = getTool(name);\n if (!tool) {\n results.push({\n type: \"tool_result\",\n toolUseId: toolCallId,\n content: [\n {\n type: \"text\" as const,\n text: `Tool \"${name}\" not found in registry`,\n },\n ],\n });\n continue;\n }\n\n const result = await executeClientTool(tool, toolCallId, input);\n results.push(result);\n }\n\n return results;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tool-executor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-executor.test.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const zod_1 = require("zod");
4
+ const tool_executor_1 = require("./tool-executor");
5
+ describe("tool-executor", () => {
6
+ describe("executeClientTool", () => {
7
+ it("executes a tool and returns text result", async () => {
8
+ const tool = {
9
+ name: "get_weather",
10
+ description: "Gets weather",
11
+ tool: async ({ city }) => `Weather in ${city} is sunny`,
12
+ inputSchema: zod_1.z.object({ city: zod_1.z.string() }),
13
+ outputSchema: zod_1.z.string(),
14
+ };
15
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-1", {
16
+ city: "Seattle",
17
+ });
18
+ expect(result).toEqual({
19
+ type: "tool_result",
20
+ toolUseId: "call-1",
21
+ content: [{ type: "text", text: "Weather in Seattle is sunny" }],
22
+ });
23
+ });
24
+ it("stringifies non-string results", async () => {
25
+ const tool = {
26
+ name: "get_data",
27
+ description: "Gets data",
28
+ tool: async () => ({ value: 42 }),
29
+ inputSchema: zod_1.z.object({}),
30
+ outputSchema: zod_1.z.object({ value: zod_1.z.number() }),
31
+ };
32
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-2", {});
33
+ expect(result).toEqual({
34
+ type: "tool_result",
35
+ toolUseId: "call-2",
36
+ content: [{ type: "text", text: '{"value":42}' }],
37
+ });
38
+ });
39
+ it("uses transformToContent when provided", async () => {
40
+ const tool = {
41
+ name: "custom_tool",
42
+ description: "Custom tool",
43
+ tool: async () => "custom result",
44
+ inputSchema: zod_1.z.object({}),
45
+ outputSchema: zod_1.z.string(),
46
+ transformToContent: (result) => [
47
+ { type: "text", text: `Transformed: ${result}` },
48
+ ],
49
+ };
50
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-3", {});
51
+ expect(result).toEqual({
52
+ type: "tool_result",
53
+ toolUseId: "call-3",
54
+ content: [{ type: "text", text: "Transformed: custom result" }],
55
+ });
56
+ });
57
+ it("handles transformToContent with non-text types by stringifying", async () => {
58
+ const tool = {
59
+ name: "image_tool",
60
+ description: "Image tool",
61
+ tool: async () => "image data",
62
+ inputSchema: zod_1.z.object({}),
63
+ outputSchema: zod_1.z.string(),
64
+ transformToContent: () => [
65
+ {
66
+ type: "image_url",
67
+ image_url: { url: "https://example.com/image.png" },
68
+ },
69
+ ],
70
+ };
71
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-4", {});
72
+ expect(result).toEqual({
73
+ type: "tool_result",
74
+ toolUseId: "call-4",
75
+ content: [
76
+ {
77
+ type: "text",
78
+ text: '{"type":"image_url","image_url":{"url":"https://example.com/image.png"}}',
79
+ },
80
+ ],
81
+ });
82
+ });
83
+ it("handles tool execution errors gracefully", async () => {
84
+ const tool = {
85
+ name: "failing_tool",
86
+ description: "A tool that fails",
87
+ tool: async () => {
88
+ throw new Error("Tool failed!");
89
+ },
90
+ inputSchema: zod_1.z.object({}),
91
+ outputSchema: zod_1.z.void(),
92
+ };
93
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-5", {});
94
+ expect(result).toEqual({
95
+ type: "tool_result",
96
+ toolUseId: "call-5",
97
+ content: [{ type: "text", text: "Tool failed!" }],
98
+ });
99
+ });
100
+ it("handles non-Error throws gracefully", async () => {
101
+ const tool = {
102
+ name: "throwing_tool",
103
+ description: "A tool that throws a string",
104
+ tool: async () => {
105
+ throw "string error";
106
+ },
107
+ inputSchema: zod_1.z.object({}),
108
+ outputSchema: zod_1.z.void(),
109
+ };
110
+ const result = await (0, tool_executor_1.executeClientTool)(tool, "call-6", {});
111
+ expect(result).toEqual({
112
+ type: "tool_result",
113
+ toolUseId: "call-6",
114
+ content: [{ type: "text", text: "Tool execution failed" }],
115
+ });
116
+ });
117
+ });
118
+ describe("executeAllPendingTools", () => {
119
+ it("executes multiple tools with Map registry", async () => {
120
+ const registry = new Map([
121
+ [
122
+ "add",
123
+ {
124
+ name: "add",
125
+ description: "Adds numbers",
126
+ tool: async ({ a, b }) => a + b,
127
+ inputSchema: zod_1.z.object({ a: zod_1.z.number(), b: zod_1.z.number() }),
128
+ outputSchema: zod_1.z.number(),
129
+ },
130
+ ],
131
+ [
132
+ "multiply",
133
+ {
134
+ name: "multiply",
135
+ description: "Multiplies numbers",
136
+ tool: async ({ a, b }) => a * b,
137
+ inputSchema: zod_1.z.object({ a: zod_1.z.number(), b: zod_1.z.number() }),
138
+ outputSchema: zod_1.z.number(),
139
+ },
140
+ ],
141
+ ]);
142
+ const toolCalls = new Map([
143
+ ["call-1", { name: "add", input: { a: 2, b: 3 } }],
144
+ ["call-2", { name: "multiply", input: { a: 4, b: 5 } }],
145
+ ]);
146
+ const results = await (0, tool_executor_1.executeAllPendingTools)(toolCalls, registry);
147
+ expect(results).toHaveLength(2);
148
+ expect(results[0]).toEqual({
149
+ type: "tool_result",
150
+ toolUseId: "call-1",
151
+ content: [{ type: "text", text: "5" }],
152
+ });
153
+ expect(results[1]).toEqual({
154
+ type: "tool_result",
155
+ toolUseId: "call-2",
156
+ content: [{ type: "text", text: "20" }],
157
+ });
158
+ });
159
+ it("executes tools with Record registry", async () => {
160
+ const registry = {
161
+ greet: {
162
+ name: "greet",
163
+ description: "Greets user",
164
+ tool: async ({ name }) => `Hello, ${name}!`,
165
+ inputSchema: zod_1.z.object({ name: zod_1.z.string() }),
166
+ outputSchema: zod_1.z.string(),
167
+ },
168
+ };
169
+ const toolCalls = new Map([
170
+ ["call-1", { name: "greet", input: { name: "World" } }],
171
+ ]);
172
+ const results = await (0, tool_executor_1.executeAllPendingTools)(toolCalls, registry);
173
+ expect(results).toHaveLength(1);
174
+ expect(results[0]).toEqual({
175
+ type: "tool_result",
176
+ toolUseId: "call-1",
177
+ content: [{ type: "text", text: "Hello, World!" }],
178
+ });
179
+ });
180
+ it("returns error result for unknown tools", async () => {
181
+ const registry = new Map();
182
+ const toolCalls = new Map([
183
+ ["call-1", { name: "unknown_tool", input: {} }],
184
+ ]);
185
+ const results = await (0, tool_executor_1.executeAllPendingTools)(toolCalls, registry);
186
+ expect(results).toHaveLength(1);
187
+ expect(results[0]).toEqual({
188
+ type: "tool_result",
189
+ toolUseId: "call-1",
190
+ content: [
191
+ { type: "text", text: 'Tool "unknown_tool" not found in registry' },
192
+ ],
193
+ });
194
+ });
195
+ it("handles mixed known and unknown tools", async () => {
196
+ const registry = new Map([
197
+ [
198
+ "known",
199
+ {
200
+ name: "known",
201
+ description: "Known tool",
202
+ tool: async () => "success",
203
+ inputSchema: zod_1.z.object({}),
204
+ outputSchema: zod_1.z.string(),
205
+ },
206
+ ],
207
+ ]);
208
+ const toolCalls = new Map([
209
+ ["call-1", { name: "known", input: {} }],
210
+ ["call-2", { name: "unknown", input: {} }],
211
+ ]);
212
+ const results = await (0, tool_executor_1.executeAllPendingTools)(toolCalls, registry);
213
+ expect(results).toHaveLength(2);
214
+ expect(results[0].content[0]).toEqual({ type: "text", text: "success" });
215
+ expect(results[1].content[0]).toEqual({
216
+ type: "text",
217
+ text: 'Tool "unknown" not found in registry',
218
+ });
219
+ });
220
+ });
221
+ });
222
+ //# sourceMappingURL=tool-executor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-executor.test.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport type { TamboTool } from \"../../model/component-metadata\";\nimport {\n executeClientTool,\n executeAllPendingTools,\n type PendingToolCall,\n} from \"./tool-executor\";\n\ndescribe(\"tool-executor\", () => {\n describe(\"executeClientTool\", () => {\n it(\"executes a tool and returns text result\", async () => {\n const tool: TamboTool = {\n name: \"get_weather\",\n description: \"Gets weather\",\n tool: async ({ city }: { city: string }) =>\n `Weather in ${city} is sunny`,\n inputSchema: z.object({ city: z.string() }),\n outputSchema: z.string(),\n };\n\n const result = await executeClientTool(tool, \"call-1\", {\n city: \"Seattle\",\n });\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"Weather in Seattle is sunny\" }],\n });\n });\n\n it(\"stringifies non-string results\", async () => {\n const tool: TamboTool = {\n name: \"get_data\",\n description: \"Gets data\",\n tool: async () => ({ value: 42 }),\n inputSchema: z.object({}),\n outputSchema: z.object({ value: z.number() }),\n };\n\n const result = await executeClientTool(tool, \"call-2\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-2\",\n content: [{ type: \"text\", text: '{\"value\":42}' }],\n });\n });\n\n it(\"uses transformToContent when provided\", async () => {\n const tool: TamboTool = {\n name: \"custom_tool\",\n description: \"Custom tool\",\n tool: async () => \"custom result\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n transformToContent: (result) => [\n { type: \"text\", text: `Transformed: ${result}` },\n ],\n };\n\n const result = await executeClientTool(tool, \"call-3\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-3\",\n content: [{ type: \"text\", text: \"Transformed: custom result\" }],\n });\n });\n\n it(\"handles transformToContent with non-text types by stringifying\", async () => {\n const tool: TamboTool = {\n name: \"image_tool\",\n description: \"Image tool\",\n tool: async () => \"image data\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n transformToContent: () => [\n {\n type: \"image_url\",\n image_url: { url: \"https://example.com/image.png\" },\n },\n ],\n };\n\n const result = await executeClientTool(tool, \"call-4\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-4\",\n content: [\n {\n type: \"text\",\n text: '{\"type\":\"image_url\",\"image_url\":{\"url\":\"https://example.com/image.png\"}}',\n },\n ],\n });\n });\n\n it(\"handles tool execution errors gracefully\", async () => {\n const tool: TamboTool = {\n name: \"failing_tool\",\n description: \"A tool that fails\",\n tool: async () => {\n throw new Error(\"Tool failed!\");\n },\n inputSchema: z.object({}),\n outputSchema: z.void(),\n };\n\n const result = await executeClientTool(tool, \"call-5\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-5\",\n content: [{ type: \"text\", text: \"Tool failed!\" }],\n });\n });\n\n it(\"handles non-Error throws gracefully\", async () => {\n const tool: TamboTool = {\n name: \"throwing_tool\",\n description: \"A tool that throws a string\",\n tool: async () => {\n throw \"string error\";\n },\n inputSchema: z.object({}),\n outputSchema: z.void(),\n };\n\n const result = await executeClientTool(tool, \"call-6\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-6\",\n content: [{ type: \"text\", text: \"Tool execution failed\" }],\n });\n });\n });\n\n describe(\"executeAllPendingTools\", () => {\n it(\"executes multiple tools with Map registry\", async () => {\n const registry = new Map<string, TamboTool>([\n [\n \"add\",\n {\n name: \"add\",\n description: \"Adds numbers\",\n tool: async ({ a, b }: { a: number; b: number }) => a + b,\n inputSchema: z.object({ a: z.number(), b: z.number() }),\n outputSchema: z.number(),\n },\n ],\n [\n \"multiply\",\n {\n name: \"multiply\",\n description: \"Multiplies numbers\",\n tool: async ({ a, b }: { a: number; b: number }) => a * b,\n inputSchema: z.object({ a: z.number(), b: z.number() }),\n outputSchema: z.number(),\n },\n ],\n ]);\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"add\", input: { a: 2, b: 3 } }],\n [\"call-2\", { name: \"multiply\", input: { a: 4, b: 5 } }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(2);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"5\" }],\n });\n expect(results[1]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-2\",\n content: [{ type: \"text\", text: \"20\" }],\n });\n });\n\n it(\"executes tools with Record registry\", async () => {\n const registry: Record<string, TamboTool> = {\n greet: {\n name: \"greet\",\n description: \"Greets user\",\n tool: async ({ name }: { name: string }) => `Hello, ${name}!`,\n inputSchema: z.object({ name: z.string() }),\n outputSchema: z.string(),\n },\n };\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"greet\", input: { name: \"World\" } }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(1);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"Hello, World!\" }],\n });\n });\n\n it(\"returns error result for unknown tools\", async () => {\n const registry = new Map<string, TamboTool>();\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"unknown_tool\", input: {} }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(1);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [\n { type: \"text\", text: 'Tool \"unknown_tool\" not found in registry' },\n ],\n });\n });\n\n it(\"handles mixed known and unknown tools\", async () => {\n const registry = new Map<string, TamboTool>([\n [\n \"known\",\n {\n name: \"known\",\n description: \"Known tool\",\n tool: async () => \"success\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n },\n ],\n ]);\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"known\", input: {} }],\n [\"call-2\", { name: \"unknown\", input: {} }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(2);\n expect(results[0].content[0]).toEqual({ type: \"text\", text: \"success\" });\n expect(results[1].content[0]).toEqual({\n type: \"text\",\n text: 'Tool \"unknown\" not found in registry',\n });\n });\n });\n});\n"]}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Return type for useTamboV1ComponentState hook.
3
+ * Similar to useState but with additional metadata.
4
+ */
5
+ export type UseTamboV1ComponentStateReturn<S> = [
6
+ currentState: S,
7
+ setState: (newState: S | ((prev: S) => S)) => void,
8
+ meta: {
9
+ isPending: boolean;
10
+ error: Error | null;
11
+ flush: () => void;
12
+ }
13
+ ];
14
+ /**
15
+ * Hook for managing component state with bidirectional server sync.
16
+ *
17
+ * This hook acts like useState but automatically syncs state changes
18
+ * to the Tambo backend. Server-side state updates are also reflected
19
+ * in the component.
20
+ *
21
+ * Must be used within a component rendered via the component renderer.
22
+ * @param keyName - The unique key to identify this state value within the component's state
23
+ * @param initialValue - Initial value for the state (used if no server state exists)
24
+ * @param debounceTime - Debounce time in milliseconds (default: 500ms)
25
+ * @returns Tuple of [currentState, setState, meta]
26
+ * @example
27
+ * ```tsx
28
+ * function Counter() {
29
+ * const [count, setCount, { isPending }] = useTamboV1ComponentState('count', 0);
30
+ *
31
+ * return (
32
+ * <div>
33
+ * <span>{count}</span>
34
+ * <button onClick={() => setCount(c => c + 1)} disabled={isPending}>
35
+ * Increment
36
+ * </button>
37
+ * </div>
38
+ * );
39
+ * }
40
+ * ```
41
+ */
42
+ export declare function useTamboV1ComponentState<S = undefined>(keyName: string, initialValue?: S, debounceTime?: number): UseTamboV1ComponentStateReturn<S | undefined>;
43
+ export declare function useTamboV1ComponentState<S>(keyName: string, initialValue: S, debounceTime?: number): UseTamboV1ComponentStateReturn<S>;
44
+ //# sourceMappingURL=use-tambo-v1-component-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-v1-component-state.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,MAAM,MAAM,8BAA8B,CAAC,CAAC,IAAI;IAC9C,YAAY,EAAE,CAAC;IACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI;IAClD,IAAI,EAAE;QACJ,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,MAAM,IAAI,CAAC;KACnB;CACF,CAAC;AAgCF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,GAAG,SAAS,EACpD,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,CAAC,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,8BAA8B,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AACjD,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,8BAA8B,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,131 @@
1
+ "use client";
2
+ /**
3
+ * useTamboV1ComponentState - Component State Hook for v1 API
4
+ *
5
+ * Provides bidirectional state synchronization between React components
6
+ * and the Tambo backend. State changes are debounced before syncing to
7
+ * the server, and server state updates are reflected in the component.
8
+ *
9
+ * Must be used within a component rendered via the component renderer.
10
+ */
11
+ import { useCallback, useEffect, useState, useRef } from "react";
12
+ import { useDebouncedCallback } from "use-debounce";
13
+ import { deepEqual } from "fast-equals";
14
+ import { useTamboClient } from "../../providers/tambo-client-provider";
15
+ import { useV1ComponentContent } from "../utils/component-renderer";
16
+ import { useStreamState } from "../providers/tambo-v1-stream-context";
17
+ /**
18
+ * Find a component content block by ID in a specific thread.
19
+ * Only searches the specified thread to prevent cross-thread data access
20
+ * and improve performance (O(m*k) instead of O(n*m*k)).
21
+ * @param streamState - The current stream state
22
+ * @param threadId - The thread ID to search in
23
+ * @param componentId - The component ID to find
24
+ * @returns The component content block, or undefined if not found
25
+ */
26
+ function findComponentContent(streamState, threadId, componentId) {
27
+ // Only search the specified thread (not all threads)
28
+ const threadState = streamState.threadMap[threadId];
29
+ if (!threadState) {
30
+ return undefined;
31
+ }
32
+ for (const message of threadState.thread.messages) {
33
+ for (const content of message.content) {
34
+ if (content.type === "component" && content.id === componentId) {
35
+ return content;
36
+ }
37
+ }
38
+ }
39
+ return undefined;
40
+ }
41
+ export function useTamboV1ComponentState(keyName, initialValue, debounceTime = 500) {
42
+ const client = useTamboClient();
43
+ const { componentId, threadId } = useV1ComponentContent();
44
+ const streamState = useStreamState();
45
+ // Find the component content to get server state (only search current thread)
46
+ const componentContent = findComponentContent(streamState, threadId, componentId);
47
+ const serverState = componentContent?.state;
48
+ const serverValue = serverState?.[keyName];
49
+ // Local state - initialized from server state or initial value
50
+ const [localState, setLocalState] = useState(() => serverValue ?? initialValue);
51
+ // Track pending state and errors
52
+ const [isPending, setIsPending] = useState(false);
53
+ const [error, setError] = useState(null);
54
+ // Track the last value we sent to avoid overwriting with stale server state
55
+ const lastSentValueRef = useRef(undefined);
56
+ // Track whether there's a pending local change that hasn't synced yet
57
+ const hasPendingLocalChangeRef = useRef(false);
58
+ // Track in-flight sync requests to avoid stale completions clearing pending state
59
+ const syncSeqRef = useRef(0);
60
+ // Debounced function to sync state to server
61
+ const syncToServer = useDebouncedCallback(async (newState) => {
62
+ const seq = ++syncSeqRef.current;
63
+ setIsPending(true);
64
+ setError(null);
65
+ lastSentValueRef.current = newState;
66
+ try {
67
+ await client.threads.state.updateState(componentId, {
68
+ threadId,
69
+ state: { [keyName]: newState },
70
+ });
71
+ // Clear pending flag after successful sync
72
+ hasPendingLocalChangeRef.current = false;
73
+ }
74
+ catch (err) {
75
+ // Clear pending flag on error to allow server reconciliation
76
+ hasPendingLocalChangeRef.current = false;
77
+ const syncError = err instanceof Error ? err : new Error(String(err));
78
+ setError(syncError);
79
+ console.error(`[useTamboV1ComponentState] Failed to sync state for ${componentId}:`, syncError);
80
+ }
81
+ finally {
82
+ // Only clear isPending if this is the most recent request
83
+ if (seq === syncSeqRef.current) {
84
+ setIsPending(false);
85
+ }
86
+ }
87
+ }, debounceTime);
88
+ // setState function that updates local state and triggers debounced sync
89
+ const setState = useCallback((newState) => {
90
+ setLocalState((prev) => {
91
+ const nextState = typeof newState === "function"
92
+ ? newState(prev)
93
+ : newState;
94
+ // Mark that we have a pending local change
95
+ hasPendingLocalChangeRef.current = true;
96
+ // Trigger debounced sync to server
97
+ void syncToServer(nextState);
98
+ return nextState;
99
+ });
100
+ }, [syncToServer]);
101
+ // Sync from server state when it changes (e.g., from streaming events)
102
+ useEffect(() => {
103
+ if (serverValue === undefined) {
104
+ return;
105
+ }
106
+ // Don't overwrite local changes that haven't synced yet
107
+ if (hasPendingLocalChangeRef.current) {
108
+ return;
109
+ }
110
+ // Only sync if the server value is different from what we last sent
111
+ // This prevents overwriting local state with stale server values
112
+ if (lastSentValueRef.current !== undefined &&
113
+ deepEqual(serverValue, lastSentValueRef.current)) {
114
+ return;
115
+ }
116
+ // Use functional update to avoid localState in deps
117
+ setLocalState((prev) => deepEqual(serverValue, prev) ? prev : serverValue);
118
+ }, [serverValue]);
119
+ // Flush pending updates on unmount
120
+ useEffect(() => {
121
+ return () => {
122
+ void syncToServer.flush();
123
+ };
124
+ }, [syncToServer]);
125
+ // Flush function for immediate sync
126
+ const flush = useCallback(() => {
127
+ void syncToServer.flush();
128
+ }, [syncToServer]);
129
+ return [localState, setState, { isPending, error, flush }];
130
+ }
131
+ //# sourceMappingURL=use-tambo-v1-component-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-v1-component-state.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * useTamboV1ComponentState - Component State Hook for v1 API\n *\n * Provides bidirectional state synchronization between React components\n * and the Tambo backend. State changes are debounced before syncing to\n * the server, and server state updates are reflected in the component.\n *\n * Must be used within a component rendered via the component renderer.\n */\n\nimport { useCallback, useEffect, useState, useRef } from \"react\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { deepEqual } from \"fast-equals\";\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useV1ComponentContent } from \"../utils/component-renderer\";\nimport { useStreamState } from \"../providers/tambo-v1-stream-context\";\nimport type { V1ComponentContent } from \"../types/message\";\n\n/**\n * Return type for useTamboV1ComponentState hook.\n * Similar to useState but with additional metadata.\n */\nexport type UseTamboV1ComponentStateReturn<S> = [\n currentState: S,\n setState: (newState: S | ((prev: S) => S)) => void,\n meta: {\n isPending: boolean;\n error: Error | null;\n flush: () => void;\n },\n];\n\n/**\n * Find a component content block by ID in a specific thread.\n * Only searches the specified thread to prevent cross-thread data access\n * and improve performance (O(m*k) instead of O(n*m*k)).\n * @param streamState - The current stream state\n * @param threadId - The thread ID to search in\n * @param componentId - The component ID to find\n * @returns The component content block, or undefined if not found\n */\nfunction findComponentContent(\n streamState: ReturnType<typeof useStreamState>,\n threadId: string,\n componentId: string,\n): V1ComponentContent | undefined {\n // Only search the specified thread (not all threads)\n const threadState = streamState.threadMap[threadId];\n if (!threadState) {\n return undefined;\n }\n\n for (const message of threadState.thread.messages) {\n for (const content of message.content) {\n if (content.type === \"component\" && content.id === componentId) {\n return content;\n }\n }\n }\n return undefined;\n}\n\n/**\n * Hook for managing component state with bidirectional server sync.\n *\n * This hook acts like useState but automatically syncs state changes\n * to the Tambo backend. Server-side state updates are also reflected\n * in the component.\n *\n * Must be used within a component rendered via the component renderer.\n * @param keyName - The unique key to identify this state value within the component's state\n * @param initialValue - Initial value for the state (used if no server state exists)\n * @param debounceTime - Debounce time in milliseconds (default: 500ms)\n * @returns Tuple of [currentState, setState, meta]\n * @example\n * ```tsx\n * function Counter() {\n * const [count, setCount, { isPending }] = useTamboV1ComponentState('count', 0);\n *\n * return (\n * <div>\n * <span>{count}</span>\n * <button onClick={() => setCount(c => c + 1)} disabled={isPending}>\n * Increment\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useTamboV1ComponentState<S = undefined>(\n keyName: string,\n initialValue?: S,\n debounceTime?: number,\n): UseTamboV1ComponentStateReturn<S | undefined>;\nexport function useTamboV1ComponentState<S>(\n keyName: string,\n initialValue: S,\n debounceTime?: number,\n): UseTamboV1ComponentStateReturn<S>;\nexport function useTamboV1ComponentState<S>(\n keyName: string,\n initialValue?: S,\n debounceTime = 500,\n): UseTamboV1ComponentStateReturn<S> {\n const client = useTamboClient();\n const { componentId, threadId } = useV1ComponentContent();\n const streamState = useStreamState();\n\n // Find the component content to get server state (only search current thread)\n const componentContent = findComponentContent(\n streamState,\n threadId,\n componentId,\n );\n const serverState = componentContent?.state as\n | Record<string, unknown>\n | undefined;\n const serverValue = serverState?.[keyName] as S | undefined;\n\n // Local state - initialized from server state or initial value\n const [localState, setLocalState] = useState<S>(\n () => serverValue ?? (initialValue as S),\n );\n\n // Track pending state and errors\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track the last value we sent to avoid overwriting with stale server state\n const lastSentValueRef = useRef<S | undefined>(undefined);\n\n // Track whether there's a pending local change that hasn't synced yet\n const hasPendingLocalChangeRef = useRef(false);\n\n // Track in-flight sync requests to avoid stale completions clearing pending state\n const syncSeqRef = useRef(0);\n\n // Debounced function to sync state to server\n const syncToServer = useDebouncedCallback(async (newState: S) => {\n const seq = ++syncSeqRef.current;\n setIsPending(true);\n setError(null);\n lastSentValueRef.current = newState;\n\n try {\n await client.threads.state.updateState(componentId, {\n threadId,\n state: { [keyName]: newState },\n });\n // Clear pending flag after successful sync\n hasPendingLocalChangeRef.current = false;\n } catch (err) {\n // Clear pending flag on error to allow server reconciliation\n hasPendingLocalChangeRef.current = false;\n const syncError = err instanceof Error ? err : new Error(String(err));\n setError(syncError);\n console.error(\n `[useTamboV1ComponentState] Failed to sync state for ${componentId}:`,\n syncError,\n );\n } finally {\n // Only clear isPending if this is the most recent request\n if (seq === syncSeqRef.current) {\n setIsPending(false);\n }\n }\n }, debounceTime);\n\n // setState function that updates local state and triggers debounced sync\n const setState = useCallback(\n (newState: S | ((prev: S) => S)) => {\n setLocalState((prev) => {\n const nextState =\n typeof newState === \"function\"\n ? (newState as (prev: S) => S)(prev)\n : newState;\n\n // Mark that we have a pending local change\n hasPendingLocalChangeRef.current = true;\n\n // Trigger debounced sync to server\n void syncToServer(nextState);\n\n return nextState;\n });\n },\n [syncToServer],\n );\n\n // Sync from server state when it changes (e.g., from streaming events)\n useEffect(() => {\n if (serverValue === undefined) {\n return;\n }\n\n // Don't overwrite local changes that haven't synced yet\n if (hasPendingLocalChangeRef.current) {\n return;\n }\n\n // Only sync if the server value is different from what we last sent\n // This prevents overwriting local state with stale server values\n if (\n lastSentValueRef.current !== undefined &&\n deepEqual(serverValue, lastSentValueRef.current)\n ) {\n return;\n }\n\n // Use functional update to avoid localState in deps\n setLocalState((prev) =>\n deepEqual(serverValue, prev) ? prev : serverValue,\n );\n }, [serverValue]);\n\n // Flush pending updates on unmount\n useEffect(() => {\n return () => {\n void syncToServer.flush();\n };\n }, [syncToServer]);\n\n // Flush function for immediate sync\n const flush = useCallback(() => {\n void syncToServer.flush();\n }, [syncToServer]);\n\n return [localState, setState, { isPending, error, flush }];\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-tambo-v1-component-state.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-v1-component-state.test.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.test.tsx"],"names":[],"mappings":""}