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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +5 -1
- package/.next/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +5 -5
- package/.next/routes-manifest.json +27 -3
- package/.next/server/app/_global-error/page.js +2 -2
- package/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +2 -2
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +2 -2
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +14 -14
- package/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/artifact/route.js +3 -3
- package/.next/server/app/api/artifact/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/files/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/bot/memory/files/route.js +10 -0
- package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -0
- package/.next/server/app/api/bot/memory/files/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/bot/memory/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/bot/memory/route/build-manifest.json +12 -0
- package/.next/server/app/api/bot/memory/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/bot/memory/route.js +14 -0
- package/.next/server/app/api/bot/memory/route.js.map +5 -0
- package/.next/server/app/api/bot/memory/route.js.nft.json +1 -0
- package/.next/server/app/api/bot/memory/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/bot/route.js +7 -7
- package/.next/server/app/api/bot/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/task/[id]/route.js +9 -9
- package/.next/server/app/api/bot/task/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/task/route.js +8 -8
- package/.next/server/app/api/bot/task/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js +6 -6
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/events/route.js +4 -5
- package/.next/server/app/api/events/route.js.nft.json +1 -1
- package/.next/server/app/api/file/[...path]/route.js +3 -3
- package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/catalog/route.js +10 -9
- package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/credits/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/llm-model/credits/route/build-manifest.json +12 -0
- package/.next/server/app/api/llm-model/credits/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/llm-model/credits/route.js +16 -0
- package/.next/server/app/api/llm-model/credits/route.js.map +5 -0
- package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -0
- package/.next/server/app/api/llm-model/credits/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/llm-model/route.js +10 -8
- package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/subscription/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/llm-model/subscription/route/build-manifest.json +12 -0
- package/.next/server/app/api/llm-model/subscription/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/llm-model/subscription/route.js +15 -0
- package/.next/server/app/api/llm-model/subscription/route.js.map +5 -0
- package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -0
- package/.next/server/app/api/llm-model/subscription/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/mcp/[name]/route.js +5 -5
- package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/oauth/callback/route.js +6 -6
- package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/route.js +5 -5
- package/.next/server/app/api/mcp/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/tools/route.js +5 -5
- package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/memory/edit/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/memory/edit/route/build-manifest.json +12 -0
- package/.next/server/app/api/memory/edit/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/memory/edit/route.js +24 -0
- package/.next/server/app/api/memory/edit/route.js.map +5 -0
- package/.next/server/app/api/memory/edit/route.js.nft.json +1 -0
- package/.next/server/app/api/memory/{tidy → edit}/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/memory/route.js +7 -8
- package/.next/server/app/api/memory/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/[source]/[name]/route.js +3 -3
- package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/route.js +3 -3
- package/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/call/route.js +9 -7
- package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/skills/route.js +9 -7
- package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/tool-call/route.js +16 -15
- package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
- package/.next/server/app/api/workspace/route.js +4 -5
- package/.next/server/app/api/workspace/route.js.nft.json +1 -1
- package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +1 -1
- package/.next/server/app/artifact/[...path]/page.js +5 -6
- package/.next/server/app/artifact/[...path]/page.js.nft.json +1 -1
- package/.next/server/app/artifact/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/favicon.ico/route.js +3 -4
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/page/server-reference-manifest.json +66 -77
- package/.next/server/app/page.js +11 -11
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +5 -1
- package/.next/server/chunks/[externals]__0dzuk6_._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__01dkp4a._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__02va5wz._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__02xjoto._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__04q--0f._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0bl-e63._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0ce8nf8._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__0ffbg85._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0j7z0r3._.js +12 -0
- package/.next/server/chunks/[root-of-the-server]__0jq4ohy._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0ls6_8y._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0ncs9uu._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0pa2n68._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0q0vvt2._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1-ga0kh._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__11n256_._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__12cabg9._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1339jnv._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__15bjnu5._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__18_teo8._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1anc1p9._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1ccon1w._.js +10 -0
- package/.next/server/chunks/[root-of-the-server]__1fizn31._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1llj3-b._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1orn-5b._.js +11 -0
- package/.next/server/chunks/[root-of-the-server]__1p8m3f4._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1wa1k7r._.js +8 -0
- package/.next/server/chunks/{_1hzrsvg._.js → _0-73of8._.js} +6 -6
- package/.next/server/chunks/{_1cbk7ms._.js → _0-fjql4._.js} +10 -10
- package/.next/server/chunks/_00xh_q0._.js +27 -0
- package/.next/server/chunks/{_0y8is-s._.js → _03a0897._.js} +1 -1
- package/.next/server/chunks/{_0pppbb5._.js → _03kp0jp._.js} +166 -35
- package/.next/server/chunks/_051qh8u._.js +3 -0
- package/.next/server/chunks/{node_modules_next_04q-o58._.js → _05dla15._.js} +2 -2
- package/.next/server/chunks/_05h2cii._.js +1 -1
- package/.next/server/chunks/_0c9j6rb._.js +49 -0
- package/.next/server/chunks/_0fzqt2y._.js +74 -44
- package/.next/server/chunks/{_0kl37zl._.js → _0ioz3nd._.js} +1 -1
- package/.next/server/chunks/_0iwfby5._.js +3 -0
- package/.next/server/chunks/{_0hin38_._.js → _0khihjk._.js} +5 -5
- package/.next/server/chunks/_0mecv0f._.js +26 -0
- package/.next/server/chunks/_0mh8j4m._.js +3 -0
- package/.next/server/chunks/{_1icgbi8._.js → _0n74zsf._.js} +2 -2
- package/.next/server/chunks/_0obojvv._.js +3 -0
- package/.next/server/chunks/_0recufk._.js +49 -0
- package/.next/server/chunks/{_1t8fv7b._.js → _0rnf-6n._.js} +2 -2
- package/.next/server/chunks/_0sb7tlz._.js +3 -0
- package/.next/server/chunks/{_0jgm3b8._.js → _0u10wmw._.js} +6 -6
- package/.next/server/chunks/{_12nr4xc._.js → _0u4aiy2._.js} +2 -2
- package/.next/server/chunks/_0wp4le3._.js +1 -1
- package/.next/server/chunks/_0y5fg-x._.js +1 -1
- package/.next/server/chunks/_1230wbx._.js +10 -0
- package/.next/server/chunks/_12nheja._.js +3 -0
- package/.next/server/chunks/_13510xh._.js +3 -0
- package/.next/server/chunks/_15hq89o._.js +1 -1
- package/.next/server/chunks/_17l5ygt._.js +49 -0
- package/.next/server/chunks/{_0ks6_sg._.js → _18-1wcc._.js} +6 -6
- package/.next/server/chunks/_1_5mnq4._.js +18 -0
- package/.next/server/chunks/{_0tzfesa._.js → _1_9mjx-._.js} +1 -1
- package/.next/server/chunks/_1d0j961._.js +6 -0
- package/.next/server/chunks/_1d5zmy8._.js +1 -1
- package/.next/server/chunks/_1drgfx4._.js +18 -0
- package/.next/server/chunks/{_1skgy7b._.js → _1e48czp._.js} +5 -5
- package/.next/server/chunks/_1f46eie._.js +3 -0
- package/.next/server/chunks/_1h5_8sk._.js +3 -0
- package/.next/server/chunks/_1hdnxb7._.js +3 -0
- package/.next/server/chunks/_1j8k_j5._.js +3 -0
- package/.next/server/chunks/{_10qam6o._.js → _1kg70wc._.js} +5 -5
- package/.next/server/chunks/_1krd9rf._.js +3 -0
- package/.next/server/chunks/_1nc0eui._.js +11 -0
- package/.next/server/chunks/_1nula3v._.js +3 -0
- package/.next/server/chunks/_1pf4qe-._.js +3 -0
- package/.next/server/chunks/_1php4eq._.js +1 -1
- package/.next/server/chunks/_1qxheoa._.js +3 -0
- package/.next/server/chunks/_1x6kd1r._.js +3 -0
- package/.next/server/chunks/_1yuv4vp._.js +1 -1
- package/.next/server/chunks/_1zjrdag._.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_bot_memory_files_route_actions_1_xd_8f.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_bot_memory_route_actions_1a8xfr7.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_llm-model_credits_route_actions_0v424pb.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_llm-model_subscription_route_actions_0-udcm5.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_memory_edit_route_actions_02sfnmr.js +3 -0
- package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
- package/.next/server/chunks/features_0rpfxbk._.js +3 -0
- package/.next/server/chunks/features_1qf3cei._.js +3 -0
- package/.next/server/chunks/features_bot_0zt92oh._.js +3 -0
- package/.next/server/chunks/features_bot_bot_query_ts_12mgkl2._.js +1 -1
- package/.next/server/chunks/features_memory_1uqvksn._.js +6 -0
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0tf290y._.js → node_modules_consola_dist_chunks_prompt_mjs_0i7cvml._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0228f43._.js → node_modules_consola_dist_chunks_prompt_mjs_0icqaqw._.js} +1 -1
- 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
- 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
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0v_7drq._.js +3 -0
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_11zjo-1._.js +3 -0
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1pycqsq._.js +3 -0
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1xoq2rl._.js +3 -0
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1y49572._.js +3 -0
- package/.next/server/chunks/ssr/[externals]__0dizgek._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__09q9med._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0_69wqr._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0hg5gib._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0i8ie7f._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__0jsmmb-._.js → [root-of-the-server]__0mz33a7._.js} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0tbkdlx._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0vnmv-s._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__0f6s48x._.js → [root-of-the-server]__0xpcv9w._.js} +3 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0xtssj3._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0zkv7z_._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +57 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__15_uhip._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__1cyjywu._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1eh7hid._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1gtlw6v._.js +43 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__1ox7hbk._.js +4 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1pduf5n._.js +3 -0
- package/.next/server/chunks/ssr/{_1mznrxk._.js → _001_ms1._.js} +3 -3
- package/.next/server/chunks/ssr/_01_6m32._.js +3 -0
- package/.next/server/chunks/ssr/_01n3o0m._.js +3 -0
- package/.next/server/chunks/ssr/_07uchnc._.js +3 -0
- package/.next/server/chunks/ssr/_0ap2fzn._.js +3 -0
- package/.next/server/chunks/ssr/_0c-ql2m._.js +3 -0
- package/.next/server/chunks/ssr/_0h42fze._.js +3 -0
- package/.next/server/chunks/ssr/_0h7zdni._.js +1 -1
- package/.next/server/chunks/ssr/_0i_6q1w._.js +41 -0
- package/.next/server/chunks/ssr/_0kbkmar._.js +3 -0
- package/.next/server/chunks/ssr/_0lu1n_x._.js +3 -0
- package/.next/server/chunks/ssr/{_077-g6s._.js → _0mb8zc8._.js} +3 -3
- package/.next/server/chunks/ssr/_0mo2w06._.js +3 -0
- package/.next/server/chunks/ssr/{_13punpm._.js → _0q0zan6._.js} +2 -2
- package/.next/server/chunks/ssr/{_0gd4vaa._.js → _0u2jv_x._.js} +94 -58
- package/.next/server/chunks/ssr/_0y0tiht._.js +4 -0
- package/.next/server/chunks/ssr/_0zhoc3r._.js +3 -0
- package/.next/server/chunks/ssr/_1-teee5._.js +3 -3
- package/.next/server/chunks/ssr/_13fke0x._.js +3 -0
- package/.next/server/chunks/ssr/{_0q_2f2x._.js → _13z3f85._.js} +2 -2
- package/.next/server/chunks/ssr/_14_lw10._.js +3 -0
- package/.next/server/chunks/ssr/_15j2_8f._.js +3 -0
- package/.next/server/chunks/ssr/{_0lc_7c8._.js → _1eoqg_g._.js} +2 -2
- package/.next/server/chunks/ssr/_1sji22n._.js +3 -0
- package/.next/server/chunks/ssr/_1spzm8z._.js +3 -0
- package/.next/server/chunks/ssr/{_19_o9d-._.js → _1vi_uo7._.js} +2 -2
- package/.next/server/chunks/ssr/_1vyd1ji._.js +3 -0
- package/.next/server/chunks/ssr/_1xvgn77._.js +3 -0
- package/.next/server/chunks/ssr/_20kd_n0._.js +42 -0
- package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +3 -0
- package/.next/server/chunks/ssr/features_config_components_config-setting_tsx_0xfwqdg._.js +1 -1
- package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
- package/.next/server/chunks/ssr/lib_date-like_ts_02is0pw._.js +3 -0
- package/.next/server/chunks/ssr/lib_realtime_12wg_dd._.js +27 -0
- package/.next/server/chunks/ssr/lib_realtime_15h_v1v._.js +27 -0
- package/.next/server/chunks/ssr/{node_modules_1d-is1o._.js → node_modules_063xwpp._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1ub40gk._.js → node_modules_0bvraul._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1nhw9qg._.js → node_modules_0eu1va6._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0xwx4u-._.js → node_modules_0h50b8n._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_043-236._.js → node_modules_0h5hnr1._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1t0y5jt._.js → node_modules_0h7u60n._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1k29j1j._.js → node_modules_0lm7_vm._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_16i4o_3._.js → node_modules_0mwym0g._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1y8_3vg._.js → node_modules_0rjg6t1._.js} +1 -1
- package/.next/server/chunks/ssr/node_modules_0x3-ply._.js +3 -0
- package/.next/server/chunks/ssr/{node_modules_108wd2o._.js → node_modules_0y_cded._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1jatz7w._.js → node_modules_0z5tsu8._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0ls96je._.js → node_modules_0zp9r92._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_06kvvuo._.js → node_modules_1-hc6uv._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1_588_4._.js → node_modules_113tz0l._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0ipn1ho._.js → node_modules_124bue5._.js} +1 -1
- package/.next/server/chunks/ssr/node_modules_17bwo43._.js +55 -0
- package/.next/server/chunks/ssr/{node_modules_0_j7-g4._.js → node_modules_1_n3ztw._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_20ynonm._.js → node_modules_1bc7gu8._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1hn_sd5._.js → node_modules_1bgb6-f._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0bue6gy._.js → node_modules_1h4a4pp._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0fbw5-u._.js → node_modules_1i7u1ia._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1ee8gav._.js → node_modules_1juq3hs._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0_fvxnt._.js → node_modules_1l0qtdu._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_13f2md6._.js → node_modules_1t9cyee._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0y2-av4._.js → node_modules_1uuj9x1._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_00d6675._.js → node_modules_1vqb6po._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1v0077l._.js → node_modules_1xx28h1._.js} +1 -1
- 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
- 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
- package/.next/server/chunks/ssr/node_modules_@vercel_oidc_dist_0qe30a_._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_consola_dist_chunks_prompt_mjs_05cwqv2._.js +47 -0
- package/.next/server/chunks/ssr/{node_modules_next_dist_0w6mzq5._.js → node_modules_next_dist_0drixxt._.js} +4 -4
- package/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +2 -2
- package/.next/server/instrumentation.js +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +67 -78
- package/.next/static/chunks/{31ttnjt6g35a0.js → 0ev4hyghq0mbb.js} +1 -1
- package/.next/static/chunks/0r5qcctujhxli.js +1 -0
- package/.next/static/chunks/0tmgrnlje14-s.js +3 -0
- package/.next/static/chunks/0x79tx04dxbpp.js +1 -0
- package/.next/static/chunks/0xzgvc0fkdb6t.js +1 -0
- package/.next/static/chunks/10teww7wt-f6h.js +1 -0
- package/.next/static/chunks/14hgtsjg-kael.css +1 -0
- package/.next/static/chunks/17donp69y4do7.js +40 -0
- package/.next/static/chunks/1dkjg87pxk0n9.js +28 -0
- package/.next/static/chunks/1ekc7ul556kbl.js +1 -0
- package/.next/static/chunks/{1khakdu_iuedc.js → 1grhjo7a5a0_-.js} +1 -1
- package/.next/static/chunks/1kq8h8wi_e0bc.js +53 -0
- package/.next/static/chunks/1okqiww3pnwka.js +1 -0
- package/.next/static/chunks/26-pr2c9ro222.js +1 -0
- package/.next/static/chunks/{2ihkf6l2jowo9.js → 280t0_e99i276.js} +3 -3
- package/.next/static/chunks/28cizcdaabd4h.js +1 -0
- package/.next/static/chunks/2a0k6jlq0_v1u.js +2 -0
- package/.next/static/chunks/2fzs9fm8yarvq.js +1 -0
- package/.next/static/chunks/2h0sd2vumhb15.js +1 -0
- package/.next/static/chunks/2hw2f6zmt7fmt.js +1 -0
- package/.next/static/chunks/2t4vhi3m8ahya.js +1 -0
- package/.next/static/chunks/2tigdtz3dpcy8.js +1 -0
- package/.next/static/chunks/3111pj5wnjgos.js +1 -0
- package/.next/static/chunks/3786h5vayt80-.js +28 -0
- package/.next/static/chunks/{3aquirz5h71da.js → 3agpgkwaa321p.js} +1 -1
- package/.next/static/chunks/3cfi_q6d_wtci.js +1 -0
- package/.next/static/chunks/3ok9_x74rip3v.js +1 -0
- package/.next/static/chunks/3xk7yqgomx7yq.js +1 -0
- package/.next/static/chunks/3xpbkl66ssib5.js +38 -0
- package/.next/static/media/favicon.37o1pjldwi2uc.ico +0 -0
- package/README.md +6 -4
- package/app/api/bot/memory/files/route.ts +14 -0
- package/app/api/bot/memory/route.ts +5 -0
- package/app/api/events/app-event.client.ts +24 -0
- package/app/api/events/app-event.server.ts +45 -0
- package/app/api/events/app-event.ts +42 -0
- package/app/api/llm-model/catalog/route.ts +12 -0
- package/app/api/llm-model/credits/route.ts +11 -0
- package/app/api/llm-model/route.ts +26 -0
- package/app/api/llm-model/subscription/route.ts +11 -0
- package/app/api/memory/edit/route.ts +7 -0
- package/app/api/memory/route.ts +21 -0
- package/app/api/query-key.ts +159 -0
- package/app/api/thursday/tool-call/route.ts +67 -0
- package/bin/thursday.mjs +3 -0
- package/components/ui/button-group.tsx +45 -0
- package/components/ui/custom-icon.tsx +259 -0
- package/components/ui/dropdown-menu.tsx +271 -0
- package/components/ui/folded-text.tsx +68 -0
- package/components/ui/input-group.tsx +157 -0
- package/components/ui/json-view.tsx +240 -0
- package/components/ui/shiny-text.tsx +55 -0
- package/components/ui/text-type.tsx +213 -0
- package/components/ui/theme-sync.tsx +9 -0
- package/database/migrations/{20260908030742_rainy_marvel_zombies → 20260910173049_numerous_spirit}/migration.sql +30 -33
- package/database/migrations/{20260908030742_rainy_marvel_zombies → 20260910173049_numerous_spirit}/snapshot.json +124 -145
- package/database/migrations/20260911030320_opposite_jack_power/migration.sql +1 -0
- package/database/migrations/20260911030320_opposite_jack_power/snapshot.json +1158 -0
- package/docs/how-it-works.md +59 -0
- package/docs/images/keeps-going.png +0 -0
- package/docs/images/task-thread.png +0 -0
- package/docs/images/two-minds.png +0 -0
- package/features/ai/chatgpt.ts +617 -0
- package/features/ai/components/chatgpt-sign-in.tsx +66 -0
- package/features/ai/components/model-picker.tsx +17 -1
- package/features/ai/components/provider-icon.tsx +1 -0
- package/features/ai/load-tools.ts +105 -39
- package/features/ai/model.schema.ts +232 -34
- package/features/ai/model.ts +169 -24
- package/features/ai/prompts/bot.prompt.ts +245 -59
- package/features/ai/prompts/memory-edit.prompt.ts +33 -0
- package/features/ai/prompts/prompt-helper.ts +75 -30
- package/features/ai/prompts/thursday.prompt.ts +42 -17
- package/features/ai/tools/bot.tool.ts +32 -30
- package/features/ai/tools/connected.ts +17 -4
- package/features/ai/tools/mcp.tool.ts +5 -5
- package/features/ai/tools/memory.tool.ts +142 -74
- package/features/ai/tools/search.tool.ts +136 -47
- package/features/ai/tools/studio.tool.ts +5 -5
- package/features/ai/tools/tool-name.ts +2 -3
- package/features/ai/tools/workspace.tool.ts +33 -4
- package/features/bot/bot.action.ts +24 -7
- package/features/bot/bot.memory.ts +89 -0
- package/features/bot/bot.query.ts +41 -6
- package/features/bot/bot.run.ts +516 -210
- package/features/bot/bot.runner.ts +463 -93
- package/features/bot/bot.schema.ts +84 -7
- package/features/bot/bot.seed.ts +89 -16
- package/features/bot/components/bot-mark.tsx +122 -20
- package/features/bot/components/bot-room.tsx +519 -391
- package/features/bot/components/bot-setting.tsx +832 -341
- package/features/bot/components/bot-tool.tsx +2 -6
- package/features/bot/components/mark-palette.tsx +54 -0
- package/features/bot/components/path-chips.tsx +1 -1
- package/features/bot/components/task-badge.tsx +26 -6
- package/features/bot/components/task-reply.tsx +22 -33
- package/features/bot/components/task-setting.tsx +20 -17
- package/features/bot/task.query.ts +233 -33
- package/features/bot/task.store.ts +53 -9
- package/features/config/components/config-setting.tsx +265 -34
- package/features/config/components/models-badge.tsx +42 -0
- package/features/config/config.action.ts +12 -0
- package/features/config/config.const.ts +38 -2
- package/features/connectors/mcp.manager.ts +10 -2
- package/features/intro/components/intro.tsx +47 -46
- package/features/memory/components/memory-edit.tsx +338 -0
- package/features/memory/components/memory-setting.tsx +86 -79
- package/features/memory/memory.action.ts +3 -43
- package/features/memory/memory.edit.ts +87 -0
- package/features/memory/memory.query.ts +33 -44
- package/features/memory/memory.schema.ts +50 -97
- package/features/settings/components/settings.tsx +2 -0
- package/features/settings/settings.alert.ts +3 -1
- package/features/skills/components/skills-setting.tsx +9 -1
- package/features/thursday/components/ascii-orb.tsx +106 -90
- package/features/thursday/components/boot.tsx +7 -0
- package/features/thursday/components/call-log.tsx +219 -92
- package/features/thursday/components/face.tsx +6 -4
- package/features/thursday/components/tab-state.tsx +97 -0
- package/features/thursday/components/thursday-mark.tsx +4 -1
- package/features/thursday/components/thursday-setting.tsx +17 -47
- package/features/thursday/components/thursday.tsx +208 -95
- package/features/thursday/thursday.action.ts +12 -17
- package/features/thursday/thursday.query.ts +61 -70
- package/features/thursday/thursday.schema.ts +20 -7
- package/features/thursday/tool-line.ts +85 -11
- package/features/thursday/use-thursday.ts +86 -59
- package/features/workspace/components/file-view.tsx +4 -2
- package/features/workspace/workspace.ts +230 -13
- package/hooks/use-draft.ts +37 -0
- package/hooks/use-hotkey.ts +105 -0
- package/hooks/use-object-state.ts +51 -0
- package/hooks/use-on-visible.ts +72 -0
- package/hooks/use-theme.ts +106 -0
- package/hooks/use-wake-word.ts +262 -0
- package/lib/limits.ts +1 -1
- package/lib/oauth-page.ts +27 -0
- package/lib/realtime/openai.ts +2 -2
- package/lib/realtime/realtime.driver.ts +34 -1
- package/lib/realtime/realtime.protocol.ts +7 -1
- package/lib/realtime/realtime.tap.ts +122 -0
- package/lib/sandbox.ts +60 -29
- package/lib/tokens.ts +19 -0
- package/package.json +1 -1
- package/skills/browser/SKILL.md +55 -34
- package/.next/server/app/api/memory/tidy/route/app-paths-manifest.json +0 -3
- package/.next/server/app/api/memory/tidy/route.js +0 -23
- package/.next/server/app/api/memory/tidy/route.js.nft.json +0 -1
- package/.next/server/chunks/[root-of-the-server]__019dx9f._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__02_2sm-._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__02kt8yn._.js +0 -10
- package/.next/server/chunks/[root-of-the-server]__05luceg._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__06t77t4._.js +0 -11
- package/.next/server/chunks/[root-of-the-server]__0bed6hu._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0dupqt7._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0h59di-._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0j_n5l3._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0le4d-p._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0m8ywyo._.js +0 -10
- package/.next/server/chunks/[root-of-the-server]__0nfuugi._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0phdgco._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0qjqtwo._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0t_dqaj._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0wvgrsl._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0yk6s3w._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0z3gelv._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__10qshki._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__113fqg5._.js +0 -12
- package/.next/server/chunks/[root-of-the-server]__11w_7_3._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__16thabu._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__173nhwf._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1_0q_9w._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1_aoyr9._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1bqhuh9._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1cqizfq._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1dow0bz._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1e-ci13._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1gmn1cs._.js +0 -10
- package/.next/server/chunks/[root-of-the-server]__1lr7j9t._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1mzp_el._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1txedx6._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1u_qvc7._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1zgpz1w._.js +0 -3
- package/.next/server/chunks/_012yhfm._.js +0 -39
- package/.next/server/chunks/_06mxlgn._.js +0 -3
- package/.next/server/chunks/_07rtlxv._.js +0 -3
- package/.next/server/chunks/_0a351g7._.js +0 -6
- package/.next/server/chunks/_0kjjmag._.js +0 -3
- package/.next/server/chunks/_0zmestz._.js +0 -55
- package/.next/server/chunks/_0zuzmt_._.js +0 -39
- package/.next/server/chunks/_12bbv5i._.js +0 -96
- package/.next/server/chunks/_15q1pig._.js +0 -3
- package/.next/server/chunks/_1drv2et._.js +0 -36
- package/.next/server/chunks/_1ic3bew._.js +0 -5
- package/.next/server/chunks/_1mxn_lb._.js +0 -3
- package/.next/server/chunks/_1uj4_io._.js +0 -10
- package/.next/server/chunks/_1x7p319._.js +0 -6
- package/.next/server/chunks/_1yldgo4._.js +0 -55
- package/.next/server/chunks/_2050gwn._.js +0 -255
- package/.next/server/chunks/_next-internal_server_app_api_memory_tidy_route_actions_0_cfuom.js +0 -3
- package/.next/server/chunks/features_0scmr4i._.js +0 -3
- package/.next/server/chunks/features_bot_task_query_ts_11xuzl3._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0vorg6w._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0ykklj0._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1ryg3wh._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1vmaq9f._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1vwbnq_._.js +0 -3
- package/.next/server/chunks/ssr/[externals]_node_crypto_1kn79-7._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__01id-v3._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0b-0i32._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0dfwvr4._.js +0 -4
- package/.next/server/chunks/ssr/[root-of-the-server]__0iuoa-r._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1-mnhyd._.js +0 -90
- package/.next/server/chunks/ssr/[root-of-the-server]__185grso._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1minz8_._.js +0 -3
- package/.next/server/chunks/ssr/_0-mc7ro._.js +0 -3
- package/.next/server/chunks/ssr/_01p5r6-._.js +0 -3
- package/.next/server/chunks/ssr/_09-0k3z._.js +0 -3
- package/.next/server/chunks/ssr/_0ay6b01._.js +0 -3
- package/.next/server/chunks/ssr/_0cvjbuz._.js +0 -3
- package/.next/server/chunks/ssr/_0fafgvl._.js +0 -3
- package/.next/server/chunks/ssr/_0j4v8of._.js +0 -3
- package/.next/server/chunks/ssr/_0l81bzy._.js +0 -3
- package/.next/server/chunks/ssr/_0nso8tp._.js +0 -3
- package/.next/server/chunks/ssr/_0sf1isi._.js +0 -3
- package/.next/server/chunks/ssr/_0ti51xc._.js +0 -3
- package/.next/server/chunks/ssr/_0y84qo6._.js +0 -3
- package/.next/server/chunks/ssr/_10uvw3l._.js +0 -3
- package/.next/server/chunks/ssr/_1dcxzqe._.js +0 -3
- package/.next/server/chunks/ssr/_1e-dgz0._.js +0 -4
- package/.next/server/chunks/ssr/_1fq7zgb._.js +0 -3
- package/.next/server/chunks/ssr/_1jbv7m1._.js +0 -3
- package/.next/server/chunks/ssr/features_bot_components_bot-setting_tsx_01ajft6._.js +0 -4
- package/.next/server/chunks/ssr/features_config_components_14jqgy4._.js +0 -3
- package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +0 -4
- package/.next/server/chunks/ssr/lib_realtime_0aetuyp._.js +0 -24
- package/.next/server/chunks/ssr/lib_realtime_18k_aj-._.js +0 -24
- package/.next/server/chunks/ssr/node_modules_zod_v4_classic_errors_05xv7vp.js +0 -3
- package/.next/server/chunks/ssr/node_modules_zod_v4_classic_external_15fmmz3.js +0 -55
- package/.next/static/chunks/0f9sq-7q_yxyl.js +0 -1
- package/.next/static/chunks/0tydnn2kybibk.js +0 -1
- package/.next/static/chunks/0yysv1gzin17t.js +0 -1
- package/.next/static/chunks/1fr5m75pwtyic.js +0 -1
- package/.next/static/chunks/1gy3bbv7usnjo.js +0 -1
- package/.next/static/chunks/1keib_gt066gc.js +0 -1
- package/.next/static/chunks/1ytnip8wdng93.js +0 -1
- package/.next/static/chunks/21rk8w7bda-su.js +0 -1
- package/.next/static/chunks/247d-r95j8xs0.js +0 -1
- package/.next/static/chunks/28g42tw8tsvhd.js +0 -1
- package/.next/static/chunks/29gyb3nubj51j.js +0 -53
- package/.next/static/chunks/2cwjgkt_hoyhj.js +0 -22
- package/.next/static/chunks/2fq_86jvq9ymq.js +0 -2
- package/.next/static/chunks/2rbf1fpd8n80-.js +0 -22
- package/.next/static/chunks/2ukj8k69y89um.js +0 -1
- package/.next/static/chunks/2uxum7qbyeyxd.js +0 -1
- package/.next/static/chunks/2wngeetfnzxkp.js +0 -2
- package/.next/static/chunks/388-t2v72jh39.css +0 -1
- package/.next/static/chunks/3fqvc0cg-atq_.js +0 -1
- package/.next/static/chunks/3p4egvfjxpatb.js +0 -1
- package/.next/static/chunks/3qe1w1ei-huhl.js +0 -1
- package/.next/static/chunks/3xxa2j56-f3nm.js +0 -3
- package/.next/static/chunks/3y40riycdip-i.js +0 -1
- package/.next/static/chunks/45a6zbtkelph9.js +0 -1
- package/.next/static/media/favicon.2vob68tjqpejf.ico +0 -0
- package/features/ai/prompts/memory-tidy.prompt.ts +0 -123
- package/features/ai/tools/tidy.tool.ts +0 -22
- package/features/memory/components/memory-tidy.tsx +0 -395
- package/features/memory/memory.tidy.ts +0 -332
- package/features/memory/tidy.query.ts +0 -135
- package/features/thursday/use-call-title.ts +0 -31
- /package/.next/server/app/api/{memory/tidy → bot/memory/files}/route/build-manifest.json +0 -0
- /package/.next/server/app/api/{memory/tidy → bot/memory/files}/route/server-reference-manifest.json +0 -0
- /package/.next/server/app/api/{memory/tidy → bot/memory/files}/route.js.map +0 -0
- /package/.next/static/{X34BUd9bfdH27ripuwwBm → x1cCqY0kWpR_VcYx_lWO5}/_buildManifest.js +0 -0
- /package/.next/static/{X34BUd9bfdH27ripuwwBm → x1cCqY0kWpR_VcYx_lWO5}/_clientMiddlewareManifest.js +0 -0
- /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
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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
|
-
|
|
21
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
29
|
-
|
|
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
|
-
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
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
|
-
.
|
|
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
|
-
.
|
|
164
|
+
.nullish()
|
|
165
165
|
.describe("A voice name the provider knows. Null for its default."),
|
|
166
166
|
instructions: z
|
|
167
167
|
.string()
|
|
168
|
-
.
|
|
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
|
-
.
|
|
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
|
-
.
|
|
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
|
-
|
|
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
|
-
.
|
|
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, {
|
|
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
|
-
.
|
|
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 {
|
|
8
|
-
|
|
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 {
|
|
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
|
|
119
|
-
export const
|
|
120
|
-
await
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
|
50
|
-
*
|
|
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
|
|
59
|
-
|
|
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()
|