thursday-agent 0.1.2 → 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 (573) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +5 -1
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +5 -5
  5. package/.next/routes-manifest.json +27 -3
  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.html +1 -1
  9. package/.next/server/app/_global-error.rsc +2 -2
  10. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  12. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/server/app/_not-found/page.js +2 -2
  14. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/server/app/_not-found.html +1 -1
  17. package/.next/server/app/_not-found.rsc +14 -14
  18. package/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  19. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +12 -12
  20. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/server/app/api/artifact/route.js +3 -3
  22. package/.next/server/app/api/artifact/route.js.nft.json +1 -1
  23. package/.next/server/app/api/bot/memory/files/route/app-paths-manifest.json +3 -0
  24. package/.next/server/app/api/bot/memory/files/route.js +10 -0
  25. package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -0
  26. package/.next/server/app/api/bot/memory/files/route_client-reference-manifest.js +3 -0
  27. package/.next/server/app/api/bot/memory/route/app-paths-manifest.json +3 -0
  28. package/.next/server/app/api/bot/memory/route/build-manifest.json +12 -0
  29. package/.next/server/app/api/bot/memory/route/server-reference-manifest.json +4 -0
  30. package/.next/server/app/api/bot/memory/route.js +14 -0
  31. package/.next/server/app/api/bot/memory/route.js.map +5 -0
  32. package/.next/server/app/api/bot/memory/route.js.nft.json +1 -0
  33. package/.next/server/app/api/bot/memory/route_client-reference-manifest.js +3 -0
  34. package/.next/server/app/api/bot/route.js +7 -7
  35. package/.next/server/app/api/bot/route.js.nft.json +1 -1
  36. package/.next/server/app/api/bot/task/[id]/route.js +9 -9
  37. package/.next/server/app/api/bot/task/[id]/route.js.nft.json +1 -1
  38. package/.next/server/app/api/bot/task/route.js +8 -8
  39. package/.next/server/app/api/bot/task/route.js.nft.json +1 -1
  40. package/.next/server/app/api/config/route.js +6 -6
  41. package/.next/server/app/api/config/route.js.nft.json +1 -1
  42. package/.next/server/app/api/events/route.js +4 -5
  43. package/.next/server/app/api/events/route.js.nft.json +1 -1
  44. package/.next/server/app/api/file/[...path]/route.js +3 -3
  45. package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
  46. package/.next/server/app/api/llm-model/catalog/route.js +10 -9
  47. package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
  48. package/.next/server/app/api/llm-model/credits/route/app-paths-manifest.json +3 -0
  49. package/.next/server/app/api/llm-model/credits/route/build-manifest.json +12 -0
  50. package/.next/server/app/api/llm-model/credits/route/server-reference-manifest.json +4 -0
  51. package/.next/server/app/api/llm-model/credits/route.js +16 -0
  52. package/.next/server/app/api/llm-model/credits/route.js.map +5 -0
  53. package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -0
  54. package/.next/server/app/api/llm-model/credits/route_client-reference-manifest.js +3 -0
  55. package/.next/server/app/api/llm-model/route.js +10 -8
  56. package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
  57. package/.next/server/app/api/llm-model/subscription/route/app-paths-manifest.json +3 -0
  58. package/.next/server/app/api/llm-model/subscription/route/build-manifest.json +12 -0
  59. package/.next/server/app/api/llm-model/subscription/route/server-reference-manifest.json +4 -0
  60. package/.next/server/app/api/llm-model/subscription/route.js +15 -0
  61. package/.next/server/app/api/llm-model/subscription/route.js.map +5 -0
  62. package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -0
  63. package/.next/server/app/api/llm-model/subscription/route_client-reference-manifest.js +3 -0
  64. package/.next/server/app/api/mcp/[name]/route.js +5 -5
  65. package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
  66. package/.next/server/app/api/mcp/oauth/callback/route.js +6 -6
  67. package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
  68. package/.next/server/app/api/mcp/route.js +5 -5
  69. package/.next/server/app/api/mcp/route.js.nft.json +1 -1
  70. package/.next/server/app/api/mcp/tools/route.js +5 -5
  71. package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
  72. package/.next/server/app/api/memory/edit/route/app-paths-manifest.json +3 -0
  73. package/.next/server/app/api/memory/edit/route/build-manifest.json +12 -0
  74. package/.next/server/app/api/memory/edit/route/server-reference-manifest.json +4 -0
  75. package/.next/server/app/api/memory/edit/route.js +24 -0
  76. package/.next/server/app/api/memory/edit/route.js.map +5 -0
  77. package/.next/server/app/api/memory/edit/route.js.nft.json +1 -0
  78. package/.next/server/app/api/memory/{tidy → edit}/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/memory/route.js +7 -8
  80. package/.next/server/app/api/memory/route.js.nft.json +1 -1
  81. package/.next/server/app/api/skills/[source]/[name]/route.js +3 -3
  82. package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
  83. package/.next/server/app/api/skills/route.js +3 -3
  84. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  85. package/.next/server/app/api/thursday/call/route.js +9 -7
  86. package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
  87. package/.next/server/app/api/thursday/skills/route.js +9 -7
  88. package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
  89. package/.next/server/app/api/thursday/tool-call/route.js +16 -15
  90. package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
  91. package/.next/server/app/api/workspace/route.js +4 -5
  92. package/.next/server/app/api/workspace/route.js.nft.json +1 -1
  93. package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +1 -1
  94. package/.next/server/app/artifact/[...path]/page.js +5 -6
  95. package/.next/server/app/artifact/[...path]/page.js.nft.json +1 -1
  96. package/.next/server/app/artifact/[...path]/page_client-reference-manifest.js +1 -1
  97. package/.next/server/app/favicon.ico/route.js +3 -4
  98. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  99. package/.next/server/app/favicon.ico.body +0 -0
  100. package/.next/server/app/page/server-reference-manifest.json +66 -77
  101. package/.next/server/app/page.js +11 -11
  102. package/.next/server/app/page.js.nft.json +1 -1
  103. package/.next/server/app/page_client-reference-manifest.js +1 -1
  104. package/.next/server/app-paths-manifest.json +5 -1
  105. package/.next/server/chunks/[externals]__0dzuk6_._.js +3 -0
  106. package/.next/server/chunks/[root-of-the-server]__01dkp4a._.js +3 -0
  107. package/.next/server/chunks/[root-of-the-server]__02va5wz._.js +3 -0
  108. package/.next/server/chunks/[root-of-the-server]__02xjoto._.js +3 -0
  109. package/.next/server/chunks/[root-of-the-server]__04q--0f._.js +8 -0
  110. package/.next/server/chunks/[root-of-the-server]__0bl-e63._.js +3 -0
  111. package/.next/server/chunks/[root-of-the-server]__0ce8nf8._.js +5 -0
  112. package/.next/server/chunks/[root-of-the-server]__0ffbg85._.js +3 -0
  113. package/.next/server/chunks/[root-of-the-server]__0j7z0r3._.js +12 -0
  114. package/.next/server/chunks/[root-of-the-server]__0jq4ohy._.js +8 -0
  115. package/.next/server/chunks/[root-of-the-server]__0ls6_8y._.js +8 -0
  116. package/.next/server/chunks/[root-of-the-server]__0ncs9uu._.js +3 -0
  117. package/.next/server/chunks/[root-of-the-server]__0pa2n68._.js +3 -0
  118. package/.next/server/chunks/[root-of-the-server]__0q0vvt2._.js +5 -0
  119. package/.next/server/chunks/[root-of-the-server]__1-ga0kh._.js +5 -0
  120. package/.next/server/chunks/[root-of-the-server]__11n256_._.js +5 -0
  121. package/.next/server/chunks/[root-of-the-server]__12cabg9._.js +3 -0
  122. package/.next/server/chunks/[root-of-the-server]__1339jnv._.js +8 -0
  123. package/.next/server/chunks/[root-of-the-server]__15bjnu5._.js +5 -0
  124. package/.next/server/chunks/[root-of-the-server]__18_teo8._.js +8 -0
  125. package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +5 -0
  126. package/.next/server/chunks/[root-of-the-server]__1anc1p9._.js +3 -0
  127. package/.next/server/chunks/[root-of-the-server]__1ccon1w._.js +10 -0
  128. package/.next/server/chunks/[root-of-the-server]__1fizn31._.js +3 -0
  129. package/.next/server/chunks/[root-of-the-server]__1llj3-b._.js +3 -0
  130. package/.next/server/chunks/[root-of-the-server]__1orn-5b._.js +11 -0
  131. package/.next/server/chunks/[root-of-the-server]__1p8m3f4._.js +3 -0
  132. package/.next/server/chunks/[root-of-the-server]__1wa1k7r._.js +8 -0
  133. package/.next/server/chunks/{_1hzrsvg._.js → _0-73of8._.js} +6 -6
  134. package/.next/server/chunks/{_1cbk7ms._.js → _0-fjql4._.js} +10 -10
  135. package/.next/server/chunks/_00xh_q0._.js +27 -0
  136. package/.next/server/chunks/{_0y8is-s._.js → _03a0897._.js} +1 -1
  137. package/.next/server/chunks/{_0pppbb5._.js → _03kp0jp._.js} +166 -35
  138. package/.next/server/chunks/_051qh8u._.js +3 -0
  139. package/.next/server/chunks/{node_modules_next_04q-o58._.js → _05dla15._.js} +2 -2
  140. package/.next/server/chunks/_05h2cii._.js +1 -1
  141. package/.next/server/chunks/_0c9j6rb._.js +49 -0
  142. package/.next/server/chunks/_0fzqt2y._.js +74 -44
  143. package/.next/server/chunks/{_0kl37zl._.js → _0ioz3nd._.js} +1 -1
  144. package/.next/server/chunks/_0iwfby5._.js +3 -0
  145. package/.next/server/chunks/{_0hin38_._.js → _0khihjk._.js} +5 -5
  146. package/.next/server/chunks/_0mecv0f._.js +26 -0
  147. package/.next/server/chunks/_0mh8j4m._.js +3 -0
  148. package/.next/server/chunks/{_1icgbi8._.js → _0n74zsf._.js} +2 -2
  149. package/.next/server/chunks/_0obojvv._.js +3 -0
  150. package/.next/server/chunks/_0recufk._.js +49 -0
  151. package/.next/server/chunks/{_1t8fv7b._.js → _0rnf-6n._.js} +2 -2
  152. package/.next/server/chunks/_0sb7tlz._.js +3 -0
  153. package/.next/server/chunks/{_0jgm3b8._.js → _0u10wmw._.js} +6 -6
  154. package/.next/server/chunks/{_12nr4xc._.js → _0u4aiy2._.js} +2 -2
  155. package/.next/server/chunks/_0wp4le3._.js +1 -1
  156. package/.next/server/chunks/_0y5fg-x._.js +1 -1
  157. package/.next/server/chunks/_1230wbx._.js +10 -0
  158. package/.next/server/chunks/_12nheja._.js +3 -0
  159. package/.next/server/chunks/_13510xh._.js +3 -0
  160. package/.next/server/chunks/_15hq89o._.js +1 -1
  161. package/.next/server/chunks/_17l5ygt._.js +49 -0
  162. package/.next/server/chunks/{_0ks6_sg._.js → _18-1wcc._.js} +6 -6
  163. package/.next/server/chunks/_1_5mnq4._.js +18 -0
  164. package/.next/server/chunks/{_0tzfesa._.js → _1_9mjx-._.js} +1 -1
  165. package/.next/server/chunks/_1d0j961._.js +6 -0
  166. package/.next/server/chunks/_1d5zmy8._.js +1 -1
  167. package/.next/server/chunks/_1drgfx4._.js +18 -0
  168. package/.next/server/chunks/{_1skgy7b._.js → _1e48czp._.js} +5 -5
  169. package/.next/server/chunks/_1f46eie._.js +3 -0
  170. package/.next/server/chunks/_1h5_8sk._.js +3 -0
  171. package/.next/server/chunks/_1hdnxb7._.js +3 -0
  172. package/.next/server/chunks/_1j8k_j5._.js +3 -0
  173. package/.next/server/chunks/{_10qam6o._.js → _1kg70wc._.js} +5 -5
  174. package/.next/server/chunks/_1krd9rf._.js +3 -0
  175. package/.next/server/chunks/_1nc0eui._.js +11 -0
  176. package/.next/server/chunks/_1nula3v._.js +3 -0
  177. package/.next/server/chunks/_1pf4qe-._.js +3 -0
  178. package/.next/server/chunks/_1php4eq._.js +1 -1
  179. package/.next/server/chunks/_1qxheoa._.js +3 -0
  180. package/.next/server/chunks/_1x6kd1r._.js +3 -0
  181. package/.next/server/chunks/_1yuv4vp._.js +1 -1
  182. package/.next/server/chunks/_1zjrdag._.js +3 -0
  183. package/.next/server/chunks/_next-internal_server_app_api_bot_memory_files_route_actions_1_xd_8f.js +3 -0
  184. package/.next/server/chunks/_next-internal_server_app_api_bot_memory_route_actions_1a8xfr7.js +3 -0
  185. package/.next/server/chunks/_next-internal_server_app_api_llm-model_credits_route_actions_0v424pb.js +3 -0
  186. package/.next/server/chunks/_next-internal_server_app_api_llm-model_subscription_route_actions_0-udcm5.js +3 -0
  187. package/.next/server/chunks/_next-internal_server_app_api_memory_edit_route_actions_02sfnmr.js +3 -0
  188. package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
  189. package/.next/server/chunks/features_0rpfxbk._.js +3 -0
  190. package/.next/server/chunks/features_1qf3cei._.js +3 -0
  191. package/.next/server/chunks/features_bot_0zt92oh._.js +3 -0
  192. package/.next/server/chunks/features_bot_bot_query_ts_12mgkl2._.js +1 -1
  193. package/.next/server/chunks/features_memory_1uqvksn._.js +6 -0
  194. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0tf290y._.js → node_modules_consola_dist_chunks_prompt_mjs_0i7cvml._.js} +1 -1
  195. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0228f43._.js → node_modules_consola_dist_chunks_prompt_mjs_0icqaqw._.js} +1 -1
  196. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0ir-vo2._.js → node_modules_consola_dist_chunks_prompt_mjs_0j61-ma._.js} +1 -1
  197. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0otw8ef._.js → node_modules_consola_dist_chunks_prompt_mjs_0r28-sm._.js} +1 -1
  198. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0v_7drq._.js +3 -0
  199. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_11zjo-1._.js +3 -0
  200. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1pycqsq._.js +3 -0
  201. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1xoq2rl._.js +3 -0
  202. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1y49572._.js +3 -0
  203. package/.next/server/chunks/ssr/[externals]__0dizgek._.js +3 -0
  204. package/.next/server/chunks/ssr/[root-of-the-server]__09q9med._.js +1 -1
  205. package/.next/server/chunks/ssr/[root-of-the-server]__0_69wqr._.js +3 -0
  206. package/.next/server/chunks/ssr/[root-of-the-server]__0hg5gib._.js +1 -1
  207. package/.next/server/chunks/ssr/[root-of-the-server]__0i8ie7f._.js +3 -0
  208. package/.next/server/chunks/ssr/{[root-of-the-server]__0jsmmb-._.js → [root-of-the-server]__0mz33a7._.js} +1 -1
  209. package/.next/server/chunks/ssr/[root-of-the-server]__0tbkdlx._.js +3 -0
  210. package/.next/server/chunks/ssr/[root-of-the-server]__0vnmv-s._.js +3 -0
  211. package/.next/server/chunks/ssr/{[root-of-the-server]__0f6s48x._.js → [root-of-the-server]__0xpcv9w._.js} +3 -3
  212. package/.next/server/chunks/ssr/[root-of-the-server]__0xtssj3._.js +1 -1
  213. package/.next/server/chunks/ssr/[root-of-the-server]__0zkv7z_._.js +3 -0
  214. package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +57 -0
  215. package/.next/server/chunks/ssr/[root-of-the-server]__15_uhip._.js +3 -0
  216. package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
  217. package/.next/server/chunks/ssr/[root-of-the-server]__1cyjywu._.js +3 -0
  218. package/.next/server/chunks/ssr/[root-of-the-server]__1eh7hid._.js +3 -0
  219. package/.next/server/chunks/ssr/[root-of-the-server]__1gtlw6v._.js +43 -0
  220. package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +1 -1
  221. package/.next/server/chunks/ssr/[root-of-the-server]__1ox7hbk._.js +4 -0
  222. package/.next/server/chunks/ssr/[root-of-the-server]__1pduf5n._.js +3 -0
  223. package/.next/server/chunks/ssr/{_1mznrxk._.js → _001_ms1._.js} +3 -3
  224. package/.next/server/chunks/ssr/_01_6m32._.js +3 -0
  225. package/.next/server/chunks/ssr/_01n3o0m._.js +3 -0
  226. package/.next/server/chunks/ssr/_07uchnc._.js +3 -0
  227. package/.next/server/chunks/ssr/_0ap2fzn._.js +3 -0
  228. package/.next/server/chunks/ssr/_0c-ql2m._.js +3 -0
  229. package/.next/server/chunks/ssr/_0h42fze._.js +3 -0
  230. package/.next/server/chunks/ssr/_0h7zdni._.js +1 -1
  231. package/.next/server/chunks/ssr/_0i_6q1w._.js +41 -0
  232. package/.next/server/chunks/ssr/_0kbkmar._.js +3 -0
  233. package/.next/server/chunks/ssr/_0lu1n_x._.js +3 -0
  234. package/.next/server/chunks/ssr/{_077-g6s._.js → _0mb8zc8._.js} +3 -3
  235. package/.next/server/chunks/ssr/_0mo2w06._.js +3 -0
  236. package/.next/server/chunks/ssr/{_13punpm._.js → _0q0zan6._.js} +2 -2
  237. package/.next/server/chunks/ssr/{_0gd4vaa._.js → _0u2jv_x._.js} +94 -58
  238. package/.next/server/chunks/ssr/_0y0tiht._.js +4 -0
  239. package/.next/server/chunks/ssr/_0zhoc3r._.js +3 -0
  240. package/.next/server/chunks/ssr/_1-teee5._.js +3 -3
  241. package/.next/server/chunks/ssr/_13fke0x._.js +3 -0
  242. package/.next/server/chunks/ssr/{_0q_2f2x._.js → _13z3f85._.js} +2 -2
  243. package/.next/server/chunks/ssr/_14_lw10._.js +3 -0
  244. package/.next/server/chunks/ssr/_15j2_8f._.js +3 -0
  245. package/.next/server/chunks/ssr/{_0lc_7c8._.js → _1eoqg_g._.js} +2 -2
  246. package/.next/server/chunks/ssr/_1sji22n._.js +3 -0
  247. package/.next/server/chunks/ssr/_1spzm8z._.js +3 -0
  248. package/.next/server/chunks/ssr/{_19_o9d-._.js → _1vi_uo7._.js} +2 -2
  249. package/.next/server/chunks/ssr/_1vyd1ji._.js +3 -0
  250. package/.next/server/chunks/ssr/_1xvgn77._.js +3 -0
  251. package/.next/server/chunks/ssr/_20kd_n0._.js +42 -0
  252. package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +3 -0
  253. package/.next/server/chunks/ssr/features_config_components_config-setting_tsx_0xfwqdg._.js +1 -1
  254. package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
  255. package/.next/server/chunks/ssr/lib_date-like_ts_02is0pw._.js +3 -0
  256. package/.next/server/chunks/ssr/lib_realtime_12wg_dd._.js +27 -0
  257. package/.next/server/chunks/ssr/lib_realtime_15h_v1v._.js +27 -0
  258. package/.next/server/chunks/ssr/{node_modules_1d-is1o._.js → node_modules_063xwpp._.js} +1 -1
  259. package/.next/server/chunks/ssr/{node_modules_1ub40gk._.js → node_modules_0bvraul._.js} +1 -1
  260. package/.next/server/chunks/ssr/{node_modules_1nhw9qg._.js → node_modules_0eu1va6._.js} +1 -1
  261. package/.next/server/chunks/ssr/{node_modules_0xwx4u-._.js → node_modules_0h50b8n._.js} +1 -1
  262. package/.next/server/chunks/ssr/{node_modules_043-236._.js → node_modules_0h5hnr1._.js} +1 -1
  263. package/.next/server/chunks/ssr/{node_modules_1t0y5jt._.js → node_modules_0h7u60n._.js} +1 -1
  264. package/.next/server/chunks/ssr/{node_modules_1k29j1j._.js → node_modules_0lm7_vm._.js} +1 -1
  265. package/.next/server/chunks/ssr/{node_modules_16i4o_3._.js → node_modules_0mwym0g._.js} +1 -1
  266. package/.next/server/chunks/ssr/{node_modules_1y8_3vg._.js → node_modules_0rjg6t1._.js} +1 -1
  267. package/.next/server/chunks/ssr/node_modules_0x3-ply._.js +3 -0
  268. package/.next/server/chunks/ssr/{node_modules_108wd2o._.js → node_modules_0y_cded._.js} +1 -1
  269. package/.next/server/chunks/ssr/{node_modules_1jatz7w._.js → node_modules_0z5tsu8._.js} +1 -1
  270. package/.next/server/chunks/ssr/{node_modules_0ls96je._.js → node_modules_0zp9r92._.js} +1 -1
  271. package/.next/server/chunks/ssr/{node_modules_06kvvuo._.js → node_modules_1-hc6uv._.js} +1 -1
  272. package/.next/server/chunks/ssr/{node_modules_1_588_4._.js → node_modules_113tz0l._.js} +1 -1
  273. package/.next/server/chunks/ssr/{node_modules_0ipn1ho._.js → node_modules_124bue5._.js} +1 -1
  274. package/.next/server/chunks/ssr/node_modules_17bwo43._.js +55 -0
  275. package/.next/server/chunks/ssr/{node_modules_0_j7-g4._.js → node_modules_1_n3ztw._.js} +1 -1
  276. package/.next/server/chunks/ssr/{node_modules_20ynonm._.js → node_modules_1bc7gu8._.js} +1 -1
  277. package/.next/server/chunks/ssr/{node_modules_1hn_sd5._.js → node_modules_1bgb6-f._.js} +1 -1
  278. package/.next/server/chunks/ssr/{node_modules_0bue6gy._.js → node_modules_1h4a4pp._.js} +1 -1
  279. package/.next/server/chunks/ssr/{node_modules_0fbw5-u._.js → node_modules_1i7u1ia._.js} +1 -1
  280. package/.next/server/chunks/ssr/{node_modules_1ee8gav._.js → node_modules_1juq3hs._.js} +1 -1
  281. package/.next/server/chunks/ssr/{node_modules_0_fvxnt._.js → node_modules_1l0qtdu._.js} +1 -1
  282. package/.next/server/chunks/ssr/{node_modules_13f2md6._.js → node_modules_1t9cyee._.js} +1 -1
  283. package/.next/server/chunks/ssr/{node_modules_0y2-av4._.js → node_modules_1uuj9x1._.js} +1 -1
  284. package/.next/server/chunks/ssr/{node_modules_00d6675._.js → node_modules_1vqb6po._.js} +1 -1
  285. package/.next/server/chunks/ssr/{node_modules_1v0077l._.js → node_modules_1xx28h1._.js} +1 -1
  286. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_092s8nx._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0d3skpl._.js} +1 -1
  287. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1nvexgu._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0i44kk5._.js} +1 -1
  288. package/.next/server/chunks/ssr/node_modules_@vercel_oidc_dist_0qe30a_._.js +3 -0
  289. package/.next/server/chunks/ssr/node_modules_consola_dist_chunks_prompt_mjs_05cwqv2._.js +47 -0
  290. package/.next/server/chunks/ssr/{node_modules_next_dist_0w6mzq5._.js → node_modules_next_dist_0drixxt._.js} +4 -4
  291. package/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +2 -2
  292. package/.next/server/instrumentation.js +1 -1
  293. package/.next/server/middleware-build-manifest.js +3 -3
  294. package/.next/server/pages/404.html +1 -1
  295. package/.next/server/pages/500.html +1 -1
  296. package/.next/server/server-reference-manifest.js +1 -1
  297. package/.next/server/server-reference-manifest.json +67 -78
  298. package/.next/static/chunks/{31ttnjt6g35a0.js → 0ev4hyghq0mbb.js} +1 -1
  299. package/.next/static/chunks/0r5qcctujhxli.js +1 -0
  300. package/.next/static/chunks/0tmgrnlje14-s.js +3 -0
  301. package/.next/static/chunks/0x79tx04dxbpp.js +1 -0
  302. package/.next/static/chunks/0xzgvc0fkdb6t.js +1 -0
  303. package/.next/static/chunks/10teww7wt-f6h.js +1 -0
  304. package/.next/static/chunks/14hgtsjg-kael.css +1 -0
  305. package/.next/static/chunks/17donp69y4do7.js +40 -0
  306. package/.next/static/chunks/1dkjg87pxk0n9.js +28 -0
  307. package/.next/static/chunks/1ekc7ul556kbl.js +1 -0
  308. package/.next/static/chunks/{1khakdu_iuedc.js → 1grhjo7a5a0_-.js} +1 -1
  309. package/.next/static/chunks/1kq8h8wi_e0bc.js +53 -0
  310. package/.next/static/chunks/1okqiww3pnwka.js +1 -0
  311. package/.next/static/chunks/26-pr2c9ro222.js +1 -0
  312. package/.next/static/chunks/{2ihkf6l2jowo9.js → 280t0_e99i276.js} +3 -3
  313. package/.next/static/chunks/28cizcdaabd4h.js +1 -0
  314. package/.next/static/chunks/2a0k6jlq0_v1u.js +2 -0
  315. package/.next/static/chunks/2fzs9fm8yarvq.js +1 -0
  316. package/.next/static/chunks/2h0sd2vumhb15.js +1 -0
  317. package/.next/static/chunks/2hw2f6zmt7fmt.js +1 -0
  318. package/.next/static/chunks/2t4vhi3m8ahya.js +1 -0
  319. package/.next/static/chunks/2tigdtz3dpcy8.js +1 -0
  320. package/.next/static/chunks/3111pj5wnjgos.js +1 -0
  321. package/.next/static/chunks/3786h5vayt80-.js +28 -0
  322. package/.next/static/chunks/{3aquirz5h71da.js → 3agpgkwaa321p.js} +1 -1
  323. package/.next/static/chunks/3cfi_q6d_wtci.js +1 -0
  324. package/.next/static/chunks/3ok9_x74rip3v.js +1 -0
  325. package/.next/static/chunks/3xk7yqgomx7yq.js +1 -0
  326. package/.next/static/chunks/3xpbkl66ssib5.js +38 -0
  327. package/.next/static/media/favicon.37o1pjldwi2uc.ico +0 -0
  328. package/README.md +6 -4
  329. package/app/api/bot/memory/files/route.ts +14 -0
  330. package/app/api/bot/memory/route.ts +5 -0
  331. package/app/api/events/app-event.client.ts +24 -0
  332. package/app/api/events/app-event.server.ts +45 -0
  333. package/app/api/events/app-event.ts +42 -0
  334. package/app/api/llm-model/catalog/route.ts +12 -0
  335. package/app/api/llm-model/credits/route.ts +11 -0
  336. package/app/api/llm-model/route.ts +26 -0
  337. package/app/api/llm-model/subscription/route.ts +11 -0
  338. package/app/api/memory/edit/route.ts +7 -0
  339. package/app/api/memory/route.ts +21 -0
  340. package/app/api/query-key.ts +159 -0
  341. package/app/api/thursday/tool-call/route.ts +67 -0
  342. package/bin/thursday.mjs +3 -0
  343. package/components/ui/button-group.tsx +45 -0
  344. package/components/ui/custom-icon.tsx +259 -0
  345. package/components/ui/dropdown-menu.tsx +271 -0
  346. package/components/ui/folded-text.tsx +68 -0
  347. package/components/ui/input-group.tsx +157 -0
  348. package/components/ui/json-view.tsx +240 -0
  349. package/components/ui/shiny-text.tsx +55 -0
  350. package/components/ui/text-type.tsx +213 -0
  351. package/components/ui/theme-sync.tsx +9 -0
  352. package/database/migrations/{20260908030742_rainy_marvel_zombies → 20260910173049_numerous_spirit}/migration.sql +30 -33
  353. package/database/migrations/{20260908030742_rainy_marvel_zombies → 20260910173049_numerous_spirit}/snapshot.json +124 -145
  354. package/database/migrations/20260911030320_opposite_jack_power/migration.sql +1 -0
  355. package/database/migrations/20260911030320_opposite_jack_power/snapshot.json +1158 -0
  356. package/docs/how-it-works.md +59 -0
  357. package/docs/images/keeps-going.png +0 -0
  358. package/docs/images/task-thread.png +0 -0
  359. package/docs/images/two-minds.png +0 -0
  360. package/features/ai/chatgpt.ts +617 -0
  361. package/features/ai/components/chatgpt-sign-in.tsx +66 -0
  362. package/features/ai/components/model-picker.tsx +17 -1
  363. package/features/ai/components/provider-icon.tsx +1 -0
  364. package/features/ai/load-tools.ts +105 -39
  365. package/features/ai/model.schema.ts +232 -34
  366. package/features/ai/model.ts +169 -24
  367. package/features/ai/prompts/bot.prompt.ts +245 -59
  368. package/features/ai/prompts/memory-edit.prompt.ts +33 -0
  369. package/features/ai/prompts/prompt-helper.ts +75 -30
  370. package/features/ai/prompts/thursday.prompt.ts +42 -17
  371. package/features/ai/tools/bot.tool.ts +32 -30
  372. package/features/ai/tools/connected.ts +17 -4
  373. package/features/ai/tools/mcp.tool.ts +5 -5
  374. package/features/ai/tools/memory.tool.ts +142 -74
  375. package/features/ai/tools/search.tool.ts +136 -47
  376. package/features/ai/tools/studio.tool.ts +5 -5
  377. package/features/ai/tools/tool-name.ts +2 -3
  378. package/features/ai/tools/workspace.tool.ts +33 -4
  379. package/features/bot/bot.action.ts +24 -7
  380. package/features/bot/bot.memory.ts +89 -0
  381. package/features/bot/bot.query.ts +41 -6
  382. package/features/bot/bot.run.ts +516 -210
  383. package/features/bot/bot.runner.ts +463 -93
  384. package/features/bot/bot.schema.ts +84 -7
  385. package/features/bot/bot.seed.ts +89 -16
  386. package/features/bot/components/bot-mark.tsx +122 -20
  387. package/features/bot/components/bot-room.tsx +519 -391
  388. package/features/bot/components/bot-setting.tsx +832 -341
  389. package/features/bot/components/bot-tool.tsx +2 -6
  390. package/features/bot/components/mark-palette.tsx +54 -0
  391. package/features/bot/components/path-chips.tsx +1 -1
  392. package/features/bot/components/task-badge.tsx +26 -6
  393. package/features/bot/components/task-reply.tsx +22 -33
  394. package/features/bot/components/task-setting.tsx +20 -17
  395. package/features/bot/task.query.ts +233 -33
  396. package/features/bot/task.store.ts +53 -9
  397. package/features/config/components/config-setting.tsx +265 -34
  398. package/features/config/components/models-badge.tsx +42 -0
  399. package/features/config/config.action.ts +12 -0
  400. package/features/config/config.const.ts +38 -2
  401. package/features/connectors/mcp.manager.ts +10 -2
  402. package/features/intro/components/intro.tsx +47 -46
  403. package/features/memory/components/memory-edit.tsx +338 -0
  404. package/features/memory/components/memory-setting.tsx +86 -79
  405. package/features/memory/memory.action.ts +3 -43
  406. package/features/memory/memory.edit.ts +87 -0
  407. package/features/memory/memory.query.ts +33 -44
  408. package/features/memory/memory.schema.ts +50 -97
  409. package/features/settings/components/settings.tsx +2 -0
  410. package/features/settings/settings.alert.ts +3 -1
  411. package/features/skills/components/skills-setting.tsx +9 -1
  412. package/features/thursday/components/ascii-orb.tsx +106 -90
  413. package/features/thursday/components/boot.tsx +7 -0
  414. package/features/thursday/components/call-log.tsx +219 -92
  415. package/features/thursday/components/face.tsx +6 -4
  416. package/features/thursday/components/tab-state.tsx +97 -0
  417. package/features/thursday/components/thursday-mark.tsx +4 -1
  418. package/features/thursday/components/thursday-setting.tsx +17 -47
  419. package/features/thursday/components/thursday.tsx +208 -95
  420. package/features/thursday/thursday.action.ts +12 -17
  421. package/features/thursday/thursday.query.ts +61 -70
  422. package/features/thursday/thursday.schema.ts +20 -7
  423. package/features/thursday/tool-line.ts +85 -11
  424. package/features/thursday/use-thursday.ts +86 -59
  425. package/features/workspace/components/file-view.tsx +4 -2
  426. package/features/workspace/workspace.ts +230 -13
  427. package/hooks/use-draft.ts +37 -0
  428. package/hooks/use-hotkey.ts +105 -0
  429. package/hooks/use-object-state.ts +51 -0
  430. package/hooks/use-on-visible.ts +72 -0
  431. package/hooks/use-theme.ts +106 -0
  432. package/hooks/use-wake-word.ts +262 -0
  433. package/lib/limits.ts +1 -1
  434. package/lib/oauth-page.ts +27 -0
  435. package/lib/realtime/openai.ts +2 -2
  436. package/lib/realtime/realtime.driver.ts +34 -1
  437. package/lib/realtime/realtime.protocol.ts +7 -1
  438. package/lib/realtime/realtime.tap.ts +122 -0
  439. package/lib/sandbox.ts +60 -29
  440. package/lib/tokens.ts +19 -0
  441. package/package.json +1 -1
  442. package/skills/browser/SKILL.md +55 -34
  443. package/.next/server/app/api/memory/tidy/route/app-paths-manifest.json +0 -3
  444. package/.next/server/app/api/memory/tidy/route.js +0 -23
  445. package/.next/server/app/api/memory/tidy/route.js.nft.json +0 -1
  446. package/.next/server/chunks/[root-of-the-server]__019dx9f._.js +0 -5
  447. package/.next/server/chunks/[root-of-the-server]__02_2sm-._.js +0 -5
  448. package/.next/server/chunks/[root-of-the-server]__02kt8yn._.js +0 -10
  449. package/.next/server/chunks/[root-of-the-server]__05luceg._.js +0 -3
  450. package/.next/server/chunks/[root-of-the-server]__06t77t4._.js +0 -11
  451. package/.next/server/chunks/[root-of-the-server]__0bed6hu._.js +0 -8
  452. package/.next/server/chunks/[root-of-the-server]__0dupqt7._.js +0 -5
  453. package/.next/server/chunks/[root-of-the-server]__0h59di-._.js +0 -5
  454. package/.next/server/chunks/[root-of-the-server]__0j_n5l3._.js +0 -3
  455. package/.next/server/chunks/[root-of-the-server]__0le4d-p._.js +0 -3
  456. package/.next/server/chunks/[root-of-the-server]__0m8ywyo._.js +0 -10
  457. package/.next/server/chunks/[root-of-the-server]__0nfuugi._.js +0 -5
  458. package/.next/server/chunks/[root-of-the-server]__0phdgco._.js +0 -8
  459. package/.next/server/chunks/[root-of-the-server]__0qjqtwo._.js +0 -5
  460. package/.next/server/chunks/[root-of-the-server]__0t_dqaj._.js +0 -3
  461. package/.next/server/chunks/[root-of-the-server]__0wvgrsl._.js +0 -3
  462. package/.next/server/chunks/[root-of-the-server]__0yk6s3w._.js +0 -5
  463. package/.next/server/chunks/[root-of-the-server]__0z3gelv._.js +0 -3
  464. package/.next/server/chunks/[root-of-the-server]__10qshki._.js +0 -3
  465. package/.next/server/chunks/[root-of-the-server]__113fqg5._.js +0 -12
  466. package/.next/server/chunks/[root-of-the-server]__11w_7_3._.js +0 -3
  467. package/.next/server/chunks/[root-of-the-server]__16thabu._.js +0 -3
  468. package/.next/server/chunks/[root-of-the-server]__173nhwf._.js +0 -8
  469. package/.next/server/chunks/[root-of-the-server]__1_0q_9w._.js +0 -3
  470. package/.next/server/chunks/[root-of-the-server]__1_aoyr9._.js +0 -3
  471. package/.next/server/chunks/[root-of-the-server]__1bqhuh9._.js +0 -8
  472. package/.next/server/chunks/[root-of-the-server]__1cqizfq._.js +0 -5
  473. package/.next/server/chunks/[root-of-the-server]__1dow0bz._.js +0 -3
  474. package/.next/server/chunks/[root-of-the-server]__1e-ci13._.js +0 -3
  475. package/.next/server/chunks/[root-of-the-server]__1gmn1cs._.js +0 -10
  476. package/.next/server/chunks/[root-of-the-server]__1lr7j9t._.js +0 -5
  477. package/.next/server/chunks/[root-of-the-server]__1mzp_el._.js +0 -3
  478. package/.next/server/chunks/[root-of-the-server]__1txedx6._.js +0 -8
  479. package/.next/server/chunks/[root-of-the-server]__1u_qvc7._.js +0 -3
  480. package/.next/server/chunks/[root-of-the-server]__1zgpz1w._.js +0 -3
  481. package/.next/server/chunks/_012yhfm._.js +0 -39
  482. package/.next/server/chunks/_06mxlgn._.js +0 -3
  483. package/.next/server/chunks/_07rtlxv._.js +0 -3
  484. package/.next/server/chunks/_0a351g7._.js +0 -6
  485. package/.next/server/chunks/_0kjjmag._.js +0 -3
  486. package/.next/server/chunks/_0zmestz._.js +0 -55
  487. package/.next/server/chunks/_0zuzmt_._.js +0 -39
  488. package/.next/server/chunks/_12bbv5i._.js +0 -96
  489. package/.next/server/chunks/_15q1pig._.js +0 -3
  490. package/.next/server/chunks/_1drv2et._.js +0 -36
  491. package/.next/server/chunks/_1ic3bew._.js +0 -5
  492. package/.next/server/chunks/_1mxn_lb._.js +0 -3
  493. package/.next/server/chunks/_1uj4_io._.js +0 -10
  494. package/.next/server/chunks/_1x7p319._.js +0 -6
  495. package/.next/server/chunks/_1yldgo4._.js +0 -55
  496. package/.next/server/chunks/_2050gwn._.js +0 -255
  497. package/.next/server/chunks/_next-internal_server_app_api_memory_tidy_route_actions_0_cfuom.js +0 -3
  498. package/.next/server/chunks/features_0scmr4i._.js +0 -3
  499. package/.next/server/chunks/features_bot_task_query_ts_11xuzl3._.js +0 -3
  500. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0vorg6w._.js +0 -3
  501. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0ykklj0._.js +0 -3
  502. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1ryg3wh._.js +0 -3
  503. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1vmaq9f._.js +0 -3
  504. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1vwbnq_._.js +0 -3
  505. package/.next/server/chunks/ssr/[externals]_node_crypto_1kn79-7._.js +0 -3
  506. package/.next/server/chunks/ssr/[root-of-the-server]__01id-v3._.js +0 -3
  507. package/.next/server/chunks/ssr/[root-of-the-server]__0b-0i32._.js +0 -3
  508. package/.next/server/chunks/ssr/[root-of-the-server]__0dfwvr4._.js +0 -4
  509. package/.next/server/chunks/ssr/[root-of-the-server]__0iuoa-r._.js +0 -3
  510. package/.next/server/chunks/ssr/[root-of-the-server]__1-mnhyd._.js +0 -90
  511. package/.next/server/chunks/ssr/[root-of-the-server]__185grso._.js +0 -3
  512. package/.next/server/chunks/ssr/[root-of-the-server]__1minz8_._.js +0 -3
  513. package/.next/server/chunks/ssr/_0-mc7ro._.js +0 -3
  514. package/.next/server/chunks/ssr/_01p5r6-._.js +0 -3
  515. package/.next/server/chunks/ssr/_09-0k3z._.js +0 -3
  516. package/.next/server/chunks/ssr/_0ay6b01._.js +0 -3
  517. package/.next/server/chunks/ssr/_0cvjbuz._.js +0 -3
  518. package/.next/server/chunks/ssr/_0fafgvl._.js +0 -3
  519. package/.next/server/chunks/ssr/_0j4v8of._.js +0 -3
  520. package/.next/server/chunks/ssr/_0l81bzy._.js +0 -3
  521. package/.next/server/chunks/ssr/_0nso8tp._.js +0 -3
  522. package/.next/server/chunks/ssr/_0sf1isi._.js +0 -3
  523. package/.next/server/chunks/ssr/_0ti51xc._.js +0 -3
  524. package/.next/server/chunks/ssr/_0y84qo6._.js +0 -3
  525. package/.next/server/chunks/ssr/_10uvw3l._.js +0 -3
  526. package/.next/server/chunks/ssr/_1dcxzqe._.js +0 -3
  527. package/.next/server/chunks/ssr/_1e-dgz0._.js +0 -4
  528. package/.next/server/chunks/ssr/_1fq7zgb._.js +0 -3
  529. package/.next/server/chunks/ssr/_1jbv7m1._.js +0 -3
  530. package/.next/server/chunks/ssr/features_bot_components_bot-setting_tsx_01ajft6._.js +0 -4
  531. package/.next/server/chunks/ssr/features_config_components_14jqgy4._.js +0 -3
  532. package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +0 -4
  533. package/.next/server/chunks/ssr/lib_realtime_0aetuyp._.js +0 -24
  534. package/.next/server/chunks/ssr/lib_realtime_18k_aj-._.js +0 -24
  535. package/.next/server/chunks/ssr/node_modules_zod_v4_classic_errors_05xv7vp.js +0 -3
  536. package/.next/server/chunks/ssr/node_modules_zod_v4_classic_external_15fmmz3.js +0 -55
  537. package/.next/static/chunks/0f9sq-7q_yxyl.js +0 -1
  538. package/.next/static/chunks/0tydnn2kybibk.js +0 -1
  539. package/.next/static/chunks/0yysv1gzin17t.js +0 -1
  540. package/.next/static/chunks/1fr5m75pwtyic.js +0 -1
  541. package/.next/static/chunks/1gy3bbv7usnjo.js +0 -1
  542. package/.next/static/chunks/1keib_gt066gc.js +0 -1
  543. package/.next/static/chunks/1ytnip8wdng93.js +0 -1
  544. package/.next/static/chunks/21rk8w7bda-su.js +0 -1
  545. package/.next/static/chunks/247d-r95j8xs0.js +0 -1
  546. package/.next/static/chunks/28g42tw8tsvhd.js +0 -1
  547. package/.next/static/chunks/29gyb3nubj51j.js +0 -53
  548. package/.next/static/chunks/2cwjgkt_hoyhj.js +0 -22
  549. package/.next/static/chunks/2fq_86jvq9ymq.js +0 -2
  550. package/.next/static/chunks/2rbf1fpd8n80-.js +0 -22
  551. package/.next/static/chunks/2ukj8k69y89um.js +0 -1
  552. package/.next/static/chunks/2uxum7qbyeyxd.js +0 -1
  553. package/.next/static/chunks/2wngeetfnzxkp.js +0 -2
  554. package/.next/static/chunks/388-t2v72jh39.css +0 -1
  555. package/.next/static/chunks/3fqvc0cg-atq_.js +0 -1
  556. package/.next/static/chunks/3p4egvfjxpatb.js +0 -1
  557. package/.next/static/chunks/3qe1w1ei-huhl.js +0 -1
  558. package/.next/static/chunks/3xxa2j56-f3nm.js +0 -3
  559. package/.next/static/chunks/3y40riycdip-i.js +0 -1
  560. package/.next/static/chunks/45a6zbtkelph9.js +0 -1
  561. package/.next/static/media/favicon.2vob68tjqpejf.ico +0 -0
  562. package/features/ai/prompts/memory-tidy.prompt.ts +0 -123
  563. package/features/ai/tools/tidy.tool.ts +0 -22
  564. package/features/memory/components/memory-tidy.tsx +0 -395
  565. package/features/memory/memory.tidy.ts +0 -332
  566. package/features/memory/tidy.query.ts +0 -135
  567. package/features/thursday/use-call-title.ts +0 -31
  568. /package/.next/server/app/api/{memory/tidy → bot/memory/files}/route/build-manifest.json +0 -0
  569. /package/.next/server/app/api/{memory/tidy → bot/memory/files}/route/server-reference-manifest.json +0 -0
  570. /package/.next/server/app/api/{memory/tidy → bot/memory/files}/route.js.map +0 -0
  571. /package/.next/static/{X34BUd9bfdH27ripuwwBm → x1cCqY0kWpR_VcYx_lWO5}/_buildManifest.js +0 -0
  572. /package/.next/static/{X34BUd9bfdH27ripuwwBm → x1cCqY0kWpR_VcYx_lWO5}/_clientMiddlewareManifest.js +0 -0
  573. /package/.next/static/{X34BUd9bfdH27ripuwwBm → x1cCqY0kWpR_VcYx_lWO5}/_ssgManifest.js +0 -0
