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
@@ -1,63 +1,68 @@
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
+ ![One mind goes silent while it works; two minds keep the call going while a bot does the work](images/two-minds.png)
10
10
 
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.
11
+ - **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.
12
+ - **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.
13
+ - **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.
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.
15
+ 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.
16
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.
17
+ 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
18
 
19
19
  ## Bots
20
20
 
21
- A bot is a text model — any of OpenAI, Anthropic, Google, xAI, or whatever the Vercel AI Gateway carries — with the whole machine:
21
+ ![A bot gets a shell, a real browser, skills, MCP servers, a studio and its own memory](images/machine.png)
22
22
 
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
23
+ A bot is a text model from any provider you added, with:
30
24
 
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.
25
+ - a **shell** in a workspace folder
26
+ - a **real browser** — its own, or the Chrome you already use
27
+ - **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))
28
+ - **skills**, methods it reads before it starts
29
+ - **MCP servers** you connected
30
+ - a **studio** for images, video, speech, and transcription
31
+ - **each other**, to hand off part of a job
32
32
 
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.
33
+ 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
34
 
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.
35
+ 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
36
 
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.
37
+ Each bot keeps its own memory as files you can open from its page.
38
38
 
39
39
  ## Jobs outlive the call
40
40
 
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.
41
+ ![Hang up mid-sentence and the job keeps going on the server](images/keeps-going.png)
42
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.
43
+ - A job runs on the local server, not in the call. Hang up and it keeps going.
44
+ - Every step is saved, so a job that stopped to ask picks up where it left off, and you can read the whole thread.
45
+ - 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.
46
+ - A model call that fails is retried once. After that, the job waits for you.
44
47
 
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.
48
+ ## Memory
46
49
 
47
- ## Memory you can read
50
+ 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.
48
51
 
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.
52
+ 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.
50
53
 
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.
54
+ ## Where your data lives
52
55
 
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.
56
+ ```text
57
+ ~/.thursday
58
+ ├── local.db calls, memory, bots, jobs, keys
59
+ └── .ai-workspace
60
+ ├── artifacts/ finished work, a folder per bot
61
+ ├── projects/ code and longer-lived projects
62
+ ├── bots/ each bot's memory and saved sessions
63
+ └── .agents/ skills you installed
64
+ ```
54
65
 
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.
66
+ 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).
56
67
 
