thursday-agent 0.4.0 → 0.6.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 (657) 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 +6 -5
  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 +5 -5
  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 +13 -13
  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 +10 -11
  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 -4
  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 +10 -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]__02846fb._.js +8 -0
  92. package/.next/server/chunks/[root-of-the-server]__049f521._.js +3 -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]__07bnah_._.js +3 -0
  96. package/.next/server/chunks/[root-of-the-server]__08eae20._.js +8 -0
  97. package/.next/server/chunks/[root-of-the-server]__0_ue8oe._.js +3 -0
  98. package/.next/server/chunks/[root-of-the-server]__0c9fgca._.js +5 -0
  99. package/.next/server/chunks/[root-of-the-server]__0g-ueei._.js +8 -0
  100. package/.next/server/chunks/[root-of-the-server]__0h_x6q6._.js +5 -0
  101. package/.next/server/chunks/{[root-of-the-server]__0pa2n68._.js → [root-of-the-server]__0kxrvxf._.js} +2 -2
  102. package/.next/server/chunks/{[root-of-the-server]__0q0vvt2._.js → [root-of-the-server]__0ov3iir._.js} +2 -2
  103. package/.next/server/chunks/[root-of-the-server]__0qwtlmx._.js +8 -0
  104. package/.next/server/chunks/[root-of-the-server]__0sm5xvm._.js +3 -0
  105. package/.next/server/chunks/[root-of-the-server]__0ye3da2._.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/_1kg70wc._.js +3 -3
  150. package/.next/server/chunks/_1klbcft._.js +5 -0
  151. package/.next/server/chunks/_1krd9rf._.js +4 -1
  152. package/.next/server/chunks/_1kwmzab._.js +3 -0
  153. package/.next/server/chunks/{_1pf4qe-._.js → _1oxj9fa._.js} +1 -1
  154. package/.next/server/chunks/{_1f46eie._.js → _1pcmdbb._.js} +1 -1
  155. package/.next/server/chunks/_1qgix-j._.js +3 -0
  156. package/.next/server/chunks/{lib_logger_ts_1exwjut._.js → _1rpchta._.js} +5 -5
  157. package/.next/server/chunks/_1vsej-s._.js +5 -0
  158. package/.next/server/chunks/_1yx0p_s._.js +5 -0
  159. package/.next/server/chunks/{_0rnf-6n._.js → _20fsr_z._.js} +6 -6
  160. package/.next/server/chunks/_2128hkj._.js +5 -0
  161. package/.next/server/chunks/_next-internal_server_app_api_bot_thread_[id]_route_actions_1fstjn2.js +3 -0
  162. package/.next/server/chunks/_next-internal_server_app_api_bot_thread_route_actions_003ccso.js +3 -0
  163. package/.next/server/chunks/_next-internal_server_app_api_workspace_missing_route_actions_1fidi6p.js +3 -0
  164. package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
  165. package/.next/server/chunks/features_0-cnt0l._.js +4 -0
  166. package/.next/server/chunks/features_0hdaci0._.js +4 -0
  167. package/.next/server/chunks/features_1e39j7-._.js +8 -0
  168. package/.next/server/chunks/features_bot_bot_query_ts_12mgkl2._.js +1 -1
  169. package/.next/server/chunks/features_memory_1uqvksn._.js +1 -1
  170. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0r28-sm._.js → node_modules_consola_dist_chunks_prompt_mjs_0a7-pbw._.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_0gzvgfv._.js} +1 -1
  172. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0i7cvml._.js → node_modules_consola_dist_chunks_prompt_mjs_107pxfn._.js} +1 -1
  173. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0icqaqw._.js → node_modules_consola_dist_chunks_prompt_mjs_15hbel8._.js} +1 -1
  174. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_18i-23e._.js +3 -0
  175. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1bewgf3._.js +3 -0
  176. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1kipdeo._.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]__09q9med._.js +1 -1
  185. package/.next/server/chunks/ssr/[root-of-the-server]__0bxsfyn._.js +101 -0
  186. package/.next/server/chunks/ssr/[root-of-the-server]__0lyi8i2._.js +1 -1
  187. package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
  188. package/.next/server/chunks/ssr/[root-of-the-server]__172cq4x._.js +3 -0
  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]__1fll8dc._.js +3 -0
  192. package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +1 -1
  193. package/.next/server/chunks/ssr/[root-of-the-server]__1nygfik._.js +5 -0
  194. package/.next/server/chunks/ssr/[root-of-the-server]__1sdphb0._.js +8 -0
  195. package/.next/server/chunks/ssr/[root-of-the-server]__1waa3rc._.js +100 -0
  196. package/.next/server/chunks/ssr/_00rehl_._.js +3 -0
  197. package/.next/server/chunks/ssr/{_1lz_cq2._.js → _02oc_h5._.js} +76 -89
  198. package/.next/server/chunks/ssr/_03_928f._.js +3 -0
  199. package/.next/server/chunks/ssr/_05yghx6._.js +3 -0
  200. package/.next/server/chunks/ssr/_08c4z-9._.js +3 -0
  201. package/.next/server/chunks/ssr/_0_qfdlw._.js +4 -0
  202. package/.next/server/chunks/ssr/_0c9e5w6._.js +9 -0
  203. package/.next/server/chunks/ssr/{_0s99bgb._.js → _0dh2e1j._.js} +9 -3
  204. package/.next/server/chunks/ssr/_0dr-ddg._.js +3 -0
  205. package/.next/server/chunks/ssr/_0eaog6_._.js +3 -0
  206. package/.next/server/chunks/ssr/_0evkpto._.js +3 -0
  207. package/.next/server/chunks/ssr/_0g_rlog._.js +3 -0
  208. package/.next/server/chunks/ssr/_0geg212._.js +3 -0
  209. package/.next/server/chunks/ssr/{_1gd8q8l._.js → _0hxt2ul._.js} +2 -2
  210. package/.next/server/chunks/ssr/_0i_6q1w._.js +2 -2
  211. package/.next/server/chunks/ssr/_0lu1n_x._.js +1 -1
  212. package/.next/server/chunks/ssr/{_15j2_8f._.js → _0wzaht-._.js} +2 -2
  213. package/.next/server/chunks/ssr/_0z-g0uy._.js +3 -0
  214. package/.next/server/chunks/ssr/_123ttsf._.js +3 -0
  215. package/.next/server/chunks/ssr/_123y-ah._.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/{_0ap2fzn._.js → _16c6_xm._.js} +2 -2
  219. package/.next/server/chunks/ssr/_18opah7._.js +3 -0
  220. package/.next/server/chunks/ssr/_18xqmny._.js +3 -0
  221. package/.next/server/chunks/ssr/_1_krfph._.js +3 -0
  222. package/.next/server/chunks/ssr/{_1-_etts._.js → _1anqots._.js} +2 -2
  223. package/.next/server/chunks/ssr/_1ey7qn-._.js +70 -0
  224. package/.next/server/chunks/ssr/_1g9vs7q._.js +3 -0
  225. package/.next/server/chunks/ssr/_1jmz33w._.js +3 -0
  226. package/.next/server/chunks/ssr/{_0n3toaw._.js → _1k0spz7._.js} +2 -2
  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/{_1fojd41._.js → _1x9pskj._.js} +3 -3
  230. package/.next/server/chunks/ssr/_1y6b5mr._.js +101 -0
  231. package/.next/server/chunks/ssr/_1ztk7p6._.js +7 -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/{_1-teee5._.js → lib_logger_ts_0-olsze._.js} +2 -7
  237. package/.next/server/chunks/ssr/{node_modules_0cxaxk9._.js → node_modules_00_51_v._.js} +1 -1
  238. package/.next/server/chunks/ssr/{node_modules_04jf_m8._.js → node_modules_022sipm._.js} +1 -1
  239. package/.next/server/chunks/ssr/{node_modules_0g7fzk3._.js → node_modules_0332gw4._.js} +1 -1
  240. package/.next/server/chunks/ssr/{node_modules_1cx_ql6._.js → node_modules_04vxchl._.js} +1 -1
  241. package/.next/server/chunks/ssr/{node_modules_1vh5ntv._.js → node_modules_0746rzi._.js} +1 -1
  242. package/.next/server/chunks/ssr/{node_modules_0yugy6m._.js → node_modules_0d5uzof._.js} +1 -1
  243. package/.next/server/chunks/ssr/{node_modules_09q35v_._.js → node_modules_0exkwcm._.js} +1 -1
  244. package/.next/server/chunks/ssr/{node_modules_08dhkiq._.js → node_modules_0fr-ml8._.js} +1 -1
  245. package/.next/server/chunks/ssr/{node_modules_14q6g4n._.js → node_modules_0mxvg8h._.js} +1 -1
  246. package/.next/server/chunks/ssr/{node_modules_0arus10._.js → node_modules_0qapgjr._.js} +1 -1
  247. package/.next/server/chunks/ssr/{node_modules_1eg7m6c._.js → node_modules_0qbfyjh._.js} +1 -1
  248. package/.next/server/chunks/ssr/{node_modules_1cz2hle._.js → node_modules_0t-9nup._.js} +1 -1
  249. package/.next/server/chunks/ssr/{node_modules_17bwo43._.js → node_modules_0tusx4d._.js} +3 -3
  250. package/.next/server/chunks/ssr/{node_modules_1efrqxi._.js → node_modules_0vsxbzp._.js} +1 -1
  251. package/.next/server/chunks/ssr/{node_modules_0_-_a--._.js → node_modules_0vv0-fg._.js} +1 -1
  252. package/.next/server/chunks/ssr/{node_modules_1gdh31p._.js → node_modules_0wsvp00._.js} +1 -1
  253. package/.next/server/chunks/ssr/{node_modules_1hpopmo._.js → node_modules_1-urho9._.js} +1 -1
  254. package/.next/server/chunks/ssr/{node_modules_1_pc9kq._.js → node_modules_16pi_dd._.js} +1 -1
  255. package/.next/server/chunks/ssr/{node_modules_00etblx._.js → node_modules_1d53yiq._.js} +1 -1
  256. package/.next/server/chunks/ssr/{node_modules_1aaxuef._.js → node_modules_1g1eihe._.js} +1 -1
  257. package/.next/server/chunks/ssr/{node_modules_198nmll._.js → node_modules_1gpednh._.js} +1 -1
  258. package/.next/server/chunks/ssr/{node_modules_0pvd7q-._.js → node_modules_1gu1pph._.js} +1 -1
  259. package/.next/server/chunks/ssr/{node_modules_0b__sgl._.js → node_modules_1he1w8_._.js} +1 -1
  260. package/.next/server/chunks/ssr/{node_modules_1qpjvy5._.js → node_modules_1lnjapm._.js} +1 -1
  261. package/.next/server/chunks/ssr/{node_modules_0940ns5._.js → node_modules_1lynj9m._.js} +1 -1
  262. package/.next/server/chunks/ssr/{node_modules_0x3-ply._.js → node_modules_1seuurl._.js} +2 -2
  263. package/.next/server/chunks/ssr/{node_modules_14om4ar._.js → node_modules_1u6w1pb._.js} +1 -1
  264. package/.next/server/chunks/ssr/{node_modules_0had7xd._.js → node_modules_1xn6saw._.js} +1 -1
  265. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1b748ic._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_067_exa._.js} +1 -1
  266. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1z4hm5e._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0nrrdaq._.js} +1 -1
  267. package/.next/server/chunks/ssr/{node_modules_@vercel_oidc_dist_06mk8id._.js → node_modules_@vercel_oidc_dist_21a5haa._.js} +1 -1
  268. package/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_trash_mjs_0px2gzr._.js +3 -0
  269. package/.next/server/middleware-build-manifest.js +3 -3
  270. package/.next/server/pages/404.html +1 -1
  271. package/.next/server/pages/500.html +1 -1
  272. package/.next/server/server-reference-manifest.js +1 -1
  273. package/.next/server/server-reference-manifest.json +68 -46
  274. package/.next/static/chunks/0dr16v67vj4n7.js +2 -0
  275. package/.next/static/chunks/0g4b348l0pve7.js +1 -0
  276. package/.next/static/chunks/0joan-69kbspd.js +1 -0
  277. package/.next/static/chunks/0vlgzqo9ka90v.js +1 -0
  278. package/.next/static/chunks/0zrupxgci5gqc.js +1 -0
  279. package/.next/static/chunks/10k2xvap03z20.css +1 -0
  280. package/.next/static/chunks/18mkhstgiqcbt.js +1 -0
  281. package/.next/static/chunks/{15m575979un5f.js → 1i-u2wzub_to1.js} +2 -2
  282. package/.next/static/chunks/1kp5nfp06nj9h.js +5 -0
  283. package/.next/static/chunks/1ohslk4568tm3.js +1 -0
  284. package/.next/static/chunks/1sbmwswc9k2-1.js +1 -0
  285. package/.next/static/chunks/1t9qms5pwwa3n.js +1 -0
  286. package/.next/static/chunks/1vj_5bnbxx84e.js +1 -0
  287. package/.next/static/chunks/1vqezbhjm3goq.js +1 -0
  288. package/.next/static/chunks/{3akmqm77muj4-.js → 1wlo979mx-y3w.js} +1 -1
  289. package/.next/static/chunks/26ql4y-43xwhp.js +1 -0
  290. package/.next/static/chunks/{0fl3gwe4-l6tz.js → 2_pnccjp6j1ca.js} +1 -1
  291. package/.next/static/chunks/2a51-ywz9b2a3.js +1 -0
  292. package/.next/static/chunks/2fvdgxih7x7hr.js +1 -0
  293. package/.next/static/chunks/2jlz8zp4jax_m.js +18 -0
  294. package/.next/static/chunks/2nvepds1fu2ux.js +1 -0
  295. package/.next/static/chunks/3addj3i4-izma.js +1 -0
  296. package/.next/static/chunks/3bfwpww3m3x4u.js +1 -0
  297. package/.next/static/chunks/3gfh7nxwusbt0.js +1 -0
  298. package/.next/static/chunks/3gwa44cvz4qoi.js +1 -0
  299. package/.next/static/chunks/{38gweqdo4jpfj.js → 3izg0a3k87q1-.js} +5 -5
  300. package/.next/static/chunks/3zk6q3-3f9swq.js +99 -0
  301. package/.next/static/chunks/3zkg5iup3v4a2.js +12 -0
  302. package/.next/static/chunks/405m0bqtoihev.js +1 -0
  303. package/.next/static/chunks/42wcg3wfg_m_p.js +1 -0
  304. package/README.md +27 -216
  305. package/app/api/events/app-event.ts +6 -4
  306. package/app/api/query-key.ts +25 -16
  307. package/bin/database.mjs +37 -0
  308. package/bin/thursday.mjs +44 -28
  309. package/components/ui/custom-icon.tsx +0 -60
  310. package/components/ui/radio-group.tsx +37 -0
  311. package/components/ui/shiny-text.tsx +33 -6
  312. package/database/migrations/{20260910173049_numerous_spirit → 20260916145701_clever_multiple_man}/migration.sql +80 -24
  313. package/database/migrations/{20260910173049_numerous_spirit → 20260916145701_clever_multiple_man}/snapshot.json +689 -110
  314. package/database/migrations/20260916160713_thread_cancelled/migration.sql +2 -0
  315. package/database/migrations/{20260911030320_opposite_jack_power → 20260916160713_thread_cancelled}/snapshot.json +706 -84
  316. package/docs/how-it-works.md +39 -36
  317. package/docs/images/keeps-going.png +0 -0
  318. package/docs/images/two-minds.png +0 -0
  319. package/docs/live-calls.md +231 -0
  320. package/docs/thread-rooms.md +71 -0
  321. package/features/ai/chatgpt.ts +1 -2
  322. package/features/ai/live.schema.ts +128 -0
  323. package/features/ai/load-tools.ts +148 -77
  324. package/features/ai/model.schema.ts +2 -120
  325. package/features/ai/model.ts +52 -88
  326. package/features/ai/prompts/bot.prompt.ts +91 -214
  327. package/features/ai/prompts/live.prompt.ts +265 -0
  328. package/features/ai/prompts/prompt-helper.ts +91 -32
  329. package/features/ai/prompts/thursday.prompt.ts +125 -172
  330. package/features/ai/tools/bot.tool.ts +38 -145
  331. package/features/ai/tools/call.tool.ts +1 -1
  332. package/features/ai/tools/connected.ts +5 -3
  333. package/features/ai/tools/mcp.tool.ts +7 -4
  334. package/features/ai/tools/memory.tool.ts +35 -31
  335. package/features/ai/tools/skills.tool.ts +36 -14
  336. package/features/ai/tools/studio.tool.ts +26 -21
  337. package/features/ai/tools/tool-name.ts +2 -5
  338. package/features/ai/tools/workspace.tool.ts +33 -10
  339. package/features/artifact/artifact.action.ts +2 -2
  340. package/features/artifact/artifact.query.ts +112 -61
  341. package/features/artifact/artifact.schema.ts +8 -6
  342. package/features/artifact/components/artifact-setting.tsx +83 -33
  343. package/features/bot/bot.action.ts +43 -36
  344. package/features/bot/bot.memory.ts +137 -20
  345. package/features/bot/bot.query.ts +28 -11
  346. package/features/bot/bot.run.ts +299 -636
  347. package/features/bot/bot.runner.ts +468 -844
  348. package/features/bot/bot.schema.ts +93 -82
  349. package/features/bot/bot.seed.ts +141 -64
  350. package/features/bot/components/bot-mark.tsx +324 -232
  351. package/features/bot/components/bot-room.tsx +1613 -697
  352. package/features/bot/components/bot-roster.tsx +8 -13
  353. package/features/bot/components/bot-setting.tsx +58 -42
  354. package/features/bot/components/bot-tool.tsx +55 -87
  355. package/features/bot/components/mark-palette.tsx +35 -32
  356. package/features/bot/components/path-chips.tsx +33 -3
  357. package/features/bot/components/thread-badge.tsx +34 -0
  358. package/features/bot/components/thread-reply.tsx +639 -0
  359. package/features/bot/components/thread-setting.tsx +674 -0
  360. package/features/bot/mark.const.ts +79 -31
  361. package/features/bot/room.query.ts +889 -0
  362. package/features/bot/room.schema.ts +64 -0
  363. package/features/bot/seed-bots.ts +2 -1
  364. package/features/bot/thread.query.ts +971 -0
  365. package/features/bot/thread.store.ts +587 -0
  366. package/features/config/components/voice-key.tsx +113 -88
  367. package/features/config/config.const.ts +5 -9
  368. package/features/connectors/mcp.schema.ts +0 -2
  369. package/features/intro/components/intro.tsx +169 -139
  370. package/features/memory/components/memory-setting.tsx +2 -7
  371. package/features/memory/memory.schema.ts +14 -23
  372. package/features/settings/components/setting-ui.tsx +0 -44
  373. package/features/settings/components/settings.tsx +12 -12
  374. package/features/settings/settings.alert.ts +3 -3
  375. package/features/settings/settings.store.ts +1 -1
  376. package/features/skills/skills.schema.ts +0 -2
  377. package/features/thursday/components/ascii-field.tsx +24 -44
  378. package/features/thursday/components/ascii-orb.tsx +359 -358
  379. package/features/thursday/components/call-log.tsx +46 -44
  380. package/features/thursday/components/face.tsx +35 -10
  381. package/features/thursday/components/tab-state.tsx +3 -3
  382. package/features/thursday/components/thursday-mark.tsx +1 -0
  383. package/features/thursday/components/thursday-setting.tsx +631 -332
  384. package/features/thursday/components/thursday.tsx +106 -41
  385. package/features/thursday/components/voice-picker.tsx +255 -0
  386. package/features/thursday/thursday.action.ts +94 -68
  387. package/features/thursday/thursday.query.ts +49 -30
  388. package/features/thursday/thursday.schema.ts +27 -30
  389. package/features/thursday/thursday.store.ts +11 -7
  390. package/features/thursday/tool-call.ts +3 -3
  391. package/features/thursday/tool-line.ts +5 -3
  392. package/features/thursday/use-thursday.ts +725 -450
  393. package/features/workspace/workspace.query.ts +17 -0
  394. package/features/workspace/workspace.ts +103 -50
  395. package/lib/live/live.schema.ts +47 -0
  396. package/lib/live/live.server.ts +155 -0
  397. package/lib/live/live.session.ts +574 -0
  398. package/lib/{realtime/realtime.tap.ts → live/live.tap.ts} +41 -12
  399. package/lib/live/live.transport.ts +152 -0
  400. package/lib/protocol/use-server-pages.ts +9 -5
  401. package/lib/utils.ts +21 -20
  402. package/package.json +2 -2
  403. package/public/voices/alloy.ogg +0 -0
  404. package/public/voices/ash.ogg +0 -0
  405. package/public/voices/ballad.ogg +0 -0
  406. package/public/voices/beacon.ogg +0 -0
  407. package/public/voices/bossa.ogg +0 -0
  408. package/public/voices/cedar.ogg +0 -0
  409. package/public/voices/cinder.ogg +0 -0
  410. package/public/voices/coral.ogg +0 -0
  411. package/public/voices/delta.ogg +0 -0
  412. package/public/voices/echo.ogg +0 -0
  413. package/public/voices/gleam.ogg +0 -0
  414. package/public/voices/marin.ogg +0 -0
  415. package/public/voices/meridian.ogg +0 -0
  416. package/public/voices/quartz.ogg +0 -0
  417. package/public/voices/ripple.ogg +0 -0
  418. package/public/voices/sage.ogg +0 -0
  419. package/public/voices/shimmer.ogg +0 -0
  420. package/public/voices/stone.ogg +0 -0
  421. package/public/voices/tempo.ogg +0 -0
  422. package/public/voices/verse.ogg +0 -0
  423. package/public/voices/vesper.ogg +0 -0
  424. package/public/voices/willow.ogg +0 -0
  425. package/scripts/artifact-paths.test.mts +25 -0
  426. package/scripts/bot-context.test.mts +1408 -0
  427. package/scripts/live-history.test.mts +115 -0
  428. package/scripts/live-session.test.mts +948 -0
  429. package/server.js +1 -1
  430. package/skills/browser/SKILL.md +17 -6
  431. package/skills/computer/SKILL.md +1 -1
  432. package/skills/find-skills/SKILL.md +3 -8
  433. package/skills/interactive-page/SKILL.md +12 -7
  434. package/skills/interactive-page/references/diagram.md +89 -0
  435. package/skills/interactive-page/scripts/archify/LICENSE +22 -0
  436. package/skills/interactive-page/scripts/archify/README.md +25 -0
  437. package/skills/interactive-page/scripts/archify/assets/JetBrainsMono-OFL.txt +93 -0
  438. package/skills/interactive-page/scripts/archify/assets/template.html +14934 -0
  439. package/skills/interactive-page/scripts/archify/bin/archify.mjs +2126 -0
  440. package/skills/interactive-page/scripts/archify/bin/open-artifact.mjs +86 -0
  441. package/skills/interactive-page/scripts/archify/bin/preview.mjs +653 -0
  442. package/skills/interactive-page/scripts/archify/bin/visual-check.mjs +829 -0
  443. package/skills/interactive-page/scripts/archify/delta/architecture-delta.mjs +1223 -0
  444. package/skills/interactive-page/scripts/archify/examples/agent-run.lifecycle.json +60 -0
  445. package/skills/interactive-page/scripts/archify/examples/agent-tool-call.workflow.json +94 -0
  446. package/skills/interactive-page/scripts/archify/examples/async-job-roundtrip.sequence.json +61 -0
  447. package/skills/interactive-page/scripts/archify/examples/cache-miss-request.sequence.json +82 -0
  448. package/skills/interactive-page/scripts/archify/examples/checkout-platform.base.architecture.json +31 -0
  449. package/skills/interactive-page/scripts/archify/examples/checkout-platform.head.architecture.json +31 -0
  450. package/skills/interactive-page/scripts/archify/examples/deployment-release.lifecycle.json +49 -0
  451. package/skills/interactive-page/scripts/archify/examples/event-stream.dataflow.json +57 -0
  452. package/skills/interactive-page/scripts/archify/examples/incident-response.workflow.json +64 -0
  453. package/skills/interactive-page/scripts/archify/examples/product-analytics.dataflow.json +76 -0
  454. package/skills/interactive-page/scripts/archify/examples/production-deployment.architecture.json +71 -0
  455. package/skills/interactive-page/scripts/archify/examples/release-delivery.workflow.json +62 -0
  456. package/skills/interactive-page/scripts/archify/examples/web-app.architecture.json +46 -0
  457. package/skills/interactive-page/scripts/archify/migrations/workflow-v2.mjs +279 -0
  458. package/skills/interactive-page/scripts/archify/recipes/scenarios.mjs +284 -0
  459. package/skills/interactive-page/scripts/archify/references/authoring-contract.md +243 -0
  460. package/skills/interactive-page/scripts/archify/references/delivery-contract.md +120 -0
  461. package/skills/interactive-page/scripts/archify/references/viewer-runtime.md +45 -0
  462. package/skills/interactive-page/scripts/archify/renderers/architecture/grid.mjs +62 -0
  463. package/skills/interactive-page/scripts/archify/renderers/architecture/render-architecture.mjs +1078 -0
  464. package/skills/interactive-page/scripts/archify/renderers/dataflow/README.md +104 -0
  465. package/skills/interactive-page/scripts/archify/renderers/dataflow/render-dataflow.mjs +483 -0
  466. package/skills/interactive-page/scripts/archify/renderers/lifecycle/README.md +115 -0
  467. package/skills/interactive-page/scripts/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
  468. package/skills/interactive-page/scripts/archify/renderers/sequence/README.md +114 -0
  469. package/skills/interactive-page/scripts/archify/renderers/sequence/render-sequence.mjs +464 -0
  470. package/skills/interactive-page/scripts/archify/renderers/shared/brand-marks.mjs +563 -0
  471. package/skills/interactive-page/scripts/archify/renderers/shared/cli.mjs +218 -0
  472. package/skills/interactive-page/scripts/archify/renderers/shared/desktop-readability.mjs +26 -0
  473. package/skills/interactive-page/scripts/archify/renderers/shared/diagnostics.mjs +127 -0
  474. package/skills/interactive-page/scripts/archify/renderers/shared/engineering-profiles.mjs +157 -0
  475. package/skills/interactive-page/scripts/archify/renderers/shared/generated-brand-marks.mjs +3 -0
  476. package/skills/interactive-page/scripts/archify/renderers/shared/generated-validators.mjs +13 -0
  477. package/skills/interactive-page/scripts/archify/renderers/shared/geometry.mjs +1423 -0
  478. package/skills/interactive-page/scripts/archify/renderers/shared/i18n.mjs +595 -0
  479. package/skills/interactive-page/scripts/archify/renderers/shared/layout-report.mjs +40 -0
  480. package/skills/interactive-page/scripts/archify/renderers/shared/legend.mjs +217 -0
  481. package/skills/interactive-page/scripts/archify/renderers/shared/output-path.mjs +340 -0
  482. package/skills/interactive-page/scripts/archify/renderers/shared/repository-evidence.mjs +238 -0
  483. package/skills/interactive-page/scripts/archify/renderers/shared/repository-location.mjs +58 -0
  484. package/skills/interactive-page/scripts/archify/renderers/shared/text-fit.mjs +49 -0
  485. package/skills/interactive-page/scripts/archify/renderers/shared/utils.mjs +232 -0
  486. package/skills/interactive-page/scripts/archify/renderers/shared/validator.mjs +86 -0
  487. package/skills/interactive-page/scripts/archify/renderers/workflow/README.md +223 -0
  488. package/skills/interactive-page/scripts/archify/renderers/workflow/render-workflow.mjs +35 -0
  489. package/skills/interactive-page/scripts/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
  490. package/skills/interactive-page/scripts/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
  491. package/skills/interactive-page/scripts/archify/schemas/README.md +211 -0
  492. package/skills/interactive-page/scripts/archify/schemas/architecture.schema.json +178 -0
  493. package/skills/interactive-page/scripts/archify/schemas/common.schema.json +115 -0
  494. package/skills/interactive-page/scripts/archify/schemas/dataflow.schema.json +243 -0
  495. package/skills/interactive-page/scripts/archify/schemas/lifecycle.schema.json +266 -0
  496. package/skills/interactive-page/scripts/archify/schemas/sequence.schema.json +223 -0
  497. package/skills/interactive-page/scripts/archify/schemas/workflow.schema.json +428 -0
  498. package/skills/interactive-page/scripts/archify/scripts/check-render-output.mjs +916 -0
  499. package/skills/interactive-page/scripts/archify/scripts/render-examples.mjs +26 -0
  500. package/skills/interactive-page/scripts/bundle-artifact.sh +9 -8
  501. package/skills/skill-creator/SKILL.md +4 -5
  502. package/.next/server/app/api/bot/task/[id]/route/app-paths-manifest.json +0 -3
  503. package/.next/server/app/api/bot/task/[id]/route.js +0 -16
  504. package/.next/server/app/api/bot/task/[id]/route.js.nft.json +0 -1
  505. package/.next/server/app/api/bot/task/[id]/route_client-reference-manifest.js +0 -3
  506. package/.next/server/app/api/bot/task/route/app-paths-manifest.json +0 -3
  507. package/.next/server/app/api/bot/task/route.js +0 -16
  508. package/.next/server/app/api/bot/task/route.js.nft.json +0 -1
  509. package/.next/server/app/api/bot/task/route_client-reference-manifest.js +0 -3
  510. package/.next/server/chunks/[root-of-the-server]__01dkp4a._.js +0 -3
  511. package/.next/server/chunks/[root-of-the-server]__02va5wz._.js +0 -3
  512. package/.next/server/chunks/[root-of-the-server]__02xjoto._.js +0 -3
  513. package/.next/server/chunks/[root-of-the-server]__04q--0f._.js +0 -8
  514. package/.next/server/chunks/[root-of-the-server]__0bl-e63._.js +0 -3
  515. package/.next/server/chunks/[root-of-the-server]__0ffbg85._.js +0 -3
  516. package/.next/server/chunks/[root-of-the-server]__0jq4ohy._.js +0 -8
  517. package/.next/server/chunks/[root-of-the-server]__0ls6_8y._.js +0 -8
  518. package/.next/server/chunks/[root-of-the-server]__0ncs9uu._.js +0 -3
  519. package/.next/server/chunks/[root-of-the-server]__1-ga0kh._.js +0 -5
  520. package/.next/server/chunks/[root-of-the-server]__11n256_._.js +0 -5
  521. package/.next/server/chunks/[root-of-the-server]__12cabg9._.js +0 -3
  522. package/.next/server/chunks/[root-of-the-server]__1339jnv._.js +0 -8
  523. package/.next/server/chunks/[root-of-the-server]__18_teo8._.js +0 -8
  524. package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +0 -5
  525. package/.next/server/chunks/[root-of-the-server]__1anc1p9._.js +0 -3
  526. package/.next/server/chunks/[root-of-the-server]__1ccon1w._.js +0 -10
  527. package/.next/server/chunks/[root-of-the-server]__1fizn31._.js +0 -3
  528. package/.next/server/chunks/[root-of-the-server]__1llj3-b._.js +0 -3
  529. package/.next/server/chunks/[root-of-the-server]__1p8m3f4._.js +0 -3
  530. package/.next/server/chunks/[root-of-the-server]__1wa1k7r._.js +0 -8
  531. package/.next/server/chunks/_0-73of8._.js +0 -55
  532. package/.next/server/chunks/_0-fjql4._.js +0 -26
  533. package/.next/server/chunks/_00xh_q0._.js +0 -25
  534. package/.next/server/chunks/_03a0897._.js +0 -3
  535. package/.next/server/chunks/_051qh8u._.js +0 -3
  536. package/.next/server/chunks/_05sovvj._.js +0 -3
  537. package/.next/server/chunks/_0fzqt2y._.js +0 -134
  538. package/.next/server/chunks/_0mecv0f._.js +0 -26
  539. package/.next/server/chunks/_0mh8j4m._.js +0 -3
  540. package/.next/server/chunks/_0obojvv._.js +0 -3
  541. package/.next/server/chunks/_0sb7tlz._.js +0 -3
  542. package/.next/server/chunks/_0sbynis._.js +0 -3
  543. package/.next/server/chunks/_0u10wmw._.js +0 -55
  544. package/.next/server/chunks/_0u4aiy2._.js +0 -3
  545. package/.next/server/chunks/_0wp4le3._.js +0 -3
  546. package/.next/server/chunks/_0y5fg-x._.js +0 -3
  547. package/.next/server/chunks/_1230wbx._.js +0 -10
  548. package/.next/server/chunks/_12nheja._.js +0 -3
  549. package/.next/server/chunks/_13510xh._.js +0 -3
  550. package/.next/server/chunks/_15hq89o._.js +0 -3
  551. package/.next/server/chunks/_18-1wcc._.js +0 -55
  552. package/.next/server/chunks/_1_9mjx-._.js +0 -3
  553. package/.next/server/chunks/_1c78vw5._.js +0 -229
  554. package/.next/server/chunks/_1h5_8sk._.js +0 -3
  555. package/.next/server/chunks/_1hdnxb7._.js +0 -3
  556. package/.next/server/chunks/_1j8k_j5._.js +0 -3
  557. package/.next/server/chunks/_1nula3v._.js +0 -3
  558. package/.next/server/chunks/_1php4eq._.js +0 -3
  559. package/.next/server/chunks/_1yuv4vp._.js +0 -3
  560. package/.next/server/chunks/_1zjrdag._.js +0 -3
  561. package/.next/server/chunks/_next-internal_server_app_api_bot_task_[id]_route_actions_1_k_8u3.js +0 -3
  562. package/.next/server/chunks/_next-internal_server_app_api_bot_task_route_actions_0xln6ra.js +0 -3
  563. package/.next/server/chunks/features_0rpfxbk._.js +0 -3
  564. package/.next/server/chunks/features_1qf3cei._.js +0 -3
  565. package/.next/server/chunks/features_bot_0zt92oh._.js +0 -3
  566. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1xoq2rl._.js +0 -3
  567. package/.next/server/chunks/ssr/[externals]__0dizgek._.js +0 -3
  568. package/.next/server/chunks/ssr/[root-of-the-server]__092knlj._.js +0 -3
  569. package/.next/server/chunks/ssr/[root-of-the-server]__0mz33a7._.js +0 -3
  570. package/.next/server/chunks/ssr/[root-of-the-server]__0s9dq5u._.js +0 -3
  571. package/.next/server/chunks/ssr/[root-of-the-server]__0s9l2sv._.js +0 -3
  572. package/.next/server/chunks/ssr/[root-of-the-server]__0vnmv-s._.js +0 -3
  573. package/.next/server/chunks/ssr/[root-of-the-server]__0xsog8n._.js +0 -3
  574. package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +0 -61
  575. package/.next/server/chunks/ssr/[root-of-the-server]__1gtlw6v._.js +0 -43
  576. package/.next/server/chunks/ssr/[root-of-the-server]__1ox7hbk._.js +0 -4
  577. package/.next/server/chunks/ssr/[root-of-the-server]__202p40z._.js +0 -3
  578. package/.next/server/chunks/ssr/_001_ms1._.js +0 -28
  579. package/.next/server/chunks/ssr/_01n3o0m._.js +0 -3
  580. package/.next/server/chunks/ssr/_0fz4mf_._.js +0 -3
  581. package/.next/server/chunks/ssr/_0gb4gmf._.js +0 -3
  582. package/.next/server/chunks/ssr/_0h42fze._.js +0 -3
  583. package/.next/server/chunks/ssr/_0h7zdni._.js +0 -3
  584. package/.next/server/chunks/ssr/_0ilna52._.js +0 -42
  585. package/.next/server/chunks/ssr/_0q0zan6._.js +0 -70
  586. package/.next/server/chunks/ssr/_0zcjrbg._.js +0 -3
  587. package/.next/server/chunks/ssr/_0zhoc3r._.js +0 -3
  588. package/.next/server/chunks/ssr/_13fke0x._.js +0 -3
  589. package/.next/server/chunks/ssr/_18cymkq._.js +0 -3
  590. package/.next/server/chunks/ssr/_1b2mjwr._.js +0 -3
  591. package/.next/server/chunks/ssr/_1f-dg-6._.js +0 -3
  592. package/.next/server/chunks/ssr/_1h0rw11._.js +0 -3
  593. package/.next/server/chunks/ssr/_1jhd09t._.js +0 -3
  594. package/.next/server/chunks/ssr/_1nnsk7z._.js +0 -3
  595. package/.next/server/chunks/ssr/_1ov37if._.js +0 -3
  596. package/.next/server/chunks/ssr/_1sji22n._.js +0 -3
  597. package/.next/server/chunks/ssr/_1vi_uo7._.js +0 -3
  598. package/.next/server/chunks/ssr/_1vyd1ji._.js +0 -3
  599. package/.next/server/chunks/ssr/_1xx4zlb._.js +0 -3
  600. package/.next/server/chunks/ssr/components_ui_1y1l7yj._.js +0 -3
  601. package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +0 -3
  602. package/.next/server/chunks/ssr/lib_realtime_12wg_dd._.js +0 -27
  603. package/.next/server/chunks/ssr/lib_realtime_15h_v1v._.js +0 -27
  604. package/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0npjf8-._.js +0 -3
  605. package/.next/static/chunks/00rd4-v8r7axp.js +0 -1
  606. package/.next/static/chunks/08qe4as2q428z.js +0 -3
  607. package/.next/static/chunks/0gnqdjn2lvdad.js +0 -2
  608. package/.next/static/chunks/0hwap1-p0m5sa.js +0 -1
  609. package/.next/static/chunks/0r5qcctujhxli.js +0 -1
  610. package/.next/static/chunks/0w52rrrmuj9r9.js +0 -1
  611. package/.next/static/chunks/0wcprt5ot5she.js +0 -1
  612. package/.next/static/chunks/10teww7wt-f6h.js +0 -1
  613. package/.next/static/chunks/17p6tk6k88dq6.js +0 -1
  614. package/.next/static/chunks/18a96rkhi4_yd.js +0 -1
  615. package/.next/static/chunks/1dkjg87pxk0n9.js +0 -28
  616. package/.next/static/chunks/1jd09sxcjddu1.js +0 -1
  617. package/.next/static/chunks/1w73ece_6bheu.js +0 -18
  618. package/.next/static/chunks/214ya3n5gxeih.js +0 -1
  619. package/.next/static/chunks/22_zkas21rpna.js +0 -1
  620. package/.next/static/chunks/2fh4-3z_q8b_w.js +0 -1
  621. package/.next/static/chunks/2h0sd2vumhb15.js +0 -1
  622. package/.next/static/chunks/2t4vhi3m8ahya.js +0 -1
  623. package/.next/static/chunks/2tigdtz3dpcy8.js +0 -1
  624. package/.next/static/chunks/2u7xt6mxg44lf.js +0 -1
  625. package/.next/static/chunks/3786h5vayt80-.js +0 -28
  626. package/.next/static/chunks/39j0fvpybzabl.js +0 -40
  627. package/.next/static/chunks/3cq5g494yuke8.css +0 -1
  628. package/.next/static/chunks/3hibbjnt85-k6.js +0 -1
  629. package/.next/static/chunks/3woj-xd7ki5_i.js +0 -1
  630. package/.next/static/chunks/3xk7yqgomx7yq.js +0 -1
  631. package/.next/static/chunks/3zmcsnuo25zvq.js +0 -1
  632. package/database/migrations/20260911030320_opposite_jack_power/migration.sql +0 -1
  633. package/docs/images/task-thread.png +0 -0
  634. package/features/bot/components/task-badge.tsx +0 -42
  635. package/features/bot/components/task-reply.tsx +0 -328
  636. package/features/bot/components/task-setting.tsx +0 -524
  637. package/features/bot/task.query.ts +0 -976
  638. package/features/bot/task.store.ts +0 -489
  639. package/lib/realtime/client-secret.ts +0 -86
  640. package/lib/realtime/open-session.ts +0 -31
  641. package/lib/realtime/openai.ts +0 -35
  642. package/lib/realtime/realtime.audio.ts +0 -196
  643. package/lib/realtime/realtime.driver.ts +0 -489
  644. package/lib/realtime/realtime.protocol.ts +0 -393
  645. package/lib/realtime/realtime.schema.ts +0 -37
  646. package/lib/realtime/realtime.session.ts +0 -106
  647. package/lib/realtime/realtime.transport.ts +0 -384
  648. package/lib/realtime/xai.ts +0 -39
  649. /package/.next/server/app/api/bot/{task → thread}/[id]/route/build-manifest.json +0 -0
  650. /package/.next/server/app/api/bot/{task → thread}/[id]/route/server-reference-manifest.json +0 -0
  651. /package/.next/server/app/api/bot/{task → thread}/[id]/route.js.map +0 -0
  652. /package/.next/server/app/api/bot/{task → thread}/route/build-manifest.json +0 -0
  653. /package/.next/server/app/api/bot/{task → thread}/route/server-reference-manifest.json +0 -0
  654. /package/.next/server/app/api/bot/{task → thread}/route.js.map +0 -0
  655. /package/.next/static/{kaTO0UHqF1bMnWgCDik2f → 0qzGoKn2wTERVZtblX1tp}/_buildManifest.js +0 -0
  656. /package/.next/static/{kaTO0UHqF1bMnWgCDik2f → 0qzGoKn2wTERVZtblX1tp}/_clientMiddlewareManifest.js +0 -0
  657. /package/.next/static/{kaTO0UHqF1bMnWgCDik2f → 0qzGoKn2wTERVZtblX1tp}/_ssgManifest.js +0 -0
