thursday-agent 0.5.0 → 0.7.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 (667) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +3 -2
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +3 -3
  5. package/.next/required-server-files.json +8 -1
  6. package/.next/routes-manifest.json +18 -6
  7. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/server/app/_global-error.html +1 -1
  9. package/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  14. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/server/app/_not-found.html +1 -1
  16. package/.next/server/app/_not-found.rsc +13 -13
  17. package/.next/server/app/_not-found.segments/_full.segment.rsc +13 -13
  18. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +12 -12
  19. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  20. package/.next/server/app/api/artifact/route.js +10 -6
  21. package/.next/server/app/api/artifact/route.js.nft.json +1 -1
  22. package/.next/server/app/api/bot/memory/files/route.js +5 -4
  23. package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -1
  24. package/.next/server/app/api/bot/memory/route.js +8 -8
  25. package/.next/server/app/api/bot/memory/route.js.nft.json +1 -1
  26. package/.next/server/app/api/bot/route.js +8 -8
  27. package/.next/server/app/api/bot/route.js.nft.json +1 -1
  28. package/.next/server/app/api/bot/thread/[id]/route/app-paths-manifest.json +3 -0
  29. package/.next/server/app/api/bot/thread/[id]/route.js +15 -0
  30. package/.next/server/app/api/bot/thread/[id]/route.js.nft.json +1 -0
  31. package/.next/server/app/api/bot/thread/[id]/route_client-reference-manifest.js +3 -0
  32. package/.next/server/app/api/bot/thread/route/app-paths-manifest.json +3 -0
  33. package/.next/server/app/api/bot/thread/route.js +15 -0
  34. package/.next/server/app/api/bot/thread/route.js.nft.json +1 -0
  35. package/.next/server/app/api/bot/thread/route_client-reference-manifest.js +3 -0
  36. package/.next/server/app/api/config/route.js +7 -7
  37. package/.next/server/app/api/config/route.js.nft.json +1 -1
  38. package/.next/server/app/api/events/route.js +3 -3
  39. package/.next/server/app/api/events/route.js.nft.json +1 -1
  40. package/.next/server/app/api/file/[...path]/route.js +4 -4
  41. package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
  42. package/.next/server/app/api/llm-model/catalog/route.js +8 -8
  43. package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
  44. package/.next/server/app/api/llm-model/credits/route.js +8 -8
  45. package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -1
  46. package/.next/server/app/api/llm-model/route.js +8 -8
  47. package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
  48. package/.next/server/app/api/llm-model/subscription/route.js +8 -8
  49. package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -1
  50. package/.next/server/app/api/mcp/[name]/route.js +6 -6
  51. package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
  52. package/.next/server/app/api/mcp/oauth/callback/route.js +4 -4
  53. package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
  54. package/.next/server/app/api/mcp/route.js +6 -6
  55. package/.next/server/app/api/mcp/route.js.nft.json +1 -1
  56. package/.next/server/app/api/mcp/tools/route.js +6 -6
  57. package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
  58. package/.next/server/app/api/memory/edit/route.js +15 -15
  59. package/.next/server/app/api/memory/edit/route.js.nft.json +1 -1
  60. package/.next/server/app/api/memory/route.js +7 -6
  61. package/.next/server/app/api/memory/route.js.nft.json +1 -1
  62. package/.next/server/app/api/skills/[source]/[name]/route.js +6 -6
  63. package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
  64. package/.next/server/app/api/skills/route.js +6 -6
  65. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  66. package/.next/server/app/api/thursday/call/route.js +10 -11
  67. package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
  68. package/.next/server/app/api/thursday/skills/route.js +9 -10
  69. package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
  70. package/.next/server/app/api/thursday/tool-call/route.js +15 -15
  71. package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
  72. package/.next/server/app/api/workspace/missing/route/app-paths-manifest.json +3 -0
  73. package/.next/server/app/api/workspace/missing/route/build-manifest.json +12 -0
  74. package/.next/server/app/api/workspace/missing/route/server-reference-manifest.json +4 -0
  75. package/.next/server/app/api/workspace/missing/route.js +12 -0
  76. package/.next/server/app/api/workspace/missing/route.js.map +5 -0
  77. package/.next/server/app/api/workspace/missing/route.js.nft.json +1 -0
  78. package/.next/server/app/api/workspace/missing/route_client-reference-manifest.js +3 -0
  79. package/.next/server/app/api/workspace/route.js +5 -5
  80. package/.next/server/app/api/workspace/route.js.nft.json +1 -1
  81. package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +1 -1
  82. package/.next/server/app/artifact/[...path]/page.js +4 -3
  83. package/.next/server/app/artifact/[...path]/page.js.nft.json +1 -1
  84. package/.next/server/app/artifact/[...path]/page_client-reference-manifest.js +1 -1
  85. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  86. package/.next/server/app/page/server-reference-manifest.json +67 -45
  87. package/.next/server/app/page.js +11 -9
  88. package/.next/server/app/page.js.nft.json +1 -1
  89. package/.next/server/app/page_client-reference-manifest.js +1 -1
  90. package/.next/server/app-paths-manifest.json +3 -2
  91. package/.next/server/chunks/[root-of-the-server]__0-06t3f._.js +8 -0
  92. package/.next/server/chunks/[root-of-the-server]__02846fb._.js +8 -0
  93. package/.next/server/chunks/[root-of-the-server]__05luceg._.js +3 -0
  94. package/.next/server/chunks/[root-of-the-server]__06--3q3._.js +8 -0
  95. package/.next/server/chunks/[root-of-the-server]__06l05n_._.js +3 -0
  96. package/.next/server/chunks/[root-of-the-server]__07bnah_._.js +3 -0
  97. package/.next/server/chunks/[root-of-the-server]__08eae20._.js +8 -0
  98. package/.next/server/chunks/[root-of-the-server]__0_ue8oe._.js +3 -0
  99. package/.next/server/chunks/[root-of-the-server]__0btqrct._.js +3 -0
  100. package/.next/server/chunks/[root-of-the-server]__0c9fgca._.js +5 -0
  101. package/.next/server/chunks/[root-of-the-server]__0h_x6q6._.js +5 -0
  102. package/.next/server/chunks/{[root-of-the-server]__0pa2n68._.js → [root-of-the-server]__0kxrvxf._.js} +2 -2
  103. package/.next/server/chunks/{[root-of-the-server]__0q0vvt2._.js → [root-of-the-server]__0ov3iir._.js} +2 -2
  104. package/.next/server/chunks/[root-of-the-server]__0qwtlmx._.js +8 -0
  105. package/.next/server/chunks/[root-of-the-server]__0sm5xvm._.js +3 -0
  106. package/.next/server/chunks/[root-of-the-server]__0zp35ul._.js +5 -0
  107. package/.next/server/chunks/[root-of-the-server]__144u9d_._.js +3 -0
  108. package/.next/server/chunks/[root-of-the-server]__18-2tsq._.js +5 -0
  109. package/.next/server/chunks/[root-of-the-server]__1e-ci13._.js +3 -0
  110. package/.next/server/chunks/[root-of-the-server]__1e2365e._.js +8 -0
  111. package/.next/server/chunks/[root-of-the-server]__1fix932._.js +8 -0
  112. package/.next/server/chunks/{[root-of-the-server]__0ce8nf8._.js → [root-of-the-server]__1g3t7vn._.js} +3 -3
  113. package/.next/server/chunks/[root-of-the-server]__1kp-83u._.js +5 -0
  114. package/.next/server/chunks/[root-of-the-server]__1kv8p3e._.js +5 -0
  115. package/.next/server/chunks/[root-of-the-server]__1orn-5b._.js +2 -3
  116. package/.next/server/chunks/_02szwk8._.js +5 -0
  117. package/.next/server/chunks/_05h2cii._.js +1 -1
  118. package/.next/server/chunks/_06c9kie._.js +216 -0
  119. package/.next/server/chunks/{_1x6kd1r._.js → _07y2gj-._.js} +1 -1
  120. package/.next/server/chunks/_0a43a-0._.js +3 -0
  121. package/.next/server/chunks/_0bujjey._.js +5 -0
  122. package/.next/server/chunks/_0c9j6rb._.js +1 -1
  123. package/.next/server/chunks/_0dkd549._.js +3 -0
  124. package/.next/server/chunks/_0ej1kvv._.js +3 -0
  125. package/.next/server/chunks/_0f6ts7z._.js +3 -0
  126. package/.next/server/chunks/_0gm9hyv._.js +55 -0
  127. package/.next/server/chunks/_0i55en5._.js +25 -0
  128. package/.next/server/chunks/_0k50n27._.js +18 -0
  129. package/.next/server/chunks/_0khihjk._.js +3 -3
  130. package/.next/server/chunks/_0n74zsf._.js +5 -5
  131. package/.next/server/chunks/_0nvm9ef._.js +3 -0
  132. package/.next/server/chunks/_0p56fn0._.js +3 -0
  133. package/.next/server/chunks/_0recufk._.js +1 -1
  134. package/.next/server/chunks/_0xbkz10._.js +3 -0
  135. package/.next/server/chunks/_10tkr26._.js +3 -0
  136. package/.next/server/chunks/{_0ioz3nd._.js → _11u2kp7._.js} +1 -1
  137. package/.next/server/chunks/_11ujpya._.js +3 -0
  138. package/.next/server/chunks/_127nx_p._.js +5 -0
  139. package/.next/server/chunks/_17l5ygt._.js +1 -1
  140. package/.next/server/chunks/_19uauj6._.js +3 -0
  141. package/.next/server/chunks/_1_5mnq4._.js +5 -5
  142. package/.next/server/chunks/_1abl6t9._.js +55 -0
  143. package/.next/server/chunks/_1d0j961._.js +3 -3
  144. package/.next/server/chunks/_1dbixxz._.js +3 -0
  145. package/.next/server/chunks/_1dc_d1q._.js +98 -0
  146. package/.next/server/chunks/_1drgfx4._.js +5 -5
  147. package/.next/server/chunks/_1e48czp._.js +3 -3
  148. package/.next/server/chunks/_1f31u5x._.js +5 -0
  149. package/.next/server/chunks/_1gnjfli._.js +3 -0
  150. package/.next/server/chunks/_1kg70wc._.js +3 -3
  151. package/.next/server/chunks/_1klbcft._.js +5 -0
  152. package/.next/server/chunks/_1krd9rf._.js +4 -1
  153. package/.next/server/chunks/_1kwmzab._.js +3 -0
  154. package/.next/server/chunks/{_1pf4qe-._.js → _1oxj9fa._.js} +1 -1
  155. package/.next/server/chunks/{_1f46eie._.js → _1pcmdbb._.js} +1 -1
  156. package/.next/server/chunks/_1qgix-j._.js +3 -0
  157. package/.next/server/chunks/{lib_logger_ts_1exwjut._.js → _1rpchta._.js} +5 -5
  158. package/.next/server/chunks/_1vsej-s._.js +5 -0
  159. package/.next/server/chunks/_1yx0p_s._.js +5 -0
  160. package/.next/server/chunks/{_0rnf-6n._.js → _20fsr_z._.js} +6 -6
  161. package/.next/server/chunks/_2128hkj._.js +5 -0
  162. package/.next/server/chunks/_next-internal_server_app_api_bot_thread_[id]_route_actions_1fstjn2.js +3 -0
  163. package/.next/server/chunks/_next-internal_server_app_api_bot_thread_route_actions_003ccso.js +3 -0
  164. package/.next/server/chunks/_next-internal_server_app_api_workspace_missing_route_actions_1fidi6p.js +3 -0
  165. package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
  166. package/.next/server/chunks/features_0-cnt0l._.js +4 -0
  167. package/.next/server/chunks/features_0hdaci0._.js +4 -0
  168. package/.next/server/chunks/features_1e39j7-._.js +8 -0
  169. package/.next/server/chunks/features_bot_bot_query_ts_12mgkl2._.js +1 -1
  170. package/.next/server/chunks/features_memory_1uqvksn._.js +1 -1
  171. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0v_7drq._.js → node_modules_consola_dist_chunks_prompt_mjs_0a7-pbw._.js} +1 -1
  172. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_17k8irj._.js → node_modules_consola_dist_chunks_prompt_mjs_0gzvgfv._.js} +1 -1
  173. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0i7cvml._.js → node_modules_consola_dist_chunks_prompt_mjs_107pxfn._.js} +1 -1
  174. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0icqaqw._.js → node_modules_consola_dist_chunks_prompt_mjs_15hbel8._.js} +1 -1
  175. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_18i-23e._.js +3 -0
  176. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1bewgf3._.js +3 -0
  177. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1nlww1m._.js +3 -0
  178. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1q77nfx._.js +3 -0
  179. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1xqdzx_._.js +3 -0
  180. package/.next/server/chunks/{node_modules_zod_v4_1801ax7._.js → node_modules_zod_v4_0lkux5-._.js} +2 -2
  181. package/.next/server/chunks/{node_modules_zod_v4_1cha_bw._.js → node_modules_zod_v4_1jmr9cq._.js} +2 -2
  182. package/.next/server/chunks/{node_modules_zod_v4_0ubdflj._.js → node_modules_zod_v4_1yrxmek._.js} +2 -2
  183. package/.next/server/chunks/node_modules_zod_v4_classic_errors_0tp0y-q.js +3 -0
  184. package/.next/server/chunks/ssr/[root-of-the-server]__0-e011f._.js +3 -0
  185. package/.next/server/chunks/ssr/[root-of-the-server]__09q9med._.js +1 -1
  186. package/.next/server/chunks/ssr/[root-of-the-server]__0lyi8i2._.js +1 -1
  187. package/.next/server/chunks/ssr/[root-of-the-server]__0pd8yr7._.js +3 -0
  188. package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
  189. package/.next/server/chunks/ssr/[root-of-the-server]__18dthbp._.js +3 -0
  190. package/.next/server/chunks/ssr/[root-of-the-server]__18e68w8._.js +3 -0
  191. package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +1 -1
  192. package/.next/server/chunks/ssr/[root-of-the-server]__1nygfik._.js +5 -0
  193. package/.next/server/chunks/ssr/[root-of-the-server]__1sdphb0._.js +8 -0
  194. package/.next/server/chunks/ssr/[root-of-the-server]__1vdmfbe._.js +3 -0
  195. package/.next/server/chunks/ssr/[root-of-the-server]__1waa3rc._.js +85 -0
  196. package/.next/server/chunks/ssr/_0-2qsxo._.js +3 -0
  197. package/.next/server/chunks/ssr/_00rehl_._.js +3 -0
  198. package/.next/server/chunks/ssr/{_1lz_cq2._.js → _02oc_h5._.js} +76 -97
  199. package/.next/server/chunks/ssr/_05yghx6._.js +3 -0
  200. package/.next/server/chunks/ssr/_07nbwap._.js +3 -0
  201. package/.next/server/chunks/ssr/_08c4z-9._.js +3 -0
  202. package/.next/server/chunks/ssr/_0_qfdlw._.js +4 -0
  203. package/.next/server/chunks/ssr/{_0m2lsd1._.js → _0b6_jv-._.js} +2 -2
  204. package/.next/server/chunks/ssr/_0evkpto._.js +3 -0
  205. package/.next/server/chunks/ssr/_0geg212._.js +3 -0
  206. package/.next/server/chunks/ssr/{_1jdgjv9._.js → _0hxt2ul._.js} +2 -2
  207. package/.next/server/chunks/ssr/_0i_6q1w._.js +2 -2
  208. package/.next/server/chunks/ssr/_0lu1n_x._.js +1 -1
  209. package/.next/server/chunks/ssr/_0no7i1o._.js +3 -0
  210. package/.next/server/chunks/ssr/_0tzg--b._.js +3 -0
  211. package/.next/server/chunks/ssr/{_15j2_8f._.js → _0wzaht-._.js} +2 -2
  212. package/.next/server/chunks/ssr/_0z-g0uy._.js +3 -0
  213. package/.next/server/chunks/ssr/_114ylv7._.js +7 -0
  214. package/.next/server/chunks/ssr/_123y-ah._.js +3 -0
  215. package/.next/server/chunks/ssr/_12c-iwh._.js +3 -0
  216. package/.next/server/chunks/ssr/_12w42gi._.js +3 -0
  217. package/.next/server/chunks/ssr/_161kqav._.js +3 -0
  218. package/.next/server/chunks/ssr/_167hchk._.js +3 -0
  219. package/.next/server/chunks/ssr/{_0ap2fzn._.js → _16c6_xm._.js} +2 -2
  220. package/.next/server/chunks/ssr/_18opah7._.js +3 -0
  221. package/.next/server/chunks/ssr/_1_krfph._.js +3 -0
  222. package/.next/server/chunks/ssr/{_0rzucul._.js → _1_x5spz._.js} +3 -3
  223. package/.next/server/chunks/ssr/_1a61fc9._.js +3 -0
  224. package/.next/server/chunks/ssr/_1ey7qn-._.js +70 -0
  225. package/.next/server/chunks/ssr/_1g9vs7q._.js +3 -0
  226. package/.next/server/chunks/ssr/_1jmz33w._.js +3 -0
  227. package/.next/server/chunks/ssr/_1rgtxhr._.js +5 -0
  228. package/.next/server/chunks/ssr/_1slp25y._.js +3 -0
  229. package/.next/server/chunks/ssr/_1w_t7h7._.js +101 -0
  230. package/.next/server/chunks/ssr/{_0s99bgb._.js → _1wyfaq_._.js} +9 -3
  231. package/.next/server/chunks/ssr/_200gt-m._.js +102 -0
  232. package/.next/server/chunks/ssr/components_ui_tabs_tsx_0ej40b4._.js +3 -0
  233. package/.next/server/chunks/ssr/features_bot_thread_query_ts_023eklt._.js +4 -0
  234. package/.next/server/chunks/ssr/features_config_components_config-setting_tsx_0xfwqdg._.js +1 -1
  235. package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
  236. package/.next/server/chunks/ssr/features_workspace_00jz2hu._.js +8 -0
  237. package/.next/server/chunks/ssr/{_1-teee5._.js → lib_logger_ts_0-olsze._.js} +2 -7
  238. package/.next/server/chunks/ssr/{node_modules_05-n6dz._.js → node_modules_02ai7br._.js} +1 -1
  239. package/.next/server/chunks/ssr/{node_modules_1chvq5f._.js → node_modules_02deexj._.js} +1 -1
  240. package/.next/server/chunks/ssr/{node_modules_0m383r2._.js → node_modules_07za262._.js} +1 -1
  241. package/.next/server/chunks/ssr/{node_modules_07dsgkx._.js → node_modules_0_s9get._.js} +1 -1
  242. package/.next/server/chunks/ssr/{node_modules_1a0kmjl._.js → node_modules_0n3c7h0._.js} +1 -1
  243. package/.next/server/chunks/ssr/{node_modules_0zeg3x_._.js → node_modules_0od6jwr._.js} +1 -1
  244. package/.next/server/chunks/ssr/{node_modules_1y79i83._.js → node_modules_0rdt7pk._.js} +1 -1
  245. package/.next/server/chunks/ssr/{node_modules_17bwo43._.js → node_modules_0tusx4d._.js} +3 -3
  246. package/.next/server/chunks/ssr/{node_modules_04sksn9._.js → node_modules_0w1z7kz._.js} +1 -1
  247. package/.next/server/chunks/ssr/{node_modules_1uyk91w._.js → node_modules_0wdupfz._.js} +1 -1
  248. package/.next/server/chunks/ssr/{node_modules_0ifp389._.js → node_modules_1720w0a._.js} +1 -1
  249. package/.next/server/chunks/ssr/{node_modules_0u9da1h._.js → node_modules_18lsg7d._.js} +1 -1
  250. package/.next/server/chunks/ssr/{node_modules_1k6n600._.js → node_modules_1b94fxf._.js} +1 -1
  251. package/.next/server/chunks/ssr/{node_modules_20c28js._.js → node_modules_1ecdo1s._.js} +1 -1
  252. package/.next/server/chunks/ssr/{node_modules_0fkeku3._.js → node_modules_1fa9ag7._.js} +1 -1
  253. package/.next/server/chunks/ssr/{node_modules_1j8j4pt._.js → node_modules_1fv-_si._.js} +1 -1
  254. package/.next/server/chunks/ssr/{node_modules_0-dr_o7._.js → node_modules_1hf461g._.js} +1 -1
  255. package/.next/server/chunks/ssr/{node_modules_1lz0oxc._.js → node_modules_1m71ta-._.js} +1 -1
  256. package/.next/server/chunks/ssr/{node_modules_1t77e4n._.js → node_modules_1n93n-g._.js} +1 -1
  257. package/.next/server/chunks/ssr/{node_modules_16mkxuo._.js → node_modules_1n9lqu9._.js} +1 -1
  258. package/.next/server/chunks/ssr/{node_modules_1k7z2j6._.js → node_modules_1npnsvd._.js} +1 -1
  259. package/.next/server/chunks/ssr/{node_modules_056qgf-._.js → node_modules_1rn2r0n._.js} +1 -1
  260. package/.next/server/chunks/ssr/{node_modules_0x3-ply._.js → node_modules_1seuurl._.js} +2 -2
  261. package/.next/server/chunks/ssr/{node_modules_0bvopy2._.js → node_modules_1vq-mfk._.js} +1 -1
  262. package/.next/server/chunks/ssr/{node_modules_0iur59s._.js → node_modules_1vzyw1t._.js} +1 -1
  263. package/.next/server/chunks/ssr/{node_modules_1k8j8n0._.js → node_modules_1w359w4._.js} +1 -1
  264. package/.next/server/chunks/ssr/{node_modules_1x0ztf4._.js → node_modules_1yajbl6._.js} +1 -1
  265. package/.next/server/chunks/ssr/{node_modules_1-y7nni._.js → node_modules_20eqhy8._.js} +1 -1
  266. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0bkwd0u._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_019sbis._.js} +1 -1
  267. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0p9a9su._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0s6piq3._.js} +1 -1
  268. package/.next/server/chunks/ssr/{node_modules_@vercel_oidc_dist_1o553h-._.js → node_modules_@vercel_oidc_dist_05itbb1._.js} +1 -1
  269. package/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_trash_mjs_0px2gzr._.js +3 -0
  270. package/.next/server/middleware-build-manifest.js +3 -3
  271. package/.next/server/pages/404.html +1 -1
  272. package/.next/server/pages/500.html +1 -1
  273. package/.next/server/server-reference-manifest.js +1 -1
  274. package/.next/server/server-reference-manifest.json +68 -46
  275. package/.next/static/chunks/07vqbk_9t4em4.js +2 -0
  276. package/.next/static/chunks/08krja1zx7nqg.js +1 -0
  277. package/.next/static/chunks/0g4b348l0pve7.js +1 -0
  278. package/.next/static/chunks/0qcuwdk132jjt.js +1 -0
  279. package/.next/static/chunks/0vlgzqo9ka90v.js +1 -0
  280. package/.next/static/chunks/{11r2yp_yh9_qn.js → 0z69gvysmave7.js} +1 -1
  281. package/.next/static/chunks/0zrupxgci5gqc.js +1 -0
  282. package/.next/static/chunks/12fvz1w5ows75.js +1 -0
  283. package/.next/static/chunks/14t03ned286iu.js +1 -0
  284. package/.next/static/chunks/156xxbkrz5lzu.js +18 -0
  285. package/.next/static/chunks/1fz14reod4lft.js +1 -0
  286. package/.next/static/chunks/1g23dbabl-vkr.js +1 -0
  287. package/.next/static/chunks/1ohslk4568tm3.js +1 -0
  288. package/.next/static/chunks/1qy_rc3oxfxok.js +1 -0
  289. package/.next/static/chunks/1sbmwswc9k2-1.js +1 -0
  290. package/.next/static/chunks/1vqezbhjm3goq.js +1 -0
  291. package/.next/static/chunks/1zea7qdl-7365.js +1 -0
  292. package/.next/static/chunks/1zvqumkg7kmo0.css +1 -0
  293. package/.next/static/chunks/26hpqt3y6bogl.js +12 -0
  294. package/.next/static/chunks/2_j5mqm6d-z18.js +99 -0
  295. package/.next/static/chunks/2dt6tu7a22svs.js +1 -0
  296. package/.next/static/chunks/2h5ls3d86kya6.js +1 -0
  297. package/.next/static/chunks/2wc6y1ht6dfuy.js +1 -0
  298. package/.next/static/chunks/{435atsnhs7ksu.js → 2xr0zpll7thyi.js} +2 -2
  299. package/.next/static/chunks/31jztc-yq30m7.js +1 -0
  300. package/.next/static/chunks/391af0i8eljzk.js +1 -0
  301. package/.next/static/chunks/3bfwpww3m3x4u.js +1 -0
  302. package/.next/static/chunks/{38gweqdo4jpfj.js → 3izg0a3k87q1-.js} +5 -5
  303. package/.next/static/chunks/3p2s2cjokx1aa.js +5 -0
  304. package/.next/static/chunks/{408ueu4hfvcg7.js → 41s3fml5oivsa.js} +1 -1
  305. package/README.md +45 -193
  306. package/app/api/events/app-event.ts +6 -4
  307. package/app/api/query-key.ts +25 -16
  308. package/bin/database.mjs +37 -0
  309. package/bin/thursday.mjs +44 -28
  310. package/components/ui/custom-icon.tsx +0 -60
  311. package/components/ui/radio-group.tsx +37 -0
  312. package/components/ui/shiny-text.tsx +33 -6
  313. package/database/migrations/{20260910173049_numerous_spirit → 20260916145701_clever_multiple_man}/migration.sql +80 -24
  314. package/database/migrations/{20260910173049_numerous_spirit → 20260916145701_clever_multiple_man}/snapshot.json +689 -110
  315. package/database/migrations/20260916160713_thread_cancelled/migration.sql +2 -0
  316. package/database/migrations/{20260911030320_opposite_jack_power → 20260916160713_thread_cancelled}/snapshot.json +706 -84
  317. package/docs/how-it-works.md +40 -35
  318. package/docs/images/keeps-going.png +0 -0
  319. package/docs/images/two-minds.png +0 -0
  320. package/docs/live-calls.md +236 -0
  321. package/docs/thread-rooms.md +71 -0
  322. package/features/ai/chatgpt.ts +1 -2
  323. package/features/ai/live.schema.ts +128 -0
  324. package/features/ai/load-tools.ts +152 -79
  325. package/features/ai/model.schema.ts +2 -120
  326. package/features/ai/model.ts +52 -88
  327. package/features/ai/prompts/bot.prompt.ts +91 -214
  328. package/features/ai/prompts/live.prompt.ts +169 -0
  329. package/features/ai/prompts/prompt-helper.ts +92 -32
  330. package/features/ai/prompts/thursday.prompt.ts +164 -190
  331. package/features/ai/tools/bot.tool.ts +38 -145
  332. package/features/ai/tools/call.tool.ts +33 -5
  333. package/features/ai/tools/connected.ts +5 -3
  334. package/features/ai/tools/mcp.tool.ts +7 -4
  335. package/features/ai/tools/memory.tool.ts +35 -31
  336. package/features/ai/tools/skills.tool.ts +11 -6
  337. package/features/ai/tools/studio.tool.ts +26 -21
  338. package/features/ai/tools/tool-name.ts +3 -5
  339. package/features/ai/tools/workspace.tool.ts +33 -10
  340. package/features/artifact/artifact.action.ts +2 -2
  341. package/features/artifact/artifact.query.ts +112 -61
  342. package/features/artifact/artifact.schema.ts +8 -6
  343. package/features/artifact/components/artifact-setting.tsx +83 -33
  344. package/features/bot/bot.action.ts +43 -36
  345. package/features/bot/bot.memory.ts +137 -20
  346. package/features/bot/bot.query.ts +28 -11
  347. package/features/bot/bot.run.ts +296 -744
  348. package/features/bot/bot.runner.ts +463 -864
  349. package/features/bot/bot.schema.ts +93 -82
  350. package/features/bot/bot.seed.ts +141 -64
  351. package/features/bot/components/bot-mark.tsx +324 -232
  352. package/features/bot/components/bot-room.tsx +1613 -697
  353. package/features/bot/components/bot-roster.tsx +8 -13
  354. package/features/bot/components/bot-setting.tsx +58 -42
  355. package/features/bot/components/bot-tool.tsx +55 -87
  356. package/features/bot/components/mark-palette.tsx +35 -32
  357. package/features/bot/components/path-chips.tsx +33 -3
  358. package/features/bot/components/thread-badge.tsx +34 -0
  359. package/features/bot/components/thread-reply.tsx +639 -0
  360. package/features/bot/components/thread-setting.tsx +674 -0
  361. package/features/bot/mark.const.ts +79 -31
  362. package/features/bot/room.query.ts +889 -0
  363. package/features/bot/room.schema.ts +64 -0
  364. package/features/bot/seed-bots.ts +2 -1
  365. package/features/bot/thread.query.ts +971 -0
  366. package/features/bot/thread.store.ts +587 -0
  367. package/features/config/components/voice-key.tsx +113 -88
  368. package/features/config/config.const.ts +5 -9
  369. package/features/connectors/mcp.schema.ts +0 -2
  370. package/features/intro/components/intro.tsx +169 -139
  371. package/features/memory/components/memory-setting.tsx +2 -7
  372. package/features/memory/memory.schema.ts +14 -23
  373. package/features/settings/components/setting-ui.tsx +0 -44
  374. package/features/settings/components/settings.tsx +12 -12
  375. package/features/settings/settings.alert.ts +3 -3
  376. package/features/settings/settings.store.ts +1 -1
  377. package/features/skills/skills.schema.ts +0 -2
  378. package/features/thursday/ascii.const.ts +74 -0
  379. package/features/thursday/components/ascii-field.tsx +24 -44
  380. package/features/thursday/components/ascii-orb.tsx +525 -381
  381. package/features/thursday/components/call-log.tsx +46 -44
  382. package/features/thursday/components/face.tsx +40 -10
  383. package/features/thursday/components/side-captions.tsx +273 -0
  384. package/features/thursday/components/tab-state.tsx +14 -6
  385. package/features/thursday/components/thursday-mark.tsx +1 -0
  386. package/features/thursday/components/thursday-setting.tsx +633 -333
  387. package/features/thursday/components/thursday.tsx +315 -274
  388. package/features/thursday/components/voice-picker.tsx +255 -0
  389. package/features/thursday/face.store.ts +5 -0
  390. package/features/thursday/thursday.action.ts +96 -72
  391. package/features/thursday/thursday.query.ts +49 -30
  392. package/features/thursday/thursday.schema.ts +37 -35
  393. package/features/thursday/thursday.store.ts +14 -7
  394. package/features/thursday/tool-call.ts +3 -3
  395. package/features/thursday/tool-line.ts +5 -3
  396. package/features/thursday/use-thursday.ts +801 -457
  397. package/features/workspace/file-kind.ts +9 -0
  398. package/features/workspace/workspace.query.ts +17 -0
  399. package/features/workspace/workspace.ts +82 -36
  400. package/hooks/use-hotkey.ts +3 -2
  401. package/lib/live/live.schema.ts +26 -0
  402. package/lib/live/live.server.ts +153 -0
  403. package/lib/live/live.session.ts +574 -0
  404. package/lib/{realtime/realtime.tap.ts → live/live.tap.ts} +41 -12
  405. package/lib/live/live.transport.ts +152 -0
  406. package/lib/protocol/use-server-pages.ts +9 -5
  407. package/lib/utils.ts +21 -20
  408. package/package.json +2 -2
  409. package/public/voices/alloy.ogg +0 -0
  410. package/public/voices/ash.ogg +0 -0
  411. package/public/voices/ballad.ogg +0 -0
  412. package/public/voices/beacon.ogg +0 -0
  413. package/public/voices/bossa.ogg +0 -0
  414. package/public/voices/cedar.ogg +0 -0
  415. package/public/voices/cinder.ogg +0 -0
  416. package/public/voices/coral.ogg +0 -0
  417. package/public/voices/delta.ogg +0 -0
  418. package/public/voices/echo.ogg +0 -0
  419. package/public/voices/gleam.ogg +0 -0
  420. package/public/voices/marin.ogg +0 -0
  421. package/public/voices/meridian.ogg +0 -0
  422. package/public/voices/quartz.ogg +0 -0
  423. package/public/voices/ripple.ogg +0 -0
  424. package/public/voices/sage.ogg +0 -0
  425. package/public/voices/shimmer.ogg +0 -0
  426. package/public/voices/stone.ogg +0 -0
  427. package/public/voices/tempo.ogg +0 -0
  428. package/public/voices/verse.ogg +0 -0
  429. package/public/voices/vesper.ogg +0 -0
  430. package/public/voices/willow.ogg +0 -0
  431. package/scripts/artifact-paths.test.mts +38 -0
  432. package/scripts/bot-context.test.mts +1408 -0
  433. package/scripts/live-history.test.mts +115 -0
  434. package/scripts/live-session.test.mts +938 -0
  435. package/server.js +1 -1
  436. package/skills/browser/SKILL.md +11 -1
  437. package/skills/computer/SKILL.md +1 -1
  438. package/skills/find-skills/SKILL.md +3 -8
  439. package/skills/interactive-page/SKILL.md +12 -7
  440. package/skills/interactive-page/references/diagram.md +89 -0
  441. package/skills/interactive-page/scripts/archify/LICENSE +22 -0
  442. package/skills/interactive-page/scripts/archify/README.md +25 -0
  443. package/skills/interactive-page/scripts/archify/assets/JetBrainsMono-OFL.txt +93 -0
  444. package/skills/interactive-page/scripts/archify/assets/template.html +14934 -0
  445. package/skills/interactive-page/scripts/archify/bin/archify.mjs +2126 -0
  446. package/skills/interactive-page/scripts/archify/bin/open-artifact.mjs +86 -0
  447. package/skills/interactive-page/scripts/archify/bin/preview.mjs +653 -0
  448. package/skills/interactive-page/scripts/archify/bin/visual-check.mjs +829 -0
  449. package/skills/interactive-page/scripts/archify/delta/architecture-delta.mjs +1223 -0
  450. package/skills/interactive-page/scripts/archify/examples/agent-run.lifecycle.json +60 -0
  451. package/skills/interactive-page/scripts/archify/examples/agent-tool-call.workflow.json +94 -0
  452. package/skills/interactive-page/scripts/archify/examples/async-job-roundtrip.sequence.json +61 -0
  453. package/skills/interactive-page/scripts/archify/examples/cache-miss-request.sequence.json +82 -0
  454. package/skills/interactive-page/scripts/archify/examples/checkout-platform.base.architecture.json +31 -0
  455. package/skills/interactive-page/scripts/archify/examples/checkout-platform.head.architecture.json +31 -0
  456. package/skills/interactive-page/scripts/archify/examples/deployment-release.lifecycle.json +49 -0
  457. package/skills/interactive-page/scripts/archify/examples/event-stream.dataflow.json +57 -0
  458. package/skills/interactive-page/scripts/archify/examples/incident-response.workflow.json +64 -0
  459. package/skills/interactive-page/scripts/archify/examples/product-analytics.dataflow.json +76 -0
  460. package/skills/interactive-page/scripts/archify/examples/production-deployment.architecture.json +71 -0
  461. package/skills/interactive-page/scripts/archify/examples/release-delivery.workflow.json +62 -0
  462. package/skills/interactive-page/scripts/archify/examples/web-app.architecture.json +46 -0
  463. package/skills/interactive-page/scripts/archify/migrations/workflow-v2.mjs +279 -0
  464. package/skills/interactive-page/scripts/archify/recipes/scenarios.mjs +284 -0
  465. package/skills/interactive-page/scripts/archify/references/authoring-contract.md +243 -0
  466. package/skills/interactive-page/scripts/archify/references/delivery-contract.md +120 -0
  467. package/skills/interactive-page/scripts/archify/references/viewer-runtime.md +45 -0
  468. package/skills/interactive-page/scripts/archify/renderers/architecture/grid.mjs +62 -0
  469. package/skills/interactive-page/scripts/archify/renderers/architecture/render-architecture.mjs +1078 -0
  470. package/skills/interactive-page/scripts/archify/renderers/dataflow/README.md +104 -0
  471. package/skills/interactive-page/scripts/archify/renderers/dataflow/render-dataflow.mjs +483 -0
  472. package/skills/interactive-page/scripts/archify/renderers/lifecycle/README.md +115 -0
  473. package/skills/interactive-page/scripts/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
  474. package/skills/interactive-page/scripts/archify/renderers/sequence/README.md +114 -0
  475. package/skills/interactive-page/scripts/archify/renderers/sequence/render-sequence.mjs +464 -0
  476. package/skills/interactive-page/scripts/archify/renderers/shared/brand-marks.mjs +563 -0
  477. package/skills/interactive-page/scripts/archify/renderers/shared/cli.mjs +218 -0
  478. package/skills/interactive-page/scripts/archify/renderers/shared/desktop-readability.mjs +26 -0
  479. package/skills/interactive-page/scripts/archify/renderers/shared/diagnostics.mjs +127 -0
  480. package/skills/interactive-page/scripts/archify/renderers/shared/engineering-profiles.mjs +157 -0
  481. package/skills/interactive-page/scripts/archify/renderers/shared/generated-brand-marks.mjs +3 -0
  482. package/skills/interactive-page/scripts/archify/renderers/shared/generated-validators.mjs +13 -0
  483. package/skills/interactive-page/scripts/archify/renderers/shared/geometry.mjs +1423 -0
  484. package/skills/interactive-page/scripts/archify/renderers/shared/i18n.mjs +595 -0
  485. package/skills/interactive-page/scripts/archify/renderers/shared/layout-report.mjs +40 -0
  486. package/skills/interactive-page/scripts/archify/renderers/shared/legend.mjs +217 -0
  487. package/skills/interactive-page/scripts/archify/renderers/shared/output-path.mjs +340 -0
  488. package/skills/interactive-page/scripts/archify/renderers/shared/repository-evidence.mjs +238 -0
  489. package/skills/interactive-page/scripts/archify/renderers/shared/repository-location.mjs +58 -0
  490. package/skills/interactive-page/scripts/archify/renderers/shared/text-fit.mjs +49 -0
  491. package/skills/interactive-page/scripts/archify/renderers/shared/utils.mjs +232 -0
  492. package/skills/interactive-page/scripts/archify/renderers/shared/validator.mjs +86 -0
  493. package/skills/interactive-page/scripts/archify/renderers/workflow/README.md +223 -0
  494. package/skills/interactive-page/scripts/archify/renderers/workflow/render-workflow.mjs +35 -0
  495. package/skills/interactive-page/scripts/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
  496. package/skills/interactive-page/scripts/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
  497. package/skills/interactive-page/scripts/archify/schemas/README.md +211 -0
  498. package/skills/interactive-page/scripts/archify/schemas/architecture.schema.json +178 -0
  499. package/skills/interactive-page/scripts/archify/schemas/common.schema.json +115 -0
  500. package/skills/interactive-page/scripts/archify/schemas/dataflow.schema.json +243 -0
  501. package/skills/interactive-page/scripts/archify/schemas/lifecycle.schema.json +266 -0
  502. package/skills/interactive-page/scripts/archify/schemas/sequence.schema.json +223 -0
  503. package/skills/interactive-page/scripts/archify/schemas/workflow.schema.json +428 -0
  504. package/skills/interactive-page/scripts/archify/scripts/check-render-output.mjs +916 -0
  505. package/skills/interactive-page/scripts/archify/scripts/render-examples.mjs +26 -0
  506. package/skills/interactive-page/scripts/bundle-artifact.sh +9 -8
  507. package/skills/skill-creator/SKILL.md +4 -5
  508. package/.next/server/app/api/bot/task/[id]/route/app-paths-manifest.json +0 -3
  509. package/.next/server/app/api/bot/task/[id]/route.js +0 -16
  510. package/.next/server/app/api/bot/task/[id]/route.js.nft.json +0 -1
  511. package/.next/server/app/api/bot/task/[id]/route_client-reference-manifest.js +0 -3
  512. package/.next/server/app/api/bot/task/route/app-paths-manifest.json +0 -3
  513. package/.next/server/app/api/bot/task/route.js +0 -16
  514. package/.next/server/app/api/bot/task/route.js.nft.json +0 -1
  515. package/.next/server/app/api/bot/task/route_client-reference-manifest.js +0 -3
  516. package/.next/server/chunks/[root-of-the-server]__026u77e._.js +0 -5
  517. package/.next/server/chunks/[root-of-the-server]__02va5wz._.js +0 -3
  518. package/.next/server/chunks/[root-of-the-server]__050zri4._.js +0 -3
  519. package/.next/server/chunks/[root-of-the-server]__0bg9710._.js +0 -3
  520. package/.next/server/chunks/[root-of-the-server]__0ffbg85._.js +0 -3
  521. package/.next/server/chunks/[root-of-the-server]__0in-d5s._.js +0 -3
  522. package/.next/server/chunks/[root-of-the-server]__0ncs9uu._.js +0 -3
  523. package/.next/server/chunks/[root-of-the-server]__0pa9k-f._.js +0 -8
  524. package/.next/server/chunks/[root-of-the-server]__0qi_m0e._.js +0 -8
  525. package/.next/server/chunks/[root-of-the-server]__0tq0m_k._.js +0 -3
  526. package/.next/server/chunks/[root-of-the-server]__0xep6j_._.js +0 -3
  527. package/.next/server/chunks/[root-of-the-server]__1-ga0kh._.js +0 -5
  528. package/.next/server/chunks/[root-of-the-server]__11n256_._.js +0 -5
  529. package/.next/server/chunks/[root-of-the-server]__144l7qt._.js +0 -8
  530. package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +0 -5
  531. package/.next/server/chunks/[root-of-the-server]__1anc1p9._.js +0 -3
  532. package/.next/server/chunks/[root-of-the-server]__1fizn31._.js +0 -3
  533. package/.next/server/chunks/[root-of-the-server]__1jg8t86._.js +0 -8
  534. package/.next/server/chunks/[root-of-the-server]__1lldzy9._.js +0 -3
  535. package/.next/server/chunks/[root-of-the-server]__1llj3-b._.js +0 -3
  536. package/.next/server/chunks/[root-of-the-server]__1p8m3f4._.js +0 -3
  537. package/.next/server/chunks/[root-of-the-server]__1peqvsi._.js +0 -3
  538. package/.next/server/chunks/[root-of-the-server]__1w8gm5h._.js +0 -10
  539. package/.next/server/chunks/[root-of-the-server]__1xt39nn._.js +0 -8
  540. package/.next/server/chunks/[root-of-the-server]__1zb8mfo._.js +0 -8
  541. package/.next/server/chunks/_0-73of8._.js +0 -55
  542. package/.next/server/chunks/_0-fjql4._.js +0 -31
  543. package/.next/server/chunks/_00xh_q0._.js +0 -25
  544. package/.next/server/chunks/_051qh8u._.js +0 -3
  545. package/.next/server/chunks/_05sovvj._.js +0 -3
  546. package/.next/server/chunks/_091bi8d._.js +0 -3
  547. package/.next/server/chunks/_0fzqt2y._.js +0 -142
  548. package/.next/server/chunks/_0lr92vd._.js +0 -3
  549. package/.next/server/chunks/_0mecv0f._.js +0 -31
  550. package/.next/server/chunks/_0mh8j4m._.js +0 -3
  551. package/.next/server/chunks/_0sb7tlz._.js +0 -3
  552. package/.next/server/chunks/_0si7xzn._.js +0 -3
  553. package/.next/server/chunks/_0u10wmw._.js +0 -55
  554. package/.next/server/chunks/_0wp4le3._.js +0 -3
  555. package/.next/server/chunks/_0y5fg-x._.js +0 -3
  556. package/.next/server/chunks/_1230wbx._.js +0 -10
  557. package/.next/server/chunks/_12nheja._.js +0 -3
  558. package/.next/server/chunks/_13510xh._.js +0 -3
  559. package/.next/server/chunks/_15hq89o._.js +0 -3
  560. package/.next/server/chunks/_18-1wcc._.js +0 -55
  561. package/.next/server/chunks/_18d7-5p._.js +0 -3
  562. package/.next/server/chunks/_1c78vw5._.js +0 -237
  563. package/.next/server/chunks/_1h5_8sk._.js +0 -3
  564. package/.next/server/chunks/_1hdnxb7._.js +0 -3
  565. package/.next/server/chunks/_1j8k_j5._.js +0 -3
  566. package/.next/server/chunks/_1nula3v._.js +0 -3
  567. package/.next/server/chunks/_1php4eq._.js +0 -3
  568. package/.next/server/chunks/_1yuv4vp._.js +0 -3
  569. package/.next/server/chunks/_1zkfbaa._.js +0 -3
  570. package/.next/server/chunks/_next-internal_server_app_api_bot_task_[id]_route_actions_1_k_8u3.js +0 -3
  571. package/.next/server/chunks/_next-internal_server_app_api_bot_task_route_actions_0xln6ra.js +0 -3
  572. package/.next/server/chunks/features_0rpfxbk._.js +0 -3
  573. package/.next/server/chunks/features_1qf3cei._.js +0 -8
  574. package/.next/server/chunks/features_bot_0zt92oh._.js +0 -3
  575. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1jidylq._.js +0 -3
  576. package/.next/server/chunks/ssr/[externals]__0dizgek._.js +0 -3
  577. package/.next/server/chunks/ssr/[root-of-the-server]__0-nob52._.js +0 -4
  578. package/.next/server/chunks/ssr/[root-of-the-server]__092knlj._.js +0 -3
  579. package/.next/server/chunks/ssr/[root-of-the-server]__0mz33a7._.js +0 -3
  580. package/.next/server/chunks/ssr/[root-of-the-server]__0s4wb56._.js +0 -3
  581. package/.next/server/chunks/ssr/[root-of-the-server]__0s9dq5u._.js +0 -3
  582. package/.next/server/chunks/ssr/[root-of-the-server]__0sd3izg._.js +0 -3
  583. package/.next/server/chunks/ssr/[root-of-the-server]__0vnmv-s._.js +0 -3
  584. package/.next/server/chunks/ssr/[root-of-the-server]__1-13tcn._.js +0 -43
  585. package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +0 -61
  586. package/.next/server/chunks/ssr/[root-of-the-server]__1zidpfl._.js +0 -3
  587. package/.next/server/chunks/ssr/_001_ms1._.js +0 -33
  588. package/.next/server/chunks/ssr/_01n3o0m._.js +0 -3
  589. package/.next/server/chunks/ssr/_04z2c7b._.js +0 -3
  590. package/.next/server/chunks/ssr/_06tssji._.js +0 -3
  591. package/.next/server/chunks/ssr/_0fk4c7d._.js +0 -3
  592. package/.next/server/chunks/ssr/_0h42fze._.js +0 -3
  593. package/.next/server/chunks/ssr/_0h7zdni._.js +0 -3
  594. package/.next/server/chunks/ssr/_0mggveb._.js +0 -3
  595. package/.next/server/chunks/ssr/_0nbpc_8._.js +0 -3
  596. package/.next/server/chunks/ssr/_0q0zan6._.js +0 -70
  597. package/.next/server/chunks/ssr/_0zcjrbg._.js +0 -3
  598. package/.next/server/chunks/ssr/_0zhoc3r._.js +0 -3
  599. package/.next/server/chunks/ssr/_11j92tu._.js +0 -3
  600. package/.next/server/chunks/ssr/_13fke0x._.js +0 -3
  601. package/.next/server/chunks/ssr/_18cymkq._.js +0 -3
  602. package/.next/server/chunks/ssr/_1ebxla1._.js +0 -3
  603. package/.next/server/chunks/ssr/_1nj4niv._.js +0 -42
  604. package/.next/server/chunks/ssr/_1ov37if._.js +0 -3
  605. package/.next/server/chunks/ssr/_1ovmc9s._.js +0 -3
  606. package/.next/server/chunks/ssr/_1sji22n._.js +0 -3
  607. package/.next/server/chunks/ssr/_1vi_uo7._.js +0 -3
  608. package/.next/server/chunks/ssr/_1vyd1ji._.js +0 -3
  609. package/.next/server/chunks/ssr/_1xx4zlb._.js +0 -3
  610. package/.next/server/chunks/ssr/components_ui_1y1l7yj._.js +0 -3
  611. package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +0 -3
  612. package/.next/server/chunks/ssr/lib_realtime_12wg_dd._.js +0 -27
  613. package/.next/server/chunks/ssr/lib_realtime_15h_v1v._.js +0 -27
  614. package/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0npjf8-._.js +0 -3
  615. package/.next/static/chunks/0n3jle9kbqfr2.js +0 -40
  616. package/.next/static/chunks/0r5qcctujhxli.js +0 -1
  617. package/.next/static/chunks/10teww7wt-f6h.js +0 -1
  618. package/.next/static/chunks/126fj4pga_72k.js +0 -1
  619. package/.next/static/chunks/159udiexf6dom.js +0 -2
  620. package/.next/static/chunks/18a96rkhi4_yd.js +0 -1
  621. package/.next/static/chunks/18gi7o2ibrgh8.js +0 -3
  622. package/.next/static/chunks/1dkjg87pxk0n9.js +0 -28
  623. package/.next/static/chunks/1q9z1tohil7xn.js +0 -1
  624. package/.next/static/chunks/1sjgfets224re.js +0 -1
  625. package/.next/static/chunks/1wszsr83t01gh.js +0 -1
  626. package/.next/static/chunks/22_zkas21rpna.js +0 -1
  627. package/.next/static/chunks/2fh4-3z_q8b_w.js +0 -1
  628. package/.next/static/chunks/2h0sd2vumhb15.js +0 -1
  629. package/.next/static/chunks/2szintyibu0s5.js +0 -1
  630. package/.next/static/chunks/2t4vhi3m8ahya.js +0 -1
  631. package/.next/static/chunks/2tigdtz3dpcy8.js +0 -1
  632. package/.next/static/chunks/3-b6b7entqazs.js +0 -1
  633. package/.next/static/chunks/3786h5vayt80-.js +0 -28
  634. package/.next/static/chunks/3cq5g494yuke8.css +0 -1
  635. package/.next/static/chunks/3dmbhsv2u_8kj.js +0 -1
  636. package/.next/static/chunks/3hibbjnt85-k6.js +0 -1
  637. package/.next/static/chunks/3i0a5px-oufgc.js +0 -1
  638. package/.next/static/chunks/3wexk9qo8zuj3.js +0 -18
  639. package/.next/static/chunks/3xk7yqgomx7yq.js +0 -1
  640. package/.next/static/chunks/3xre8bu_pk1p_.js +0 -1
  641. package/.next/static/chunks/3zv6t3i77xhr_.js +0 -1
  642. package/database/migrations/20260911030320_opposite_jack_power/migration.sql +0 -1
  643. package/docs/images/task-thread.png +0 -0
  644. package/features/bot/components/task-badge.tsx +0 -42
  645. package/features/bot/components/task-reply.tsx +0 -328
  646. package/features/bot/components/task-setting.tsx +0 -524
  647. package/features/bot/task.query.ts +0 -1079
  648. package/features/bot/task.store.ts +0 -487
  649. package/lib/realtime/client-secret.ts +0 -86
  650. package/lib/realtime/open-session.ts +0 -31
  651. package/lib/realtime/openai.ts +0 -35
  652. package/lib/realtime/realtime.audio.ts +0 -196
  653. package/lib/realtime/realtime.driver.ts +0 -489
  654. package/lib/realtime/realtime.protocol.ts +0 -393
  655. package/lib/realtime/realtime.schema.ts +0 -37
  656. package/lib/realtime/realtime.session.ts +0 -106
  657. package/lib/realtime/realtime.transport.ts +0 -384
  658. package/lib/realtime/xai.ts +0 -39
  659. /package/.next/server/app/api/bot/{task → thread}/[id]/route/build-manifest.json +0 -0
  660. /package/.next/server/app/api/bot/{task → thread}/[id]/route/server-reference-manifest.json +0 -0
  661. /package/.next/server/app/api/bot/{task → thread}/[id]/route.js.map +0 -0
  662. /package/.next/server/app/api/bot/{task → thread}/route/build-manifest.json +0 -0
  663. /package/.next/server/app/api/bot/{task → thread}/route/server-reference-manifest.json +0 -0
  664. /package/.next/server/app/api/bot/{task → thread}/route.js.map +0 -0
  665. /package/.next/static/{G6-gNoyGDEcgAsq-L4PE1 → yyRVBc0xxYQsh3GpbQX9b}/_buildManifest.js +0 -0
  666. /package/.next/static/{G6-gNoyGDEcgAsq-L4PE1 → yyRVBc0xxYQsh3GpbQX9b}/_clientMiddlewareManifest.js +0 -0
  667. /package/.next/static/{G6-gNoyGDEcgAsq-L4PE1 → yyRVBc0xxYQsh3GpbQX9b}/_ssgManifest.js +0 -0
