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,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
  };
@@ -118,7 +118,7 @@ const imageTool = async (): Promise<StudioTool | null> => {
118
118
  ),
119
119
  aspectRatio: z
120
120
  .enum(RATIOS)
121
- .nullable()
121
+ .nullish()
122
122
  .describe("Aspect ratio. Null for square."),
123
123
  }),
124
124
  execute: async ({ prompt, aspectRatio }, { sandbox, abortSignal }) => {
@@ -161,11 +161,11 @@ const speechTool = async (): Promise<StudioTool | null> => {
161
161
  ),
162
162
  voice: z
163
163
  .string()
164
- .nullable()
164
+ .nullish()
165
165
  .describe("A voice name the provider knows. Null for its default."),
166
166
  instructions: z
167
167
  .string()
168
- .nullable()
168
+ .nullish()
169
169
  .describe(
170
170
  'How to read it — "slowly", "warm", "like a news anchor". Null for plain.',
171
171
  ),
@@ -259,14 +259,14 @@ const videoTool = async (): Promise<StudioTool | null> => {
259
259
  ),
260
260
  aspectRatio: z
261
261
  .enum(["16:9", "9:16"])
262
- .nullable()
262
+ .nullish()
263
263
  .describe("Aspect ratio. Null for 16:9."),
264
264
  seconds: z
265
265
  .number()
266
266
  .int()
267
267
  .min(2)
268
268
  .max(10)
269
- .nullable()
269
+ .nullish()
270
270
  .describe(
271
271
  "Length in seconds, 2 to 10. Null for the provider's default.",
272
272
  ),
@@ -8,6 +8,7 @@ export const TOOL_NAMES = {
8
8
  memory_remember: "memory_remember",
9
9
  memory_forget: "memory_forget",
10
10
  memory_show: "memory_show",
11
+ memory_conversation: "memory_conversation",
11
12
 
12
13
  bash: "bash",
13
14
  write_file: "write_file",
@@ -24,11 +25,9 @@ export const TOOL_NAMES = {
24
25
  ask_bot: "ask_bot",
25
26
  ask_thursday: "ask_thursday",
26
27
  ask_back: "ask_back",
27
- report: "report",
28
+ answer: "answer",
28
29
 
29
30
  end_call: "end_call",
30
-
31
- tidy_done: "tidy_done",
32
31
  } as const;
33
32
 
34
33
  /**
@@ -1,6 +1,7 @@
1
1
  import { relative } from "node:path";
2
2
  import { type ToolSet, tool } from "ai";
3
3
  import z from "zod";
4
+ import { EXEC_TIMEOUT_MS } from "@/config";
4
5
  import { TOOL_NAMES } from "@/features/ai/tools/tool-name";
5
6
  import { writeRefusal } from "@/features/workspace/workspace";
6
7
  import type { Sandbox } from "@/lib/sandbox";
@@ -15,6 +16,8 @@ export const createWorkspaceTools = (
15
16
  write: boolean;
16
17
  /** Per-run environment for `bash` (a job's browser session). */
17
18
  env?: Record<string, string>;
19
+ /** Attach the shell guide to this run's first `bash` result (bots only). */
20
+ guide?: boolean;
18
21
  },
19
22
  ): ToolSet => {
20
23
  /** Fold absolute sandbox paths against cwd; they still resolve when handed back. */
@@ -23,20 +26,30 @@ export const createWorkspaceTools = (
23
26
  return r && !r.startsWith("..") ? r : p;
24
27
  };
25
28
 
29
+ // The tool set is built per run, so one guide per run lives in this closure.
30
+ let owed = options.guide === true;
31
+
26
32
  const bash = tool({
27
33
  description: "Run a bash command.",
28
34
  inputSchema: z.object({
29
35
  command: z.string(),
30
36
  description: z
31
37
  .string()
32
- .nullable()
38
+ .nullish()
33
39
  .describe(
34
40
  "One short line for the user: what this command does and why. Shown on their screen while it runs — not a restatement of the command.",
35
41
  ),
36
42
  }),
37
43
  // The only tool here long-running enough to be cancelled.
38
- execute: ({ command }, { abortSignal }) =>
39
- sandbox.exec(command, { signal: abortSignal, env: options.env }),
44
+ execute: async ({ command }, { abortSignal }) => {
45
+ const result = await sandbox.exec(command, {
46
+ signal: abortSignal,
47
+ env: options.env,
48
+ });
49
+ if (!owed) return result;
50
+ owed = false;
51
+ return { ...result, guide: SHELL_GUIDE };
52
+ },
40
53
  });
41
54
 
42
55
  if (!options.write) return { [TOOL_NAMES.bash]: bash };
@@ -53,7 +66,7 @@ export const createWorkspaceTools = (
53
66
  content: z.string(),
54
67
  description: z
55
68
  .string()
56
- .nullable()
69
+ .nullish()
57
70
  .describe(
58
71
  "One short line for the user: what this file is. Shown on their screen next to the path.",
59
72
  ),
@@ -69,3 +82,19 @@ export const createWorkspaceTools = (
69
82
 
70
83
  return { [TOOL_NAMES.bash]: bash, [TOOL_NAMES.write_file]: writeFile };
71
84
  };
85
+
86
+ /**
87
+ * How this shell differs from a terminal, attached to a run's first `bash`
88
+ * result and never again. Each line is a way a job is lost for minutes and
89
+ * none can be found out from a command's output: state that silently does not
90
+ * carry, a question nobody will answer, a variable that was removed rather
91
+ * than never set. What this machine *has* is not here — that decides the first
92
+ * command, so it is in the prompt (prompts/bot.prompt environment).
93
+ */
94
+ const SHELL_GUIDE = `## The shell here
95
+
96
+ Every command is a new shell: \`cd\`, exported variables and an activated venv are gone by the next one — chain what depends on the last step into a single command.
97
+
98
+ Nothing is watching it. A command that stops to ask never gets an answer and is killed after ${EXEC_TIMEOUT_MS / 1000}s, so pass the flag that skips the question (\`-y\`, \`--yes\`, \`--no-input\`), and send anything genuinely long to the background with its output redirected to a file.
99
+
100
+ Keys are not in the environment: every variable named like a key, a token or a secret is removed before the shell starts. An empty one is not an unset one — say which it was, and ask for what a command needs.`;
@@ -4,11 +4,23 @@ import { z } from "zod";
4
4
  import { textModelProviderSchema } from "@/features/ai/model.schema";
5
5
  import { serverAction } from "@/lib/protocol/server-action";
6
6
  import { publicError } from "@/lib/public-error";
7
- import { createBot, deleteBot, findBot, updateBot } from "./bot.query";
8
- import { answerTask, cancelTask, removeTask, startTask } from "./bot.runner";
7
+ import {
8
+ createBot,
9
+ deleteBot,
10
+ findBot,
11
+ updateBot,
12
+ writeBotMemoryOn,
13
+ } from "./bot.query";
14
+ import {
15
+ answerTask,
16
+ cancelTask,
17
+ removeFinishedTasks,
18
+ removeTask,
19
+ startTask,
20
+ } from "./bot.runner";
9
21
  import { BotFormSchema, botIconSchema } from "./bot.schema";
10
22
  import { findBotSeed, rollSeedColors } from "./bot.seed";
11
- import { deleteFinishedTasks, markReported, resolveTask } from "./task.query";
23
+ import { markSeen, resolveTask } from "./task.query";
12
24
 
13
25
  export const createBotAction = serverAction(async (input: unknown) => {
14
26
  const form = BotFormSchema.parse(input);
@@ -67,6 +79,11 @@ export const deleteBotAction = serverAction(async (name: string) => {
67
79
  if (!(await deleteBot(name))) publicError("Bot not found");
68
80
  });
69
81
 
82
+ /** Switched off, no bot is shown its own memory. What is already written stays on disk. */
83
+ export const setBotMemoryOnAction = serverAction(async (on: unknown) => {
84
+ await writeBotMemoryOn(on === true);
85
+ });
86
+
70
87
  // Tasks are opened by the `delegate` tool during a call, or here when the user
71
88
  // hands one over from the screen. Each returns at once, the run itself continues
72
89
  // in bot.runner behind `after()`.
@@ -115,9 +132,9 @@ export const cancelTaskAction = serverAction(async (ref: string) => {
115
132
  return { id: task.id, label: task.label, status: "cancelled" as const };
116
133
  });
117
134
 
118
- /** Marks tasks as relayed to the call, clearing their inbox dot. Batched because a call opening relays everything pending at once. */
119
- export const markReportedAction = serverAction(async (ids: string[]) => {
120
- await markReported(ids.filter((id) => typeof id === "string" && id));
135
+ /** Marks endings as had by the user: relayed on a call, or on a task list they opened. Batched, since both reach many at once. */
136
+ export const markSeenAction = serverAction(async (ids: string[]) => {
137
+ await markSeen(ids.filter((id) => typeof id === "string" && id));
121
138
  });
122
139
 
123
140
  export const deleteTaskAction = serverAction(async (id: string) => {
@@ -126,5 +143,5 @@ export const deleteTaskAction = serverAction(async (id: string) => {
126
143
 
127
144
  /** Empties the log of what is over. Running and waiting jobs are not touched. */
128
145
  export const clearFinishedTasksAction = serverAction(async () => {
129
- return { removed: await deleteFinishedTasks() };
146
+ return { removed: await removeFinishedTasks() };
130
147
  });
@@ -0,0 +1,89 @@
1
+ import { open, readdir, stat } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { BOT_MEMORY_LISTED } from "@/config";
4
+ import { botFolder, WORKSPACE } from "@/features/workspace/workspace";
5
+ import type { BotMemory, BotMemoryFile } from "./bot.schema";
6
+
7
+ /**
8
+ * A bot's own memory: files it keeps in its folder, one topic each, written and read with
9
+ * its own shell. The disk is the only index — a file's first line is its listing line — so
10
+ * keeping something is one write, and no list can fall out of step with the files.
11
+ */
12
+
13
+ /** Workspace-relative, the way a prompt names it (config PATHS.bots). */
14
+ export const botMemoryFolder = (bot: string): string =>
15
+ `${botFolder(bot)}/memory`;
16
+
17
+ /** Enough of a file to find its first line in; the rest is the bot's to open. */
18
+ const HEAD_BYTES = 1024;
19
+
20
+ /**
21
+ * Newest first. `limit` is how many are read for their first line: the prompt lists
22
+ * BOT_MEMORY_LISTED, the bot's page (Settings > Bots) as many as a Workspace folder shows.
23
+ */
24
+ export async function listBotMemory(
25
+ bot: string,
26
+ limit = BOT_MEMORY_LISTED,
27
+ ): Promise<BotMemory> {
28
+ const folder = botMemoryFolder(bot);
29
+ const dir = join(WORKSPACE, folder);
30
+ const names = await readdir(dir).catch(() => []);
31
+ const found = await Promise.all(
32
+ names
33
+ .filter((name) => !name.startsWith("."))
34
+ .map(async (name) => {
35
+ const info = await stat(join(dir, name)).catch(() => null);
36
+ return info?.isFile()
37
+ ? { name, changed: info.mtimeMs, bytes: info.size }
38
+ : null;
39
+ }),
40
+ );
41
+ const files = found
42
+ .filter((file) => file !== null)
43
+ .sort((a, b) => b.changed - a.changed);
44
+ const entries = await Promise.all(
45
+ files.slice(0, limit).map(
46
+ async ({ name, changed, bytes }): Promise<BotMemoryFile> => ({
47
+ file: name,
48
+ path: `${folder}/${name}`,
49
+ line: await firstLine(join(dir, name)),
50
+ at: new Date(changed),
51
+ bytes,
52
+ }),
53
+ ),
54
+ );
55
+ return { folder, entries, total: files.length };
56
+ }
57
+
58
+ /**
59
+ * The line a file is listed by: its first, without a heading's `#`. A file that opens with
60
+ * frontmatter anyway — a shape models are trained on — is listed by its `description`, or by
61
+ * the first line after it.
62
+ */
63
+ async function firstLine(path: string): Promise<string> {
64
+ const handle = await open(path, "r").catch(() => null);
65
+ if (!handle) return "";
66
+ try {
67
+ const head = Buffer.alloc(HEAD_BYTES);
68
+ const { bytesRead } = await handle.read(head, 0, HEAD_BYTES, 0);
69
+ const lines = head
70
+ .toString("utf8", 0, bytesRead)
71
+ .split("\n")
72
+ .map((line) => line.trim())
73
+ .filter(Boolean);
74
+ if (lines[0] === "---") {
75
+ const said = lines.find((line) => line.startsWith("description:"));
76
+ if (said) {
77
+ return said
78
+ .slice("description:".length)
79
+ .trim()
80
+ .replace(/^["']|["']$/g, "");
81
+ }
82
+ const end = lines.indexOf("---", 1);
83
+ return end > 0 ? (lines[end + 1] ?? "").replace(/^#+\s*/, "") : "";
84
+ }
85
+ return (lines[0] ?? "").replace(/^#+\s*/, "");
86
+ } finally {
87
+ await handle.close();
88
+ }
89
+ }
@@ -7,10 +7,13 @@ import {
7
7
  taskTable,
8
8
  } from "@/database/tables";
9
9
  import type { TextModelProviderId } from "@/features/ai/model.schema";
10
+ import { readConfig, writeConfig } from "@/features/config/config.query";
10
11
  import {
12
+ BOT_MEMORY_KEY,
11
13
  type BotForm,
12
14
  type BotIcon,
13
15
  DEFAULT_BOT,
16
+ isBotMemoryOn,
14
17
  type JobBot,
15
18
  type PinnedTool,
16
19
  pickedModel,
@@ -26,6 +29,8 @@ const asJobBot = (row: {
26
29
  /** Empty runs on the app default model (bot.run resolveModel). */
27
30
  provider: TextModelProviderId | null;
28
31
  model: string | null;
32
+ disabled: boolean;
33
+ compactAt: number | null;
29
34
  }): JobBot => ({
30
35
  name: row.name,
31
36
  description: row.description,
@@ -33,21 +38,36 @@ const asJobBot = (row: {
33
38
  icon: row.icon,
34
39
  provider: row.provider,
35
40
  model: row.model,
41
+ disabled: row.disabled,
42
+ compactAt: row.compactAt,
36
43
  });
37
44
 
38
- /** Who a job can go to: the user's bots, or DEFAULT_BOT when there are none. */
45
+ /**
46
+ * Who a job can go to: the user's bots, or DEFAULT_BOT when there are none.
47
+ * Switched-off bots are left out here and nowhere else — this one read is what
48
+ * every prompt's roster and `delegate`'s list are built from, so off is off in
49
+ * all of them without a second rule to keep.
50
+ */
39
51
  export async function listJobBots(): Promise<JobBot[]> {
40
52
  const rows = await database
41
53
  .select()
42
54
  .from(botTable)
43
55
  .orderBy(botTable.createdAt);
44
56
 
45
- return rows.length ? rows.map(asJobBot) : [DEFAULT_BOT];
57
+ // The fallback answers "no bots exist", never "every bot is off": switching
58
+ // them all off is a choice, and conjuring a worker would undo it.
59
+ return rows.length
60
+ ? rows.filter((row) => !row.disabled).map(asJobBot)
61
+ : [DEFAULT_BOT];
46
62
  }
47
63
 
48
64
  /**
49
- * The bot a job names. Exact name first, then case-insensitive only; no looser
50
- * matching. A miss returns null so `delegate` can list the roster instead.
65
+ * The bot a job names, switched off or not: a job already under way resumes
66
+ * through here, and refusing it would strand a thread the user can still answer.
67
+ * `delegate` is what checks `disabled`, because that is where a bot is picked.
68
+ *
69
+ * Exact name first, then case-insensitive only; no looser matching. A miss
70
+ * returns null so `delegate` can list the roster instead.
51
71
  */
52
72
  export async function findJobBot(name: string): Promise<JobBot | null> {
53
73
  const row = await findBot(name);
@@ -55,8 +75,14 @@ export async function findJobBot(name: string): Promise<JobBot | null> {
55
75
 
56
76
  // Case is not a different name: the spoken name arrives through a transcript
57
77
  const said = name.trim().toLowerCase();
58
- const bots = await listJobBots();
59
- return bots.find((bot) => bot.name.toLowerCase() === said) ?? null;
78
+ const [match] = await database
79
+ .select()
80
+ .from(botTable)
81
+ .where(eq(sql`lower(${botTable.name})`, said));
82
+ if (match) return asJobBot(match);
83
+
84
+ // The worker that exists when no row does; it has no row to match against
85
+ return DEFAULT_BOT.name.toLowerCase() === said ? DEFAULT_BOT : null;
60
86
  }
61
87
 
62
88
  /** Bots with their pinned tools and token totals: a set of queries plus grouping, not a join. */
@@ -112,6 +138,15 @@ export async function findAllBots() {
112
138
  }));
113
139
  }
114
140
 
141
+ /** Whether bots keep their own memory at all (bot.schema BOT_MEMORY_KEY). */
142
+ export async function readBotMemoryOn(): Promise<boolean> {
143
+ return isBotMemoryOn(await readConfig(BOT_MEMORY_KEY));
144
+ }
145
+
146
+ export async function writeBotMemoryOn(on: boolean): Promise<void> {
147
+ await writeConfig(BOT_MEMORY_KEY, on ? "on" : "off");
148
+ }
149
+
115
150
  export async function findBot(name: string) {
116
151
  const [bot] = await database
117
152
  .select()