thursday-agent 0.2.0 → 0.4.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 (541) 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 +12 -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 +25 -0
  134. package/.next/server/chunks/_051qh8u._.js +3 -0
  135. package/.next/server/chunks/{node_modules_next_04q-o58._.js → _05dla15._.js} +2 -2
  136. package/.next/server/chunks/_05h2cii._.js +1 -1
  137. package/.next/server/chunks/_0c9j6rb._.js +49 -0
  138. package/.next/server/chunks/_0fzqt2y._.js +134 -0
  139. package/.next/server/chunks/{_0vnutv9._.js → _0ioz3nd._.js} +1 -1
  140. package/.next/server/chunks/_0iwfby5._.js +3 -0
  141. package/.next/server/chunks/_0mecv0f._.js +26 -0
  142. package/.next/server/chunks/_0mh8j4m._.js +3 -0
  143. package/.next/server/chunks/_0n74zsf._.js +4 -4
  144. package/.next/server/chunks/_0obojvv._.js +3 -0
  145. package/.next/server/chunks/_0recufk._.js +49 -0
  146. package/.next/server/chunks/_0rnf-6n._.js +4 -4
  147. package/.next/server/chunks/_0sb7tlz._.js +3 -0
  148. package/.next/server/chunks/_0u10wmw._.js +5 -5
  149. package/.next/server/chunks/_0u4aiy2._.js +3 -0
  150. package/.next/server/chunks/_0wp4le3._.js +1 -1
  151. package/.next/server/chunks/_0y5fg-x._.js +1 -1
  152. package/.next/server/chunks/_1230wbx._.js +10 -0
  153. package/.next/server/chunks/_12nheja._.js +3 -0
  154. package/.next/server/chunks/_13510xh._.js +3 -0
  155. package/.next/server/chunks/_15hq89o._.js +1 -1
  156. package/.next/server/chunks/_17l5ygt._.js +49 -0
  157. package/.next/server/chunks/_18-1wcc._.js +5 -5
  158. package/.next/server/chunks/_1_5mnq4._.js +4 -4
  159. package/.next/server/chunks/_1_9mjx-._.js +3 -0
  160. package/.next/server/chunks/{_0pppbb5._.js → _1c78vw5._.js} +166 -37
  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]__092knlj._.js +3 -0
  195. package/.next/server/chunks/ssr/[root-of-the-server]__09q9med._.js +1 -1
  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]__0s9dq5u._.js +3 -0
  200. package/.next/server/chunks/ssr/{[root-of-the-server]__0m1b5ky._.js → [root-of-the-server]__0s9l2sv._.js} +1 -1
  201. package/.next/server/chunks/ssr/[root-of-the-server]__0tbkdlx._.js +3 -0
  202. package/.next/server/chunks/ssr/[root-of-the-server]__0vnmv-s._.js +3 -0
  203. package/.next/server/chunks/ssr/{[root-of-the-server]__0f6s48x._.js → [root-of-the-server]__0xpcv9w._.js} +3 -3
  204. package/.next/server/chunks/ssr/[root-of-the-server]__0xsog8n._.js +3 -0
  205. package/.next/server/chunks/ssr/[root-of-the-server]__0xtssj3._.js +1 -1
  206. package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +61 -0
  207. package/.next/server/chunks/ssr/[root-of-the-server]__15_uhip._.js +3 -0
  208. package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
  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]__1qfqvmg._.js → [root-of-the-server]__202p40z._.js} +2 -2
  213. package/.next/server/chunks/ssr/{_1mznrxk._.js → _001_ms1._.js} +3 -3
  214. package/.next/server/chunks/ssr/_01n3o0m._.js +3 -0
  215. package/.next/server/chunks/ssr/_0ap2fzn._.js +3 -0
  216. package/.next/server/chunks/ssr/_0fz4mf_._.js +3 -0
  217. package/.next/server/chunks/ssr/_0gb4gmf._.js +3 -0
  218. package/.next/server/chunks/ssr/_0h42fze._.js +3 -0
  219. package/.next/server/chunks/ssr/_0h7zdni._.js +1 -1
  220. package/.next/server/chunks/ssr/_0i_6q1w._.js +41 -0
  221. package/.next/server/chunks/ssr/_0ilna52._.js +42 -0
  222. package/.next/server/chunks/ssr/_0n3toaw._.js +3 -0
  223. package/.next/server/chunks/ssr/{_13punpm._.js → _0q0zan6._.js} +2 -2
  224. package/.next/server/chunks/ssr/{_077-g6s._.js → _0s99bgb._.js} +3 -3
  225. package/.next/server/chunks/ssr/_0zcjrbg._.js +3 -0
  226. package/.next/server/chunks/ssr/_0zhoc3r._.js +3 -0
  227. package/.next/server/chunks/ssr/{_1lip4th._.js → _1-_etts._.js} +2 -2
  228. package/.next/server/chunks/ssr/_1-teee5._.js +3 -3
  229. package/.next/server/chunks/ssr/_13fke0x._.js +3 -0
  230. package/.next/server/chunks/ssr/_15j2_8f._.js +3 -0
  231. package/.next/server/chunks/ssr/_1b2mjwr._.js +3 -0
  232. package/.next/server/chunks/ssr/{_09ja_w1._.js → _1f-dg-6._.js} +2 -2
  233. package/.next/server/chunks/ssr/_1fojd41._.js +4 -0
  234. package/.next/server/chunks/ssr/_1gd8q8l._.js +3 -0
  235. package/.next/server/chunks/ssr/{_1m3bsfr._.js → _1h0rw11._.js} +2 -2
  236. package/.next/server/chunks/ssr/_1jhd09t._.js +3 -0
  237. package/.next/server/chunks/ssr/{_040sk32._.js → _1lz_cq2._.js} +84 -88
  238. package/.next/server/chunks/ssr/_1nnsk7z._.js +3 -0
  239. package/.next/server/chunks/ssr/_1sji22n._.js +3 -0
  240. package/.next/server/chunks/ssr/{_0x_nu5e._.js → _1vi_uo7._.js} +2 -2
  241. package/.next/server/chunks/ssr/_1vyd1ji._.js +1 -1
  242. package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +3 -0
  243. package/.next/server/chunks/ssr/features_config_components_config-setting_tsx_0xfwqdg._.js +1 -1
  244. package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
  245. package/.next/server/chunks/ssr/{node_modules_0kxz4gt._.js → node_modules_00etblx._.js} +1 -1
  246. package/.next/server/chunks/ssr/{node_modules_18_dk7_._.js → node_modules_04jf_m8._.js} +1 -1
  247. package/.next/server/chunks/ssr/{node_modules_0_n241r._.js → node_modules_08dhkiq._.js} +1 -1
  248. package/.next/server/chunks/ssr/{node_modules_0n1kj4p._.js → node_modules_0940ns5._.js} +1 -1
  249. package/.next/server/chunks/ssr/{node_modules_17lrt3y._.js → node_modules_09q35v_._.js} +1 -1
  250. package/.next/server/chunks/ssr/{node_modules_1toafc-._.js → node_modules_0_-_a--._.js} +1 -1
  251. package/.next/server/chunks/ssr/{node_modules_0lrjk5t._.js → node_modules_0arus10._.js} +1 -1
  252. package/.next/server/chunks/ssr/{node_modules_04n7mjs._.js → node_modules_0b__sgl._.js} +1 -1
  253. package/.next/server/chunks/ssr/{node_modules_0iz1rzd._.js → node_modules_0cxaxk9._.js} +1 -1
  254. package/.next/server/chunks/ssr/{node_modules_0ndvxub._.js → node_modules_0g7fzk3._.js} +1 -1
  255. package/.next/server/chunks/ssr/{node_modules_0kl7-tn._.js → node_modules_0had7xd._.js} +1 -1
  256. package/.next/server/chunks/ssr/{node_modules_19dp7ko._.js → node_modules_0pvd7q-._.js} +1 -1
  257. package/.next/server/chunks/ssr/node_modules_0x3-ply._.js +3 -0
  258. package/.next/server/chunks/ssr/{node_modules_1dwguw_._.js → node_modules_0yugy6m._.js} +1 -1
  259. package/.next/server/chunks/ssr/{node_modules_004qlr4._.js → node_modules_14om4ar._.js} +1 -1
  260. package/.next/server/chunks/ssr/{node_modules_1q0p85z._.js → node_modules_14q6g4n._.js} +1 -1
  261. package/.next/server/chunks/ssr/node_modules_17bwo43._.js +55 -0
  262. package/.next/server/chunks/ssr/{node_modules_1hd-5tv._.js → node_modules_198nmll._.js} +1 -1
  263. package/.next/server/chunks/ssr/{node_modules_0m93zeg._.js → node_modules_1_pc9kq._.js} +1 -1
  264. package/.next/server/chunks/ssr/{node_modules_1n5ygqe._.js → node_modules_1aaxuef._.js} +1 -1
  265. package/.next/server/chunks/ssr/{node_modules_01qnv-a._.js → node_modules_1cx_ql6._.js} +1 -1
  266. package/.next/server/chunks/ssr/{node_modules_1zu988w._.js → node_modules_1cz2hle._.js} +1 -1
  267. package/.next/server/chunks/ssr/{node_modules_1xyd7ov._.js → node_modules_1efrqxi._.js} +1 -1
  268. package/.next/server/chunks/ssr/{node_modules_13r44jq._.js → node_modules_1eg7m6c._.js} +1 -1
  269. package/.next/server/chunks/ssr/{node_modules_08d8bke._.js → node_modules_1gdh31p._.js} +1 -1
  270. package/.next/server/chunks/ssr/{node_modules_1hn8z1f._.js → node_modules_1hpopmo._.js} +1 -1
  271. package/.next/server/chunks/ssr/{node_modules_20yebtj._.js → node_modules_1qpjvy5._.js} +1 -1
  272. package/.next/server/chunks/ssr/{node_modules_09xhur7._.js → node_modules_1vh5ntv._.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_1b748ic._.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_1z4hm5e._.js} +1 -1
  275. package/.next/server/chunks/ssr/node_modules_@vercel_oidc_dist_06mk8id._.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/00rd4-v8r7axp.js +1 -0
  285. package/.next/static/chunks/08qe4as2q428z.js +3 -0
  286. package/.next/static/chunks/{31ttnjt6g35a0.js → 0ev4hyghq0mbb.js} +1 -1
  287. package/.next/static/chunks/0fl3gwe4-l6tz.js +1 -0
  288. package/.next/static/chunks/0gnqdjn2lvdad.js +2 -0
  289. package/.next/static/chunks/0hwap1-p0m5sa.js +1 -0
  290. package/.next/static/chunks/0r5qcctujhxli.js +1 -0
  291. package/.next/static/chunks/0w52rrrmuj9r9.js +1 -0
  292. package/.next/static/chunks/{07kl352c-lvcz.js → 0wcprt5ot5she.js} +1 -1
  293. package/.next/static/chunks/10teww7wt-f6h.js +1 -0
  294. package/.next/static/chunks/15m575979un5f.js +38 -0
  295. package/.next/static/chunks/17p6tk6k88dq6.js +1 -0
  296. package/.next/static/chunks/{3_h9txt3tq8t8.js → 1dkjg87pxk0n9.js} +1 -1
  297. package/.next/static/chunks/1jd09sxcjddu1.js +1 -0
  298. package/.next/static/chunks/1kq8h8wi_e0bc.js +53 -0
  299. package/.next/static/chunks/{18vhba44l1fc9.js → 1w73ece_6bheu.js} +1 -1
  300. package/.next/static/chunks/{3ard_noqapnw1.js → 214ya3n5gxeih.js} +1 -1
  301. package/.next/static/chunks/22_zkas21rpna.js +1 -0
  302. package/.next/static/chunks/2h0sd2vumhb15.js +1 -0
  303. package/.next/static/chunks/2t4vhi3m8ahya.js +1 -0
  304. package/.next/static/chunks/2tigdtz3dpcy8.js +1 -0
  305. package/.next/static/chunks/2u7xt6mxg44lf.js +1 -0
  306. package/.next/static/chunks/39j0fvpybzabl.js +40 -0
  307. package/.next/static/chunks/3akmqm77muj4-.js +1 -0
  308. package/.next/static/chunks/3cq5g494yuke8.css +1 -0
  309. package/.next/static/chunks/3woj-xd7ki5_i.js +1 -0
  310. package/.next/static/chunks/3xk7yqgomx7yq.js +1 -0
  311. package/.next/static/chunks/3zmcsnuo25zvq.js +1 -0
  312. package/.next/static/media/favicon.37o1pjldwi2uc.ico +0 -0
  313. package/README.md +47 -22
  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 -7
  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/port.mjs +65 -0
  324. package/bin/thursday.mjs +5 -33
  325. package/components/ui/shiny-text.tsx +48 -134
  326. package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/migration.sql +24 -34
  327. package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/snapshot.json +71 -145
  328. package/database/migrations/20260911030320_opposite_jack_power/migration.sql +1 -0
  329. package/database/migrations/{20260909063821_bitter_tenebrous → 20260911030320_opposite_jack_power}/snapshot.json +57 -184
  330. package/docs/how-it-works.md +11 -7
  331. package/docs/images/face-dark.png +0 -0
  332. package/docs/images/face-light.png +0 -0
  333. package/docs/images/keeps-going.png +0 -0
  334. package/features/ai/chatgpt.ts +639 -0
  335. package/features/ai/components/chatgpt-sign-in.tsx +66 -0
  336. package/features/ai/components/model-picker.tsx +17 -1
  337. package/features/ai/components/provider-icon.tsx +1 -0
  338. package/features/ai/load-tools.ts +78 -56
  339. package/features/ai/model.schema.ts +232 -34
  340. package/features/ai/model.ts +169 -24
  341. package/features/ai/prompts/bot.prompt.ts +207 -114
  342. package/features/ai/prompts/memory-edit.prompt.ts +33 -0
  343. package/features/ai/prompts/prompt-helper.ts +45 -26
  344. package/features/ai/prompts/thursday.prompt.ts +57 -27
  345. package/features/ai/tools/bot.tool.ts +35 -52
  346. package/features/ai/tools/connected.ts +17 -4
  347. package/features/ai/tools/memory.tool.ts +181 -117
  348. package/features/ai/tools/search.tool.ts +136 -47
  349. package/features/ai/tools/tool-name.ts +2 -6
  350. package/features/ai/tools/workspace.tool.ts +5 -1
  351. package/features/bot/bot.action.ts +14 -19
  352. package/features/bot/bot.memory.ts +89 -0
  353. package/features/bot/bot.query.ts +37 -57
  354. package/features/bot/bot.run.ts +512 -242
  355. package/features/bot/bot.runner.ts +434 -120
  356. package/features/bot/bot.schema.ts +104 -19
  357. package/features/bot/bot.seed.ts +89 -16
  358. package/features/bot/components/bot-mark.tsx +122 -20
  359. package/features/bot/components/bot-room.tsx +214 -132
  360. package/features/bot/components/bot-setting.tsx +790 -402
  361. package/features/bot/components/bot-tool.tsx +2 -7
  362. package/features/bot/components/mark-palette.tsx +54 -0
  363. package/features/bot/components/path-chips.tsx +1 -1
  364. package/features/bot/components/task-badge.tsx +26 -6
  365. package/features/bot/components/task-reply.tsx +22 -33
  366. package/features/bot/components/task-setting.tsx +20 -17
  367. package/features/bot/task.query.ts +240 -34
  368. package/features/bot/task.store.ts +76 -13
  369. package/features/config/components/config-setting.tsx +265 -34
  370. package/features/config/components/models-badge.tsx +42 -0
  371. package/features/config/config.action.ts +12 -0
  372. package/features/config/config.const.ts +38 -2
  373. package/features/connectors/mcp.manager.ts +10 -2
  374. package/features/intro/components/intro.tsx +47 -46
  375. package/features/memory/components/memory-edit.tsx +340 -0
  376. package/features/memory/components/memory-setting.tsx +75 -77
  377. package/features/memory/memory.action.ts +3 -43
  378. package/features/memory/memory.edit.ts +87 -0
  379. package/features/memory/memory.query.ts +24 -42
  380. package/features/memory/memory.schema.ts +29 -106
  381. package/features/settings/components/settings.tsx +2 -0
  382. package/features/settings/settings.alert.ts +3 -1
  383. package/features/thursday/components/ascii-orb.tsx +106 -90
  384. package/features/thursday/components/boot.tsx +7 -0
  385. package/features/thursday/components/call-log.tsx +219 -92
  386. package/features/thursday/components/face.tsx +6 -4
  387. package/features/thursday/components/tab-state.tsx +97 -0
  388. package/features/thursday/components/thursday-mark.tsx +4 -1
  389. package/features/thursday/components/thursday-setting.tsx +17 -47
  390. package/features/thursday/components/thursday.tsx +208 -98
  391. package/features/thursday/thursday.action.ts +12 -17
  392. package/features/thursday/thursday.query.ts +61 -70
  393. package/features/thursday/thursday.schema.ts +20 -7
  394. package/features/thursday/tool-line.ts +85 -12
  395. package/features/thursday/use-thursday.ts +87 -60
  396. package/features/workspace/components/file-view.tsx +4 -2
  397. package/features/workspace/workspace.ts +110 -26
  398. package/lib/limits.ts +1 -1
  399. package/lib/oauth-page.ts +27 -0
  400. package/lib/realtime/openai.ts +2 -2
  401. package/lib/realtime/realtime.protocol.ts +1 -1
  402. package/lib/realtime/realtime.tap.ts +122 -0
  403. package/lib/sandbox.ts +59 -36
  404. package/package.json +1 -1
  405. package/skills/browser/SKILL.md +55 -34
  406. package/.next/server/app/api/bot/notes/route/app-paths-manifest.json +0 -3
  407. package/.next/server/app/api/bot/notes/route.js +0 -14
  408. package/.next/server/app/api/bot/notes/route_client-reference-manifest.js +0 -3
  409. package/.next/server/app/api/memory/tidy/route/app-paths-manifest.json +0 -3
  410. package/.next/server/app/api/memory/tidy/route.js +0 -22
  411. package/.next/server/app/api/memory/tidy/route.js.nft.json +0 -1
  412. package/.next/server/chunks/0d-b_next_dist_server_app-render_after-task-async-storage_external_0-exn7p.js +0 -3
  413. package/.next/server/chunks/[root-of-the-server]__0-npkh_._.js +0 -3
  414. package/.next/server/chunks/[root-of-the-server]__005var5._.js +0 -3
  415. package/.next/server/chunks/[root-of-the-server]__019dx9f._.js +0 -5
  416. package/.next/server/chunks/[root-of-the-server]__02_2sm-._.js +0 -5
  417. package/.next/server/chunks/[root-of-the-server]__04_8spk._.js +0 -3
  418. package/.next/server/chunks/[root-of-the-server]__05luceg._.js +0 -3
  419. package/.next/server/chunks/[root-of-the-server]__06t77t4._.js +0 -11
  420. package/.next/server/chunks/[root-of-the-server]__0bed6hu._.js +0 -8
  421. package/.next/server/chunks/[root-of-the-server]__0cro2dz._.js +0 -5
  422. package/.next/server/chunks/[root-of-the-server]__0dupqt7._.js +0 -5
  423. package/.next/server/chunks/[root-of-the-server]__0emr6go._.js +0 -3
  424. package/.next/server/chunks/[root-of-the-server]__0le4d-p._.js +0 -3
  425. package/.next/server/chunks/[root-of-the-server]__0m8ywyo._.js +0 -10
  426. package/.next/server/chunks/[root-of-the-server]__0nfuugi._.js +0 -5
  427. package/.next/server/chunks/[root-of-the-server]__0p32jfz._.js +0 -12
  428. package/.next/server/chunks/[root-of-the-server]__0phdgco._.js +0 -8
  429. package/.next/server/chunks/[root-of-the-server]__0wvgrsl._.js +0 -3
  430. package/.next/server/chunks/[root-of-the-server]__10qshki._.js +0 -3
  431. package/.next/server/chunks/[root-of-the-server]__11j52t0._.js +0 -5
  432. package/.next/server/chunks/[root-of-the-server]__1692zrv._.js +0 -3
  433. package/.next/server/chunks/[root-of-the-server]__16thabu._.js +0 -3
  434. package/.next/server/chunks/[root-of-the-server]__173nhwf._.js +0 -8
  435. package/.next/server/chunks/[root-of-the-server]__1_aoyr9._.js +0 -3
  436. package/.next/server/chunks/[root-of-the-server]__1bn73ih._.js +0 -10
  437. package/.next/server/chunks/[root-of-the-server]__1bqhuh9._.js +0 -8
  438. package/.next/server/chunks/[root-of-the-server]__1cqizfq._.js +0 -5
  439. package/.next/server/chunks/[root-of-the-server]__1e-ci13._.js +0 -3
  440. package/.next/server/chunks/[root-of-the-server]__1fboj2j._.js +0 -3
  441. package/.next/server/chunks/[root-of-the-server]__1lr7j9t._.js +0 -5
  442. package/.next/server/chunks/[root-of-the-server]__1oli73c._.js +0 -3
  443. package/.next/server/chunks/[root-of-the-server]__1txedx6._.js +0 -8
  444. package/.next/server/chunks/[root-of-the-server]__1untqv8._.js +0 -5
  445. package/.next/server/chunks/[root-of-the-server]__1zgpz1w._.js +0 -3
  446. package/.next/server/chunks/_00_584r._.js +0 -293
  447. package/.next/server/chunks/_012yhfm._.js +0 -39
  448. package/.next/server/chunks/_06mxlgn._.js +0 -3
  449. package/.next/server/chunks/_07rtlxv._.js +0 -3
  450. package/.next/server/chunks/_0a351g7._.js +0 -6
  451. package/.next/server/chunks/_0kjjmag._.js +0 -3
  452. package/.next/server/chunks/_0nn99o2._.js +0 -3
  453. package/.next/server/chunks/_0zuzmt_._.js +0 -39
  454. package/.next/server/chunks/_106co2o._.js +0 -3
  455. package/.next/server/chunks/_12bbv5i._.js +0 -100
  456. package/.next/server/chunks/_15q1pig._.js +0 -3
  457. package/.next/server/chunks/_19wg5yn._.js +0 -138
  458. package/.next/server/chunks/_1bt95p9._.js +0 -55
  459. package/.next/server/chunks/_1cbk7ms._.js +0 -26
  460. package/.next/server/chunks/_1drv2et._.js +0 -40
  461. package/.next/server/chunks/_1ic3bew._.js +0 -5
  462. package/.next/server/chunks/_1mxn_lb._.js +0 -3
  463. package/.next/server/chunks/_1rysr-r._.js +0 -10
  464. package/.next/server/chunks/_1u3rwbr._.js +0 -3
  465. package/.next/server/chunks/_1x7p319._.js +0 -6
  466. package/.next/server/chunks/_next-internal_server_app_api_bot_notes_route_actions_0qcsyu7.js +0 -3
  467. package/.next/server/chunks/_next-internal_server_app_api_memory_tidy_route_actions_0_cfuom.js +0 -3
  468. package/.next/server/chunks/features_bot_task_query_ts_11xuzl3._.js +0 -3
  469. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0gzvgfv._.js +0 -3
  470. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0vorg6w._.js +0 -3
  471. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1tpvamf._.js +0 -3
  472. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1vmaq9f._.js +0 -3
  473. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1y9-wcr._.js +0 -3
  474. package/.next/server/chunks/ssr/[externals]_node_crypto_1kn79-7._.js +0 -3
  475. package/.next/server/chunks/ssr/[root-of-the-server]__0iuoa-r._.js +0 -3
  476. package/.next/server/chunks/ssr/[root-of-the-server]__0un-erv._.js +0 -4
  477. package/.next/server/chunks/ssr/[root-of-the-server]__1-mnhyd._.js +0 -92
  478. package/.next/server/chunks/ssr/[root-of-the-server]__1bww500._.js +0 -3
  479. package/.next/server/chunks/ssr/[root-of-the-server]__1vcdast._.js +0 -3
  480. package/.next/server/chunks/ssr/[root-of-the-server]__1xwnu-h._.js +0 -3
  481. package/.next/server/chunks/ssr/_0-mc7ro._.js +0 -3
  482. package/.next/server/chunks/ssr/_01p5r6-._.js +0 -3
  483. package/.next/server/chunks/ssr/_03webdr._.js +0 -3
  484. package/.next/server/chunks/ssr/_09-0k3z._.js +0 -3
  485. package/.next/server/chunks/ssr/_0f_b_9s._.js +0 -3
  486. package/.next/server/chunks/ssr/_0fafgvl._.js +0 -3
  487. package/.next/server/chunks/ssr/_0sf1isi._.js +0 -3
  488. package/.next/server/chunks/ssr/_0su6_08._.js +0 -3
  489. package/.next/server/chunks/ssr/_0ti51xc._.js +0 -3
  490. package/.next/server/chunks/ssr/_0w5bgak._.js +0 -3
  491. package/.next/server/chunks/ssr/_0y84qo6._.js +0 -3
  492. package/.next/server/chunks/ssr/_1ciyoo3._.js +0 -3
  493. package/.next/server/chunks/ssr/_1e-dgz0._.js +0 -4
  494. package/.next/server/chunks/ssr/_1fq7zgb._.js +0 -3
  495. package/.next/server/chunks/ssr/_1g6l4uj._.js +0 -3
  496. package/.next/server/chunks/ssr/_1ruzehw._.js +0 -3
  497. package/.next/server/chunks/ssr/features_bot_components_bot-setting_tsx_01ajft6._.js +0 -4
  498. package/.next/server/chunks/ssr/features_config_components_14jqgy4._.js +0 -3
  499. package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +0 -4
  500. package/.next/server/chunks/ssr/node_modules_zod_v4_classic_external_15fmmz3.js +0 -55
  501. package/.next/static/chunks/05b6nx_o3_f_n.js +0 -1
  502. package/.next/static/chunks/0dmns-gi0raa4.js +0 -1
  503. package/.next/static/chunks/0f9sq-7q_yxyl.js +0 -1
  504. package/.next/static/chunks/0oc4_xoia77dg.css +0 -1
  505. package/.next/static/chunks/0pheo8m3a-rzi.js +0 -1
  506. package/.next/static/chunks/19i8h2t-5evjx.js +0 -1
  507. package/.next/static/chunks/1c5fcj473025q.js +0 -1
  508. package/.next/static/chunks/1pi_hbmjw-f-z.js +0 -1
  509. package/.next/static/chunks/1twt6k09vg4np.js +0 -1
  510. package/.next/static/chunks/1ytnip8wdng93.js +0 -1
  511. package/.next/static/chunks/28gotuisldmom.js +0 -1
  512. package/.next/static/chunks/2998p0y7k1c8z.js +0 -3
  513. package/.next/static/chunks/29gyb3nubj51j.js +0 -53
  514. package/.next/static/chunks/2l233xfycjpd8.js +0 -1
  515. package/.next/static/chunks/2p5n7pa3c40t-.js +0 -2
  516. package/.next/static/chunks/2ru1q132af7h7.js +0 -1
  517. package/.next/static/chunks/2t8wqycwg3y04.js +0 -2
  518. package/.next/static/chunks/2uxum7qbyeyxd.js +0 -1
  519. package/.next/static/chunks/32z_ypgtchw48.js +0 -1
  520. package/.next/static/chunks/33pyjb3xd1iez.js +0 -1
  521. package/.next/static/chunks/3omud5xunrk1f.js +0 -1
  522. package/.next/static/chunks/42dnrkbph9e-1.js +0 -1
  523. package/.next/static/media/favicon.2vob68tjqpejf.ico +0 -0
  524. package/database/migrations/20260909063821_bitter_tenebrous/migration.sql +0 -1
  525. package/features/ai/prompts/memory-tidy.prompt.ts +0 -129
  526. package/features/ai/tools/tidy.tool.ts +0 -22
  527. package/features/bot/bot.notes.ts +0 -120
  528. package/features/memory/components/memory-tidy.tsx +0 -395
  529. package/features/memory/components/memory-view.tsx +0 -84
  530. package/features/memory/memory.tidy.ts +0 -332
  531. package/features/memory/tidy.query.ts +0 -135
  532. package/features/thursday/use-call-title.ts +0 -31
  533. /package/.next/server/app/api/bot/{notes → memory/files}/route/build-manifest.json +0 -0
  534. /package/.next/server/app/api/bot/{notes → memory/files}/route/server-reference-manifest.json +0 -0
  535. /package/.next/server/app/api/bot/{notes → memory/files}/route.js.map +0 -0
  536. /package/.next/server/app/api/{memory/tidy → bot/memory}/route/build-manifest.json +0 -0
  537. /package/.next/server/app/api/{memory/tidy → bot/memory}/route/server-reference-manifest.json +0 -0
  538. /package/.next/server/app/api/{memory/tidy → bot/memory}/route.js.map +0 -0
  539. /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → kaTO0UHqF1bMnWgCDik2f}/_buildManifest.js +0 -0
  540. /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → kaTO0UHqF1bMnWgCDik2f}/_clientMiddlewareManifest.js +0 -0
  541. /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → kaTO0UHqF1bMnWgCDik2f}/_ssgManifest.js +0 -0