@@ -1,63 +1,66 @@
1
1
  # How it works
2
2
 
3
- The README says what Thursday is. This says what each part may touch, so you can guess what will happen before you say it.
3
+ What each part does, so you can guess what will happen before you say it.
4
4
 
5
5
  ## The call
6
6
 
7
- A call is a session with a realtime speech model — OpenAI Realtime or xAI Grok Voice, whichever key you gave. Audio in, audio out, interruptions and all. The model hears a prompt assembled the moment the line opens: who she is, what she remembers about you, which bots exist, what was said on the last calls.
7
+ A call runs on two models: **GPT-Live 1** holds the conversation, and a Responses model (**GPT-5.6 Luna** by default) thinks and uses tools behind it. The voice keeps listening while the backend works.
8
8
 
9
- She holds three things and nothing else:
9
+ - **Quick things, she answers herself.** She reads and writes your memory and runs one shell command at a time: open a file, check a folder, play something.
10
+ - **Everything else goes to a bot.** She hands it over and keeps talking. A speech model that ran a browser itself would go silent for minutes.
11
+ - **When a job comes back,** she tells you in a sentence. A file it made opens on your screen, and a question it asks shows up as buttons.
10
12
 
11
- - **Memory.** A folder of notes about you. She reads a note before answering out of it and writes the moment something worth keeping comes up — one fact per line, dates as dates. A rule you lay down ("answer in Korean", "keep it short") is carried into every call.
12
- - **One command.** A shell, for the things that take a second: open a file, play something, look at what is in a folder. One command is something she does, not a job she hands over.
13
- - **The roster.** The bots, by name, and what each is for.
13
+ Settings › Thursday picks the voice, the backend model and its reasoning, web search, the wake word and hotkey, and whether she calls you when a job ends.
14
14
 
