thursday-agent 0.2.0 → 0.3.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 (535) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +5 -2
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +5 -5
  5. package/.next/routes-manifest.json +24 -6
  6. package/.next/server/app/_global-error/page.js +2 -2
  7. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/_global-error.html +1 -1
  10. package/.next/server/app/_global-error.rsc +2 -2
  11. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  13. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/server/app/_not-found/page.js +2 -2
  15. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  16. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  17. package/.next/server/app/_not-found.html +1 -1
  18. package/.next/server/app/_not-found.rsc +14 -14
  19. package/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +12 -12
  21. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  22. package/.next/server/app/api/artifact/route.js +3 -3
  23. package/.next/server/app/api/artifact/route.js.nft.json +1 -1
  24. package/.next/server/app/api/bot/memory/files/route/app-paths-manifest.json +3 -0
  25. package/.next/server/app/api/bot/memory/files/route.js +10 -0
  26. package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -0
  27. package/.next/server/app/api/bot/memory/files/route_client-reference-manifest.js +3 -0
  28. package/.next/server/app/api/bot/memory/route/app-paths-manifest.json +3 -0
  29. package/.next/server/app/api/bot/memory/route.js +14 -0
  30. package/.next/server/app/api/bot/{notes → memory}/route.js.nft.json +1 -1
  31. package/.next/server/app/api/bot/memory/route_client-reference-manifest.js +3 -0
  32. package/.next/server/app/api/bot/route.js +6 -6
  33. package/.next/server/app/api/bot/route.js.nft.json +1 -1
  34. package/.next/server/app/api/bot/task/[id]/route.js +8 -8
  35. package/.next/server/app/api/bot/task/[id]/route.js.nft.json +1 -1
  36. package/.next/server/app/api/bot/task/route.js +8 -8
  37. package/.next/server/app/api/bot/task/route.js.nft.json +1 -1
  38. package/.next/server/app/api/config/route.js +5 -5
  39. package/.next/server/app/api/config/route.js.nft.json +1 -1
  40. package/.next/server/app/api/events/route.js +4 -5
  41. package/.next/server/app/api/events/route.js.nft.json +1 -1
  42. package/.next/server/app/api/file/[...path]/route.js +3 -3
  43. package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
  44. package/.next/server/app/api/llm-model/catalog/route.js +9 -8
  45. package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
  46. package/.next/server/app/api/llm-model/credits/route/app-paths-manifest.json +3 -0
  47. package/.next/server/app/api/llm-model/credits/route/build-manifest.json +12 -0
  48. package/.next/server/app/api/llm-model/credits/route/server-reference-manifest.json +4 -0
  49. package/.next/server/app/api/llm-model/credits/route.js +16 -0
  50. package/.next/server/app/api/llm-model/credits/route.js.map +5 -0
  51. package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -0
  52. package/.next/server/app/api/llm-model/credits/route_client-reference-manifest.js +3 -0
  53. package/.next/server/app/api/llm-model/route.js +10 -8
  54. package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
  55. package/.next/server/app/api/llm-model/subscription/route/app-paths-manifest.json +3 -0
  56. package/.next/server/app/api/llm-model/subscription/route/build-manifest.json +12 -0
  57. package/.next/server/app/api/llm-model/subscription/route/server-reference-manifest.json +4 -0
  58. package/.next/server/app/api/llm-model/subscription/route.js +15 -0
  59. package/.next/server/app/api/llm-model/subscription/route.js.map +5 -0
  60. package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -0
  61. package/.next/server/app/api/llm-model/subscription/route_client-reference-manifest.js +3 -0
  62. package/.next/server/app/api/mcp/[name]/route.js +4 -4
  63. package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
  64. package/.next/server/app/api/mcp/oauth/callback/route.js +5 -5
  65. package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
  66. package/.next/server/app/api/mcp/route.js +4 -4
  67. package/.next/server/app/api/mcp/route.js.nft.json +1 -1
  68. package/.next/server/app/api/mcp/tools/route.js +4 -4
  69. package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
  70. package/.next/server/app/api/memory/edit/route/app-paths-manifest.json +3 -0
  71. package/.next/server/app/api/memory/edit/route/build-manifest.json +12 -0
  72. package/.next/server/app/api/memory/edit/route/server-reference-manifest.json +4 -0
  73. package/.next/server/app/api/memory/edit/route.js +24 -0
  74. package/.next/server/app/api/memory/edit/route.js.map +5 -0
  75. package/.next/server/app/api/memory/edit/route.js.nft.json +1 -0
  76. package/.next/server/app/api/memory/{tidy → edit}/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/memory/route.js +6 -7
  78. package/.next/server/app/api/memory/route.js.nft.json +1 -1
  79. package/.next/server/app/api/skills/[source]/[name]/route.js +3 -3
  80. package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
  81. package/.next/server/app/api/skills/route.js +3 -3
  82. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  83. package/.next/server/app/api/thursday/call/route.js +9 -7
  84. package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
  85. package/.next/server/app/api/thursday/skills/route.js +9 -7
  86. package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
  87. package/.next/server/app/api/thursday/tool-call/route.js +17 -15
  88. package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
  89. package/.next/server/app/api/workspace/route.js +4 -5
  90. package/.next/server/app/api/workspace/route.js.nft.json +1 -1
  91. package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +1 -1
  92. package/.next/server/app/artifact/[...path]/page.js +5 -6
  93. package/.next/server/app/artifact/[...path]/page.js.nft.json +1 -1
  94. package/.next/server/app/artifact/[...path]/page_client-reference-manifest.js +1 -1
  95. package/.next/server/app/favicon.ico/route.js +3 -4
  96. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  97. package/.next/server/app/favicon.ico.body +0 -0
  98. package/.next/server/app/page/server-reference-manifest.json +57 -90
  99. package/.next/server/app/page.js +10 -10
  100. package/.next/server/app/page.js.nft.json +1 -1
  101. package/.next/server/app/page_client-reference-manifest.js +1 -1
  102. package/.next/server/app-paths-manifest.json +5 -2
  103. package/.next/server/chunks/[externals]__0dzuk6_._.js +3 -0
  104. package/.next/server/chunks/[root-of-the-server]__01dkp4a._.js +3 -0
  105. package/.next/server/chunks/[root-of-the-server]__02va5wz._.js +1 -1
  106. package/.next/server/chunks/[root-of-the-server]__02xjoto._.js +3 -0
  107. package/.next/server/chunks/[root-of-the-server]__04q--0f._.js +8 -0
  108. package/.next/server/chunks/[root-of-the-server]__0bl-e63._.js +3 -0
  109. package/.next/server/chunks/[root-of-the-server]__0ce8nf8._.js +5 -0
  110. package/.next/server/chunks/[root-of-the-server]__0ffbg85._.js +3 -0
  111. package/.next/server/chunks/[root-of-the-server]__0j7z0r3._.js +12 -0
  112. package/.next/server/chunks/[root-of-the-server]__0jq4ohy._.js +8 -0
  113. package/.next/server/chunks/[root-of-the-server]__0ls6_8y._.js +8 -0
  114. package/.next/server/chunks/[root-of-the-server]__0ncs9uu._.js +3 -0
  115. package/.next/server/chunks/[root-of-the-server]__0pa2n68._.js +3 -0
  116. package/.next/server/chunks/[root-of-the-server]__0q0vvt2._.js +5 -0
  117. package/.next/server/chunks/[root-of-the-server]__1-ga0kh._.js +5 -0
  118. package/.next/server/chunks/[root-of-the-server]__11n256_._.js +5 -0
  119. package/.next/server/chunks/[root-of-the-server]__12cabg9._.js +3 -0
  120. package/.next/server/chunks/[root-of-the-server]__1339jnv._.js +8 -0
  121. package/.next/server/chunks/[root-of-the-server]__15bjnu5._.js +5 -0
  122. package/.next/server/chunks/[root-of-the-server]__18_teo8._.js +8 -0
  123. package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +5 -0
  124. package/.next/server/chunks/[root-of-the-server]__1anc1p9._.js +3 -0
  125. package/.next/server/chunks/[root-of-the-server]__1ccon1w._.js +5 -5
  126. package/.next/server/chunks/[root-of-the-server]__1fizn31._.js +3 -0
  127. package/.next/server/chunks/[root-of-the-server]__1llj3-b._.js +3 -0
  128. package/.next/server/chunks/[root-of-the-server]__1orn-5b._.js +11 -0
  129. package/.next/server/chunks/[root-of-the-server]__1p8m3f4._.js +3 -0
  130. package/.next/server/chunks/[root-of-the-server]__1wa1k7r._.js +8 -0
  131. package/.next/server/chunks/_0-73of8._.js +5 -5
  132. package/.next/server/chunks/_0-fjql4._.js +26 -0
  133. package/.next/server/chunks/_00xh_q0._.js +27 -0
  134. package/.next/server/chunks/{_0pppbb5._.js → _03kp0jp._.js} +163 -36
  135. package/.next/server/chunks/_051qh8u._.js +3 -0
  136. package/.next/server/chunks/{node_modules_next_04q-o58._.js → _05dla15._.js} +2 -2
  137. package/.next/server/chunks/_05h2cii._.js +1 -1
  138. package/.next/server/chunks/_0c9j6rb._.js +49 -0
  139. package/.next/server/chunks/_0fzqt2y._.js +130 -0
  140. package/.next/server/chunks/{_0vnutv9._.js → _0ioz3nd._.js} +1 -1
  141. package/.next/server/chunks/_0iwfby5._.js +3 -0
  142. package/.next/server/chunks/_0mecv0f._.js +26 -0
  143. package/.next/server/chunks/_0mh8j4m._.js +3 -0
  144. package/.next/server/chunks/_0n74zsf._.js +4 -4
  145. package/.next/server/chunks/_0obojvv._.js +3 -0
  146. package/.next/server/chunks/_0recufk._.js +49 -0
  147. package/.next/server/chunks/_0rnf-6n._.js +4 -4
  148. package/.next/server/chunks/_0sb7tlz._.js +3 -0
  149. package/.next/server/chunks/_0u10wmw._.js +5 -5
  150. package/.next/server/chunks/_0u4aiy2._.js +3 -0
  151. package/.next/server/chunks/_0wp4le3._.js +1 -1
  152. package/.next/server/chunks/_0y5fg-x._.js +1 -1
  153. package/.next/server/chunks/_1230wbx._.js +10 -0
  154. package/.next/server/chunks/_12nheja._.js +3 -0
  155. package/.next/server/chunks/_13510xh._.js +3 -0
  156. package/.next/server/chunks/_15hq89o._.js +1 -1
  157. package/.next/server/chunks/_17l5ygt._.js +49 -0
  158. package/.next/server/chunks/_18-1wcc._.js +5 -5
  159. package/.next/server/chunks/_1_5mnq4._.js +4 -4
  160. package/.next/server/chunks/_1_9mjx-._.js +3 -0
  161. package/.next/server/chunks/_1d0j961._.js +6 -0
  162. package/.next/server/chunks/_1d5zmy8._.js +1 -1
  163. package/.next/server/chunks/_1drgfx4._.js +4 -4
  164. package/.next/server/chunks/_1f46eie._.js +3 -0
  165. package/.next/server/chunks/_1h5_8sk._.js +3 -0
  166. package/.next/server/chunks/_1hdnxb7._.js +3 -0
  167. package/.next/server/chunks/_1j8k_j5._.js +3 -0
  168. package/.next/server/chunks/_1krd9rf._.js +3 -0
  169. package/.next/server/chunks/_1nc0eui._.js +11 -0
  170. package/.next/server/chunks/_1nula3v._.js +3 -0
  171. package/.next/server/chunks/_1pf4qe-._.js +3 -0
  172. package/.next/server/chunks/_1php4eq._.js +1 -1
  173. package/.next/server/chunks/_1qxheoa._.js +3 -0
  174. package/.next/server/chunks/_1x6kd1r._.js +3 -0
  175. package/.next/server/chunks/_1yuv4vp._.js +1 -1
  176. package/.next/server/chunks/_1zjrdag._.js +3 -0
  177. package/.next/server/chunks/_next-internal_server_app_api_bot_memory_files_route_actions_1_xd_8f.js +3 -0
  178. package/.next/server/chunks/_next-internal_server_app_api_bot_memory_route_actions_1a8xfr7.js +3 -0
  179. package/.next/server/chunks/_next-internal_server_app_api_llm-model_credits_route_actions_0v424pb.js +3 -0
  180. package/.next/server/chunks/_next-internal_server_app_api_llm-model_subscription_route_actions_0-udcm5.js +3 -0
  181. package/.next/server/chunks/_next-internal_server_app_api_memory_edit_route_actions_02sfnmr.js +3 -0
  182. package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
  183. package/.next/server/chunks/features_0rpfxbk._.js +3 -0
  184. package/.next/server/chunks/features_1qf3cei._.js +3 -0
  185. package/.next/server/chunks/features_bot_0zt92oh._.js +3 -0
  186. package/.next/server/chunks/features_bot_bot_query_ts_12mgkl2._.js +3 -0
  187. package/.next/server/chunks/features_memory_1uqvksn._.js +6 -0
  188. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0a1rd09._.js → node_modules_consola_dist_chunks_prompt_mjs_0i7cvml._.js} +1 -1
  189. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_06067w6._.js → node_modules_consola_dist_chunks_prompt_mjs_0icqaqw._.js} +1 -1
  190. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_096ais_._.js → node_modules_consola_dist_chunks_prompt_mjs_0r28-sm._.js} +1 -1
  191. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_02s3hjt._.js → node_modules_consola_dist_chunks_prompt_mjs_0v_7drq._.js} +1 -1
  192. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1xoq2rl._.js +3 -0
  193. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0tvkfgh._.js → node_modules_consola_dist_chunks_prompt_mjs_1y49572._.js} +1 -1
  194. package/.next/server/chunks/ssr/[root-of-the-server]__09q9med._.js +1 -1
  195. package/.next/server/chunks/ssr/{[root-of-the-server]__1qfqvmg._.js → [root-of-the-server]__0_69wqr._.js} +2 -2
  196. package/.next/server/chunks/ssr/[root-of-the-server]__0hg5gib._.js +1 -1
  197. package/.next/server/chunks/ssr/[root-of-the-server]__0i8ie7f._.js +3 -0
  198. package/.next/server/chunks/ssr/{[root-of-the-server]__0jsmmb-._.js → [root-of-the-server]__0mz33a7._.js} +1 -1
  199. package/.next/server/chunks/ssr/[root-of-the-server]__0tbkdlx._.js +3 -0
  200. package/.next/server/chunks/ssr/[root-of-the-server]__0vnmv-s._.js +3 -0
  201. package/.next/server/chunks/ssr/{[root-of-the-server]__0f6s48x._.js → [root-of-the-server]__0xpcv9w._.js} +3 -3
  202. package/.next/server/chunks/ssr/[root-of-the-server]__0xtssj3._.js +1 -1
  203. package/.next/server/chunks/ssr/[root-of-the-server]__0zkv7z_._.js +3 -0
  204. package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +57 -0
  205. package/.next/server/chunks/ssr/[root-of-the-server]__15_uhip._.js +3 -0
  206. package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
  207. package/.next/server/chunks/ssr/{[root-of-the-server]__0m1b5ky._.js → [root-of-the-server]__1cyjywu._.js} +1 -1
  208. package/.next/server/chunks/ssr/[root-of-the-server]__1eh7hid._.js +3 -0
  209. package/.next/server/chunks/ssr/[root-of-the-server]__1gtlw6v._.js +43 -0
  210. package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +1 -1
  211. package/.next/server/chunks/ssr/[root-of-the-server]__1ox7hbk._.js +4 -0
  212. package/.next/server/chunks/ssr/[root-of-the-server]__1pduf5n._.js +3 -0
  213. package/.next/server/chunks/ssr/{_1mznrxk._.js → _001_ms1._.js} +3 -3
  214. package/.next/server/chunks/ssr/_01_6m32._.js +3 -0
  215. package/.next/server/chunks/ssr/_01n3o0m._.js +3 -0
  216. package/.next/server/chunks/ssr/_07uchnc._.js +3 -0
  217. package/.next/server/chunks/ssr/_0ap2fzn._.js +3 -0
  218. package/.next/server/chunks/ssr/_0c-ql2m._.js +3 -0
  219. package/.next/server/chunks/ssr/_0h42fze._.js +3 -0
  220. package/.next/server/chunks/ssr/_0h7zdni._.js +1 -1
  221. package/.next/server/chunks/ssr/_0i_6q1w._.js +41 -0
  222. package/.next/server/chunks/ssr/_0kbkmar._.js +3 -0
  223. package/.next/server/chunks/ssr/{_077-g6s._.js → _0mb8zc8._.js} +3 -3
  224. package/.next/server/chunks/ssr/_0mo2w06._.js +3 -0
  225. package/.next/server/chunks/ssr/{_13punpm._.js → _0q0zan6._.js} +2 -2
  226. package/.next/server/chunks/ssr/{_040sk32._.js → _0u2jv_x._.js} +76 -82
  227. package/.next/server/chunks/ssr/_0y0tiht._.js +4 -0
  228. package/.next/server/chunks/ssr/_0zhoc3r._.js +3 -0
  229. package/.next/server/chunks/ssr/_1-teee5._.js +3 -3
  230. package/.next/server/chunks/ssr/_13fke0x._.js +3 -0
  231. package/.next/server/chunks/ssr/{_1lip4th._.js → _13z3f85._.js} +2 -2
  232. package/.next/server/chunks/ssr/_14_lw10._.js +3 -0
  233. package/.next/server/chunks/ssr/_15j2_8f._.js +3 -0
  234. package/.next/server/chunks/ssr/{_09ja_w1._.js → _1eoqg_g._.js} +2 -2
  235. package/.next/server/chunks/ssr/_1sji22n._.js +3 -0
  236. package/.next/server/chunks/ssr/_1spzm8z._.js +3 -0
  237. package/.next/server/chunks/ssr/{_0x_nu5e._.js → _1vi_uo7._.js} +2 -2
  238. package/.next/server/chunks/ssr/_1vyd1ji._.js +1 -1
  239. package/.next/server/chunks/ssr/{_1m3bsfr._.js → _1xvgn77._.js} +2 -2
  240. package/.next/server/chunks/ssr/_20kd_n0._.js +42 -0
  241. package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +3 -0
  242. package/.next/server/chunks/ssr/features_config_components_config-setting_tsx_0xfwqdg._.js +1 -1
  243. package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
  244. package/.next/server/chunks/ssr/lib_date-like_ts_02is0pw._.js +3 -0
  245. package/.next/server/chunks/ssr/{node_modules_18_dk7_._.js → node_modules_063xwpp._.js} +1 -1
  246. package/.next/server/chunks/ssr/{node_modules_01qnv-a._.js → node_modules_0bvraul._.js} +1 -1
  247. package/.next/server/chunks/ssr/{node_modules_0n1kj4p._.js → node_modules_0eu1va6._.js} +1 -1
  248. package/.next/server/chunks/ssr/{node_modules_0kl7-tn._.js → node_modules_0h50b8n._.js} +1 -1
  249. package/.next/server/chunks/ssr/{node_modules_0_n241r._.js → node_modules_0h5hnr1._.js} +1 -1
  250. package/.next/server/chunks/ssr/{node_modules_0lrjk5t._.js → node_modules_0h7u60n._.js} +1 -1
  251. package/.next/server/chunks/ssr/{node_modules_0ndvxub._.js → node_modules_0lm7_vm._.js} +1 -1
  252. package/.next/server/chunks/ssr/{node_modules_13r44jq._.js → node_modules_0mwym0g._.js} +1 -1
  253. package/.next/server/chunks/ssr/{node_modules_17lrt3y._.js → node_modules_0rjg6t1._.js} +1 -1
  254. package/.next/server/chunks/ssr/node_modules_0x3-ply._.js +3 -0
  255. package/.next/server/chunks/ssr/{node_modules_004qlr4._.js → node_modules_0y_cded._.js} +1 -1
  256. package/.next/server/chunks/ssr/{node_modules_0kxz4gt._.js → node_modules_0z5tsu8._.js} +1 -1
  257. package/.next/server/chunks/ssr/{node_modules_0iz1rzd._.js → node_modules_0zp9r92._.js} +1 -1
  258. package/.next/server/chunks/ssr/{node_modules_19dp7ko._.js → node_modules_1-hc6uv._.js} +1 -1
  259. package/.next/server/chunks/ssr/{node_modules_1q0p85z._.js → node_modules_113tz0l._.js} +1 -1
  260. package/.next/server/chunks/ssr/{node_modules_1toafc-._.js → node_modules_124bue5._.js} +1 -1
  261. package/.next/server/chunks/ssr/node_modules_17bwo43._.js +55 -0
  262. package/.next/server/chunks/ssr/{node_modules_08d8bke._.js → node_modules_1_n3ztw._.js} +1 -1
  263. package/.next/server/chunks/ssr/{node_modules_1dwguw_._.js → node_modules_1bc7gu8._.js} +1 -1
  264. package/.next/server/chunks/ssr/{node_modules_20yebtj._.js → node_modules_1bgb6-f._.js} +1 -1
  265. package/.next/server/chunks/ssr/{node_modules_1n5ygqe._.js → node_modules_1h4a4pp._.js} +1 -1
  266. package/.next/server/chunks/ssr/{node_modules_04n7mjs._.js → node_modules_1i7u1ia._.js} +1 -1
  267. package/.next/server/chunks/ssr/{node_modules_1hn8z1f._.js → node_modules_1juq3hs._.js} +1 -1
  268. package/.next/server/chunks/ssr/{node_modules_1xyd7ov._.js → node_modules_1l0qtdu._.js} +1 -1
  269. package/.next/server/chunks/ssr/{node_modules_0m93zeg._.js → node_modules_1t9cyee._.js} +1 -1
  270. package/.next/server/chunks/ssr/{node_modules_09xhur7._.js → node_modules_1uuj9x1._.js} +1 -1
  271. package/.next/server/chunks/ssr/{node_modules_1hd-5tv._.js → node_modules_1vqb6po._.js} +1 -1
  272. package/.next/server/chunks/ssr/{node_modules_1zu988w._.js → node_modules_1xx28h1._.js} +1 -1
  273. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0m9a4y0._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0d3skpl._.js} +1 -1
  274. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_13w_wy9._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0i44kk5._.js} +1 -1
  275. package/.next/server/chunks/ssr/node_modules_@vercel_oidc_dist_0qe30a_._.js +3 -0
  276. package/.next/server/chunks/ssr/{node_modules_next_dist_0w6mzq5._.js → node_modules_next_dist_0drixxt._.js} +4 -4
  277. package/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +2 -2
  278. package/.next/server/instrumentation.js +1 -1
  279. package/.next/server/middleware-build-manifest.js +3 -3
  280. package/.next/server/pages/404.html +1 -1
  281. package/.next/server/pages/500.html +1 -1
  282. package/.next/server/server-reference-manifest.js +1 -1
  283. package/.next/server/server-reference-manifest.json +58 -91
  284. package/.next/static/chunks/{31ttnjt6g35a0.js → 0ev4hyghq0mbb.js} +1 -1
  285. package/.next/static/chunks/0r5qcctujhxli.js +1 -0
  286. package/.next/static/chunks/0tmgrnlje14-s.js +3 -0
  287. package/.next/static/chunks/0x79tx04dxbpp.js +1 -0
  288. package/.next/static/chunks/0xzgvc0fkdb6t.js +1 -0
  289. package/.next/static/chunks/10teww7wt-f6h.js +1 -0
  290. package/.next/static/chunks/14hgtsjg-kael.css +1 -0
  291. package/.next/static/chunks/17donp69y4do7.js +40 -0
  292. package/.next/static/chunks/{3_h9txt3tq8t8.js → 1dkjg87pxk0n9.js} +1 -1
  293. package/.next/static/chunks/1ekc7ul556kbl.js +1 -0
  294. package/.next/static/chunks/{3ard_noqapnw1.js → 1grhjo7a5a0_-.js} +1 -1
  295. package/.next/static/chunks/1kq8h8wi_e0bc.js +53 -0
  296. package/.next/static/chunks/1okqiww3pnwka.js +1 -0
  297. package/.next/static/chunks/26-pr2c9ro222.js +1 -0
  298. package/.next/static/chunks/{18vhba44l1fc9.js → 280t0_e99i276.js} +1 -1
  299. package/.next/static/chunks/28cizcdaabd4h.js +1 -0
  300. package/.next/static/chunks/2a0k6jlq0_v1u.js +2 -0
  301. package/.next/static/chunks/2fzs9fm8yarvq.js +1 -0
  302. package/.next/static/chunks/2h0sd2vumhb15.js +1 -0
  303. package/.next/static/chunks/2hw2f6zmt7fmt.js +1 -0
  304. package/.next/static/chunks/2t4vhi3m8ahya.js +1 -0
  305. package/.next/static/chunks/2tigdtz3dpcy8.js +1 -0
  306. package/.next/static/chunks/3111pj5wnjgos.js +1 -0
  307. package/.next/static/chunks/{07kl352c-lvcz.js → 3agpgkwaa321p.js} +1 -1
  308. package/.next/static/chunks/3cfi_q6d_wtci.js +1 -0
  309. package/.next/static/chunks/3ok9_x74rip3v.js +1 -0
  310. package/.next/static/chunks/3xk7yqgomx7yq.js +1 -0
  311. package/.next/static/chunks/3xpbkl66ssib5.js +38 -0
  312. package/.next/static/media/favicon.37o1pjldwi2uc.ico +0 -0
  313. package/README.md +6 -4
  314. package/app/api/bot/memory/files/route.ts +14 -0
  315. package/app/api/bot/memory/route.ts +5 -0
  316. package/app/api/events/app-event.ts +3 -5
  317. package/app/api/llm-model/credits/route.ts +11 -0
  318. package/app/api/llm-model/route.ts +6 -1
  319. package/app/api/llm-model/subscription/route.ts +11 -0
  320. package/app/api/memory/edit/route.ts +7 -0
  321. package/app/api/memory/route.ts +21 -0
  322. package/app/api/query-key.ts +19 -4
  323. package/bin/thursday.mjs +3 -0
  324. package/components/ui/shiny-text.tsx +48 -134
  325. package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/migration.sql +24 -34
  326. package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/snapshot.json +71 -145
  327. package/database/migrations/20260911030320_opposite_jack_power/migration.sql +1 -0
  328. package/database/migrations/{20260909063821_bitter_tenebrous → 20260911030320_opposite_jack_power}/snapshot.json +57 -184
  329. package/features/ai/chatgpt.ts +617 -0
  330. package/features/ai/components/chatgpt-sign-in.tsx +66 -0
  331. package/features/ai/components/model-picker.tsx +17 -1
  332. package/features/ai/components/provider-icon.tsx +1 -0
  333. package/features/ai/load-tools.ts +58 -42
  334. package/features/ai/model.schema.ts +232 -34
  335. package/features/ai/model.ts +169 -24
  336. package/features/ai/prompts/bot.prompt.ts +156 -65
  337. package/features/ai/prompts/memory-edit.prompt.ts +33 -0
  338. package/features/ai/prompts/prompt-helper.ts +45 -26
  339. package/features/ai/prompts/thursday.prompt.ts +40 -17
  340. package/features/ai/tools/bot.tool.ts +35 -52
  341. package/features/ai/tools/connected.ts +17 -4
  342. package/features/ai/tools/memory.tool.ts +133 -72
  343. package/features/ai/tools/search.tool.ts +136 -47
  344. package/features/ai/tools/tool-name.ts +2 -5
  345. package/features/ai/tools/workspace.tool.ts +2 -1
  346. package/features/bot/bot.action.ts +8 -18
  347. package/features/bot/bot.memory.ts +89 -0
  348. package/features/bot/bot.query.ts +37 -57
  349. package/features/bot/bot.run.ts +507 -241
  350. package/features/bot/bot.runner.ts +410 -114
  351. package/features/bot/bot.schema.ts +79 -19
  352. package/features/bot/bot.seed.ts +89 -16
  353. package/features/bot/components/bot-mark.tsx +122 -20
  354. package/features/bot/components/bot-room.tsx +159 -130
  355. package/features/bot/components/bot-setting.tsx +790 -402
  356. package/features/bot/components/bot-tool.tsx +2 -6
  357. package/features/bot/components/mark-palette.tsx +54 -0
  358. package/features/bot/components/path-chips.tsx +1 -1
  359. package/features/bot/components/task-badge.tsx +26 -6
  360. package/features/bot/components/task-reply.tsx +22 -33
  361. package/features/bot/components/task-setting.tsx +20 -17
  362. package/features/bot/task.query.ts +215 -28
  363. package/features/bot/task.store.ts +53 -9
  364. package/features/config/components/config-setting.tsx +265 -34
  365. package/features/config/components/models-badge.tsx +42 -0
  366. package/features/config/config.action.ts +12 -0
  367. package/features/config/config.const.ts +38 -2
  368. package/features/connectors/mcp.manager.ts +10 -2
  369. package/features/intro/components/intro.tsx +47 -46
  370. package/features/memory/components/memory-edit.tsx +338 -0
  371. package/features/memory/components/memory-setting.tsx +75 -77
  372. package/features/memory/memory.action.ts +3 -43
  373. package/features/memory/memory.edit.ts +87 -0
  374. package/features/memory/memory.query.ts +24 -42
  375. package/features/memory/memory.schema.ts +29 -106
  376. package/features/settings/components/settings.tsx +2 -0
  377. package/features/settings/settings.alert.ts +3 -1
  378. package/features/thursday/components/ascii-orb.tsx +106 -90
  379. package/features/thursday/components/boot.tsx +7 -0
  380. package/features/thursday/components/call-log.tsx +219 -92
  381. package/features/thursday/components/face.tsx +6 -4
  382. package/features/thursday/components/tab-state.tsx +97 -0
  383. package/features/thursday/components/thursday-mark.tsx +4 -1
  384. package/features/thursday/components/thursday-setting.tsx +17 -47
  385. package/features/thursday/components/thursday.tsx +208 -95
  386. package/features/thursday/thursday.action.ts +12 -17
  387. package/features/thursday/thursday.query.ts +61 -70
  388. package/features/thursday/thursday.schema.ts +20 -7
  389. package/features/thursday/tool-line.ts +85 -11
  390. package/features/thursday/use-thursday.ts +86 -59
  391. package/features/workspace/components/file-view.tsx +4 -2
  392. package/features/workspace/workspace.ts +110 -26
  393. package/lib/limits.ts +1 -1
  394. package/lib/oauth-page.ts +27 -0
  395. package/lib/realtime/openai.ts +2 -2
  396. package/lib/realtime/realtime.protocol.ts +1 -1
  397. package/lib/realtime/realtime.tap.ts +122 -0
  398. package/lib/sandbox.ts +59 -36
  399. package/package.json +1 -1
  400. package/skills/browser/SKILL.md +55 -34
  401. package/.next/server/app/api/bot/notes/route/app-paths-manifest.json +0 -3
  402. package/.next/server/app/api/bot/notes/route.js +0 -14
  403. package/.next/server/app/api/bot/notes/route_client-reference-manifest.js +0 -3
  404. package/.next/server/app/api/memory/tidy/route/app-paths-manifest.json +0 -3
  405. package/.next/server/app/api/memory/tidy/route.js +0 -22
  406. package/.next/server/app/api/memory/tidy/route.js.nft.json +0 -1
  407. package/.next/server/chunks/0d-b_next_dist_server_app-render_after-task-async-storage_external_0-exn7p.js +0 -3
  408. package/.next/server/chunks/[root-of-the-server]__0-npkh_._.js +0 -3
  409. package/.next/server/chunks/[root-of-the-server]__005var5._.js +0 -3
  410. package/.next/server/chunks/[root-of-the-server]__019dx9f._.js +0 -5
  411. package/.next/server/chunks/[root-of-the-server]__02_2sm-._.js +0 -5
  412. package/.next/server/chunks/[root-of-the-server]__04_8spk._.js +0 -3
  413. package/.next/server/chunks/[root-of-the-server]__05luceg._.js +0 -3
  414. package/.next/server/chunks/[root-of-the-server]__06t77t4._.js +0 -11
  415. package/.next/server/chunks/[root-of-the-server]__0bed6hu._.js +0 -8
  416. package/.next/server/chunks/[root-of-the-server]__0cro2dz._.js +0 -5
  417. package/.next/server/chunks/[root-of-the-server]__0dupqt7._.js +0 -5
  418. package/.next/server/chunks/[root-of-the-server]__0emr6go._.js +0 -3
  419. package/.next/server/chunks/[root-of-the-server]__0le4d-p._.js +0 -3
  420. package/.next/server/chunks/[root-of-the-server]__0m8ywyo._.js +0 -10
  421. package/.next/server/chunks/[root-of-the-server]__0nfuugi._.js +0 -5
  422. package/.next/server/chunks/[root-of-the-server]__0p32jfz._.js +0 -12
  423. package/.next/server/chunks/[root-of-the-server]__0phdgco._.js +0 -8
  424. package/.next/server/chunks/[root-of-the-server]__0wvgrsl._.js +0 -3
  425. package/.next/server/chunks/[root-of-the-server]__10qshki._.js +0 -3
  426. package/.next/server/chunks/[root-of-the-server]__11j52t0._.js +0 -5
  427. package/.next/server/chunks/[root-of-the-server]__1692zrv._.js +0 -3
  428. package/.next/server/chunks/[root-of-the-server]__16thabu._.js +0 -3
  429. package/.next/server/chunks/[root-of-the-server]__173nhwf._.js +0 -8
  430. package/.next/server/chunks/[root-of-the-server]__1_aoyr9._.js +0 -3
  431. package/.next/server/chunks/[root-of-the-server]__1bn73ih._.js +0 -10
  432. package/.next/server/chunks/[root-of-the-server]__1bqhuh9._.js +0 -8
  433. package/.next/server/chunks/[root-of-the-server]__1cqizfq._.js +0 -5
  434. package/.next/server/chunks/[root-of-the-server]__1e-ci13._.js +0 -3
  435. package/.next/server/chunks/[root-of-the-server]__1fboj2j._.js +0 -3
  436. package/.next/server/chunks/[root-of-the-server]__1lr7j9t._.js +0 -5
  437. package/.next/server/chunks/[root-of-the-server]__1oli73c._.js +0 -3
  438. package/.next/server/chunks/[root-of-the-server]__1txedx6._.js +0 -8
  439. package/.next/server/chunks/[root-of-the-server]__1untqv8._.js +0 -5
  440. package/.next/server/chunks/[root-of-the-server]__1zgpz1w._.js +0 -3
  441. package/.next/server/chunks/_00_584r._.js +0 -293
  442. package/.next/server/chunks/_012yhfm._.js +0 -39
  443. package/.next/server/chunks/_06mxlgn._.js +0 -3
  444. package/.next/server/chunks/_07rtlxv._.js +0 -3
  445. package/.next/server/chunks/_0a351g7._.js +0 -6
  446. package/.next/server/chunks/_0kjjmag._.js +0 -3
  447. package/.next/server/chunks/_0nn99o2._.js +0 -3
  448. package/.next/server/chunks/_0zuzmt_._.js +0 -39
  449. package/.next/server/chunks/_106co2o._.js +0 -3
  450. package/.next/server/chunks/_12bbv5i._.js +0 -100
  451. package/.next/server/chunks/_15q1pig._.js +0 -3
  452. package/.next/server/chunks/_19wg5yn._.js +0 -138
  453. package/.next/server/chunks/_1bt95p9._.js +0 -55
  454. package/.next/server/chunks/_1cbk7ms._.js +0 -26
  455. package/.next/server/chunks/_1drv2et._.js +0 -40
  456. package/.next/server/chunks/_1ic3bew._.js +0 -5
  457. package/.next/server/chunks/_1mxn_lb._.js +0 -3
  458. package/.next/server/chunks/_1rysr-r._.js +0 -10
  459. package/.next/server/chunks/_1u3rwbr._.js +0 -3
  460. package/.next/server/chunks/_1x7p319._.js +0 -6
  461. package/.next/server/chunks/_next-internal_server_app_api_bot_notes_route_actions_0qcsyu7.js +0 -3
  462. package/.next/server/chunks/_next-internal_server_app_api_memory_tidy_route_actions_0_cfuom.js +0 -3
  463. package/.next/server/chunks/features_bot_task_query_ts_11xuzl3._.js +0 -3
  464. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0gzvgfv._.js +0 -3
  465. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0vorg6w._.js +0 -3
  466. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1tpvamf._.js +0 -3
  467. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1vmaq9f._.js +0 -3
  468. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1y9-wcr._.js +0 -3
  469. package/.next/server/chunks/ssr/[externals]_node_crypto_1kn79-7._.js +0 -3
  470. package/.next/server/chunks/ssr/[root-of-the-server]__0iuoa-r._.js +0 -3
  471. package/.next/server/chunks/ssr/[root-of-the-server]__0un-erv._.js +0 -4
  472. package/.next/server/chunks/ssr/[root-of-the-server]__1-mnhyd._.js +0 -92
  473. package/.next/server/chunks/ssr/[root-of-the-server]__1bww500._.js +0 -3
  474. package/.next/server/chunks/ssr/[root-of-the-server]__1vcdast._.js +0 -3
  475. package/.next/server/chunks/ssr/[root-of-the-server]__1xwnu-h._.js +0 -3
  476. package/.next/server/chunks/ssr/_0-mc7ro._.js +0 -3
  477. package/.next/server/chunks/ssr/_01p5r6-._.js +0 -3
  478. package/.next/server/chunks/ssr/_03webdr._.js +0 -3
  479. package/.next/server/chunks/ssr/_09-0k3z._.js +0 -3
  480. package/.next/server/chunks/ssr/_0f_b_9s._.js +0 -3
  481. package/.next/server/chunks/ssr/_0fafgvl._.js +0 -3
  482. package/.next/server/chunks/ssr/_0sf1isi._.js +0 -3
  483. package/.next/server/chunks/ssr/_0su6_08._.js +0 -3
  484. package/.next/server/chunks/ssr/_0ti51xc._.js +0 -3
  485. package/.next/server/chunks/ssr/_0w5bgak._.js +0 -3
  486. package/.next/server/chunks/ssr/_0y84qo6._.js +0 -3
  487. package/.next/server/chunks/ssr/_1ciyoo3._.js +0 -3
  488. package/.next/server/chunks/ssr/_1e-dgz0._.js +0 -4
  489. package/.next/server/chunks/ssr/_1fq7zgb._.js +0 -3
  490. package/.next/server/chunks/ssr/_1g6l4uj._.js +0 -3
  491. package/.next/server/chunks/ssr/_1ruzehw._.js +0 -3
  492. package/.next/server/chunks/ssr/features_bot_components_bot-setting_tsx_01ajft6._.js +0 -4
  493. package/.next/server/chunks/ssr/features_config_components_14jqgy4._.js +0 -3
  494. package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +0 -4
  495. package/.next/server/chunks/ssr/node_modules_zod_v4_classic_external_15fmmz3.js +0 -55
  496. package/.next/static/chunks/05b6nx_o3_f_n.js +0 -1
  497. package/.next/static/chunks/0dmns-gi0raa4.js +0 -1
  498. package/.next/static/chunks/0f9sq-7q_yxyl.js +0 -1
  499. package/.next/static/chunks/0oc4_xoia77dg.css +0 -1
  500. package/.next/static/chunks/0pheo8m3a-rzi.js +0 -1
  501. package/.next/static/chunks/19i8h2t-5evjx.js +0 -1
  502. package/.next/static/chunks/1c5fcj473025q.js +0 -1
  503. package/.next/static/chunks/1pi_hbmjw-f-z.js +0 -1
  504. package/.next/static/chunks/1twt6k09vg4np.js +0 -1
  505. package/.next/static/chunks/1ytnip8wdng93.js +0 -1
  506. package/.next/static/chunks/28gotuisldmom.js +0 -1
  507. package/.next/static/chunks/2998p0y7k1c8z.js +0 -3
  508. package/.next/static/chunks/29gyb3nubj51j.js +0 -53
  509. package/.next/static/chunks/2l233xfycjpd8.js +0 -1
  510. package/.next/static/chunks/2p5n7pa3c40t-.js +0 -2
  511. package/.next/static/chunks/2ru1q132af7h7.js +0 -1
  512. package/.next/static/chunks/2t8wqycwg3y04.js +0 -2
  513. package/.next/static/chunks/2uxum7qbyeyxd.js +0 -1
  514. package/.next/static/chunks/32z_ypgtchw48.js +0 -1
  515. package/.next/static/chunks/33pyjb3xd1iez.js +0 -1
  516. package/.next/static/chunks/3omud5xunrk1f.js +0 -1
  517. package/.next/static/chunks/42dnrkbph9e-1.js +0 -1
  518. package/.next/static/media/favicon.2vob68tjqpejf.ico +0 -0
  519. package/database/migrations/20260909063821_bitter_tenebrous/migration.sql +0 -1
  520. package/features/ai/prompts/memory-tidy.prompt.ts +0 -129
  521. package/features/ai/tools/tidy.tool.ts +0 -22
  522. package/features/bot/bot.notes.ts +0 -120
  523. package/features/memory/components/memory-tidy.tsx +0 -395
  524. package/features/memory/memory.tidy.ts +0 -332
  525. package/features/memory/tidy.query.ts +0 -135
  526. package/features/thursday/use-call-title.ts +0 -31
  527. /package/.next/server/app/api/bot/{notes → memory/files}/route/build-manifest.json +0 -0
  528. /package/.next/server/app/api/bot/{notes → memory/files}/route/server-reference-manifest.json +0 -0
  529. /package/.next/server/app/api/bot/{notes → memory/files}/route.js.map +0 -0
  530. /package/.next/server/app/api/{memory/tidy → bot/memory}/route/build-manifest.json +0 -0
  531. /package/.next/server/app/api/{memory/tidy → bot/memory}/route/server-reference-manifest.json +0 -0
  532. /package/.next/server/app/api/{memory/tidy → bot/memory}/route.js.map +0 -0
  533. /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → x1cCqY0kWpR_VcYx_lWO5}/_buildManifest.js +0 -0
  534. /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → x1cCqY0kWpR_VcYx_lWO5}/_clientMiddlewareManifest.js +0 -0
  535. /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → x1cCqY0kWpR_VcYx_lWO5}/_ssgManifest.js +0 -0