@@ -0,0 +1,255 @@
1
+ "use client";
2
+
3
+ import { Check, ChevronDown, X } from "lucide-react";
4
+ import { useCallback, useEffect, useRef, useState } from "react";
5
+ import { Button } from "@/components/ui/button";
6
+ import { Input, inputClassName } from "@/components/ui/input";
7
+ import { ShinyText } from "@/components/ui/shiny-text";
8
+ import { toast } from "@/components/ui/toast";
9
+ import {
10
+ LIVE_VOICE_NOTE,
11
+ LIVE_VOICES,
12
+ voiceSamplePath,
13
+ } from "@/features/ai/live.schema";
14
+ import { Face } from "@/features/thursday/components/face";
15
+ import type { ThursdayFace } from "@/features/thursday/thursday.schema";
16
+ import { createClipTap, SPECTRUM_BANDS } from "@/lib/live/live.tap";
17
+ import { cn, errorToString } from "@/lib/utils";
18
+
19
+ /**
20
+ * Choosing a voice by ear. A name plays its recorded line and her own face
21
+ * speaks it — the same component and the same bands a call moves her with, so
22
+ * what you hear and see here is what the call will be. Only Save writes, so
23
+ * hearing eleven voices stores none of them.
24
+ */
25
+
26
+ const SILENT = new Array<number>(SPECTRUM_BANDS).fill(0);
27
+
28
+ export function VoicePicker({
29
+ voice,
30
+ face,
31
+ onChange,
32
+ }: {
33
+ /** The saved voice: what the next call opens with. */
34
+ voice: string;
35
+ face: ThursdayFace;
36
+ onChange: (voice: string) => void;
37
+ }) {
38
+ const [open, setOpen] = useState(false);
39
+ const [heard, setHeard] = useState(voice);
40
+ const [playing, setPlaying] = useState(false);
41
+ const [typed, setTyped] = useState("");
42
+
43
+ const clip = useRef<HTMLAudioElement>(null);
44
+ // A tap belongs to the element it routes, which exists only while the picker is open.
45
+ const tap = useRef<{
46
+ element: HTMLAudioElement;
47
+ clip: ReturnType<typeof createClipTap>;
48
+ } | null>(null);
49
+ // Each play and each stop takes the next number; a failure reported for an
50
+ // earlier one changes nothing.
51
+ const plays = useRef(0);
52
+ // The face reads the spectrum once per animation frame, so what it reads is a
53
+ // ref, not state: a stable function, and silence when nothing is playing.
54
+ const sounding = useRef(false);
55
+ const spectrum = useCallback(
56
+ () => (tap.current && sounding.current ? tap.current.clip.read() : SILENT),
57
+ [],
58
+ );
59
+ const showPlaying = (on: boolean) => {
60
+ sounding.current = on;
61
+ setPlaying(on);
62
+ };
63
+
64
+ // The element goes when the picker closes; its graph goes with it.
65
+ useEffect(() => {
66
+ if (!open) return;
67
+ return () => {
68
+ const held = tap.current;
69
+ tap.current = null;
70
+ if (!held) return;
71
+ held.element.pause();
72
+ void held.clip.close();
73
+ };
74
+ }, [open]);
75
+
76
+ const failed = (play: number, cause: unknown) => {
77
+ if (play !== plays.current) return;
78
+ plays.current++;
79
+ showPlaying(false);
80
+ toast.add({
81
+ type: "error",
82
+ title: "Voice sample did not play",
83
+ description: errorToString(cause),
84
+ });
85
+ };
86
+
87
+ const stop = () => {
88
+ plays.current++;
89
+ const audio = clip.current;
90
+ if (audio) {
91
+ audio.pause();
92
+ audio.currentTime = 0;
93
+ }
94
+ showPlaying(false);
95
+ };
96
+
97
+ const audition = (next: string) => {
98
+ const audio = clip.current;
99
+ if (!audio) return;
100
+ if (playing && next === heard) {
101
+ stop();
102
+ return;
103
+ }
104
+ setHeard(next);
105
+ setTyped("");
106
+ // The graph is built inside the gesture that plays: an AudioContext made
107
+ // before one is refused. An element is routed once, so it keeps its tap.
108
+ if (tap.current?.element !== audio) {
109
+ void tap.current?.clip.close();
110
+ tap.current = { element: audio, clip: createClipTap(audio) };
111
+ }
112
+ void tap.current.clip.resume();
113
+ const play = ++plays.current;
114
+ audio.src = voiceSamplePath(next);
115
+ showPlaying(true);
116
+ void audio.play().catch((cause: unknown) => {
117
+ // A later click or a stop cut this one short; that play owns the state.
118
+ if (cause instanceof DOMException && cause.name === "AbortError") return;
119
+ failed(play, cause);
120
+ });
121
+ };
122
+
123
+ const close = () => {
124
+ stop();
125
+ setOpen(false);
126
+ setTyped("");
127
+ setHeard(voice);
128
+ };
129
+
130
+ const save = () => {
131
+ const picked = typed.trim() || heard;
132
+ stop();
133
+ setOpen(false);
134
+ setTyped("");
135
+ setHeard(picked);
136
+ if (picked !== voice) onChange(picked);
137
+ };
138
+
139
+ if (!open) {
140
+ return (
141
+ <button
142
+ type="button"
143
+ onClick={() => setOpen(true)}
144
+ aria-label="Voice"
145
+ className={cn(
146
+ inputClassName,
147
+ "flex items-center gap-2 text-left font-mono text-sm hover:border-ring",
148
+ )}
149
+ >
150
+ <span className="shrink-0">{voice}</span>
151
+ <span className="min-w-0 truncate text-[11px] text-muted-foreground">
152
+ {LIVE_VOICE_NOTE[voice as keyof typeof LIVE_VOICE_NOTE]}
153
+ </span>
154
+ <ChevronDown className="ml-auto size-3.5 shrink-0 text-muted-foreground" />
155
+ </button>
156
+ );
157
+ }
158
+
159
+ return (
160
+ <div className="@container space-y-2">
161
+ {/* Nothing here plays through the page's own speakers but this element. */}
162
+ <audio
163
+ ref={clip}
164
+ onEnded={() => showPlaying(false)}
165
+ // A clip that breaks after it starts fails here, not in play()
166
+ onError={(event) => {
167
+ if (!sounding.current) return;
168
+ failed(
169
+ plays.current,
170
+ event.currentTarget.error?.message || "The clip could not be read.",
171
+ );
172
+ }}
173
+ >
174
+ <track kind="captions" />
175
+ </audio>
176
+
177
+ <div className="rounded-xl border border-border/60 p-3">
178
+ <div className="mb-2 flex items-center gap-2">
179
+ <span className="font-mono text-[11px] text-muted-foreground">
180
+ click a name to hear it
181
+ </span>
182
+ <Button
183
+ variant="ghost"
184
+ size="icon-xs"
185
+ className="ml-auto"
186
+ aria-label="Close"
187
+ onClick={close}
188
+ >
189
+ <X />
190
+ </Button>
191
+ </div>
192
+
193
+ <div className="grid gap-4 @md:grid-cols-[11rem_minmax(0,1fr)]">
194
+ <div className="flex flex-col items-center gap-2">
195
+ <Face
196
+ look={face}
197
+ status={playing ? "speaking" : "idle"}
198
+ getSpectrum={spectrum}
199
+ size={176}
200
+ className="w-44"
201
+ />
202
+ <span className="text-sm font-medium">
203
+ {playing ? <ShinyText text={heard} /> : heard}
204
+ </span>
205
+ <span className="h-4 font-mono text-[11px] text-muted-foreground">
206
+ {LIVE_VOICE_NOTE[heard as keyof typeof LIVE_VOICE_NOTE]}
207
+ </span>
208
+ </div>
209
+
210
+ <div className="max-h-56 min-w-0 overflow-y-auto">
211
+ {LIVE_VOICES.map((name) => (
212
+ <button
213
+ type="button"
214
+ key={name}
215
+ onClick={() => audition(name)}
216
+ className={cn(
217
+ "flex w-full items-center gap-2 rounded-md px-1.5 py-1.5 text-sm outline-none hover:bg-accent focus-visible:bg-accent",
218
+ name === heard && "bg-accent text-accent-foreground",
219
+ )}
220
+ >
221
+ <span className="flex-1 text-left">
222
+ {playing && name === heard ? <ShinyText text={name} /> : name}
223
+ </span>
224
+ <span className="shrink truncate font-mono text-[11px] text-muted-foreground">
225
+ {LIVE_VOICE_NOTE[name]}
226
+ </span>
227
+ <Check
228
+ className={cn(
229
+ "size-3.5 shrink-0",
230
+ name === voice ? "opacity-100" : "opacity-0",
231
+ )}
232
+ />
233
+ </button>
234
+ ))}
235
+ </div>
236
+ </div>
237
+ </div>
238
+
239
+ {/* A voice id that is not on the list still runs; it simply has no clip. */}
240
+ <div className="flex gap-2">
241
+ <Input
242
+ value={typed}
243
+ onChange={(event) => setTyped(event.target.value)}
244
+ placeholder="another voice id"
245
+ aria-label="Another voice id"
246
+ spellCheck={false}
247
+ className="font-mono text-sm"
248
+ />
249
+ <Button className="shrink-0" onClick={save}>
250
+ Save
251
+ </Button>
252
+ </div>
253
+ </div>
254
+ );
255
+ }
@@ -40,6 +40,11 @@ export function setThursdayFace(next: ThursdayFace) {
40
40
  announce();
41
41
  }