57
- ## What is not here
58
-
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.
62
-
63
- For the code — which file owns what, and why — read [CLAUDE.md](../CLAUDE.md).
68
+ 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,236 @@
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; under `## Always` the ending rule, backchannel, interruption and a short delegation policy; profile and preferences with the note listing | Listen, speak, backchannel, handle interruptions, hand everything but conversation to the backend |
16
+ | Responses backend | `thursday.prompt`: who Thursday is, memory with ids, bot roster, threads and what bots can reach, this computer, what to return, earlier calls with their jobs; tool schemas | Recall, update and tidy memory, run short commands, ask before handing work over, 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 holds conversation and
28
+ memory only. Right under the identity, `## Always` groups what holds on every turn: the ending
29
+ rule (the only line marked `IMPORTANT`), the guide's starter backchannel and interruption
30
+ policies, and under the guide's `Delegation policy` label three lines — hand everything but
31
+ greetings, small talk and a brief clarification to the backend; hand over whatever the user says
32
+ about themselves, their people, their plans or how they want things done as they say it, unless
33
+ it is already written in the prompt; answer from what the backend returns without guessing while
34
+ waiting. Live decides by itself whether to delegate, so the rule stays even this short. It says
35
+ nothing else about how to speak; it sees no tool schema and no tool name but `end_call`, in the
36
+ ending rule. The backend prompt holds the work: memory (merging a fact that repeats or changes one
37
+ already kept, and tidying with the user past the limits), background work and threads, this
38
+ computer, what to return, and the earlier calls. Before handing work to a bot it returns one question — which bot, a new thread or
39
+ one already open — unless the user already said or left it to Thursday.
40
+
41
+ ## Settings and upgrades
42
+
43
+ Voice uses the fixed `gpt-live-1` model. Settings › Thursday exposes a voice and
44
+ additional voice instructions; for the backend, a model,
45
+ optional reasoning effort, web search, and additional backend instructions. Both
46
+ instruction fields add to the app's prompts and never replace them. The model list
47
+ shows recent models; an older or custom ID can be typed and saved. Live accepts any
48
+ reasoning settings when the call opens and fails the backend's first response when the
49
+ model does not take one, so the server asks the token-count endpoint first
50
+ (`acceptedReasoning`), once per model and effort. A setting refused by name, the effort or
51
+ the summary, is dropped and not shown; a refused model or key still reaches the user when the
52
+ call opens. Auto reasoning sends no effort.
53
+ Web search adds the `web_search` tool only when switched on. Changes apply from the
54
+ next call.
55
+
56
+ Settings stay in the browser under the existing `thursday.settings` key, beside wake
57
+ word, shortcut, captions and call-back (`thursday.store`). `migrateLiveSettings`
58
+ upgrades stored values: an OpenAI voice and backend model carry over, a Grok voice is
59
+ retired without touching historical calls or xAI text and media keys, and the old
60
+ shared instruction is copied into both new instruction fields. Each field recovers on
61
+ its own, so one malformed value falls back to its default and leaves the rest.
62
+
63
+ Every call is kept on this machine. Live transcription needs no separate model or
64
+ request, so there is nothing to switch off to save cost. Keep `store: false` in the
65
+ provider request: local history is distinct from OpenAI session recording and fork
66
+ storage.
67
+
68
+ ## Connection and opening
69
+
70
+ 1. In the user's gesture, before anything awaits, prepare playback. Then request
71
+ microphone access and gather WebRTC ICE.
72
+ 2. Send the SDP offer and the parsed settings to `openCallAction`. The browser sends
73
+ settings only; the server reads the key.
74
+ 3. On the server, assemble both prompts and the current tool manifest. Create the
75
+ Live session with the fixed voice model, the chosen voice, voice instructions and
76
+ `delegation.responses` backend settings. No `input`: earlier calls are the backend's to read.
77
+ Insert the call row only after the provider accepts, so a refusal leaves no open row.
78
+ 4. Apply the SDP answer and wait for `session.started`. Do not send Realtime startup
79
+ configuration, audio commits, or a voice `response.create`.
80
+ 5. Send the opening as `session.instructions.append`, so she speaks first: a first call
81
+ (no profile facts) greets the user and asks what to call them, and any other call opens
82
+ with a short greeting.
83
+ Updates that arrived while connecting follow once she has voiced the opening.
84
+ For work that changed after the last call ended (a call tells what came up during it),
85
+ the page rings instead of opening a line (call-back): the user answers it like any
86
+ call, declines it, or lets it ring out after `CALL_BACK.ringMs`. An answered ring opens
87
+ with the fact that
88
+ she placed it, ahead of every other opening, and the first open work goes in as soon
89
+ as she has voiced that, without waiting for a quiet line: why she called is the first
90
+ thing asked. The opening names no bot text; the work itself follows as commentary.
91
+
92
+ A hang-up during startup invalidates that attempt, so a connection that finishes
93
+ later is closed rather than taking over the screen. Do not change machine trust,
94
+ certificate, or proxy configuration to hide connection errors.
95
+
96
+ ## Tools and background updates
97
+
98
+ Live speech and backend work have independent lifecycles. Unwrap `response.event`
99
+ and associate its delegation with the response ID from `response.created`. Collect
100
+ complete function calls from `response.output_item.done`, deduplicate by call ID, and
101
+ run existing server handlers through the tool-call route. Terminal response snapshots
102
+ intentionally omit output items. Submit every function output with
103
+ `response.item.create`, then explicitly continue with one `response.create`. That
104
+ command continues backend work; it does not grant permission for Live to speak. A
105
+ response that ends incomplete after asking for tools is still continued once its outputs
106
+ are in, or the backend turn never finishes; a failed or cancelled response, or a second
107
+ incomplete in a row, only warns. A function call the output cap cuts off arrives as an
108
+ item with status `incomplete` and fragment arguments, and Live ends that handoff with a
109
+ top-level `error` instead of a terminal event: the call is not run and its response
110
+ counts as finished, though calls it completed before the cut still have their results
111
+ continued once. The backend is asked for `reasoning.summary: "auto"` unless the
112
+ effort is `none`. Each finished summary part (nested `response.reasoning_summary_text.done`,
113
+ only while the model reasons) is stored with its call in `call_thought` to look into
114
+ later; while the backend has the turn, the activity line shows the bold title of the latest
115
+ one, and nothing reads it back into a prompt. Tools are sent without `strict`, so each schema that allows it is
116
+ decoded to the schema; `strict: false` would let a model write arguments that are not
117
+ JSON, and `strict: true` is refused while any schema has optional fields. Live has no
118
+ `response.cancel`.
119
+
120
+ Long work enters the existing bot runner and returns a thread receipt immediately.
121
+ Background questions and results follow the existing durable relay queue. A voice
122
+ interruption never cancels a thread by itself. Route an explicit cancellation or
123
+ correction to the owning thread and report its actual outcome.
124
+
125
+ | Update | Live event |
126
+ | --- | --- |
127
+ | Opening, idle goodbye, other trusted behavior | `session.instructions.append` |
128
+ | Screen actions the voice should know but need not say | `session.thinking.append` |
129
+ | A bot's result or question to convey | `session.commentary.append` |
130
+
131
+ Bot output is never sent as instructions. Each append carries a required
132
+ `delegation_id`, `null` for application updates in Responses mode; a response ID is
133
+ not a client delegation ID. Appends are serialized and matched to their
134
+ acknowledgement by `client_event_id`. An update longer than one append is split at
135
+ word boundaries under 480 UTF-8 bytes, which keeps within the 500-token limit for any
136
+ script, and sent chunk by chunk. A rejected or unacknowledged chunk drops the rest of
137
+ its update, warns, and is never replayed. An acknowledgement is not proof of speech.
138
+
139
+ Live never speaks unprompted, so what waits on the user reaches them only when the page puts
140
+ it in. The relay clock (`useThursday` `relayOpenWork`) reads the inbox once a second and sends
141
+ open work only when neither side's words have been transcribed for `CALL_RELAY.quietMs` and
142
+ no backend work or tool is running: questions not answered, jobs stopped or finished and not
143
+ yet seen, and progress from jobs still running. Up to `CALL_RELAY.perTurn` items of one
144
+ kind go in one commentary append, most pressing first, so an ending never shares an append with
145
+ a question. The activity line carries the update from the moment
146
+ it goes out until her voice has finished it, and nothing else goes in until her voice has started
147
+ and stopped (at most `CALL_RELAY.readMs`). An item is handled when it is answered, marked seen
148
+ by the backend's `thread` `seen` once the user has been told enough, or opened on screen — the
149
+ backend's `thread` `open` opens it in the call screen's room (a `showThread` event). Each item
150
+ goes in once a call (`told`, in memory), and it stays in the inbox and on screen until handled.
151
+ One her voice carried stays out of later calls too while the page is open; one it did not (Live
152
+ refused it, she never spoke, the call ended first) goes in again on the next call, never in a
153
+ loop on this one. The key carries the job's last change, so a job that resumes and asks or ends
154
+ again is a new item, and a reload puts what is still open in once more. Nothing goes in while
155
+ the call is ending or a goodbye has been asked for. A relay is facts only, with no note
156
+ ahead of it.
157
+
158
+ A relay names the bot and the thread and, for a question, where its answer goes (thread,
159
+ recipient, `replyTo`). The backend reads relays in its conversation and routes the user's
160
+ answer from those facts, so a relay carries no instructions. Relay rows are accepted
161
+ (`acceptThreadRelaysAction`) once Live acknowledges the append; an ending also covers its
162
+ job's progress rows. Being put to her does not mark a result seen.
163
+
164
+ ## Transcript and screen
165
+
166
+ Input and output transcript events contain `delta`, `start_ms`, and `end_ms`. They
167
+ have no authoritative completed-turn event. The session folds fragments into
168
+ revisable display groups by speaker and time, deduplicates them by event ID, and
169
+ checkpoints changed groups every `LIVE_CALL.transcriptSaveMs` with their exact
170
+ fragments. A late fragment revises its group, which is saved again. Never derive
171
+ actions or cancellations from the grouping. Backend text is not a transcript of spoken
172
+ audio and never becomes a caption.
173
+
174
+ `call_message.fragments` keeps the original fragments beside each saved group; a
175
+ revision replaces them and keeps the group's `seq`. Rows written before Live have no
176
+ fragments and remain readable.
177
+
178
+ Track playback and backend work independently, from her audio level and backend events.
179
+ The idle clock rewinds on new transcribed words, her voice and backend work, not on
180
+ microphone level alone, so a noisy room does not hold a call open, and not on an update she
181
+ voices on her own, so waiting results do not either. A sound the transcript writes in
182
+ brackets (`[sigh]`) is not words. After `CALL_IDLE.hangUpMs` the page hangs up without asking
183
+ for a goodbye, which would leave the ending to the model.
184
+
185
+ ## Closing and recovery
186
+
187
+ The user wanting the call to end, however they say it, sets everything else aside: the
188
+ voice answers yes and hands it to the backend at once, and the backend runs `end_call`
189
+ without deliberating. The ending rule names `end_call` in the voice prompt too, the one tool
190
+ name it holds: without it, ending read as something to say rather than do.
191
+ The page does not close on `end_call` itself: it waits until her voice has been quiet
192
+ for `CALL_END.quietMs`, or `CALL_END.unsaidMs` when nothing was said, never past
193
+ `CALL_END.maxMs`. `end_call` and `emote` (a word of up to eight characters on her face,
194
+ offered only while the face is the ascii orb) are answered by the page, not the tool-call
195
+ route. A call the user did not end — quiet, `end_call`, Live closing the session, a dropped
196
+ connection — leaves the reason in the idle hint until the next call.
197
+
198
+ Stop accepting new work, send `session.close`, and keep the connection while waiting
199
+ for `session.closed`. Its reason and billed seconds are recorded on the call row
200
+ (`ended_reason`, `seconds`) next to the backend model. Without a confirmation within
201
+ `LIVE_CALL.closeMs`, the call warns and the seconds stay unknown. The screen shows
202
+ Ending until cleanup finishes and blocks a second call during that interval.
203
+ Background jobs follow existing presence rules and survive the call.
204
+
205
+ A new connection is a new session. Seed it with relevant saved history and current
206
+ thread state. Reconcile completed operations and suppress stale results; never replay
207
+ tools merely because the previous connection disappeared. Live charges active session
208
+ time, including silence and backend waits; backend tokens are separate.
209
+
210
+ ## Validation
211
+
212
+ `pnpm test:live` covers tool continuation, including the one continuation after an
213
+ incomplete response, fragment grouping and late revision, closing with and without
214
+ confirmation, activity while speaking and working, append ordering, acknowledgement,
215
+ rejection and chunking, the provider request with optional reasoning and web search,
216
+ settings migration, both assembled call prompts and the identity they share, and fragment
217
+ persistence against a migrated database. Also run typecheck, lint, build and
218
+ `pnpm test:bot`, and read both assembled prompts.
219
+
220
+ Inspect settings on desktop and narrow screens. Real-call checks cover a first
221
+ greeting, overlapping speech, a short tool call, a bot
222
+ question answered during other work, correction, cancellation, a late result,
223
+ reconnect, and the recorded seconds. Count durable tool calls and thread
224
+ messages as well as listening to the actual audio.
225
+
226
+ ## Official references
227
+
228
+ - [Getting started](https://developers.openai.com/api/docs/guides/live)
229
+ - [Voice prompting](https://developers.openai.com/api/docs/guides/live-prompting)
230
+ - [Sessions, transcripts, and closure](https://developers.openai.com/api/docs/guides/live-conversations)
231
+ - [Responses delegation and updates](https://developers.openai.com/api/docs/guides/live-delegation)
232
+ - [Migration](https://developers.openai.com/api/docs/guides/live-migration)
233
+ - [Partner integrations](https://developers.openai.com/api/docs/guides/live-partner-integrations)
234
+
235
+ Thursday uses direct browser WebRTC. LiveKit, Pipecat, and telephone integrations
236
+ 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
+ }