@@ -8,7 +8,7 @@ import { insideWorkspace } from "@/features/workspace/workspace";
8
8
  /**
9
9
  * Specs for the tools that move work between the voice session and bots. Only what the model
10
10
  * sees lives here; execution belongs to whoever runs the tool (load-tools, bot.run), and the
11
- * screen draws a call off its spec (task.query). `report` has its own execute because what it
11
+ * screen draws a call off its spec (task.query). `answer` has its own execute because what it
12
12
  * checks is a file on disk.
13
13
  */
14
14
 
@@ -45,12 +45,12 @@ export const askBotSpec = {
45
45
  request: z
46
46
  .string()
47
47
  .describe(
48
- "The part they take, as a brief: the outcome you want, the shape to hand it back in (a path, a number, a list), and every name, path, number and limit that bears on it. They see nothing but this and `context` — not the call, not your thread so write it long rather than short; a brief that leaves them guessing costs a whole run.",
48
+ "The part they take: the outcome you want, the shape to hand it back in (a path, a number, a list), and every name, path, number and limit that bears on it. It reaches them under the job and the call it came from, which are attached for you write the part, not the job again.",
49
49
  ),
50
50
  context: z
51
51
  .string()
52
52
  .describe(
53
- "The job you were given, quoted, and whatever you have found that bears on this part — exact values, and the paths of files you wrote for them to read. They cannot see your work, your tool output, or the call.",
53
+ "What you have done on the job so far and why this part is theirs — exact values, and the paths of files you wrote for them to read. They see this, the part, the job and the call; not your thread or your tool output, so a value you leave out is one they fetch again.",
54
54
  ),
55
55
  }),