15
- Everything else — anything that takes more than a few seconds — she hands to a bot with `delegate` and keeps talking. That is deliberate: the call must never go silent, and a speech model that runs a browser would be silent for minutes.
16
-
17
- When a job comes back, it arrives as a system note, not as you speaking. She tells you in one sentence, in her own words. A file the job made opens on your screen by itself; a question the job asks becomes buttons on screen and words in your ear.
15
+ The voice is billed per active minute, silence included; the backend is billed per token. Both use your OpenAI API key, not a ChatGPT subscription.
18
16
 
19
17
  ## Bots
20
18
 
21
- A bot is a text model — any of OpenAI, Anthropic, Google, xAI, or whatever the Vercel AI Gateway carries — with the whole machine:
19
+ ![A bot gets a shell, a real browser, skills, MCP servers, a studio and its own memory](images/machine.png)
22
20
 
23
- - a **shell** in a workspace folder, with no pager and no secrets in its environment
24
- - a **real browser** (Chromium through Playwright), headless until a sign-in or something you should see, and able to attach to the Chrome you already use
25
- - the **filesystem**, read anywhere, written only inside the workspace and where you pointed it
26
- - **skills** — written-down methods it reads before starting: the browser, this Mac, building a page, finding and writing skills
27
- - **MCP servers** you connected, searched by name and called by schema, with OAuth handled
28
- - a **studio** of image, video, speech and transcription models
29
- - **each other**: a bot hands a part of its job to the bot that exists for it, and folds the answer into its own report
21
+ A bot is a text model from any provider you added, with:
30
22
 