@@ -1,22 +1,29 @@
1
1
  import { tool } from "ai";
2
2
  import * as z from "zod";
3
- import { appEvents } from "@/app/api/events/app-event.server";
3
+ import { MEMORY_CONVERSATION_PAGE, MEMORY_LIMITS } from "@/config";
4
+ import {
5
+ callStamp,
6
+ conversationLines,
7
+ saidStamp,
8
+ } from "@/features/ai/prompts/prompt-helper";
4
9
  import { TOOL_NAMES } from "@/features/ai/tools/tool-name";
5
10
  import {
11
+ findFactCall,
6
12
  forgetFactById,
7
13
  readNotes,
8
14
  resolveNotePath,
9
15
  writeNotes,
10
16
  } from "@/features/memory/memory.query";
11
17
  import {
12
- ALWAYS_LOADED_MAX,
13
- isAlwaysListed,
18
+ APP_NAMED_NOTES,
19
+ appNoteLine,
20
+ isAppNamed,
14
21
  isMemoryPath,
15
- MANY_FACTS,
16
- MEMORY_ALWAYS_LISTED,
17
22
  MEMORY_INBOX,
23
+ type MemoryNoteView,
18
24
  type MemorySource,
19
25
  } from "@/features/memory/memory.schema";
26
+ import { readCallConversation } from "@/features/thursday/thursday.query";
20
27
 