56
56
  };
@@ -103,41 +103,21 @@ export const askThursdaySpec = {
103
103
 
104
104
  /**
105
105
  * The one way a run ends on its own terms; the loop is stopped by it (`hasToolCall`, bot.run).
106
- * `complete` cannot be inferred: a run out of steps and a finished run look the same from outside.
107
- * `notes` is what the bot wants changed about its own instructions, in its own words — never
108
- * the text itself. A bot that rewrites the whole thing here edits it around the job it was on
109
- * and drops what that job was not about; a pass of its own writes it (features/bot/bot.notes).
106
+ * Whether the job is over is the runtime's to say, never an argument: an answer ends it, and a
107
+ * run the app stopped first (bot.run `stopped`) waits to be continued.
110
108
  */
111
- export const reportSpec = (notes: boolean) => ({
112
- name: TOOL_NAMES.report,
109
+ export const answerSpec = {
110
+ name: TOOL_NAMES.answer,
113
111
  description:
114
- "Hand back what the job produced. Calling this ends the job — nothing after it runs.",
112
+ "Answer the job you were given. Calling this ends the job — nothing after it runs.",
115
113
  parameters: z.object({
116
114
  result: z
117
115
  .string()
118
116
  .describe(
119
- "The result itself, in a few lines — what you found or did, not a replay of how. Thursday reads this out loud, so write what a person needs to hear. If you could not do it, say what stopped you.",
117
+ "The answer itself — what you found or did, not a replay of how. As long as the answer needs and no longer: one number is one line. In the user's language; the thread is on their screen. If you could not do it, say what stopped you.",
120
118
  ),
121
- complete: z
122
- .boolean()
123
- .describe(
124
- "True when the whole request is done. False when work is left over — the user is then asked whether to keep going, and `result` is what they decide on.",
125
- ),
126
- ...(notes
127
- ? {
128
- notes: reportNotes,
129
- }
130
- : {}),
131
119
  }),
132
- });
133
-
134
- /** Only attached while Settings > Bots keeps them (bot.schema BOT_NOTES_KEY). */
135
- const reportNotes = z
136
- .string()
137
- .nullish()
138
- .describe(
139
- "What should change in your own instructions before your next job here — something to add, something wrong to correct, something to drop. Your own words, any length; someone else writes it in. Nothing to say is the usual answer, and leaving it out costs nothing: they already say what they say.",
140
- );
120
+ };
141
121
 
142
122
  /** The voice session's handle on a job already handed over. Run by the server, like `delegate` (load-tools). */
143
123
  export const taskSpec = {
@@ -150,7 +130,7 @@ export const taskSpec = {
150
130
  .string()
151
131
  .nullish()
152
132
  .describe(
153
- "The job, by its label or by the handle a past call's transcript carries. With `status`: null for every job in one line each — that is the list — or name one to get its report in full.",
133
+ 'The job, by its label or by the handle a past call\'s transcript carries. Leave it out with `answer` and it goes to the job that moved last — what "that one" means a moment after it answered. With `status`: null for every job in one line each — that is the list — or name one to get its answer in full.',
154
134
  ),
155
135
  answer: z
156
136
  .string()
@@ -168,36 +148,39 @@ export const askThursdayTool = tool({
168
148
  });
169
149
 
170
150
  /**
171
- * `report` does have an execute, and it only acknowledges. The loop is stopped
151
+ * `answer` does have an execute, and it only acknowledges. The loop is stopped
172
152
  * by `hasToolCall` after the step, not by the absence of an execute — that way
173
153
  * the call and its result are both written to the thread, and a resumed run
174
154
  * reads a finished exchange rather than a call left hanging.
175
155
  */
176
- export const createReportTool = (notes: boolean) => {
177
- const spec = reportSpec(notes);
178
- return tool({
179
- description: spec.description,
180
- inputSchema: spec.parameters,
181
- execute: async ({ result, complete }) => {
182
- const missing = await missingFiles(result);
183
- if (missing.length) {
184
- return `${NOT_HANDED_BACK} these files do not exist ${missing.join(", ")}. Write them first, or take the paths out of the result.`;
185
- }
186
- return complete
187
- ? "Handed back. The job is closed; nothing further runs."
188
- : "Handed back as unfinished. The user decides whether to continue.";
189
- },
190
- });
191
- };
156
+ export const answerTool = tool({
157
+ description: answerSpec.description,
158
+ inputSchema: answerSpec.parameters,
159
+ execute: async ({ result }) => {
160
+ const missing = await missingFiles(result);
161
+ if (missing.length) {
162
+ return `${NOT_ANSWERED} these files do not exist — ${missing.join(", ")}. Write them first, or take the paths out of the answer.`;
163
+ }
164
+ return "Answered. The job is closed; nothing further runs.";
165
+ },
166
+ });
192
167
 
193
168
  /**
194
- * A report naming a workspace file that does not exist is refused: the path becomes a link
169
+ * An answer naming a workspace file that does not exist is refused: the path becomes a link
195
170
  * and opens by itself (bot.runner artifactIn). Paths outside the workspace are not checked.
196
171
  */
197
- const NOT_HANDED_BACK = "Not handed back:";
172
+ const NOT_ANSWERED = "Not answered:";
173
+
174
+ /**
175
+ * `answer` was called `report` before it was renamed. A stored thread keeps the name the
176
+ * call was made under, and the room draws that call as the job's prose — so the three
177
+ * places that read messages back match either name. Nothing writes the old one.
178
+ */
179
+ export const isAnswerCall = (toolName: string): boolean =>
180
+ toolName === TOOL_NAMES.answer || toolName === "report";
198
181
 
199
- export const reportAccepted = (output: unknown): boolean =>
200
- typeof output !== "string" || !output.startsWith(NOT_HANDED_BACK);
182
+ export const answerAccepted = (output: unknown): boolean =>
183
+ typeof output !== "string" || !output.startsWith(NOT_ANSWERED);
201
184
 
202
185
  async function missingFiles(result: string): Promise<string[]> {
203
186
  const missing: string[] = [];
@@ -1,5 +1,5 @@
1
1
  import z from "zod";
2
- import { STUDIO_SERVER } from "@/config";
2
+ import { CONNECTED_TOOL_TIMEOUT_MS, STUDIO_SERVER } from "@/config";
3
3
  import {
4
4
  McpAuthRequiredError,
5
5
  mcpManager,
@@ -80,6 +80,8 @@ export async function findConnectedSchemas(
80
80
  /**
81
81
  * Run one, wherever it lives. Long answers are folded (lib/sandbox fold). Failures are reported,
82
82
  * not thrown; a server that wants the user to sign in first comes back as its own status with the url.
83
+ * One deadline covers both sources (config CONNECTED_TOOL_TIMEOUT_MS): nothing behind this door
84
+ * bounds itself, and a tool that never answers would hold the job's step for good.
83
85
  */
84
86
  export async function callConnectedTool(
85
87
  sandbox: Sandbox,
@@ -88,11 +90,15 @@ export async function callConnectedTool(
88
90
  args: Record<string, unknown> | undefined,
89
91
  abortSignal?: AbortSignal,
90
92
  ): Promise<McpCallOutcome> {
93
+ const deadline = AbortSignal.timeout(CONNECTED_TOOL_TIMEOUT_MS);
94
+ const signal = abortSignal
95
+ ? AbortSignal.any([abortSignal, deadline])
96
+ : deadline;
91
97
  try {
92
98
  const text =
93
99
  server === STUDIO_SERVER
94
- ? await callStudioTool(sandbox, name, args, abortSignal)
95
- : await callMcpTool(server, name, args);
100
+ ? await callStudioTool(sandbox, name, args, signal)
101
+ : await callMcpTool(server, name, args, signal);
96
102
  if (typeof text !== "string") return text;
97
103
  return {
98
104
  status: "ok",
@@ -106,6 +112,12 @@ export async function callConnectedTool(
106
112
  authorizationUrl: error.authorizationUrl,
107
113
  };
108
114
  }
115
+ if (deadline.aborted && !abortSignal?.aborted) {
116
+ return {
117
+ status: "error",
118
+ text: `${name} on ${server} gave no answer in ${CONNECTED_TOOL_TIMEOUT_MS / 60_000} minutes and was given up on.`,
119
+ };
120
+ }
109
121
  return { status: "error", text: errorToString(error) };
110
122
  }
111
123
  }
@@ -131,9 +143,10 @@ async function callMcpTool(
131
143
  server: string,
132
144
  name: string,
133
145
  args: Record<string, unknown> | undefined,
146
+ signal: AbortSignal,
134
147
  ): Promise<string | McpCallOutcome> {
135
148
  const outcome = flattenToolResult(
136
- await mcpManager.callTool(server, name, args),
149
+ await mcpManager.callTool(server, name, args, signal),
137
150
  );
138
151
  return outcome.status === "ok" ? outcome.text : outcome;
139
152
  }
@@ -1,22 +1,30 @@
1
1
  import { tool } from "ai";
2
2
  import * as z from "zod";
3
3
  import { appEvents } from "@/app/api/events/app-event.server";
4
+ import { MEMORY_CONVERSATION_PAGE, MEMORY_LIMITS } from "@/config";
5
+ import {
6
+ callStamp,
7
+ conversationLines,
8
+ saidStamp,
9
+ } from "@/features/ai/prompts/prompt-helper";
4
10
  import { TOOL_NAMES } from "@/features/ai/tools/tool-name";
5
11
  import {
12
+ findFactCall,
6
13
  forgetFactById,
7
14
  readNotes,
8
15
  resolveNotePath,
9
16
  writeNotes,
10
17
  } from "@/features/memory/memory.query";
11
18
  import {
12
- ALWAYS_LOADED_MAX,
13
- isAlwaysListed,
19
+ APP_NAMED_NOTES,
20
+ appNoteLine,
21
+ isAppNamed,
14
22
  isMemoryPath,
15
- MANY_FACTS,
16
- MEMORY_ALWAYS_LISTED,
17
23
  MEMORY_INBOX,
24
+ type MemoryNoteView,
18
25
  type MemorySource,
19
26
  } from "@/features/memory/memory.schema";
27
+ import { readCallConversation } from "@/features/thursday/thursday.query";
20
28
 
21
29
  const GONE =
22
30
  "Deleted for good. The listing in your instructions is from when this session opened and still shows it that way until the next one.";
@@ -24,16 +32,56 @@ const GONE =
24
32
  const WROTE =
25
33
  "Saved. The listing in your instructions is from when this session opened and will not show this until the next one — the note below is current.";
26
34
 
27
- /** Attached only when a note past MANY_FACTS is actually opened, instead of a standing rule in the prompt. */
28
- const tooMany = (path: string, count: number) =>
29
- ` ${path} carries ${count} factsenough that it is worth tidying. Put it on screen with \`${TOOL_NAMES.memory_show}\` and ask which of it they no longer need.`;
35
+ /**
36
+ * A note as a model reads it: how many facts it holds now, and `said` on each
37
+ * fact a call wrote the local time of that call, the same stamp its
38
+ * conversation opens with, so a fact from a call already in the prompt reads
39
+ * as that call. Never the Date itself: it would serialise as UTC.
40
+ */
41
+ const withCount = (note: MemoryNoteView) => ({
42
+ ...note,
43
+ facts: note.facts.map(({ saidAt, ...fact }) =>
44
+ saidAt ? { ...fact, said: saidStamp(saidAt) } : fact,
45
+ ),
46
+ factCount: note.facts.length,
47
+ });
48
+
49
+ /** Why a fact has no conversation to open, by the hand that wrote it. */
50
+ const noConversation = (source: MemorySource | null) =>
51
+ source === "user"
52
+ ? "Typed on the screen — there is no conversation behind it."
53
+ : source === "bot"
54
+ ? "Saved by a bot during a job — there is no conversation behind it."
55
+ : "The conversation it was saved in is not kept.";
56
+
57
+ /**
58
+ * Said when a note has outgrown the recommended size, and only then — the write
59
+ * itself always goes through. It names no tool: this one answers the call and a
60
+ * bot, and only one of them has a screen to put a note on. How to do it is the
61
+ * call prompt's (prompts/thursday.prompt); the ask is the same either way,
62
+ * because a bot that turned up a fact can hand the same request back with it.
63
+ */
64
+ const overSize = (count: number) =>
65
+ count > MEMORY_LIMITS.factsPerNote
66
+ ? ` This note now holds ${count} facts, past the ${MEMORY_LIMITS.factsPerNote} one note holds well. Ask the user which of it is no longer true and delete what they name.`
67
+ : "";
30
68
 
31
69
  /**
32
70
  * @param source Which hand these writes are recorded under. The runtime knows
33
- * it without being told — the call, the read-back pass — so no model ever
34
- * chooses it (load-tools, memory.schema MemorySource).
71
+ * it without being told, so no model ever chooses it (load-tools,
72
+ * memory.schema MemorySource).
73
+ * @param callId The call these tools serve, when there is one: recorded on
74
+ * what `memory_remember` writes, and the conversation `memory_conversation`
75
+ * does not hand back because the model is already in it.
76
+ * @param options.countReads Whether opening a note counts as reading it. The
77
+ * counts rank notes cold in the call prompt, so only a runtime that recalls on
78
+ * the user's behalf counts; an edit opening a note to change it does not.
35
79
  */
36
- export const createMemoryTools = (source: MemorySource) => ({
80
+ export const createMemoryTools = (
81
+ source: MemorySource,
82
+ callId: string | null = null,
83
+ { countReads = true }: { countReads?: boolean } = {},
84
+ ) => ({
37
85
  [TOOL_NAMES.memory_recall]: tool({
38
86
  description: "Open one note from the listing, whole.",
39
87
  inputSchema: z.object({
@@ -44,14 +92,13 @@ export const createMemoryTools = (source: MemorySource) => ({
44
92
  ),
45
93
  }),
46
94
  execute: async ({ path }) => {
47
- const { notes } = await readNotes([path]);
95
+ const { notes } = await readNotes([path], { touch: countReads });
48
96
  const note = notes[0];
49
97
  // A missing note is an answer to relay, not a reason to retry spellings
50
98
  if (!note)
51
99
  return { note: `Nothing on the listing called ${path.trim()}.` };
52
- return note.facts.length > MANY_FACTS
53
- ? { ...note, note: tooMany(note.path, note.facts.length).trim() }
54
- : note;
100
+ const over = overSize(note.facts.length);
101
+ return over ? { ...withCount(note), note: over.trim() } : withCount(note);
55
102
  },
56
103
  }),
57
104
 
@@ -79,7 +126,7 @@ export const createMemoryTools = (source: MemorySource) => ({
79
126
  .boolean()
80
127
  .nullish()
81
128
  .describe(
82
- `True carries this line into every call's instructions without opening its note — for what to call them, their language and register, a standing rule. At most ${ALWAYS_LOADED_MAX}. Null leaves it; false makes a carried line an ordinary fact.`,
129
+ `True carries this line into every call's instructions without opening its note — for what to call them, their language and register, a standing rule. At most ${MEMORY_LIMITS.carried}. Null leaves it; false makes a carried line an ordinary fact.`,
83
130
  ),
84
131
  })
85
132
  .array()
@@ -91,7 +138,7 @@ export const createMemoryTools = (source: MemorySource) => ({
91
138
  .string()
92
139
  .nullish()
93
140
  .describe(
94
- `One line saying what this note is about, not what it currently says. Give it for a new note, or when the line no longer fits. Null leaves it; ${MEMORY_ALWAYS_LISTED.join(" and ")} keep their own line.`,
141
+ `One line saying what this note is about, not what it currently says. Give it for a new note, or when the line no longer fits. Null leaves it; ${APP_NAMED_NOTES.join(", ")} keep their own line.`,
95
142
  ),
96
143
  aliases: z
97
144
  .string()
@@ -106,11 +153,15 @@ export const createMemoryTools = (source: MemorySource) => ({
106
153
  const said = input.path.trim();
107
154
  const known = await resolveNotePath(said);
108
155
  const aliases = input.aliases ?? null;
109
- // The listing line of the always-listed notes belongs to the app (memory.query ensureRootNotes);
110
- // the model's description is ignored there. `alwaysLoad` is not forced on them either:
111
- // the first-call opener (thursday.prompt) asks the model to set it.
112
- const owned = isAlwaysListed(known ?? said);
113
- const description = owned ? null : input.description?.trim() || null;
156
+ // The listing line of the app-named notes is the app's (memory.schema
157
+ // isAppNamed); the model's description is ignored there and its own line
158
+ // written instead, so the inbox cannot end up described by whatever fell
159
+ // into it. `alwaysLoad` is not forced on them: the first-call opener
160
+ // (thursday.prompt) asks the model to set it.
161
+ const target = known ?? said;
162
+ const description = isAppNamed(target)
163
+ ? appNoteLine(target)
164
+ : input.description?.trim() || null;
114
165
  const facts = input.facts ?? [];
115
166
  if (!facts.length && !description && !aliases) {
116
167
  return {
@@ -126,14 +177,14 @@ export const createMemoryTools = (source: MemorySource) => ({
126
177
  // A new path outside the convention goes to inbox, which keeps its own line and takes no aliases
127
178
  const filed =
128
179
  known || isMemoryPath(said)
129
- ? { path: known ?? said, description, aliases, facts }
180
+ ? { path: target, description, aliases, facts }
130
181
  : {
131
182
  path: MEMORY_INBOX,
132
- description: "Facts with nowhere obvious to go",
183
+ description: appNoteLine(MEMORY_INBOX),
133
184
  facts,
134
185
  };
135
186
 
136
- const write = await writeNotes([filed], source);
187
+ const write = await writeNotes([filed], source, callId);
137
188
 
138
189
  // The write already succeeded; what follows are requests, not failures.
139
190
  // A path filed elsewhere must be said, or the model reports it saved where it asked.
@@ -145,17 +196,71 @@ export const createMemoryTools = (source: MemorySource) => ({
145
196
  const unnamed = write.unnamed.length
146
197
  ? ` ${write.unnamed[0]} is new and has no line yet — the listing shows its first fact instead. Call again with \`description\` (one line about what it is) and \`aliases\` (the names they say for it).`
147
198
  : "";
148
- // Carried lines are full: saved as an ordinary fact, and the user picks what to drop (ALWAYS_LOADED_MAX)
199
+ // Carried lines are full: saved as an ordinary fact, and the user picks what to drop (config MEMORY_LIMITS.carried)
149
200
  const notLoaded = write.notLoaded.length
150
- ? ` All ${ALWAYS_LOADED_MAX} carried lines are taken, so ${write.notLoaded
201
+ ? ` All ${MEMORY_LIMITS.carried} carried lines are taken, so ${write.notLoaded
151
202
  .map((text) => `"${text}"`)
152
203
  .join(
153
204
  ", ",
154
205
  )} saved as an ordinary fact. Say which carried line you would drop for it and let them choose.`
155
206
  : "";
207
+ const written = withCount(write.notes[0]);
208
+ return {
209
+ ...written,
210
+ note: `${WROTE}${elsewhere}${unnamed}${notLoaded}${overSize(written.factCount)}`,
211
+ };
212
+ },
213
+ }),
214
+
215
+ [TOOL_NAMES.memory_conversation]: tool({
216
+ description:
217
+ "Open the conversation a fact was saved in, whole: what each side said, and which tools were used.",
218
+ inputSchema: z.object({
219
+ factId: z
220
+ .number()
221
+ .int()
222
+ .describe("The id that came with the fact when its note was opened."),
223
+ page: z
224
+ .number()
225
+ .int()
226
+ .min(1)
227
+ .nullish()
228
+ .describe(
229
+ `${MEMORY_CONVERSATION_PAGE} turns a page, oldest first. Null for the first.`,
230
+ ),
231
+ }),
232
+ execute: async ({ factId, page }) => {
233
+ const fact = await findFactCall(factId);
234
+ if (!fact) return { note: `No fact with id ${factId}.` };
235
+ if (!fact.callId) return { note: noConversation(fact.source) };
236
+ // Already in the model's context: handing it back only spends it twice
237
+ if (fact.callId === callId) {
238
+ return {
239
+ note: "Said in this call — it is the conversation you are in.",
240
+ };
241
+ }
242
+
243
+ const at = page ?? 1;
244
+ const read = await readCallConversation(
245
+ fact.callId,
246
+ at,
247
+ MEMORY_CONVERSATION_PAGE,
248
+ );
249
+ if (!read) return { note: noConversation(fact.source) };
250
+ const pages = Math.max(
251
+ 1,
252
+ Math.ceil(read.total / MEMORY_CONVERSATION_PAGE),
253
+ );
254
+ if (at > pages) {
255
+ return {
256
+ note: `That conversation has ${pages} page${pages > 1 ? "s" : ""}.`,
257
+ };
258
+ }
156
259
  return {
157
- ...write.notes[0],
158
- note: `${WROTE}${elsewhere}${unnamed}${notLoaded}`,
260
+ when: callStamp(read.startedAt),
261
+ page: at,
262
+ pages,
263
+ conversation: conversationLines(read.turns),
159
264
  };
160
265
  },
161
266
  }),
@@ -216,47 +321,3 @@ what to drop and you drop it.`,
216
321
  },
217
322
  }),
218
323
  });
219
-
220
- /**
221
- * The bot's write. Same act under the same name, without what only the call can
222
- * do: no `replaces`, no carried lines, no naming a note — a bot has neither the
223
- * user in front of it nor the listing's history. Rare by nature; what the job
224
- * turned up belongs in the report, and only what outlives the job comes here.
225
- */
226
- export const botRememberTool = tool({
227
- description:
228
- "Save a lasting fact about the user. Only for what outlives this job; what the job itself turned up goes in the report.",
229
- inputSchema: z.object({
230
- path: z
231
- .string()
232
- .describe(
233
- "Exactly as the listing writes it, or a new path following the same convention.",
234
- ),
235
- facts: z
236
- .string()
237
- .array()
238
- .describe("One statement each, standing on its own later."),
239
- }),
240
- execute: async ({ path, facts }) => {
241
- const said = path.trim();
242
- const written = facts.map((text) => text.trim()).filter(Boolean);
243
- if (!written.length) return { note: "Nothing to write: send a fact." };
244
-
245
- const known = await resolveNotePath(said);
246
- // A path outside the convention goes to inbox, as it does for the call
247
- const filed = known || isMemoryPath(said) ? (known ?? said) : MEMORY_INBOX;
248
-
249
- await writeNotes(
250
- [{ path: filed, facts: written.map((text) => ({ text })) }],
251
- "bot",
252
- );
253
-
254
- // A write filed elsewhere must be said, or the report claims the wrong place
255
- return {
256
- note:
257
- filed === said
258
- ? `Saved to ${filed}.`
259
- : `Saved to ${filed}: "${said}" is not a path this listing can carry.`,
260
- };
261
- },
262
- });