31
- A job ends in the thing that was asked for — the account made, the page built, the comparison in a table — and a report, written to be heard, because she reads it out loud. Anything that does not fit in a few lines is a file under `artifacts/`, and the report names it.
23
+ - a **shell** in a workspace folder
24
+ - a **real browser** — its own, or the Chrome you already use
25
+ - **your files** — it reads anywhere and writes where your user can; only its file tool is kept out of the app and the workspace root ([SECURITY.md](../SECURITY.md))
26
+ - **skills**, methods it reads before it starts
27
+ - **MCP servers** you connected
28
+ - a **studio** for images, video, speech, and transcription
29
+ - **each other**, to hand off part of a job
32
30
 
33
- What only you can give — a sign-in it holds no session for, a decision between two real options — stops the job at that point. The bot sets it up one action away, asks, and continues when the answer comes. Credentials you handed it are used only after it asks. A payment is the one thing it never finishes: it takes the purchase to the last screen, leaves that window open on yours, and reports what it buys and for how much.
31
+ The first run lets you pick a few starter bots; more are ready in Settings › Bots, or make your own with a name and one sentence about what it is for. That sentence is how Thursday decides who gets a job. Switch a bot off without deleting it.
34
32
 
35
- Three bots come with the app, split by temperament: **Jarvis** plans a job, hands parts to whoever fits and does the rest; **Navigator** goes and looks; **Scribe** writes. More are ready-made in settings — **Insta** draws, captions and posts to Instagram, **Voyage** plans a trip with a map for each day — or make your own: a name, a sentence about what it is for, optionally a model and a few pinned tools. The sentence is what she reads when deciding who gets the job. A bot can be switched off without being deleted.
33
+ A job ends in the thing you asked for and a short report. Anything longer than a few lines is a file in `artifacts/`. When only you can do something — sign in, choose between two real options — the bot sets it up, asks, and waits. It never presses Pay: a purchase stops on the last screen, left open for you.
36
34
 