21
28
  const GONE =
22
29
  "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 +31,56 @@ const GONE =
24
31
  const WROTE =
25
32
  "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
33
 
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.`;
34
+ /**
35
+ * A note as a model reads it: how many facts it holds now, and `said` on each
36
+ * fact a call wrote the local time of that call, the same stamp its
37
+ * conversation opens with, so a fact from a call already in the prompt reads
38
+ * as that call. Never the Date itself: it would serialise as UTC.
39
+ */
40
+ const withCount = (note: MemoryNoteView) => ({
41
+ ...note,
42
+ facts: note.facts.map(({ saidAt, ...fact }) =>
43
+ saidAt ? { ...fact, said: saidStamp(saidAt) } : fact,
44
+ ),
45
+ factCount: note.facts.length,
46
+ });
47
+
48
+ /** Why a fact has no conversation to open, by the hand that wrote it. */
49
+ const noConversation = (source: MemorySource | null) =>
50
+ source === "user"
51
+ ? "Typed on the screen — there is no conversation behind it."
52
+ : source === "bot"
53
+ ? "Saved by a bot during a job — there is no conversation behind it."
54
+ : "The conversation it was saved in is not kept.";
55
+
56
+ /**
57
+ * Said when a note has outgrown the recommended size, and only then — the write
58
+ * itself always goes through. It names no tool: this one answers the call and a
59
+ * bot, and how to settle it with the user is the call's to say (prompts/thursday.prompt);
60
+ * the ask is the same either way, because a bot that turned up a fact can hand
61
+ * the same request back with it.
62
+ */
63
+ const overSize = (count: number) =>
64
+ count > MEMORY_LIMITS.factsPerNote
65
+ ? ` 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.`
66
+ : "";
30
67
 
31
68
  /**
32
69
  * @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).
70
+ * it without being told, so no model ever chooses it (load-tools,
71
+ * memory.schema MemorySource).
72
+ * @param callId The call these tools serve, when there is one: recorded on
73
+ * what `memory_remember` writes, and the conversation `memory_conversation`
74
+ * does not hand back because the model is already in it.
75
+ * @param options.countReads Whether opening a note counts as reading it. The
76
+ * counts rank notes cold in the call prompt, so only a runtime that recalls on
77
+ * the user's behalf counts; an edit opening a note to change it does not.
35
78
  */
36
- export const createMemoryTools = (source: MemorySource) => ({
79
+ export const createMemoryTools = (
80
+ source: MemorySource,
81
+ callId: string | null = null,
82
+ { countReads = true }: { countReads?: boolean } = {},
83
+ ) => ({
37
84
  [TOOL_NAMES.memory_recall]: tool({
38
85
  description: "Open one note from the listing, whole.",
39
86
  inputSchema: z.object({
@@ -44,14 +91,13 @@ export const createMemoryTools = (source: MemorySource) => ({
44
91
  ),
45
92
  }),
46
93
  execute: async ({ path }) => {
47
- const { notes } = await readNotes([path]);
94
+ const { notes } = await readNotes([path], { touch: countReads });
48
95
  const note = notes[0];
49
96
  // A missing note is an answer to relay, not a reason to retry spellings
50
97
  if (!note)
51
98
  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;
99
+ const over = overSize(note.facts.length);
100
+ return over ? { ...withCount(note), note: over.trim() } : withCount(note);
55
101
  },
56
102
  }),
57
103
 
@@ -67,7 +113,9 @@ export const createMemoryTools = (source: MemorySource) => ({
67
113
  .object({
68
114
  text: z
69
115
  .string()
70
- .describe("One statement that stands on its own later."),
116
+ .describe(
117
+ 'One statement that stands on its own later — a date as a date, never "next week".',
118
+ ),
71
119
  replaces: z
72
120
  .number()
73
121
  .int()
@@ -79,7 +127,7 @@ export const createMemoryTools = (source: MemorySource) => ({
79
127
  .boolean()
80
128
  .nullish()
81
129
  .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.`,