@@ -1,4 +1,4 @@
1
- import { RECENT_CALL } from "@/config";
1
+ import { MEMORY_LIMITS, RECENT_CALL } from "@/config";
2
2
  import { TOOL_NAMES } from "@/features/ai/tools/tool-name";
3
3
  import { listJobBots } from "@/features/bot/bot.query";
4
4
  import type { JobBot } from "@/features/bot/bot.schema";
@@ -29,6 +29,7 @@ import { listConnectedToolNames } from "../tools/connected";
29
29
  import {
30
30
  carriedLines,
31
31
  type LoadedPrompt,
32
+ logPromptSize,
32
33
  mcpServerLines,
33
34
  noteLines,
34
35
  nowLine,
@@ -85,6 +86,7 @@ export async function loadThursdayPrompt(
85
86
  .filter(Boolean)
86
87
  .join("\n\n");
87
88
 
89
+ logPromptSize("thursday", text);
88
90
  logger.debug(`thursday prompt\n${text}`);
89
91
 
90
92
  return {
@@ -157,27 +159,46 @@ ${carriedLines(carried)}`
157
159
 
158
160
  ${noteLines(index, crowded)}
159
161
 
160
- Open a note before answering out of it; a topic not listed is one you know nothing about.
162
+ Open a note before answering out of it; a topic not listed is one you know nothing about. A fact marked \`said\` came from a call; open that call with \`${TOOL_NAMES.memory_conversation}\` only when the line itself cannot answer — exactly what they said, or why it was saved.
161
163
 
162
164
  Anything worth knowing next time goes in the moment it comes up, without asking — one fact per line, dates as dates. A rule they lay down for you — their language, how long an answer runs, when to hang up — is \`alwaysLoad\`; unsaved, it dies with the call. What stopped being true is corrected with \`replaces\`, not left standing beside it. Never claim to remember what you did not save.
163
165
 
164
166
  ${MEMORY_PATHS.map((entry) => `- ${entry.path} — ${entry.of}`).join("\n")}`;
165
167
 
166
- // Tidying rules only when there is something to tidy
167
- const why = heavy.length
168
- ? `Too long to hold in one piece: ${heavy
168
+ // Only when there is something to tidy, and it names a few notes rather than
169
+ // every one it caught: a warning that lists everything is a second listing,
170
+ // and what it is warning about is that the first one is already too long.
171
+ const full = heavy.length
172
+ ? `${[...heavy]
173
+ .sort((a, b) => b.factCount - a.factCount)
174
+ .slice(0, 3)
169
175
  .map((note) => `${note.path} (${note.factCount})`)
170
- .join(", ")}.`
171
- : `This listing is past its size. Coldest: ${index
176
+ .join(", ")} ${heavy.length > 1 ? "have" : "has"} grown past ${
177
+ MEMORY_LIMITS.factsPerNote
178
+ } facts, more than one note holds well. Put ${
179
+ heavy.length > 1 ? "each" : "it"
180
+ } on their screen with \`${TOOL_NAMES.memory_show}\`, read back what is stale and forget only what they name.`
181
+ : "";
182
+ const many = crowded
183
+ ? `Memory is past ${MEMORY_LIMITS.facts} facts in all. The coldest notes are ${index
172
184
  .slice(-4)
173
185
  .map((note) => note.path)
174
- .join(", ")}.`;
175
- const tidy =
176
- crowded || heavy.length
177
- ? `${why} In a lull, put one on their screen with \`${TOOL_NAMES.memory_show}\` and forget only what they name.`
178
- : "";
179
-
180
- return [head, alreadyKnown, listing, tidy].filter(Boolean).join("\n\n");
186
+ .join(
187
+ ", ",
188
+ )} ask whether any of them is still worth keeping, and delete the note if not.`
189
+ : "";
190
+ // Ahead of anything else she would raise, never ahead of what they came with
191
+ const tidy = [full, many].filter(Boolean).join(" ");
192
+
193
+ return [
194
+ head,
195
+ alreadyKnown,
196
+ listing,
197
+ tidy &&
198
+ `${tidy} Get this settled before anything else you would bring up yourself — not before what they came to you with.`,
199
+ ]
200
+ .filter(Boolean)
201
+ .join("\n\n");
181
202
  }
182
203
 
183
204
  /** Last calls verbatim, marked as past so the model does not answer as if just asked. Absent on the first call. */
@@ -242,7 +263,7 @@ Who you hand work to — the names \`${TOOL_NAMES.delegate}\` takes.
242
263
 
243
264
  ${input.roster.map((bot) => `- **${bot.name}** — ${bot.description}`).join("\n")}`;
244
265
 
245
- const machine = `**A bot has the whole machine** — this computer, a real browser, the web, files, a shell to build whatever is missing — and far more time than you. It signs in where it has to, with the window in front of them, and carries a job to the end: the thing bought, the account made, the page built. How, and whether, is its call; yours is what they want — so a thing you have no idea how to do is a job, not a no. Bots borrow each other, so a job that spans several things is still one job for one bot.`;
266
+ const machine = `**A bot has the whole machine** — this computer, a real browser, the web, files, a shell to build whatever is missing — and far more time than you. It signs in where it has to, with the window in front of them, and carries a job to the end: the account made, the page built. How, and whether, is its call; yours is what they want — so a thing you have no idea how to do is a job, not a no. Bots borrow each other, so a job that spans several things is still one job for one bot.`;
246
267
 
247
268
  const hands = [
248
269
  input.skills.length
@@ -263,9 +284,13 @@ ${hands.join("\n\n")}`
263
284
 
264
285
  const handingOver = `**Anything that takes more than a few seconds is a bot's** — one note or one file is yours. \`${TOOL_NAMES.delegate}\` answers at once: say who has it and keep talking. Put the request in their own words, with what it stands on and nothing they did not say; if something only they can say is missing — how much, which one, by when — ask that first.
265
286
 
266
- A job you handed over is followed with \`${TOOL_NAMES.task}\`to answer what it asks, change its course, or continue it never with a second \`${TOOL_NAMES.delegate}\`; with no job named it lists what is open.`;
287
+ **The conversation belongs to the job, not to the bot** hand the same bot a second job and it starts from nothing, knowing neither what was asked nor what it found. So more about a job you already handed over goes to \`${TOOL_NAMES.task}\` by its name, and the bot wakes with that job's own thread; with no name given it takes the one that moved last.`;
267
288
 
268
- const comingBack = `A job comes back as a system note, not the user speaking: tell them in one sentence, in your own words. A file it names opens on their screen by itself — say what it holds, not the path. A question arrives the same way: answer it yourself if you can, else read them the options and send back what they say.`;
289
+ // An answer is written to her, and the whole of it is already drawn on the
290
+ // user's screen (bot-room). Saying so is what keeps its length from deciding
291
+ // hers: a bot that answers a one-line question in one line and a bot that
292
+ // hands back a table both end in one spoken sentence.
293
+ const comingBack = `A job comes back as a system note, not the user speaking. **It was written to you, not to them** — its length is not how much to say, and the whole of it is already on their screen. Give them the part that answers what they asked, in one sentence, in your own words. A file it names opens there by itself — say what it holds, not the path. A question arrives the same way: answer it yourself if you can, else read them the options and send back what they say.`;
269
294
 
270
295
  return [list, machine, catalogue, handingOver, comingBack]
271
296
  .filter(Boolean)
@@ -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
  };
@@ -94,7 +94,7 @@ export const askThursdaySpec = {
94
94
  // joined string, and a schema rejection only loops. The reader takes arrays only (task.query optionsOf)
95
95
  options: z
96
96
  .union([z.string().array(), z.string()])
97
- .nullable()
97
+ .nullish()
98
98
  .describe(
99
99
  'Only when there really are choices — two or three, each short, as an array: ["Signed in", "Not yet"]. Null for an open question.',
100
100
  ),
@@ -103,22 +103,18 @@ 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.
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.
107
108
  */
108
- export const reportSpec = {
109
- name: TOOL_NAMES.report,
109
+ export const answerSpec = {
110
+ name: TOOL_NAMES.answer,
110
111
  description:
111
- "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.",
112
113
  parameters: z.object({
113
114
  result: z
114
115
  .string()
115
116
  .describe(
116
- "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
- ),
118
- complete: z
119
- .boolean()
120
- .describe(
121
- "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.",
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.",
122
118
  ),
123
119
  }),
124
120
  };
@@ -132,13 +128,13 @@ export const taskSpec = {
132
128
  action: z.enum(["status", "answer", "cancel"]),
133
129
  task: z
134
130
  .string()
135
- .nullable()
131
+ .nullish()
136
132
  .describe(
137
- "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.',
138
134
  ),
139
135
  answer: z
140
136
  .string()
141
- .nullable()
137
+ .nullish()
142
138
  .describe(
143
139
  "With `answer`: what to tell the bot — the answer to its question, a course correction for a job still running, or what to do next on one that finished.",
144
140
  ),
@@ -152,33 +148,39 @@ export const askThursdayTool = tool({
152
148
  });
153
149
 
154
150
  /**
155
- * `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
156
152
  * by `hasToolCall` after the step, not by the absence of an execute — that way
157
153
  * the call and its result are both written to the thread, and a resumed run
158
154
  * reads a finished exchange rather than a call left hanging.
159
155
  */
160
- export const reportTool = tool({
161
- description: reportSpec.description,
162
- inputSchema: reportSpec.parameters,
163
- execute: async ({ result, complete }) => {
156
+ export const answerTool = tool({
157
+ description: answerSpec.description,
158
+ inputSchema: answerSpec.parameters,
159
+ execute: async ({ result }) => {
164
160
  const missing = await missingFiles(result);
165
161
  if (missing.length) {
166
- return `${NOT_HANDED_BACK} these files do not exist — ${missing.join(", ")}. Write them first, or take the paths out of the result.`;
162
+ return `${NOT_ANSWERED} these files do not exist — ${missing.join(", ")}. Write them first, or take the paths out of the answer.`;
167
163
  }
168
- return complete
169
- ? "Handed back. The job is closed; nothing further runs."
170
- : "Handed back as unfinished. The user decides whether to continue.";
164
+ return "Answered. The job is closed; nothing further runs.";
171
165
  },
172
166
  });
173
167
 
174
168
  /**
175
- * 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
176
170
  * and opens by itself (bot.runner artifactIn). Paths outside the workspace are not checked.
177
171
  */
178
- 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";
179
181
 
180
- export const reportAccepted = (output: unknown): boolean =>
181
- typeof output !== "string" || !output.startsWith(NOT_HANDED_BACK);
182
+ export const answerAccepted = (output: unknown): boolean =>
183
+ typeof output !== "string" || !output.startsWith(NOT_ANSWERED);
182
184
 
183
185
  async function missingFiles(result: string): Promise<string[]> {
184
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
  }
@@ -22,9 +22,9 @@ const MAX_SCHEMAS = 8;
22
22
  export const mcpToolSpec = {
23
23
  [TOOL_NAMES.tool_search]: {
24
24
  name: TOOL_NAMES.tool_search,
25
- description: `Fetch what a connected server's tools take, so they can be called.
26
-
27
- The Connected tools section names every server and every tool on it, and that is all it names: there is no description and no parameter schema, so a tool cannot be invoked from that list alone. Name a server and the tools on it, and this returns each one's description and its exact inputSchema. Then run one with \`${TOOL_NAMES.tool_call}\`.`,
25
+ // What it is, not when to reach for it: the Connected tools chapter says
26
+ // that the listing carries names alone and that this is how a schema is got
27
+ description: `Return the description and exact inputSchema of tools on a connected server, so they can be called with \`${TOOL_NAMES.tool_call}\`.`,
28
28
  parameters: z.object({
29
29
  server: z
30
30
  .string()
@@ -48,13 +48,13 @@ The Connected tools section names every server and every tool on it, and that is
48
48
  tool: z.string().describe("Its name, as search returned it."),
49
49
  args: z
50
50
  .record(z.string(), z.unknown())
51
- .nullable()
51
+ .nullish()
52
52
  .describe(
53
53
  "Arguments matching the inputSchema search returned — do not guess. Null when it takes none.",
54
54
  ),
55
55
  description: z
56
56
  .string()
57
- .nullable()
57
+ .nullish()
58
58
  .describe(
59
59
  "One short line for the user: what this call is for. Shown on their screen while it runs.",
60
60
  ),
@@ -1,21 +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,
25
+ type MemorySource,
18
26
  } from "@/features/memory/memory.schema";
27
+ import { readCallConversation } from "@/features/thursday/thursday.query";
19
28
 
20
29
  const GONE =
21
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.";
@@ -23,11 +32,56 @@ const GONE =
23
32
  const WROTE =
24
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.";
25
34
 
26
- /** Attached only when a note past MANY_FACTS is actually opened, instead of a standing rule in the prompt. */
27
- const tooMany = (path: string, count: number) =>
28
- ` ${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.";
29
56
 
30
- export const createMemoryTools = () => ({
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
+ : "";
68
+
69
+ /**
70
+ * @param source Which hand these writes are recorded under. The runtime knows
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.
79
+ */
80
+ export const createMemoryTools = (
81
+ source: MemorySource,
82
+ callId: string | null = null,
83
+ { countReads = true }: { countReads?: boolean } = {},
84
+ ) => ({
31
85
  [TOOL_NAMES.memory_recall]: tool({
32
86
  description: "Open one note from the listing, whole.",
33
87
  inputSchema: z.object({
@@ -38,14 +92,13 @@ export const createMemoryTools = () => ({
38
92
  ),
39
93
  }),
40
94
  execute: async ({ path }) => {
41
- const { notes } = await readNotes([path]);
95
+ const { notes } = await readNotes([path], { touch: countReads });
42
96
  const note = notes[0];
43
97
  // A missing note is an answer to relay, not a reason to retry spellings
44
98
  if (!note)
45
99
  return { note: `Nothing on the listing called ${path.trim()}.` };
46
- return note.facts.length > MANY_FACTS
47
- ? { ...note, note: tooMany(note.path, note.facts.length).trim() }
48
- : note;
100
+ const over = overSize(note.facts.length);
101
+ return over ? { ...withCount(note), note: over.trim() } : withCount(note);
49
102
  },
50
103
  }),
51
104
 
@@ -65,32 +118,32 @@ export const createMemoryTools = () => ({
65
118
  replaces: z
66
119
  .number()
67
120
  .int()
68
- .nullable()
121
+ .nullish()
69
122
  .describe(
70
123
  "The id of the fact this replaces — from this note as handed back here or by `memory_recall`. Null if this is new. A fact that stopped being true is replaced rather than deleted, and so is a note saying the same thing twice: replacing keeps what changed on the record, deleting does not.",
71
124
  ),
72
125
  alwaysLoad: z
73
126
  .boolean()
74
- .nullable()
127
+ .nullish()
75
128
  .describe(
76
- `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.`,
77
130
  ),
78
131
  })
79
132
  .array()
80
- .nullable()
133
+ .nullish()
81
134
  .describe(
82
135
  "What to write under this note. Send everything that came up at once: one call is one pause in the conversation, three calls are three. Null when only naming it.",
83
136
  ),
84
137
  description: z
85
138
  .string()
86
- .nullable()
139
+ .nullish()
87
140
  .describe(
88
- `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.`,
89
142
  ),
90
143
  aliases: z
91
144
  .string()
92
145
  .array()
93
- .nullable()
146
+ .nullish()
94
147
  .describe(
95
148
  'What the user calls this note out loud, in the language they say it — the words they would use to ask for it, not the facts inside. A note at people/yuri might be "Yuri" and "my wife". Replaces the set it has, so send the whole set. Null leaves it.',
96
149
  ),
@@ -100,11 +153,15 @@ export const createMemoryTools = () => ({
100
153
  const said = input.path.trim();
101
154
  const known = await resolveNotePath(said);
102
155
  const aliases = input.aliases ?? null;
103
- // The listing line of the always-listed notes belongs to the app (memory.query ensureRootNotes);
104
- // the model's description is ignored there. `alwaysLoad` is not forced on them either:
105
- // the first-call opener (thursday.prompt) asks the model to set it.
106
- const owned = isAlwaysListed(known ?? said);
107
- 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;
108
165
  const facts = input.facts ?? [];
109
166
  if (!facts.length && !description && !aliases) {
110
167
  return {
@@ -120,14 +177,14 @@ export const createMemoryTools = () => ({
120
177
  // A new path outside the convention goes to inbox, which keeps its own line and takes no aliases
121
178
  const filed =
122
179
  known || isMemoryPath(said)
123
- ? { path: known ?? said, description, aliases, facts }
180
+ ? { path: target, description, aliases, facts }
124
181
  : {
125
182
  path: MEMORY_INBOX,
126
- description: "Facts with nowhere obvious to go",
183
+ description: appNoteLine(MEMORY_INBOX),
127
184
  facts,
128
185
  };
129
186
 
130
- const write = await writeNotes([filed]);
187
+ const write = await writeNotes([filed], source, callId);
131
188
 
132
189
  // The write already succeeded; what follows are requests, not failures.
133
190
  // A path filed elsewhere must be said, or the model reports it saved where it asked.
@@ -139,17 +196,71 @@ export const createMemoryTools = () => ({
139
196
  const unnamed = write.unnamed.length
140
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).`
141
198
  : "";
142
- // 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)
143
200
  const notLoaded = write.notLoaded.length
144
- ? ` All ${ALWAYS_LOADED_MAX} carried lines are taken, so ${write.notLoaded
201
+ ? ` All ${MEMORY_LIMITS.carried} carried lines are taken, so ${write.notLoaded
145
202
  .map((text) => `"${text}"`)
146
203
  .join(
147
204
  ", ",
148
205
  )} saved as an ordinary fact. Say which carried line you would drop for it and let them choose.`
149
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
+ }
150
259
  return {
151
- ...write.notes[0],
152
- note: `${WROTE}${elsewhere}${unnamed}${notLoaded}`,
260
+ when: callStamp(read.startedAt),
261
+ page: at,
262
+ pages,
263
+ conversation: conversationLines(read.turns),
153
264
  };
154
265
  },
155
266
  }),
@@ -210,46 +321,3 @@ what to drop and you drop it.`,
210
321
  },
211
322
  }),
212
323
  });
213
-
214
- /**
215
- * The bot's write. Same act under the same name, without what only the call can
216
- * do: no `replaces`, no carried lines, no naming a note — a bot has neither the
217
- * user in front of it nor the listing's history. Rare by nature; what the job
218
- * turned up belongs in the report, and only what outlives the job comes here.
219
- */
220
- export const botRememberTool = tool({
221
- description:
222
- "Save a lasting fact about the user. Only for what outlives this job; what the job itself turned up goes in the report.",
223
- inputSchema: z.object({
224
- path: z
225
- .string()
226
- .describe(
227
- "Exactly as the listing writes it, or a new path following the same convention.",
228
- ),
229
- facts: z
230
- .string()
231
- .array()
232
- .describe("One statement each, standing on its own later."),
233
- }),
234
- execute: async ({ path, facts }) => {
235
- const said = path.trim();
236
- const written = facts.map((text) => text.trim()).filter(Boolean);
237
- if (!written.length) return { note: "Nothing to write: send a fact." };
238
-
239
- const known = await resolveNotePath(said);
240
- // A path outside the convention goes to inbox, as it does for the call
241
- const filed = known || isMemoryPath(said) ? (known ?? said) : MEMORY_INBOX;
242
-
243
- await writeNotes([
244
- { path: filed, facts: written.map((text) => ({ text })) },
245
- ]);
246
-
247
- // A write filed elsewhere must be said, or the report claims the wrong place
248
- return {
249
- note:
250
- filed === said
251
- ? `Saved to ${filed}.`
252
- : `Saved to ${filed}: "${said}" is not a path this listing can carry.`,
253
- };
254
- },
255
- });