37
- Each bot keeps its own memory as files in its folder (`bots/<name>/memory/`), one topic per file, and reads the list at the start of every job. Its page in settings shows them; open one in place or delete it.
35
+ Each bot keeps its own memory as files you can open from its page.
38
36
 
39
37
  ## Jobs outlive the call
40
38
 
41
- A job runs on the server. It is not in the tab, and it does not stop when you hang up. Every step — the request, each tool call, what came back, the report — is written as a row, and the screen is a projection of those rows. When you come back, the jobs that finished are waiting, and she tells you about them on the next call, or rings you if you turned that on.
42
-
43
- A job that stopped to ask, or ran out of its step budget, is resumed from where it stopped: the same thread, with your answer appended. A long thread is compacted — the model summarizes what happened so far and continues from the summary.
44
-
45
- With no browser on the app for ten seconds, running jobs stop where they stand, so nothing spends your keys while nobody is looking. A job the app stopped — a closed tab, a restart, a model call that failed — picks itself back up when it can, up to three times in a row before it waits for you. A job a bot or a person stopped waits for a person.
39
+ ![Hang up mid-sentence and the job keeps going on the server](images/keeps-going.png)
46
40
 
47
- ## Memory you can read
41
+ - A job runs on the local server, not in the call. Hang up and it keeps going.
42
+ - Every step is saved, so a job that stopped to ask picks up where it left off, and you can read the whole thread.
43
+ - Close the app, and after ten seconds running jobs pause. Open it again and they continue, so nothing spends your keys while you are away.
44
+ - A model call that fails is retried once. After that, the job waits for you.
48
45
 
49
- Memory is notes in the database on your disk, in the data folder (`~/.thursday` when installed with `npx`, the checkout otherwise). Each note is a topic — `profile`, `preferences`, `people/…`, and whatever she creates — and holds one fact per line. A few are `alwaysLoad` and travel into every call: your name, your language, how you like to be addressed, the rules you gave her.
46
+ ## Memory
50
47
 
51
- She writes the moment something worth keeping comes up. Each fact remembers the call it was said in, so when a line is not enough she can open that conversation again. Nothing re-reads calls after they end: what is kept is what was written.
48
+ Memory is a set of notes about you, one fact per line: your name, your language, the people you mention, the rules you give her. A few notes go into every call.
52
49
 
53
- You can open any note from settings and read exactly what she knows. To change it, type what changed on the Memory screen, pick a model, and watch each edit land. When the listing gets long she says so in a lull, puts a note on your screen and forgets only what you name.
50
+ Open any note in Settings › Memory to see exactly what she knows. To change it, type what changed and watch each edit land. Bots read your memory but never write it.
54
51
 