42
42
 
43
+ /** The face as it is now, for code outside React. */
44
+ export function thursdayFace(): ThursdayFace {
45
+ return face;
46
+ }
47
+
43
48
  export function useThursdayFace(): ThursdayFace {
44
49
  return useSyncExternalStore(
45
50
  (listener) => {
@@ -2,65 +2,50 @@
2
2
 
3
3
  import { asSchema } from "ai";
4
4
  import z from "zod";
5
+ import { LIVE_PROVIDER } from "@/features/ai/live.schema";
5
6
  import { loadTools } from "@/features/ai/load-tools";
6
- import {
7
- SPEACH_MODEL_PROVIDER_LIST,
8
- SPEACH_MODEL_PROVIDERS,
9
- type SpeachModelRef,
10
- } from "@/features/ai/model.schema";
7
+ import { loadLivePrompt } from "@/features/ai/prompts/live.prompt";
11
8
  import { loadThursdayPrompt } from "@/features/ai/prompts/thursday.prompt";
12
- import { removeTask } from "@/features/bot/bot.runner";
13
- import { listAllTaskIds } from "@/features/bot/task.query";
9
+ import { removeThread } from "@/features/bot/bot.runner";
10
+ import { listAllThreadIds } from "@/features/bot/thread.query";
14
11
  import { readConfig } from "@/features/config/config.query";
15
12
  import { deleteAllNotes } from "@/features/memory/memory.query";
13
+ import {
14
+ LIVE_MODEL,
15
+ LiveCloseSchema,
16
+ type ToolManifest,
17
+ } from "@/lib/live/live.schema";
18
+ import { acceptedReasoning, createLiveCall } from "@/lib/live/live.server";
16
19
  import { serverAction } from "@/lib/protocol/server-action";
17
20
  import { publicError } from "@/lib/public-error";
18
- import { issueClientSecret } from "@/lib/realtime/client-secret";
19
- import type { ToolManifest } from "@/lib/realtime/realtime.schema";
20
21
  import {
21
22
  deleteCall,
22
23
  deleteEndedCalls,
23
24
  endCall,
24
25
  insertCall,
26
+ saveThought,
25
27
  saveTurns,
26
28
  writeCallSkillsOn,
27
29
  } from "./thursday.query";
28
30
  import {
29
31
  type CallHandshake,
32
+ CallThoughtSchema,
30
33
  CallTurnSchema,
31
- type ThursdaySettings,
32
34
  ThursdaySettingsSchema,
33
35
  } from "./thursday.schema";
34
36
 
35
37
  // Server actions run one at a time per client, so the recording actions stay
36
38
  // small: a tool call mid-sentence may be queued behind them.
37
39
 
38
- /** The picked model if its key still exists, else the first provider with a key. */
39
- async function resolveVoiceModel(
40
- picked: ThursdaySettings["model"],
41
- ): Promise<SpeachModelRef> {
42
- if (
43
- picked &&
44
- (await readConfig(SPEACH_MODEL_PROVIDERS[picked.provider].apiKeyName))
45
- ) {
46
- return picked;
47
- }
48
-
49
- // Voice and model ids are provider-specific, so neither carries over.
50
- for (const provider of SPEACH_MODEL_PROVIDER_LIST) {
51
- if (await readConfig(provider.apiKeyName)) {
52
- return { provider: provider.id, voice: null, model: null };
53
- }
54
- }
55
- publicError("No voice key — calls run on one. Add one in Config.");
56
- }
40
+ /** An offer with every ICE candidate gathered stays far below this. */
41
+ const SDP_MAX_LENGTH = 65_536;
57
42
 
58
43
  /**
59
44
  * The same tool set /api/thursday/tool-call executes. Tools without `execute`
60
- * (`end_call`) are included: the model must see them and the page intercepts them.
45
+ * (`end_call`, `emote`) are included: the model must see them and the page intercepts them.
61
46
  */
62
- async function loadToolManifest(): Promise<ToolManifest[]> {
63
- const tools = await loadTools({ target: "thursday" });
47
+ async function loadToolManifest(faceWords: boolean): Promise<ToolManifest[]> {
48
+ const tools = await loadTools({ target: "thursday", faceWords });
64
49
 
65
50
  return Object.entries(tools).map(([name, definition]) => {
66
51
  const { $schema, ...parameters } = asSchema(definition.inputSchema)
@@ -78,47 +63,65 @@ async function loadToolManifest(): Promise<ToolManifest[]> {
78
63
  }
79
64
 
80
65
  /**
81
- * Opens a call: inserts the row and returns the credential plus what to send
82
- * once connected. Settings live in the browser (thursday.store), so they arrive
83
- * as an argument and are parsed, not trusted.
66
+ * Opens a Live call from the browser's SDP offer. Both prompts, the tool manifest
67
+ * and the account key stay here; the browser gets the SDP answer, the call row
68
+ * and what it needs to draw and save the call. `calledBack` is the page placing it
69
+ * for waiting work rather than the user, which changes what she opens with.
84
70
  */
85
71
  export const openCallAction = serverAction(
86
- async (settings: ThursdaySettings): Promise<CallHandshake> => {
72
+ async (
73
+ settings: unknown,
74
+ sdp: unknown,
75
+ calledBack?: unknown,
76
+ ): Promise<CallHandshake> => {
87
77
  const thursday = ThursdaySettingsSchema.parse(settings);
78
+ const offer = z.string().min(1).max(SDP_MAX_LENGTH).parse(sdp);
79
+ const apiKey = await readConfig(LIVE_PROVIDER.apiKeyName);
80
+ if (!apiKey) {
81
+ publicError(`No ${LIVE_PROVIDER.label} key — add one in Config.`);
82
+ }
88
83
 
89
- const ref = await resolveVoiceModel(thursday.model);
90
- const provider = SPEACH_MODEL_PROVIDERS[ref.provider];
91
- const apiKey = await readConfig(provider.apiKeyName);
92
- if (!apiKey) publicError(`No ${provider.label} key — add one in Config.`);
93
-
94
- // Assembled per call, never cached: the prompt reads what earlier calls stored.
95
- const [prompt, tools] = await Promise.all([
96
- loadThursdayPrompt(thursday.systemPrompt, thursday.locale),
97
- loadToolManifest(),
84
+ // Assembled per call, never cached: both prompts read what earlier calls stored.
85
+ const [voice, backend, tools, reasoning] = await Promise.all([
86
+ loadLivePrompt({
87
+ voicePrompt: thursday.voicePrompt,
88
+ locale: thursday.locale,
89
+ calledBack: z.boolean().default(false).parse(calledBack),
90
+ }),
91
+ loadThursdayPrompt(thursday.backendPrompt),
92
+ loadToolManifest(thursday.faceWords ?? false),
93
+ acceptedReasoning({
94
+ apiKey,
95
+ model: thursday.backendModel,
96
+ effort: thursday.reasoningEffort,
97
+ }),
98
98
  ]);
99
99
 
100
- // Free-text model ids are not validated here; the provider rejects at issue time.
101
- const model = ref.model ?? provider.models[0].id;
102
- // Issue before insert: a rejected credential must not leave an open call row
103
- // nobody can close.
104
- const credential = await issueClientSecret({
105
- provider: ref.provider,
100
+ // Connect before insert: a refused key or model must not leave an open row nobody can close.
101
+ // Free-text model ids are not checked here; the provider refuses them and says why.
102
+ const connection = await createLiveCall({
106
103
  apiKey,
107
- model,
104
+ sdp: offer,
105
+ voice: thursday.voice,
106
+ instructions: voice.text,
107
+ backend: {
108
+ model: thursday.backendModel,
109
+ instructions: backend,
110
+ tools,
111
+ reasoning,
112
+ webSearch: thursday.webSearch,
113
+ },
114
+ });
115
+ const callId = await insertCall({
116
+ provider: LIVE_PROVIDER.id,
117
+ model: LIVE_MODEL,
118
+ backendModel: thursday.backendModel,
108
119
  });
109
- const callId = await insertCall({ provider: ref.provider, model });
110
120
 
111
121
  return {
112
122
  callId,
113
- provider: ref.provider,
114
- credential,
115
- session: {
116
- model,
117
- voice: ref.voice ?? provider.defaultVoice,
118
- instructions: prompt.text,
119
- tools,
120
- },
121
- opening: prompt.opening,
123
+ sdp: connection.transport.sdp,
124
+ opening: voice.opening,
122
125
  };
123
126
  },
124
127
  );
@@ -132,14 +135,35 @@ export const setCallSkillsAction = serverAction(async (on: unknown) => {
132
135
  });
133
136
 
134
137
  export const saveTurnsAction = serverAction(
135
- async (callId: string, turns: unknown) => {
136
- await saveTurns(callId, CallTurnSchema.array().min(1).parse(turns));
138
+ async (callId: unknown, turns: unknown) => {
139
+ await saveTurns(
140
+ z.string().min(1).parse(callId),
141
+ CallTurnSchema.array().min(1).parse(turns),
142
+ );
137
143
  },
138
144
  );
139
145
 
140
- export const endCallAction = serverAction(async (callId: string) => {
141
- await endCall(callId);
142
- });
146
+ export const saveThoughtAction = serverAction(
147
+ async (callId: unknown, thought: unknown) => {
148
+ await saveThought(
149
+ z.string().min(1).parse(callId),
150
+ CallThoughtSchema.parse(thought),
151
+ );
152
+ },
153
+ );
154
+
155
+ /**
156
+ * Ends the row. `close` is what `session.closed` confirmed; absent when the
157
+ * confirmation never came, which leaves the billed seconds unknown.
158
+ */
159
+ export const endCallAction = serverAction(
160
+ async (callId: unknown, close?: unknown) => {
161
+ await endCall(
162
+ z.string().min(1).parse(callId),
163
+ LiveCloseSchema.nullish().parse(close),
164
+ );
165
+ },
166
+ );
143
167
 
144
168
  /**
145
169
  * Deletes a call and its turns; the next call's prompt no longer includes it.
@@ -161,19 +185,19 @@ export const deleteEndedCallsAction = serverAction(async () =>
161
185
 
162
186
  /**
163
187
  * Wipes what the app has kept of its own use: every ended call and its turns,
164
- * every job and its thread, and every memory note. Keys, bots and connectors
188
+ * every thread and its messages, and every memory note. Keys, bots and connectors
165
189
  * stay — the set `pnpm reset` calls History.
166
190
  *
167
191
  * History is not one domain, so this reaches into three and each clears its own
168
- * rows. Live work is stopped before its row goes: `removeTask` aborts a running
192
+ * rows. Live work is stopped before its row goes: `removeThread` aborts a running
169
193
  * job and closes its shell.
170
194
  */
171
195
  export const resetHistoryAction = serverAction(async () => {
172
- const taskIds = await listAllTaskIds();
173
- for (const id of taskIds) await removeTask(id);
196
+ const threadIds = await listAllThreadIds();
197
+ for (const id of threadIds) await removeThread(id);
174
198
 
175
199
  const calls = await deleteEndedCalls();
176
200
  const notes = await deleteAllNotes();
177
201
 
178
- return { calls, tasks: taskIds.length, notes };
202
+ return { calls, threads: threadIds.length, notes };
179
203
  });
@@ -11,11 +11,17 @@ import {
11
11
  } from "drizzle-orm";
12
12
  import { CALL_HISTORY_PAGE } from "@/config";
13
13
  import { database } from "@/database/db";
14
- import { callMessageTable, callTable } from "@/database/tables";
15
- import { listCallJobs } from "@/features/bot/task.query";
14
+ import {
15
+ callMessageTable,
16
+ callTable,
17
+ callThoughtTable,
18
+ } from "@/database/tables";
19
+ import { listCallJobs } from "@/features/bot/thread.query";
16
20
  import { readConfig, writeConfig } from "@/features/config/config.query";
21
+ import type { LiveClose } from "@/lib/live/live.schema";
17
22
  import {
18
23
  type CallRecord,
24
+ type CallThought,
19
25
  type CallTurn,
20
26
  isSkillsOn,
21
27
  THURSDAY_KEYS,
@@ -35,7 +41,11 @@ export async function writeCallSkillsOn(on: boolean) {
35
41
  await writeConfig(THURSDAY_KEYS.skills, on ? "on" : "off");
36
42
  }
37
43
 
38
- export async function insertCall(input: { provider: string; model: string }) {
44
+ export async function insertCall(input: {
45
+ provider: string;
46
+ model: string;
47
+ backendModel: string;
48
+ }) {
39
49
  const [call] = await database
40
50
  .insert(callTable)
41
51
  .values({ id: crypto.randomUUID(), ...input })
@@ -43,11 +53,23 @@ export async function insertCall(input: { provider: string; model: string }) {
43
53
  return call.id;
44
54
  }
45
55
 
46
- /** Ends the call; false if it already ended, so end-of-call work runs once. */
47
- export async function endCall(id: string): Promise<boolean> {
56
+ /**
57
+ * Ends the call; false if it already ended, so end-of-call work runs once.
58
+ * `close` is what the provider confirmed on `session.closed`; without it the
59
+ * row keeps null seconds, which reads as "never confirmed", not as zero.
60
+ */
61
+ export async function endCall(
62
+ id: string,
63
+ close?: LiveClose | null,
64
+ ): Promise<boolean> {
48
65
  const ended = await database
49
66
  .update(callTable)
50
- .set({ endedAt: new Date() })
67
+ .set({
68
+ endedAt: new Date(),
69
+ ...(close
70
+ ? { endedReason: close.reason, seconds: close.seconds ?? null }
71
+ : {}),
72
+ })
51
73
  .where(and(eq(callTable.id, id), isNull(callTable.endedAt)))
52
74
  .returning({ id: callTable.id });
53
75
  return ended.length > 0;
@@ -61,14 +83,28 @@ export async function saveTurns(callId: string, turns: CallTurn[]) {
61
83
  for (const turn of turns) {
62
84
  await database
63
85
  .insert(callMessageTable)
64
- .values({ callId, ...turn })
86
+ .values({ callId, ...turn, fragments: turn.fragments ?? null })
65
87
  .onConflictDoUpdate({
66
88
  target: [callMessageTable.callId, callMessageTable.id],
67
- set: { text: turn.text, role: turn.role, tool: turn.tool ?? null },
89
+ set: {
90
+ text: turn.text,
91
+ role: turn.role,
92
+ tool: turn.tool ?? null,
93
+ // A late fragment revises the group; the originals go with it.
94
+ fragments: turn.fragments ?? null,
95
+ },
68
96
  });
69
97
  }
70
98
  }
71
99
 
100
+ /** A summary part arrives once, whole; a repeat keeps the first. */
101
+ export async function saveThought(callId: string, thought: CallThought) {
102
+ await database
103
+ .insert(callThoughtTable)
104
+ .values({ callId, ...thought })
105
+ .onConflictDoNothing();
106
+ }
107
+
72
108
  export type CallGroup = {
73
109
  callId: string;
74
110
  startedAt: Date;
@@ -120,27 +156,6 @@ export async function listRecentTurns(limit: number): Promise<CallGroup[]> {
120
156
  .map((group) => ({ ...group, turns: group.turns.reverse() }));
121
157
  }
122
158
 
123
- /** The last spoken turns of one call in order, without tool turns. */
124
- export async function listCallTurns(
125
- callId: string,
126
- limit: number,
127
- ): Promise<{ role: "user" | "assistant"; text: string }[]> {
128
- const rows = await database
129
- .select({ role: callMessageTable.role, text: callMessageTable.text })
130
- .from(callMessageTable)
131
- .where(
132
- and(
133
- eq(callMessageTable.callId, callId),
134
- inArray(callMessageTable.role, ["user", "assistant"]),
135
- ),
136
- )
137
- .orderBy(desc(callMessageTable.seq))
138
- .limit(limit);
139
- return rows
140
- .reverse()
141
- .map((row) => ({ role: row.role as "user" | "assistant", text: row.text }));
142
- }
143
-
144
159
  /**
145
160
  * One page of a call, every turn in order, tool turns included; null when the
146
161
  * call is gone. Tool turns keep their name and nothing else is read by the
@@ -202,7 +217,7 @@ export async function isAnyCallLive() {
202
217
 
203
218
  /**
204
219
  * Deletes an ended call and its turns (call_message cascades). A live call is
205
- * refused: its tab keeps writing turns against the row. Tasks keep a dangling
220
+ * refused: its tab keeps writing turns against the row. Threads keep a dangling
206
221
  * `callId`, which reads as "not on the line".
207
222
  */
208
223
  export async function deleteCall(id: string): Promise<boolean> {
@@ -238,8 +253,11 @@ export async function listCallHistory(options: {
238
253
  id: callTable.id,
239
254
  provider: callTable.provider,
240
255
  model: callTable.model,
256
+ backendModel: callTable.backendModel,
241
257
  startedAt: callTable.startedAt,
242
258
  endedAt: callTable.endedAt,
259
+ endedReason: callTable.endedReason,
260
+ seconds: callTable.seconds,
243
261
  })
244
262
  .from(callTable)
245
263
  .innerJoin(callMessageTable, eq(callMessageTable.callId, callTable.id))
@@ -260,6 +278,7 @@ export async function listCallHistory(options: {
260
278
  tool: callMessageTable.tool,
261
279
  text: callMessageTable.text,
262
280
  seq: callMessageTable.seq,
281
+ fragments: callMessageTable.fragments,
263
282
  at: callMessageTable.at,
264
283
  })
265
284
  .from(callMessageTable)