130
+ `True carries this line into every call's instructions without opening its note — for what every call needs before any note is opened: what to call them, their language and register. At most ${MEMORY_LIMITS.carried}. Null leaves it; false makes a carried line an ordinary fact.`,
83
131
  ),
84
132
  })
85
133
  .array()
@@ -91,7 +139,7 @@ export const createMemoryTools = (source: MemorySource) => ({
91
139
  .string()
92
140
  .nullish()
93
141
  .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.`,
142
+ `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
143
  ),
96
144
  aliases: z
97
145
  .string()
@@ -106,11 +154,15 @@ export const createMemoryTools = (source: MemorySource) => ({
106
154
  const said = input.path.trim();
107
155
  const known = await resolveNotePath(said);
108
156
  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;
157
+ // The listing line of the app-named notes is the app's (memory.schema
158
+ // isAppNamed); the model's description is ignored there and its own line
159
+ // written instead, so the inbox cannot end up described by whatever fell
160
+ // into it. `alwaysLoad` is not forced on them: the first-call opener
161
+ // (thursday.prompt) asks the model to set it.
162
+ const target = known ?? said;
163
+ const description = isAppNamed(target)
164
+ ? appNoteLine(target)
165
+ : input.description?.trim() || null;
114
166
  const facts = input.facts ?? [];
115
167
  if (!facts.length && !description && !aliases) {
116
168
  return {
@@ -124,139 +176,151 @@ export const createMemoryTools = (source: MemorySource) => ({
124
176
  };
125
177
  }
126
178
  // A new path outside the convention goes to inbox, which keeps its own line and takes no aliases
127
- const filed =
128
- known || isMemoryPath(said)
129
- ? { path: known ?? said, description, aliases, facts }
130
- : {
131
- path: MEMORY_INBOX,
132
- description: "Facts with nowhere obvious to go",
133
- facts,
134
- };
179
+ const toInbox = !known && !isMemoryPath(said);
180
+ const filed = toInbox
181
+ ? {
182
+ path: MEMORY_INBOX,
183
+ description: appNoteLine(MEMORY_INBOX),
184
+ facts,
185
+ }
186
+ : { path: target, description, aliases, facts };
135
187
 
136
- const write = await writeNotes([filed], source);
188
+ const write = await writeNotes([filed], source, callId);
137
189
 
138
190
  // The write already succeeded; what follows are requests, not failures.
139
- // A path filed elsewhere must be said, or the model reports it saved where it asked.
140
- const elsewhere =
141
- filed.path !== said
142
- ? ` Filed under ${filed.path}: "${said}" is not a path this listing can carry. If that is not where it belongs, write it again under one that is.`
143
- : "";
191
+ // Only a path that landed in inbox is said: one reached by a name the
192
+ // listing carries is where it was asked for, however it was spelled.
193
+ const elsewhere = toInbox
194
+ ? ` Filed under ${filed.path}: "${said}" is not a path this listing can carry. If that is not where it belongs, write it again under one that is.`
195
+ : "";
144
196
 
145
197
  const unnamed = write.unnamed.length
146
198
  ? ` ${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
199
  : "";
148
- // Carried lines are full: saved as an ordinary fact, and the user picks what to drop (ALWAYS_LOADED_MAX)
200
+ // Carried lines are full: saved as an ordinary fact, and the user picks what to drop (config MEMORY_LIMITS.carried)
149
201
  const notLoaded = write.notLoaded.length
150
- ? ` All ${ALWAYS_LOADED_MAX} carried lines are taken, so ${write.notLoaded
202
+ ? ` All ${MEMORY_LIMITS.carried} carried lines are taken, so ${write.notLoaded
151
203
  .map((text) => `"${text}"`)
152
204
  .join(
153
205
  ", ",
154
206
  )} saved as an ordinary fact. Say which carried line you would drop for it and let them choose.`
155
207
  : "";
208
+ const written = withCount(write.notes[0]);
156
209
  return {
157
- ...write.notes[0],
158
- note: `${WROTE}${elsewhere}${unnamed}${notLoaded}`,
210
+ ...written,
211
+ note: `${WROTE}${elsewhere}${unnamed}${notLoaded}${overSize(written.factCount)}`,
159
212
  };
160
213
  },
161
214
  }),
162
215
 
163
- [TOOL_NAMES.memory_show]: tool({
164
- description: `Put a note on the user's screen so they can see it while you
165
- talk about it, and take it away again. They cannot edit it there they say
166
- what to drop and you drop it.`,
216
+ [TOOL_NAMES.memory_conversation]: tool({
217
+ description:
218
+ "Open the conversation a fact was saved in, whole: what each side said, and which tools were used.",
167
219
  inputSchema: z.object({
168
- path: z
169
- .string()
170
- .nullable()
220
+ factId: z
221
+ .number()
222
+ .int()
223
+ .describe("The id that came with the fact when its note was opened."),
224
+ page: z
225
+ .number()
226
+ .int()
227
+ .min(1)
228
+ .nullish()
171
229
  .describe(
172
- "The note to put on screen, exactly as the listing writes it. Null takes it away.",
230
+ `${MEMORY_CONVERSATION_PAGE} turns a page, oldest first. Null for the first.`,
173
231
  ),
174
232
  }),
175
- execute: async ({ path }) => {
176
- if (!path?.trim()) {
177
- appEvents.emit({ type: "memory-view", path: null });
178
- return { note: "Taken off the screen." };
233
+ execute: async ({ factId, page }) => {
234
+ const fact = await findFactCall(factId);
235
+ if (!fact) return { note: `No fact with id ${factId}.` };
236
+ if (!fact.callId) return { note: noConversation(fact.source) };
237
+ // Already in the model's context: handing it back only spends it twice
238
+ if (fact.callId === callId) {
239
+ return {
240
+ note: "Said in this call — it is the conversation you are in.",
241
+ };
179
242
  }
180
- // The screen gets only the path and reads facts over GET, so deletions show up on their own
181
- const { notes } = await readNotes([path], { touch: false });
182
- const note = notes[0];
183
- if (!note) {
184
- return { note: `Nothing on the listing called ${path.trim()}.` };
243
+
244
+ const at = page ?? 1;
245
+ const read = await readCallConversation(
246
+ fact.callId,
247
+ at,
248
+ MEMORY_CONVERSATION_PAGE,
249
+ );
250
+ if (!read) return { note: noConversation(fact.source) };
251
+ const pages = Math.max(
252
+ 1,
253
+ Math.ceil(read.total / MEMORY_CONVERSATION_PAGE),
254
+ );
255
+ if (at > pages) {
256
+ return {
257
+ note: `That conversation has ${pages} page${pages > 1 ? "s" : ""}.`,
258
+ };
185
259
  }
186
- appEvents.emit({ type: "memory-view", path: note.path });
187
260
  return {
188
- ...note,
189
- note: "It is on their screen now, in this order. Ask what they no longer need, and forget only what they name.",
261
+ when: callStamp(read.startedAt),
262
+ page: at,
263
+ pages,
264
+ conversation: conversationLines(read.turns),
190
265
  };
191
266
  },
192
267
  }),
193
268
 
194
269
  [TOOL_NAMES.memory_forget]: tool({
195
- description: "Delete one fact for good.",
270
+ description: "Delete facts for good.",
196
271
  inputSchema: z.object({
197
- factId: z
272
+ factIds: z
198
273
  .number()
199
274
  .int()
200
- .describe("The id that came with the fact when the note was opened."),
275
+ .array()
276
+ .min(1)
277
+ .describe(
278
+ "The ids that came with the facts when their notes were opened — every one to delete, in one call.",
279
+ ),
201
280
  }),
202
- execute: async ({ factId }) => {
203
- const forgotten = await forgetFactById(factId);
204
- if (!forgotten) {
205
- return { note: `No fact with id ${factId}. Nothing was deleted.` };
281
+ execute: async ({ factIds }) => {
282
+ const missing: number[] = [];
283
+ /** Notes that lost their last fact, and went with it (memory.query forgetFactById). */
284
+ const gone: string[] = [];
285
+ /** Notes that still hold something, handed back as they are now. */
286
+ const left = new Set<string>();
287
+ for (const id of new Set(factIds)) {
288
+ const forgotten = await forgetFactById(id);
289
+ if (!forgotten) {
290
+ missing.push(id);
291
+ continue;
292
+ }
293
+ if (forgotten.noteGone) {
294
+ left.delete(forgotten.path);
295
+ gone.push(forgotten.path);
296
+ } else {
297
+ left.add(forgotten.path);
298
+ }
206
299
  }
207
300
 
208
- // The note goes with its last fact; the listing still shows it until the next session, so say so
209
- if (forgotten.noteGone) {
301
+ if (!gone.length && !left.size) {
210
302
  return {
211
- note: `${GONE} That was the last fact under ${forgotten.path}, so the note went with it.`,
303
+ note: `No fact with id ${missing.join(", ")}. Nothing was deleted.`,
212
304
  };
213
305
  }
214
- const { notes } = await readNotes([forgotten.path], { touch: false });
215
- return { ...notes[0], note: GONE };
216
- },
217
- }),
218
- });
219
306
 
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."),
307
+ // The notes that went are still on the listing until the next session, so say so
308
+ const said = [
309
+ GONE,
310
+ gone.length === 1
311
+ ? `That was the last fact under ${gone[0]}, so the note went with it.`
312
+ : gone.length
313
+ ? `That was the last of ${gone.join(", ")}, so those notes went with them.`
314
+ : "",
315
+ missing.length
316
+ ? `No fact with id ${missing.join(", ")}, so those were skipped.`
317
+ : "",
318
+ ]
319
+ .filter(Boolean)
320
+ .join(" ");
321
+ if (!left.size) return { note: said };
322
+ const { notes } = await readNotes([...left], { touch: false });
323
+ return { notes: notes.map(withCount), note: said };
324
+ },
239
325
  }),
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
326
  });
@@ -1,14 +1,25 @@
1
1
  import { generateText, type ToolSet, tool } from "ai";
2
2
  import z from "zod";
3
+ import { SEARCH } from "@/config";
3
4
  import type { TextModel } from "@/features/ai/model";
4
5
  import { TOOL_NAMES } from "@/features/ai/tools/tool-name";
6
+ import { EXA_API_KEY } from "@/features/config/config.const";
7
+ import { readConfig } from "@/features/config/config.query";
5
8
  import type { Sandbox } from "@/lib/sandbox";
9
+ import { clip, errorToString } from "@/lib/utils";
6
10
 
7
11
  /**
8
- * Web search as one tool with one name. The provider-native search runs one call down on a
9
- * search-capable model (`resolveSearchModel`), never in the bot's own request: a provider tool
10
- * cannot be handed to another provider's model, names and result shapes differ per provider,
11
- * and Google cannot send its search tool alongside function tools in one request.
12
+ * Web search as one tool with one name, served whichever way this install can.
13
+ *
14
+ * Exa when its key is set: one HTTP call, the pages themselves back. Otherwise the run's own
15
+ * model's native search, one call down on a searcher that sees nothing but the question — a
16
+ * provider tool cannot be handed to another provider's model, names and result shapes differ
17
+ * per provider, and Google cannot send its search tool alongside function tools in one request.
18
+ *
19
+ * A run whose model has no search of its own (the gateway) and no Exa key gets no search tool:
20
+ * it goes to the browser. Borrowing whichever provider had a key meant a second model call on a
21
+ * model nobody picked, which is where the minute-long searches came from — search is one lookup
22
+ * or it is a job, and a job is what the browser already is.
12
23
  */
13
24
 
14
25
  /** System prompt for the model one call down; it sees nothing but the question. */
@@ -17,57 +28,135 @@ what supports it. Say plainly what you could not find or confirm — do not fill
17
28
  the gap with a guess. Every number carries the date you saw it. Be brief: this
18
29
  is read by another model, not by a person.`;
19
30
 
20
- /** How many sources are worth carrying back. Past this it is noise. */
21
- const SOURCE_LIMIT = 8;
31
+ const DESCRIPTION =
32
+ "Search the web and get back what the pages say, with their links. For a fact, a price, a date, what a page says. Not for a page that has to be clicked, filled, or signed into — that is the browser.";
22
33
 
23
- /** Absent when no provider that searches has a key (features/ai/model); the bot goes to the browser instead. */
24
- export const createSearchTool = (
25
- search: TextModel | null,
34
+ const QUERY = z
35
+ .string()
36
+ .describe(
37
+ "What you want to know, as one full question. Put the place and the time in when they matter — the searcher sees nothing but this line.",
38
+ );
39
+
40
+ /** Exa's own endpoint. One POST: the whole point of this path is that it is not a model call. */
41
+ const EXA_URL = "https://api.exa.ai/search";
42
+
43
+ /** One hit as Exa sends it; only the fields that are read back are named. */
44
+ type ExaHit = {
45
+ title?: string | null;
46
+ url?: string | null;
47
+ publishedDate?: string | null;
48
+ text?: string | null;
49
+ };
50
+
51
+ async function exaSearch(
52
+ apiKey: string,
53
+ query: string,
54
+ signal: AbortSignal,
55
+ ): Promise<string> {
56
+ const response = await fetch(EXA_URL, {
57
+ method: "POST",
58
+ signal,
59
+ headers: { "content-type": "application/json", "x-api-key": apiKey },
60
+ body: JSON.stringify({
61
+ query,
62
+ type: "auto",
63
+ numResults: SEARCH.sources,
64
+ contents: {
65
+ text: { maxCharacters: SEARCH.excerptChars },
66
+ // A page Exa has not cached is fetched now, but one slow site does not hold the search
67
+ livecrawl: "fallback",
68
+ livecrawlTimeout: 5_000,
69
+ },
70
+ }),
71
+ });
72
+ // Exa's own words: only it can say whether the key is wrong, spent or rate-limited
73
+ if (!response.ok)
74
+ return `Exa answered ${response.status}: ${clip((await response.text()).trim(), 200)}`;
75
+
76
+ const body = (await response.json()) as { results?: ExaHit[] };
77
+ const hits = body.results ?? [];
78
+ if (!hits.length)
79
+ return "Nothing came back for that. Try other words, or open a page in the browser.";
80
+
81
+ return hits
82
+ .map((hit) => {
83
+ const head = [hit.title?.trim(), hit.url?.trim()]
84
+ .filter(Boolean)
85
+ .join(" — ");
86
+ const date = hit.publishedDate?.slice(0, 10);
87
+ return [date ? `${head} · ${date}` : head, hit.text?.trim()]
88
+ .filter(Boolean)
89
+ .join("\n");
90
+ })
91
+ .join("\n\n");
92
+ }
93
+
94
+ async function askSearcher(
95
+ searcher: { model: TextModel["model"]; tools: ToolSet },
96
+ query: string,
97
+ signal: AbortSignal,
98
+ ): Promise<string> {
99
+ const { text, sources } = await generateText({
100
+ model: searcher.model,
101
+ tools: searcher.tools,
102
+ system: SEARCHER,
103
+ prompt: query,
104
+ abortSignal: signal,
105
+ });
106
+
107
+ const urls = [
108
+ ...new Set(
109
+ sources.flatMap((source) =>
110
+ source.sourceType === "url"
111
+ ? [source.title ? `${source.title} — ${source.url}` : source.url]
112
+ : [],
113
+ ),
114
+ ),
115
+ ].slice(0, SEARCH.sources);
116
+
117
+ return [text.trim(), urls.length ? `Sources:\n${urls.join("\n")}` : ""]
118
+ .filter(Boolean)
119
+ .join("\n\n");
120
+ }
121
+
122
+ /** Absent when there is neither an Exa key nor a run model that searches; the bot goes to the browser instead. */
123
+ export const createSearchTool = async (
124
+ run: TextModel | null | undefined,
26
125
  sandbox: Sandbox,
27
- ): ToolSet => {
28
- if (!search?.searchTools) return {};
29
- const { model, searchTools } = search;
126
+ ): Promise<ToolSet> => {
127
+ const exaKey = await readConfig(EXA_API_KEY);
128
+ // This run's own model, never a borrowed one. A const so the closure below keeps the narrowing
129
+ const native = run?.searchTools
130
+ ? { model: run.model, tools: run.searchTools }
131
+ : null;
132
+
133
+ const search = exaKey
134
+ ? (query: string, signal: AbortSignal) => exaSearch(exaKey, query, signal)
135
+ : native
136
+ ? (query: string, signal: AbortSignal) =>
137
+ askSearcher(native, query, signal)
138
+ : null;
139
+ if (!search) return {};
30
140
 
31
141
  return {
32
142
  [TOOL_NAMES.web_search]: tool({
33
- description:
34
- "Search the web and get back an answer with its sources. For a fact, a price, a date, what a page says. Not for a page that has to be clicked, filled, or signed into — that is the browser.",
35
- inputSchema: z.object({
36
- query: z
37
- .string()
38
- .describe(
39
- "What you want to know, as one full question. Put the place and the time in when they matter — the searcher sees nothing but this line.",
40
- ),
41
- }),
143
+ description: DESCRIPTION,
144
+ inputSchema: z.object({ query: QUERY }),
42
145
  execute: async ({ query }, { abortSignal }) => {
43
- const { text, sources } = await generateText({
44
- model,
45
- tools: searchTools,
46
- system: SEARCHER,
47
- prompt: query,
48
- abortSignal,
146
+ const deadline = AbortSignal.timeout(SEARCH.timeoutMs);
147
+ const signal = abortSignal
148
+ ? AbortSignal.any([abortSignal, deadline])
149
+ : deadline;
150
+
151
+ const answer = await search(query, signal).catch((cause: unknown) => {
152
+ // The job itself was cancelled: that is not a result to hand back
153
+ if (abortSignal?.aborted) throw cause;
154
+ if (deadline.aborted)
155
+ return `The search did not come back in ${SEARCH.timeoutMs / 1000}s. Ask something narrower, or open the page in the browser.`;
156
+ return `Search failed: ${errorToString(cause)}. The browser is the other way in.`;
49
157
  });
50
158
 
51
- const urls = [
52
- ...new Set(
53
- sources.flatMap((source) =>
54
- source.sourceType === "url"
55
- ? [
56
- source.title
57
- ? `${source.title} — ${source.url}`
58
- : source.url,
59
- ]
60
- : [],
61
- ),
62
- ),
63
- ].slice(0, SOURCE_LIMIT);
64
-
65
- return sandbox.fold(
66
- [text.trim(), urls.length ? `Sources:\n${urls.join("\n")}` : ""]
67
- .filter(Boolean)
68
- .join("\n\n"),
69
- "web-search",
70
- );
159
+ return sandbox.fold(answer, "web-search");
71
160
  },
72
161
  }),
73
162
  };
@@ -7,7 +7,7 @@ export const TOOL_NAMES = {
7
7
  memory_recall: "memory_recall",
8
8
  memory_remember: "memory_remember",
9
9
  memory_forget: "memory_forget",
10
- memory_show: "memory_show",
10
+ memory_conversation: "memory_conversation",
11
11
 
12
12
  bash: "bash",
13
13
  write_file: "write_file",
@@ -24,13 +24,9 @@ export const TOOL_NAMES = {
24
24
  ask_bot: "ask_bot",
25
25
  ask_thursday: "ask_thursday",
26
26
  ask_back: "ask_back",
27
- report: "report",
27
+ answer: "answer",
28
28
 
29
29
  end_call: "end_call",
30
-
31
- tidy_done: "tidy_done",
32
-
33
- update_notes: "update_notes",
34
30
  } as const;
35
31
 
36
32
  /**