55
- Bots read your memory but do not write it. What a bot learns about its own work goes into its own memory files; what it learns about you goes into its report, and whether that is worth keeping is her call, with you.
52
+ ## Where your data lives
56
53
 
57
- ## What is not here
54
+ ```text
55
+ ~/.thursday
56
+ ├── local.db calls, memory, bots, jobs, keys
57
+ └── .ai-workspace
58
+ ├── artifacts/ finished work, a folder per bot
59
+ ├── projects/ code and longer-lived projects
60
+ ├── bots/ each bot's memory and saved sessions
61
+ └── .agents/ skills you installed
62
+ ```
58
63
 
59
- - **No cloud.** The server is the one on your machine; keys are stored locally and sent only to the provider you chose.
60
- - **No account.** There is nothing to sign up for. There is also no login, which is why the server binds to `127.0.0.1` — see [SECURITY.md](../SECURITY.md).
61
- - **No prompt engineering on your side.** The prompts are assembled from your data on every session; the one thing you can add is an instruction to her, and one to each bot, in settings.
64
+ When you run from source, the same files live in the checkout. The server listens only on `127.0.0.1`, and there is no login — see [SECURITY.md](../SECURITY.md).
62
65
 
63
- For the code — which file owns what, and why — read [CLAUDE.md](../CLAUDE.md).
66
+ For contributors: [live calls](live-calls.md) and [thread rooms](thread-rooms.md) are the engine contracts, and [AGENTS.md](../AGENTS.md) maps the code.
Binary file
Binary file
@@ -0,0 +1,231 @@
1
+ # Live calls
2
+
3
+ Thursday uses GPT-Live 1 for voice and Responses delegation for short reasoning and
4
+ tool use. The default backend is GPT-5.6 Luna. Background bots keep their own
5
+ models, prompts, durable threads, and execution budgets; the voice settings do not
6
+ change the text or media providers available to them.
7
+
8
+ This document is the implementation contract for calls. Keep it aligned with the
9
+ code when changing session events, settings, prompts, or persistence.
10
+
11
+ ## Responsibilities
12
+
13
+ | Runtime | Context and instructions | Work |
14
+ | --- | --- | --- |
15
+ | Live voice | `live.prompt`: who Thursday is, the delegation policy (what the backend can do, when to hand over), profile and preferences with the note listing; earlier spoken turns as `input` behind a developer note | Listen, speak, backchannel, handle interruptions, decide when the backend is needed |
16
+ | Responses backend | `thursday.prompt`: who Thursday is, the voice conversation it works from, memory with ids, bot roster and what bots can reach, this computer, what to return, earlier calls with their jobs; tool schemas | Recall and update memory, run short commands, route thread messages and cancellations, delegate long work |
17
+ | Background bots | `bot.prompt` and the stored participant transcript | Shell, browser, MCP, skills, and work that outlives a call |
18
+ | Application | Authoritative database and tool implementations | Validate actions, retain results, enforce thread limits, render progress, save call history |
19
+
20
+ Use Responses delegation because Live supplies conversation context and manages the
21
+ backend connection. Do not build a second transcript-to-thread orchestrator. Client
22
+ delegation is a different integration: its notification contains metadata, not thread
23
+ text, so the application would have to reconstruct the request and operate the backend.
24
+
25
+ The voice and the backend are one assistant. Both prompts open with the same identity
26
+ (`thursdayIdentity`) and the same rule for ending the call (`callEnding`), read the same
27
+ memory, and neither is told it is part of something else. The voice prompt follows the
28
+ GPT-Live prompting guide's `Delegation policy` labels —
29
+ `Backend tools`, `Delegate to the backend when`, `Do not delegate to the backend when` — and
30
+ says nothing about how to speak, which the Live model does itself; it never sees tool names
31
+ or schemas. The backend prompt follows the guide's backend template: the voice conversation
32
+ it works from (transcripts can be wrong and corrected later), one chapter per capability the
33
+ voice lists, and what to return.
34
+
35
+ ## Settings and upgrades
36
+
37
+ Voice uses the fixed `gpt-live-1` model. Settings › Thursday exposes a voice and
38
+ additional voice instructions; for the backend, a model,
39
+ optional reasoning effort, web search, and additional backend instructions. Both
40
+ instruction fields add to the app's prompts and never replace them. The model list
41
+ shows recent models; an older or custom ID can be typed and saved. Live accepts any
42
+ reasoning settings when the call opens and fails the backend's first response when the
43
+ model does not take one, so the server asks the token-count endpoint first
44
+ (`acceptedReasoning`), once per model and effort. A setting refused by name, the effort or
45
+ the summary, is dropped and not shown; a refused model or key still reaches the user when the
46
+ call opens. Auto reasoning sends no effort.
47
+ Web search adds the `web_search` tool only when switched on. Changes apply from the
48
+ next call.
49
+
50
+ Settings stay in the browser under the existing `thursday.settings` key, beside wake
51
+ word, shortcut, captions and call-back (`thursday.store`). `migrateLiveSettings`
52
+ upgrades stored values: an OpenAI voice and backend model carry over, a Grok voice is
53
+ retired without touching historical calls or xAI text and media keys, and the old
54
+ shared instruction is copied into both new instruction fields. Each field recovers on
55
+ its own, so one malformed value falls back to its default and leaves the rest.
56
+
57
+ Every call is kept on this machine. Live transcription needs no separate model or
58
+ request, so there is nothing to switch off to save cost. Keep `store: false` in the
59
+ provider request: local history is distinct from OpenAI session recording and fork
60
+ storage.
61
+
62
+ ## Connection and opening
63
+
64
+ 1. In the user's gesture, before anything awaits, prepare playback. Then request
65
+ microphone access and gather WebRTC ICE.
66
+ 2. Send the SDP offer and the parsed settings to `openCallAction`. The browser sends
67
+ settings only; the server reads the key.
68
+ 3. On the server, assemble both prompts and the current tool manifest. Create the
69
+ Live session with the fixed voice model, the chosen voice, voice instructions,
70
+ earlier spoken turns in `input`, and `delegation.responses` backend settings.
71
+ Insert the call row only after the provider accepts, so a refusal leaves no open row.
72
+ 4. Apply the SDP answer and wait for `session.started`. Do not send Realtime startup
73
+ configuration, audio commits, or a voice `response.create`.
74
+ 5. Send the opening as `session.instructions.append`, so she speaks first: a first call
75
+ (no profile facts) greets the user and asks what to call them, memory past
76
+ `MEMORY_LIMITS` raises tidying, and any other call opens with a short greeting.
77
+ Updates that arrived while connecting follow once she has voiced the opening.
78
+ A call the page placed for waiting work (call-back) opens instead with the fact that
79
+ she placed it, ahead of every other opening, and the first open work goes in as soon
80
+ as she has voiced that, without waiting for a quiet line: why she called is the first
81
+ thing asked. The opening names no bot text; the work itself follows as commentary.
82
+
83
+ `input` opens with a developer message saying the turns after it are from earlier calls
84
+ and that none is a request now, then holds user and assistant turns, newest kept first
85
+ within `RECENT_CALL` and the provider limits of 128 messages and 8,192 tokens. Tool turns
86
+ stay out, since voice holds no tools. It always ends on an assistant turn: a call that
87
+ ended on the user's words would leave a turn that Live answers the moment the next call
88
+ opens.
89
+
90
+ A hang-up during startup invalidates that attempt, so a connection that finishes
91
+ later is closed rather than taking over the screen. Do not change machine trust,
92
+ certificate, or proxy configuration to hide connection errors.
93
+
94
+ ## Tools and background updates
95
+
96
+ Live speech and backend work have independent lifecycles. Unwrap `response.event`
97
+ and associate its delegation with the response ID from `response.created`. Collect
98
+ complete function calls from `response.output_item.done`, deduplicate by call ID, and
99
+ run existing server handlers through the tool-call route. Terminal response snapshots
100
+ intentionally omit output items. Submit every function output with
101
+ `response.item.create`, then explicitly continue with one `response.create`. That
102
+ command continues backend work; it does not grant permission for Live to speak. A
103
+ response that ends incomplete after asking for tools is still continued once its outputs
104
+ are in, or the backend turn never finishes; a failed or cancelled response, or a second
105
+ incomplete in a row, only warns. A function call the output cap cuts off arrives as an
106
+ item with status `incomplete` and fragment arguments, and Live ends that handoff with a
107
+ top-level `error` instead of a terminal event: the call is not run and its response
108
+ counts as finished, though calls it completed before the cut still have their results
109
+ continued once. The backend is asked for `reasoning.summary: "auto"` unless the
110
+ effort is `none`. Each finished summary part (nested `response.reasoning_summary_text.done`,
111
+ only while the model reasons) is stored with its call in `call_thought` to look into
112
+ later; nothing draws it or reads it back into a prompt. Tools are sent without `strict`, so each schema that allows it is
113
+ decoded to the schema; `strict: false` would let a model write arguments that are not
114
+ JSON, and `strict: true` is refused while any schema has optional fields. Live has no
115
+ `response.cancel`.
116
+
117
+ Long work enters the existing bot runner and returns a thread receipt immediately.
118
+ Background questions and results follow the existing durable relay queue. A voice
119
+ interruption never cancels a thread by itself. Route an explicit cancellation or
120
+ correction to the owning thread and report its actual outcome.
121
+
122
+ | Update | Live event |
123
+ | --- | --- |
124
+ | Opening, idle goodbye, other trusted behavior | `session.instructions.append` |
125
+ | Screen actions the voice should know but need not say | `session.thinking.append` |
126
+ | A bot's result or question to convey | `session.commentary.append` |
127
+
128
+ Bot output is never sent as instructions. Each append carries a required
129
+ `delegation_id`, `null` for application updates in Responses mode; a response ID is
130
+ not a client delegation ID. Appends are serialized and matched to their
131
+ acknowledgement by `client_event_id`. An update longer than one append is split at
132
+ word boundaries under 480 UTF-8 bytes, which keeps within the 500-token limit for any
133
+ script, and sent chunk by chunk. A rejected or unacknowledged chunk drops the rest of
134
+ its update, warns, and is never replayed. An acknowledgement is not proof of speech.
135
+
136
+ Live never speaks unprompted, so what waits on the user reaches them only when the page puts
137
+ it in. The relay clock (`useThursday` `relayOpenWork`) reads the inbox once a second and sends
138
+ open work only when neither side's words have been transcribed for `CALL_RELAY.quietMs` and
139
+ no backend work or tool is running: questions not answered, jobs stopped or finished and not
140
+ yet seen, and progress from jobs still running. Up to `CALL_RELAY.perTurn` items of one
141
+ kind go in one commentary append, most pressing first, so an ending never shares an append with
142
+ a question. The activity line carries the update from the moment
143
+ it goes out until her voice has finished it, and nothing else goes in until her voice has started
144
+ and stopped (at most `CALL_RELAY.readMs`). An item is handled when it is answered, marked seen
145
+ by the backend's `thread` `seen` once the user has been told enough, or opened on screen — the
146
+ backend's `thread` `open` opens it in the call screen's room (a `showThread` event). Each item
147
+ goes in once a call (`told`, in memory), and it stays in the inbox and on screen until handled.
148
+ One her voice carried stays out of later calls too while the page is open; one it did not (Live
149
+ refused it, she never spoke, the call ended first) goes in again on the next call, never in a
150
+ loop on this one. The key carries the job's last change, so a job that resumes and asks or ends
151
+ again is a new item, and a reload puts what is still open in once more. Nothing goes in while
152
+ the call is ending or a goodbye has been asked for. The first relay of a call follows an
153
+ `instructions` note that what she has already told the user need not be said again, so the
154
+ relay itself stays facts only.
155
+
156
+ A relay names the bot and the thread and, for a question, where its answer goes (thread,
157
+ recipient, `replyTo`). The backend reads relays in its conversation and routes the user's
158
+ answer from those facts, so a relay carries no instructions. Relay rows are accepted
159
+ (`acceptThreadRelaysAction`) once Live acknowledges the append; an ending also covers its
160
+ job's progress rows. Being put to her does not mark a result seen.
161
+
162
+ ## Transcript and screen
163
+
164
+ Input and output transcript events contain `delta`, `start_ms`, and `end_ms`. They
165
+ have no authoritative completed-turn event. The session folds fragments into
166
+ revisable display groups by speaker and time, deduplicates them by event ID, and
167
+ checkpoints changed groups every `LIVE_CALL.transcriptSaveMs` with their exact
168
+ fragments. A late fragment revises its group, which is saved again. Never derive
169
+ actions or cancellations from the grouping. Backend text is not a transcript of spoken
170
+ audio and never becomes a caption.
171
+
172
+ `call_message.fragments` keeps the original fragments beside each saved group; a
173
+ revision replaces them and keeps the group's `seq`. Rows written before Live have no
174
+ fragments and remain readable.
175
+
176
+ Track playback and backend work independently, from her audio level and backend events.
177
+ The idle clock rewinds on new transcribed words, her voice and backend work, not on
178
+ microphone level alone, so a noisy room does not hold a call open, and not on an update she
179
+ voices on her own, so waiting results do not either. New words from the user are owed an
180
+ answer unless her voice has been heard since they first came in, since transcripts lag the
181
+ audio; with nothing back for `CALL_IDLE.agentSilentMs` the page hangs up. After
182
+ `CALL_IDLE.hangUpMs` she is asked for a goodbye, and the page hangs up
183
+ `CALL_IDLE.graceMs` later if the line is still open.
184
+
185
+ ## Closing and recovery
186
+
187
+ A request to end the call, whether to hang up or a goodbye, sets everything else aside:
188
+ the voice hands it to the backend at once and says a brief okay while `end_call` runs.
189
+ The page does not close on `end_call` itself: it waits until her voice has been quiet
190
+ for `CALL_END.quietMs`, or `CALL_END.unsaidMs` when nothing was said, never past
191
+ `CALL_END.maxMs`.
192
+
193
+ Stop accepting new work, send `session.close`, and keep the connection while waiting
194
+ for `session.closed`. Its reason and billed seconds are recorded on the call row
195
+ (`ended_reason`, `seconds`) next to the backend model. Without a confirmation within
196
+ `LIVE_CALL.closeMs`, the call warns and the seconds stay unknown. The screen shows
197
+ Ending until cleanup finishes and blocks a second call during that interval.
198
+ Background jobs follow existing presence rules and survive the call.
199
+
200
+ A new connection is a new session. Seed it with relevant saved history and current
201
+ thread state. Reconcile completed operations and suppress stale results; never replay
202
+ tools merely because the previous connection disappeared. Live charges active session
203
+ time, including silence and backend waits; backend tokens are separate.
204
+
205
+ ## Validation
206
+
207
+ `pnpm test:live` covers tool continuation, including the one continuation after an
208
+ incomplete response, fragment grouping and late revision, closing with and without
209
+ confirmation, activity while speaking and working, append ordering, acknowledgement,
210
+ rejection and chunking, the provider request with optional reasoning and web search,
211
+ settings migration, both assembled call prompts and the identity they share, and fragment
212
+ persistence against a migrated database. Also run typecheck, lint, build and
213
+ `pnpm test:bot`, and read both assembled prompts.
214
+
215
+ Inspect settings on desktop and narrow screens. Real-call checks cover a first
216
+ greeting, overlapping speech, a short tool call, a bot
217
+ question answered during other work, correction, cancellation, a late result,
218
+ reconnect, and the recorded seconds. Count durable tool calls and thread
219
+ messages as well as listening to the actual audio.
220
+
221
+ ## Official references
222
+
223
+ - [Getting started](https://developers.openai.com/api/docs/guides/live)
224
+ - [Voice prompting](https://developers.openai.com/api/docs/guides/live-prompting)
225
+ - [Sessions, transcripts, and closure](https://developers.openai.com/api/docs/guides/live-conversations)
226
+ - [Responses delegation and updates](https://developers.openai.com/api/docs/guides/live-delegation)
227
+ - [Migration](https://developers.openai.com/api/docs/guides/live-migration)
228
+ - [Partner integrations](https://developers.openai.com/api/docs/guides/live-partner-integrations)
229
+
230
+ Thursday uses direct browser WebRTC. LiveKit, Pipecat, and telephone integrations
231
+ are not required for this media path.
@@ -0,0 +1,71 @@
1
+ # Thread rooms
2
+
3
+ A thread has one coordinator and a persistent participant for each canonical bot name. Thursday introduces the work to the coordinator. Bots exchange messages and run independently; the coordinator brings the results back to Thursday. A model invocation is one period of activity, not a new bot.
4
+
5
+ ## Identity and context
6
+
7
+ A participant is identified by `(threadId, bot)`. Every continuation for that participant reads the same stored history, beginning with its original briefing and, after compaction, its latest summary. Requests from a different colleague do not create another context or browser identity. Browser session names derive from the thread and canonical bot name.
8
+
9
+ `parentId` identifies the conversation to which a continuation returns. It does not identify the participant. If A waits for B and B asks A a question, A handles that question in its own context, returns the answer to B, and keeps its original responsibility to report to Thursday. Only exchanged messages enter the other participant's context. The human can inspect all recorded activity; workspace files remain shared resources.
10
+
11
+ ## Messages and turns
12
+
13
+ Bots use `send_message(to, text, kind?, options?, replyTo?)`. A send commits before returning a receipt. The sender can continue independent work or end its turn. A natural final message returns to the current correspondent; a silent ending is valid. There is no completion tool or required closing phrase.
14
+
15
+ An explicit `replyTo` routes a message to an open incoming exchange. An ordinary send to another bot opens a new exchange. For Thursday, `kind: "message"` (the default) sends an update without opening a question or delaying completion. Use `kind: "question"` for user input; it carries an addressable question ID and optional answer choices. Other participants continue while a question is open, but the question ends the asker's turn: until it is answered, that bot runs nothing, messages to it wait in its inbox, and words from the user side addressed to it answer the question. With several questions open and none named, an answer is refused with the list. The screen and the call's `thread` tool can direct an answer or a new message to a particular participant. An answer is words like any other: a question that offers `Continue` among its choices is answered by it, and only a stop the app made is resumed by that word.
16
+
17
+ The room and its participants have separate lifecycles:
18
+
19
+ | Continuation state | Meaning |
20
+ | --- | --- |
21
+ | `queued` | Ready for the scheduler. |
22
+ | `running` | Claimed by one live turn. |
23
+ | `waiting` | The turn ended with downstream work still open. |
24
+ | `external` | A message to Thursday awaits a user response. |
25
+ | `paused` | Interrupted work awaits a permitted resume. |
26
+ | `done` | The continuation has no unread messages or open downstream work. |
27
+ | `cancelled` | The user stopped the continuation. |
28
+
29
+ Incoming messages queue a waiting continuation. At completion, the engine checks the inbox and downstream work in the same transaction that releases the claim. A message racing with an ending is handled by the current turn or its successor.
30
+
31
+ The coordinator's normal final message completes the thread only when all work has settled. If activity settles without a coordinator report, the scheduler permits one wrap-up turn. An empty final turn leaves an idle, resumable room; it does not cause an automatic retry loop. A participant that already replied with `replyTo` and then ends silently sends nothing more; its reply is the answer.
32
+
33
+ ## Durable state
34
+
35
+ `room.query.ts` owns transactional scheduling and messaging. `bot.runner.ts` holds live promises and abort controllers. `bot.run.ts` runs one `ToolLoopAgent` and persists events through the runner.
36
+
37
+ | Table | Responsibility |
38
+ | --- | --- |
39
+ | `thread` | Room status, coordinator, reporting epoch, automatic turn budget. |
40
+ | `thread_work` | Continuations, return routes, claims and claim generations. |
41
+ | `thread_delivery` | Durable inbox and insertion acknowledgement. |
42
+ | `thread_message` | Model history and the human-visible activity projection. |
43
+ | `thread_relay` | Reports and questions awaiting delivery to Thursday. |
44
+
45
+ A partial unique index allows only one running continuation for a bot in a thread. Model execution never holds the room's command lock. Cancellation and manual resume share that lock; cancellation drains the old runs before a new run can start. Generation checks reject a stale run's attempts to send messages or settle work. Actual tool results received during shutdown are retained before the drain ends.
46
+
47
+ Message receipts use a stable key derived from the thread, sender and tool call ID. A repeated send returns the committed receipt. Recovery also reconstructs a known receipt when the send committed but its tool-result row did not. Inbox insertion and acknowledgement are transactional. Transcript sequence numbers are allocated at the database boundary, so different bots cannot overwrite each other's rows.
48
+
49
+ The SDK can prepare another model step before a streaming consumer finishes writing the previous step. A persistence barrier prevents that next step from starting early. Compaction is written before newly consumed inbox messages, preserving the same ordering on resume.
50
+
51
+ `BOT_RUN` in `config.ts` bounds concurrent participants, distinct participants, pending exchanges, steps per turn and automatic turns across the room. User messages and manual resumes reset the room's turn budget. Browser presence returning does not reset it.
52
+
53
+ ## Interruption and recovery
54
+
55
+ Closing the last app browser pauses work; returning resumes only work paused for browser absence. A model call that breaks — a dropped or garbled stream, an overload, a model gone quiet, a context refused as too long — is tried once more from the stored conversation after a short wait, with a note saying why. A second break, a provider's refusal (the key, the credit, the model id), the content filter, a server restart, a resource limit such as the step limit, or a user stop waits for a person. The stored conversation and browser identity remain available. Browser processes, login state and element references may require inspection after a restart.
56
+
57
+ Before a local tool executes, its validated call is stored. Before another model step starts, its result is stored. On resume, a local call with no result receives an interruption result in the model projection: the outcome is unknown and the current state must be inspected before repeating the action. The original audit rows remain intact. Real results are preserved, malformed argument fragments do not become executable calls, and native provider operations without results become explicit interruption notes instead of fabricated local results.
58
+
59
+ This does not provide exactly-once execution against arbitrary external services. A server can disappear after a remote action succeeds and before its result is stored. The engine preserves that uncertainty and offers manual recovery rather than replaying external actions automatically.
60
+
61
+ A thread is created together with its coordinator's first continuation, so every thread is a room from its first row.
62
+
63
+ Thursday relays are persisted independently of whether a thread has been opened on screen. Unaccepted reports remain in the inbox beyond the usual finished-thread limit. Opening a thread, or Thursday marking it seen, settles its relays; so does a resume for the stop it picks up from, and new words for how it last stopped or ended. A call accepts a relay once Live acknowledges the update; this is not proof that the user heard the audio, and an update Live never acknowledged is relayed again on a later call. A question or ending she voiced is not presented again on a later call while the page stays open; it stays on screen until handled.
64
+
65
+ The screen keeps unanswered questions visible even while other participants work, and keeps unread endings until the user opens them. A thread reads as the conversation between its participants: every message as words, the open tab's bot's own work in full, and each other bot's work between its messages folded into a row that opens in place. It opens on its own bot's tab, which holds every participant; another bot's tab holds only what reached that bot's context. The collapsed thread panel shows both without relying on a call. Thursday's status tool returns up to ten threads, prioritizing open work and filling the remaining places with recent endings; naming a thread returns its full result and pending questions.
66
+
67
+ ## Verification
68
+
69
+ `pnpm test:bot` runs the real scheduler, SQLite queries, tools, prompts and SDK loop against isolated temporary data and deterministic model streams. It checks continuity, private histories, routing, concurrent questions, completion races, interruption, cancellation, compaction and committed-message recovery. Provider adapter tests inspect serialized OpenAI, Anthropic and Google requests at a mocked HTTP boundary. They do not call live models.
70
+
71
+ Run `pnpm typecheck`, `pnpm lint` and `pnpm build` as well. Browser checks cover the thread screen, participant selection, separate drafts, Markdown and long URLs. TypeScript alone does not validate Next.js client/server directives or the rendered layout.
@@ -521,8 +521,7 @@ async function codexFetch(
521
521
  /**
522
522
  * A 429 is either a rate limit a moment fixes or the plan's usage spent until its window resets
523
523
  * — hours, or on Free a month. The second becomes a 402 in the backend's words: the sdk does not
524
- * retry it, and a job fails with it (model.ts modelFailureOf) instead of waking every few
525
- * minutes to be refused again.
524
+ * retry it, so a job fails with it at once instead of being refused again and again.
526
525
  */
527
526
  async function usageLimitOf(response: Response): Promise<Response> {
528
527
  const text = await response.text();
@@ -0,0 +1,128 @@
1
+ import { z } from "zod";
2
+ import { COMMON_VALIDATE } from "@/lib/limits";
3
+ import { LIVE_BACKEND_MODEL } from "@/lib/live/live.schema";
4
+ import { TEXT_MODEL_PROVIDERS } from "./model.schema";
5
+
6
+ export const LIVE_PROVIDER = {
7
+ id: "openai",
8
+ label: "OpenAI",
9
+ apiKeyName: TEXT_MODEL_PROVIDERS.openai.apiKeyName,
10
+ } as const;
11
+
12
+ /** Suggestions only: custom voices and older backend model IDs remain valid input. */
13
+ export const LIVE_VOICES = [
14
+ "marin",
15
+ "cedar",
16
+ "gleam",
17
+ "meridian",
18
+ "quartz",
19
+ "ripple",
20
+ "vesper",
21
+ "willow",
22
+ "stone",
23
+ "bossa",
24
+ "tempo",
25
+ "beacon",
26
+ "delta",
27
+ "cinder",
28
+ "alloy",
29
+ "ash",
30
+ "ballad",
31
+ "coral",
32
+ "echo",
33
+ "sage",
34
+ "shimmer",
35
+ "verse",
36
+ ] as const;
37
+
38
+ /**
39
+ * Regional influence and presentation, as OpenAI documents them for the voices
40
+ * GPT-Live adds. The rest — marin, cedar and the voices shared with Realtime —
41
+ * have no documented character, and an invented one would read as fact.
42
+ */
43
+ export const LIVE_VOICE_NOTE: Partial<
44
+ Record<(typeof LIVE_VOICES)[number], string>
45
+ > = {
46
+ gleam: "North American · feminine",
47
+ meridian: "North American · masculine",
48
+ quartz: "Australian · feminine",
49
+ ripple: "Australian · masculine",
50
+ vesper: "British · masculine",
51
+ willow: "Irish · feminine",
52
+ stone: "Irish · masculine",
53
+ bossa: "Portuguese · feminine",
54
+ tempo: "Portuguese · masculine",
55
+ beacon: "Filipino · masculine",
56
+ delta: "Southern U.S. · feminine",
57
+ cinder: "Southern U.S. · masculine",
58
+ };
59
+
60
+ /** A recorded line in this voice. Only the listed voices have one. */
61
+ export const voiceSamplePath = (voice: string) => `/voices/${voice}.ogg`;
62
+
63
+ export const LIVE_BACKEND_MODELS = TEXT_MODEL_PROVIDERS.openai.suggestModels;
64
+ export const LIVE_REASONING = [
65
+ "none",
66
+ "minimal",
67
+ "low",
68
+ "medium",
69
+ "high",
70
+ "xhigh",
71
+ ] as const;
72
+
73
+ const instruction = z.string().max(COMMON_VALIDATE.prompt.max).default("");
74
+
75
+ export const LiveSettingsSchema = z.object({
76
+ voice: z.string().trim().min(1).max(128).default("marin"),
77
+ voicePrompt: instruction,
78
+ backendModel: z.string().trim().min(1).max(128).default(LIVE_BACKEND_MODEL),
79
+ backendPrompt: instruction,
80
+ /**
81
+ * A call waits out loud, so the backend reasons as little as the work allows.
82
+ * Null omits the parameter, for a model that only runs on its own default.
83
+ */
84
+ reasoningEffort: z.enum(LIVE_REASONING).nullable().default("low"),
85
+ webSearch: z.boolean().default(false),
86
+ });
87
+ export type LiveSettings = z.infer<typeof LiveSettingsSchema>;
88
+ export const LIVE_DEFAULTS = LiveSettingsSchema.parse({});
89
+
90
+ /**
91
+ * Settings stored before Live-only, or hand-edited, into valid ones. An OpenAI
92
+ * voice and backend model carry over; a Grok voice does not, since its names
93
+ * mean nothing to Live. The one shared instruction goes into both new fields so
94
+ * nothing the user wrote is lost. Each field recovers on its own: one bad value
95
+ * falls back to its default and leaves the rest as they were.
96
+ */
97
+ export function migrateLiveSettings(value: unknown): Record<string, unknown> {
98
+ const stored =
99
+ value && typeof value === "object"
100
+ ? (value as Record<string, unknown>)
101
+ : {};
102
+ const { model, systemPrompt, ...rest } = stored;
103
+ const legacy = z
104
+ .object({
105
+ provider: z.string(),
106
+ voice: z.string().nullish(),
107
+ backendModel: z.string().nullish(),
108
+ })
109
+ .safeParse(model);
110
+ const openai =
111
+ legacy.success && legacy.data.provider === "openai" ? legacy.data : null;
112
+
113
+ const candidate: Record<keyof LiveSettings, unknown> = {
114
+ voice: stored.voice ?? openai?.voice,
115
+ voicePrompt: stored.voicePrompt ?? systemPrompt,
116
+ backendModel: stored.backendModel ?? openai?.backendModel,
117
+ backendPrompt: stored.backendPrompt ?? systemPrompt,
118
+ reasoningEffort: stored.reasoningEffort,
119
+ webSearch: stored.webSearch,
120
+ };
121
+ const live = Object.fromEntries(
122
+ (Object.keys(candidate) as (keyof LiveSettings)[]).map((key) => {
123
+ const parsed = LiveSettingsSchema.shape[key].safeParse(candidate[key]);
124
+ return [key, parsed.success ? parsed.data : LIVE_DEFAULTS[key]];
125
+ }),
126
+ );
127
+ return { ...rest, ...live };
128
+ }