thursday-agent 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +5 -2
- package/.next/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +5 -5
- package/.next/routes-manifest.json +24 -6
- 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/page_client-reference-manifest.js +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.js +14 -0
- package/.next/server/app/api/bot/{notes → memory}/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/bot/route.js +6 -6
- package/.next/server/app/api/bot/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/task/[id]/route.js +8 -8
- 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 +5 -5
- 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 +9 -8
- 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 +4 -4
- package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/oauth/callback/route.js +5 -5
- package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/route.js +4 -4
- package/.next/server/app/api/mcp/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/tools/route.js +4 -4
- 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 +6 -7
- 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 +17 -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 +57 -90
- package/.next/server/app/page.js +10 -10
- 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 -2
- 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 +1 -1
- 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 +5 -5
- 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 +12 -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/_0-73of8._.js +5 -5
- package/.next/server/chunks/_0-fjql4._.js +26 -0
- package/.next/server/chunks/_00xh_q0._.js +25 -0
- 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 +134 -0
- package/.next/server/chunks/{_0vnutv9._.js → _0ioz3nd._.js} +1 -1
- package/.next/server/chunks/_0iwfby5._.js +3 -0
- package/.next/server/chunks/_0mecv0f._.js +26 -0
- package/.next/server/chunks/_0mh8j4m._.js +3 -0
- package/.next/server/chunks/_0n74zsf._.js +4 -4
- package/.next/server/chunks/_0obojvv._.js +3 -0
- package/.next/server/chunks/_0recufk._.js +49 -0
- package/.next/server/chunks/_0rnf-6n._.js +4 -4
- package/.next/server/chunks/_0sb7tlz._.js +3 -0
- package/.next/server/chunks/_0u10wmw._.js +5 -5
- package/.next/server/chunks/_0u4aiy2._.js +3 -0
- 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/_18-1wcc._.js +5 -5
- package/.next/server/chunks/_1_5mnq4._.js +4 -4
- package/.next/server/chunks/_1_9mjx-._.js +3 -0
- package/.next/server/chunks/{_0pppbb5._.js → _1c78vw5._.js} +166 -37
- package/.next/server/chunks/_1d0j961._.js +6 -0
- package/.next/server/chunks/_1d5zmy8._.js +1 -1
- package/.next/server/chunks/_1drgfx4._.js +4 -4
- 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/_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 +3 -0
- package/.next/server/chunks/features_memory_1uqvksn._.js +6 -0
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0a1rd09._.js → node_modules_consola_dist_chunks_prompt_mjs_0i7cvml._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_06067w6._.js → node_modules_consola_dist_chunks_prompt_mjs_0icqaqw._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_096ais_._.js → node_modules_consola_dist_chunks_prompt_mjs_0r28-sm._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_02s3hjt._.js → node_modules_consola_dist_chunks_prompt_mjs_0v_7drq._.js} +1 -1
- 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_0tvkfgh._.js → node_modules_consola_dist_chunks_prompt_mjs_1y49572._.js} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__092knlj._.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]__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]__0s9dq5u._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__0m1b5ky._.js → [root-of-the-server]__0s9l2sv._.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]__0xsog8n._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0xtssj3._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +61 -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]__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]__1qfqvmg._.js → [root-of-the-server]__202p40z._.js} +2 -2
- package/.next/server/chunks/ssr/{_1mznrxk._.js → _001_ms1._.js} +3 -3
- package/.next/server/chunks/ssr/_01n3o0m._.js +3 -0
- package/.next/server/chunks/ssr/_0ap2fzn._.js +3 -0
- package/.next/server/chunks/ssr/_0fz4mf_._.js +3 -0
- package/.next/server/chunks/ssr/_0gb4gmf._.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/_0ilna52._.js +42 -0
- package/.next/server/chunks/ssr/_0n3toaw._.js +3 -0
- package/.next/server/chunks/ssr/{_13punpm._.js → _0q0zan6._.js} +2 -2
- package/.next/server/chunks/ssr/{_077-g6s._.js → _0s99bgb._.js} +3 -3
- package/.next/server/chunks/ssr/_0zcjrbg._.js +3 -0
- package/.next/server/chunks/ssr/_0zhoc3r._.js +3 -0
- package/.next/server/chunks/ssr/{_1lip4th._.js → _1-_etts._.js} +2 -2
- package/.next/server/chunks/ssr/_1-teee5._.js +3 -3
- package/.next/server/chunks/ssr/_13fke0x._.js +3 -0
- package/.next/server/chunks/ssr/_15j2_8f._.js +3 -0
- package/.next/server/chunks/ssr/_1b2mjwr._.js +3 -0
- package/.next/server/chunks/ssr/{_09ja_w1._.js → _1f-dg-6._.js} +2 -2
- package/.next/server/chunks/ssr/_1fojd41._.js +4 -0
- package/.next/server/chunks/ssr/_1gd8q8l._.js +3 -0
- package/.next/server/chunks/ssr/{_1m3bsfr._.js → _1h0rw11._.js} +2 -2
- package/.next/server/chunks/ssr/_1jhd09t._.js +3 -0
- package/.next/server/chunks/ssr/{_040sk32._.js → _1lz_cq2._.js} +84 -88
- package/.next/server/chunks/ssr/_1nnsk7z._.js +3 -0
- package/.next/server/chunks/ssr/_1sji22n._.js +3 -0
- package/.next/server/chunks/ssr/{_0x_nu5e._.js → _1vi_uo7._.js} +2 -2
- package/.next/server/chunks/ssr/_1vyd1ji._.js +1 -1
- 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/{node_modules_0kxz4gt._.js → node_modules_00etblx._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_18_dk7_._.js → node_modules_04jf_m8._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0_n241r._.js → node_modules_08dhkiq._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0n1kj4p._.js → node_modules_0940ns5._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_17lrt3y._.js → node_modules_09q35v_._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1toafc-._.js → node_modules_0_-_a--._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0lrjk5t._.js → node_modules_0arus10._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_04n7mjs._.js → node_modules_0b__sgl._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0iz1rzd._.js → node_modules_0cxaxk9._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0ndvxub._.js → node_modules_0g7fzk3._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0kl7-tn._.js → node_modules_0had7xd._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_19dp7ko._.js → node_modules_0pvd7q-._.js} +1 -1
- package/.next/server/chunks/ssr/node_modules_0x3-ply._.js +3 -0
- package/.next/server/chunks/ssr/{node_modules_1dwguw_._.js → node_modules_0yugy6m._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_004qlr4._.js → node_modules_14om4ar._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1q0p85z._.js → node_modules_14q6g4n._.js} +1 -1
- package/.next/server/chunks/ssr/node_modules_17bwo43._.js +55 -0
- package/.next/server/chunks/ssr/{node_modules_1hd-5tv._.js → node_modules_198nmll._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0m93zeg._.js → node_modules_1_pc9kq._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1n5ygqe._.js → node_modules_1aaxuef._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_01qnv-a._.js → node_modules_1cx_ql6._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1zu988w._.js → node_modules_1cz2hle._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1xyd7ov._.js → node_modules_1efrqxi._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_13r44jq._.js → node_modules_1eg7m6c._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_08d8bke._.js → node_modules_1gdh31p._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1hn8z1f._.js → node_modules_1hpopmo._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_20yebtj._.js → node_modules_1qpjvy5._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_09xhur7._.js → node_modules_1vh5ntv._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0m9a4y0._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1b748ic._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_13w_wy9._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1z4hm5e._.js} +1 -1
- package/.next/server/chunks/ssr/node_modules_@vercel_oidc_dist_06mk8id._.js +3 -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 +58 -91
- package/.next/static/chunks/00rd4-v8r7axp.js +1 -0
- package/.next/static/chunks/08qe4as2q428z.js +3 -0
- package/.next/static/chunks/{31ttnjt6g35a0.js → 0ev4hyghq0mbb.js} +1 -1
- package/.next/static/chunks/0fl3gwe4-l6tz.js +1 -0
- package/.next/static/chunks/0gnqdjn2lvdad.js +2 -0
- package/.next/static/chunks/0hwap1-p0m5sa.js +1 -0
- package/.next/static/chunks/0r5qcctujhxli.js +1 -0
- package/.next/static/chunks/0w52rrrmuj9r9.js +1 -0
- package/.next/static/chunks/{07kl352c-lvcz.js → 0wcprt5ot5she.js} +1 -1
- package/.next/static/chunks/10teww7wt-f6h.js +1 -0
- package/.next/static/chunks/15m575979un5f.js +38 -0
- package/.next/static/chunks/17p6tk6k88dq6.js +1 -0
- package/.next/static/chunks/{3_h9txt3tq8t8.js → 1dkjg87pxk0n9.js} +1 -1
- package/.next/static/chunks/1jd09sxcjddu1.js +1 -0
- package/.next/static/chunks/1kq8h8wi_e0bc.js +53 -0
- package/.next/static/chunks/{18vhba44l1fc9.js → 1w73ece_6bheu.js} +1 -1
- package/.next/static/chunks/{3ard_noqapnw1.js → 214ya3n5gxeih.js} +1 -1
- package/.next/static/chunks/22_zkas21rpna.js +1 -0
- package/.next/static/chunks/2h0sd2vumhb15.js +1 -0
- package/.next/static/chunks/2t4vhi3m8ahya.js +1 -0
- package/.next/static/chunks/2tigdtz3dpcy8.js +1 -0
- package/.next/static/chunks/2u7xt6mxg44lf.js +1 -0
- package/.next/static/chunks/39j0fvpybzabl.js +40 -0
- package/.next/static/chunks/3akmqm77muj4-.js +1 -0
- package/.next/static/chunks/3cq5g494yuke8.css +1 -0
- package/.next/static/chunks/3woj-xd7ki5_i.js +1 -0
- package/.next/static/chunks/3xk7yqgomx7yq.js +1 -0
- package/.next/static/chunks/3zmcsnuo25zvq.js +1 -0
- package/.next/static/media/favicon.37o1pjldwi2uc.ico +0 -0
- package/README.md +47 -22
- 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.ts +3 -7
- package/app/api/llm-model/credits/route.ts +11 -0
- package/app/api/llm-model/route.ts +6 -1
- 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 +19 -4
- package/bin/port.mjs +65 -0
- package/bin/thursday.mjs +5 -33
- package/components/ui/shiny-text.tsx +48 -134
- package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/migration.sql +24 -34
- package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/snapshot.json +71 -145
- package/database/migrations/20260911030320_opposite_jack_power/migration.sql +1 -0
- package/database/migrations/{20260909063821_bitter_tenebrous → 20260911030320_opposite_jack_power}/snapshot.json +57 -184
- package/docs/how-it-works.md +11 -7
- package/docs/images/face-dark.png +0 -0
- package/docs/images/face-light.png +0 -0
- package/docs/images/keeps-going.png +0 -0
- package/features/ai/chatgpt.ts +639 -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 +78 -56
- package/features/ai/model.schema.ts +232 -34
- package/features/ai/model.ts +169 -24
- package/features/ai/prompts/bot.prompt.ts +207 -114
- package/features/ai/prompts/memory-edit.prompt.ts +33 -0
- package/features/ai/prompts/prompt-helper.ts +45 -26
- package/features/ai/prompts/thursday.prompt.ts +57 -27
- package/features/ai/tools/bot.tool.ts +35 -52
- package/features/ai/tools/connected.ts +17 -4
- package/features/ai/tools/memory.tool.ts +181 -117
- package/features/ai/tools/search.tool.ts +136 -47
- package/features/ai/tools/tool-name.ts +2 -6
- package/features/ai/tools/workspace.tool.ts +5 -1
- package/features/bot/bot.action.ts +14 -19
- package/features/bot/bot.memory.ts +89 -0
- package/features/bot/bot.query.ts +37 -57
- package/features/bot/bot.run.ts +512 -242
- package/features/bot/bot.runner.ts +434 -120
- package/features/bot/bot.schema.ts +104 -19
- package/features/bot/bot.seed.ts +89 -16
- package/features/bot/components/bot-mark.tsx +122 -20
- package/features/bot/components/bot-room.tsx +214 -132
- package/features/bot/components/bot-setting.tsx +790 -402
- package/features/bot/components/bot-tool.tsx +2 -7
- 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 +240 -34
- package/features/bot/task.store.ts +76 -13
- 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 +340 -0
- package/features/memory/components/memory-setting.tsx +75 -77
- package/features/memory/memory.action.ts +3 -43
- package/features/memory/memory.edit.ts +87 -0
- package/features/memory/memory.query.ts +24 -42
- package/features/memory/memory.schema.ts +29 -106
- package/features/settings/components/settings.tsx +2 -0
- package/features/settings/settings.alert.ts +3 -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 -98
- 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 -12
- package/features/thursday/use-thursday.ts +87 -60
- package/features/workspace/components/file-view.tsx +4 -2
- package/features/workspace/workspace.ts +110 -26
- package/lib/limits.ts +1 -1
- package/lib/oauth-page.ts +27 -0
- package/lib/realtime/openai.ts +2 -2
- package/lib/realtime/realtime.protocol.ts +1 -1
- package/lib/realtime/realtime.tap.ts +122 -0
- package/lib/sandbox.ts +59 -36
- package/package.json +1 -1
- package/skills/browser/SKILL.md +55 -34
- package/.next/server/app/api/bot/notes/route/app-paths-manifest.json +0 -3
- package/.next/server/app/api/bot/notes/route.js +0 -14
- package/.next/server/app/api/bot/notes/route_client-reference-manifest.js +0 -3
- package/.next/server/app/api/memory/tidy/route/app-paths-manifest.json +0 -3
- package/.next/server/app/api/memory/tidy/route.js +0 -22
- package/.next/server/app/api/memory/tidy/route.js.nft.json +0 -1
- package/.next/server/chunks/0d-b_next_dist_server_app-render_after-task-async-storage_external_0-exn7p.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0-npkh_._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__005var5._.js +0 -3
- 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]__04_8spk._.js +0 -3
- 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]__0cro2dz._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0dupqt7._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0emr6go._.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]__0p32jfz._.js +0 -12
- package/.next/server/chunks/[root-of-the-server]__0phdgco._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0wvgrsl._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__10qshki._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__11j52t0._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1692zrv._.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_aoyr9._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1bn73ih._.js +0 -10
- 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]__1e-ci13._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1fboj2j._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1lr7j9t._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1oli73c._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1txedx6._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1untqv8._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1zgpz1w._.js +0 -3
- package/.next/server/chunks/_00_584r._.js +0 -293
- 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/_0nn99o2._.js +0 -3
- package/.next/server/chunks/_0zuzmt_._.js +0 -39
- package/.next/server/chunks/_106co2o._.js +0 -3
- package/.next/server/chunks/_12bbv5i._.js +0 -100
- package/.next/server/chunks/_15q1pig._.js +0 -3
- package/.next/server/chunks/_19wg5yn._.js +0 -138
- package/.next/server/chunks/_1bt95p9._.js +0 -55
- package/.next/server/chunks/_1cbk7ms._.js +0 -26
- package/.next/server/chunks/_1drv2et._.js +0 -40
- package/.next/server/chunks/_1ic3bew._.js +0 -5
- package/.next/server/chunks/_1mxn_lb._.js +0 -3
- package/.next/server/chunks/_1rysr-r._.js +0 -10
- package/.next/server/chunks/_1u3rwbr._.js +0 -3
- package/.next/server/chunks/_1x7p319._.js +0 -6
- package/.next/server/chunks/_next-internal_server_app_api_bot_notes_route_actions_0qcsyu7.js +0 -3
- package/.next/server/chunks/_next-internal_server_app_api_memory_tidy_route_actions_0_cfuom.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_0gzvgfv._.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_1tpvamf._.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_1y9-wcr._.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]__0iuoa-r._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0un-erv._.js +0 -4
- package/.next/server/chunks/ssr/[root-of-the-server]__1-mnhyd._.js +0 -92
- package/.next/server/chunks/ssr/[root-of-the-server]__1bww500._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1vcdast._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1xwnu-h._.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/_03webdr._.js +0 -3
- package/.next/server/chunks/ssr/_09-0k3z._.js +0 -3
- package/.next/server/chunks/ssr/_0f_b_9s._.js +0 -3
- package/.next/server/chunks/ssr/_0fafgvl._.js +0 -3
- package/.next/server/chunks/ssr/_0sf1isi._.js +0 -3
- package/.next/server/chunks/ssr/_0su6_08._.js +0 -3
- package/.next/server/chunks/ssr/_0ti51xc._.js +0 -3
- package/.next/server/chunks/ssr/_0w5bgak._.js +0 -3
- package/.next/server/chunks/ssr/_0y84qo6._.js +0 -3
- package/.next/server/chunks/ssr/_1ciyoo3._.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/_1g6l4uj._.js +0 -3
- package/.next/server/chunks/ssr/_1ruzehw._.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/node_modules_zod_v4_classic_external_15fmmz3.js +0 -55
- package/.next/static/chunks/05b6nx_o3_f_n.js +0 -1
- package/.next/static/chunks/0dmns-gi0raa4.js +0 -1
- package/.next/static/chunks/0f9sq-7q_yxyl.js +0 -1
- package/.next/static/chunks/0oc4_xoia77dg.css +0 -1
- package/.next/static/chunks/0pheo8m3a-rzi.js +0 -1
- package/.next/static/chunks/19i8h2t-5evjx.js +0 -1
- package/.next/static/chunks/1c5fcj473025q.js +0 -1
- package/.next/static/chunks/1pi_hbmjw-f-z.js +0 -1
- package/.next/static/chunks/1twt6k09vg4np.js +0 -1
- package/.next/static/chunks/1ytnip8wdng93.js +0 -1
- package/.next/static/chunks/28gotuisldmom.js +0 -1
- package/.next/static/chunks/2998p0y7k1c8z.js +0 -3
- package/.next/static/chunks/29gyb3nubj51j.js +0 -53
- package/.next/static/chunks/2l233xfycjpd8.js +0 -1
- package/.next/static/chunks/2p5n7pa3c40t-.js +0 -2
- package/.next/static/chunks/2ru1q132af7h7.js +0 -1
- package/.next/static/chunks/2t8wqycwg3y04.js +0 -2
- package/.next/static/chunks/2uxum7qbyeyxd.js +0 -1
- package/.next/static/chunks/32z_ypgtchw48.js +0 -1
- package/.next/static/chunks/33pyjb3xd1iez.js +0 -1
- package/.next/static/chunks/3omud5xunrk1f.js +0 -1
- package/.next/static/chunks/42dnrkbph9e-1.js +0 -1
- package/.next/static/media/favicon.2vob68tjqpejf.ico +0 -0
- package/database/migrations/20260909063821_bitter_tenebrous/migration.sql +0 -1
- package/features/ai/prompts/memory-tidy.prompt.ts +0 -129
- package/features/ai/tools/tidy.tool.ts +0 -22
- package/features/bot/bot.notes.ts +0 -120
- package/features/memory/components/memory-tidy.tsx +0 -395
- package/features/memory/components/memory-view.tsx +0 -84
- 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/bot/{notes → memory/files}/route/build-manifest.json +0 -0
- /package/.next/server/app/api/bot/{notes → memory/files}/route/server-reference-manifest.json +0 -0
- /package/.next/server/app/api/bot/{notes → memory/files}/route.js.map +0 -0
- /package/.next/server/app/api/{memory/tidy → bot/memory}/route/build-manifest.json +0 -0
- /package/.next/server/app/api/{memory/tidy → bot/memory}/route/server-reference-manifest.json +0 -0
- /package/.next/server/app/api/{memory/tidy → bot/memory}/route.js.map +0 -0
- /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → kaTO0UHqF1bMnWgCDik2f}/_buildManifest.js +0 -0
- /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → kaTO0UHqF1bMnWgCDik2f}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → kaTO0UHqF1bMnWgCDik2f}/_ssgManifest.js +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { format } from "date-fns";
|
|
3
4
|
import {
|
|
4
5
|
ArrowUp,
|
|
5
6
|
Check,
|
|
7
|
+
ChevronDown,
|
|
6
8
|
ChevronLeft,
|
|
7
9
|
ChevronRight,
|
|
8
10
|
ChevronsRight,
|
|
@@ -10,6 +12,7 @@ import {
|
|
|
10
12
|
History,
|
|
11
13
|
Loader2,
|
|
12
14
|
Plus,
|
|
15
|
+
RotateCw,
|
|
13
16
|
X,
|
|
14
17
|
} from "lucide-react";
|
|
15
18
|
import {
|
|
@@ -27,16 +30,15 @@ import { Bubble, BubbleContent } from "@/components/ui/bubble";
|
|
|
27
30
|
import { Button } from "@/components/ui/button";
|
|
28
31
|
import { FoldedText } from "@/components/ui/folded-text";
|
|
29
32
|
import { Markdown } from "@/components/ui/markdown";
|
|
30
|
-
import ShinyText from "@/components/ui/shiny-text";
|
|
33
|
+
import { ShinyText, type ShinyTone } from "@/components/ui/shiny-text";
|
|
31
34
|
import { Textarea } from "@/components/ui/textarea";
|
|
32
35
|
import { toast } from "@/components/ui/toast";
|
|
33
|
-
import {
|
|
34
|
-
import { markReportedAction, startTaskAction } from "@/features/bot/bot.action";
|
|
36
|
+
import { startTaskAction } from "@/features/bot/bot.action";
|
|
35
37
|
import {
|
|
36
38
|
type Bot,
|
|
37
39
|
type BotIcon,
|
|
38
40
|
DEFAULT_BOT,
|
|
39
|
-
|
|
41
|
+
isAppStop,
|
|
40
42
|
TASK_CONTINUE,
|
|
41
43
|
} from "@/features/bot/bot.schema";
|
|
42
44
|
import { BotMark } from "@/features/bot/components/bot-mark";
|
|
@@ -47,7 +49,6 @@ import { openSettings } from "@/features/settings/settings.store";
|
|
|
47
49
|
import { ThursdayMark } from "@/features/thursday/components/thursday-mark";
|
|
48
50
|
import { FileViewer } from "@/features/workspace/components/file-view";
|
|
49
51
|
import { shortAgo, toDate } from "@/lib/date-like";
|
|
50
|
-
import { unwrapResult } from "@/lib/protocol/result";
|
|
51
52
|
import { useServerAction } from "@/lib/protocol/use-server-action";
|
|
52
53
|
import { revalidate, useServerRoute } from "@/lib/protocol/use-server-route";
|
|
53
54
|
import {
|
|
@@ -71,6 +72,7 @@ import {
|
|
|
71
72
|
type TaskViewStatus,
|
|
72
73
|
threadItems,
|
|
73
74
|
useBotTasks,
|
|
75
|
+
useSeenOnDetail,
|
|
74
76
|
} from "../task.store";
|
|
75
77
|
import { BotTool } from "./bot-tool";
|
|
76
78
|
|
|
@@ -178,41 +180,23 @@ export const BotRoom = memo(function BotRoom() {
|
|
|
178
180
|
}
|
|
179
181
|
}, [tasks, handoff]);
|
|
180
182
|
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
// move `updatedAt`, so the set only bridges the gap until the next poll.
|
|
184
|
-
const marked = useRef(new Set<string>());
|
|
185
|
-
useEffect(() => {
|
|
186
|
-
if (!current || current.relayed) return;
|
|
187
|
-
if (current.status !== "done" && current.status !== "failed") return;
|
|
188
|
-
const key = `${current.id}@${toDate(current.updatedAt).getTime()}`;
|
|
189
|
-
if (marked.current.has(key)) return;
|
|
190
|
-
marked.current.add(key);
|
|
191
|
-
// unwrapResult folds Result failures and rejections into one path; on failure
|
|
192
|
-
// release the key so the task can be marked again.
|
|
193
|
-
void markReportedAction([current.id])
|
|
194
|
-
.then(unwrapResult)
|
|
195
|
-
.then(() => revalidate(queryKey.tasks))
|
|
196
|
-
.catch((cause) => {
|
|
197
|
-
marked.current.delete(key);
|
|
198
|
-
toast.add({
|
|
199
|
-
type: "error",
|
|
200
|
-
title: "Could not mark the task as read",
|
|
201
|
-
description: errorToString(cause),
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
}, [current]);
|
|
183
|
+
// Reading a thread is reading its ending; that is what clears its dot.
|
|
184
|
+
useSeenOnDetail(open ? current : null);
|
|
205
185
|
|
|
206
186
|
const busy = tasks.filter((entry) => entry.status === "working").length;
|
|
207
187
|
const attention = newest.filter(needsYou);
|
|
208
188
|
const pending = attention.length;
|
|
189
|
+
const unread = newest.filter(isUnread);
|
|
190
|
+
const failed = unread.filter((entry) => entry.status === "failed").length;
|
|
209
191
|
|
|
210
192
|
const closeCompose = useCallback(() => setComposing(false), []);
|
|
211
193
|
|
|
212
194
|
return (
|
|
213
|
-
|
|
195
|
+
// As wide as the resting pill may grow: 80% of the window. The open room
|
|
196
|
+
// keeps its own 33rem inside it.
|
|
197
|
+
<div className="pointer-events-none absolute right-5 bottom-5 z-10 flex w-[min(80vw,calc(100vw-2.5rem))] flex-col items-end gap-2">
|
|
214
198
|
{open ? (
|
|
215
|
-
<div className="pointer-events-auto flex max-h-[min(44rem,78vh)] w-full animate-in flex-col overflow-hidden rounded-3xl bg-background/75 shadow-2xl shadow-black/6 ring-1 ring-border/50 backdrop-blur-xl fade-in slide-in-from-bottom-1 duration-200">
|
|
199
|
+
<div className="pointer-events-auto flex max-h-[min(44rem,78vh)] w-132 max-w-full animate-in flex-col overflow-hidden rounded-3xl bg-background/75 shadow-2xl shadow-black/6 ring-1 ring-border/50 backdrop-blur-xl fade-in slide-in-from-bottom-1 duration-200">
|
|
216
200
|
{current ? (
|
|
217
201
|
<>
|
|
218
202
|
<ThreadHeader
|
|
@@ -267,6 +251,8 @@ export const BotRoom = memo(function BotRoom() {
|
|
|
267
251
|
count={tasks.length}
|
|
268
252
|
busy={busy}
|
|
269
253
|
pending={pending}
|
|
254
|
+
unread={unread.length}
|
|
255
|
+
failed={failed}
|
|
270
256
|
composing={composing}
|
|
271
257
|
onCompose={() => setComposing(true)}
|
|
272
258
|
onCloseCompose={closeCompose}
|
|
@@ -275,8 +261,10 @@ export const BotRoom = memo(function BotRoom() {
|
|
|
275
261
|
setOpen(true);
|
|
276
262
|
}}
|
|
277
263
|
onOpen={() => {
|
|
278
|
-
//
|
|
279
|
-
|
|
264
|
+
// One thing to look at opens straight into its thread: a single
|
|
265
|
+
// question, or with none waiting, a single answer nobody has read.
|
|
266
|
+
const only = attention.length ? attention : unread;
|
|
267
|
+
if (!picked && only.length === 1) setPicked(only[0].id);
|
|
280
268
|
setOpen(true);
|
|
281
269
|
}}
|
|
282
270
|
/>
|
|
@@ -441,7 +429,7 @@ function crewOf(
|
|
|
441
429
|
};
|
|
442
430
|
}
|
|
443
431
|
|
|
444
|
-
/** Blanks the question in the reply box when it already is the last thread line (
|
|
432
|
+
/** Blanks the question in the reply box when it already is the last thread line (stops the app made). */
|
|
445
433
|
function askFor(task: TaskView): TaskView["ask"] {
|
|
446
434
|
if (!task.ask?.question) return task.ask;
|
|
447
435
|
const last = task.lines.at(-1);
|
|
@@ -451,46 +439,69 @@ function askFor(task: TaskView): TaskView["ask"] {
|
|
|
451
439
|
}
|
|
452
440
|
|
|
453
441
|
/**
|
|
454
|
-
* A task that cannot move until the user answers: a question, or a
|
|
442
|
+
* A task that cannot move until the user answers: a question, or a stop the app made.
|
|
455
443
|
*
|
|
456
444
|
* A finished job is not on this list. It has nothing for the user to do, and
|
|
457
|
-
* counting it here made the chip hold itself open over
|
|
458
|
-
* act on.
|
|
445
|
+
* counting it here made the chip hold itself open over an answer nobody had to
|
|
446
|
+
* act on. An answer says itself once, in the sentence, and then it is a row in
|
|
459
447
|
* the room like every other one.
|
|
460
448
|
*/
|
|
461
449
|
const needsYou = (task: TaskView) => task.status === "waiting";
|
|
462
450
|
|
|
451
|
+
/** An ending nobody has opened. It needs the user too, to read rather than to answer. */
|
|
452
|
+
const isUnread = (task: TaskView) =>
|
|
453
|
+
(task.status === "done" || task.status === "failed") && !task.seen;
|
|
454
|
+
|
|
463
455
|
/**
|
|
464
456
|
* What the room itself is doing, and nothing else — the right side of the pill.
|
|
465
457
|
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
*
|
|
458
|
+
* What is still moving shines, like every other running line: a wait in amber,
|
|
459
|
+
* running jobs in muted ink beside the spinner. An ending does not — an answer
|
|
460
|
+
* nobody has opened is something to read, not something happening.
|
|
469
461
|
*/
|
|
470
462
|
function restingState({
|
|
471
463
|
count,
|
|
472
464
|
busy,
|
|
473
465
|
pending,
|
|
466
|
+
unread,
|
|
467
|
+
failed,
|
|
474
468
|
}: {
|
|
475
469
|
count: number;
|
|
476
470
|
busy: number;
|
|
477
471
|
pending: number;
|
|
478
|
-
|
|
472
|
+
/** Endings nobody has opened, failures included. */
|
|
473
|
+
unread: number;
|
|
474
|
+
failed: number;
|
|
475
|
+
}): { text: string; tone: string; shine: ShinyTone | null } {
|
|
479
476
|
if (pending > 0)
|
|
480
477
|
return {
|
|
481
478
|
text: pending === 1 ? "waiting on you" : `${pending} waiting on you`,
|
|
482
479
|
tone: WAITING_INK,
|
|
483
|
-
shine:
|
|
480
|
+
shine: "waiting",
|
|
481
|
+
};
|
|
482
|
+
// Unread outranks running: a job still going will say so again, and an answer
|
|
483
|
+
// left unopened will not.
|
|
484
|
+
if (failed > 0)
|
|
485
|
+
return {
|
|
486
|
+
text: failed === 1 ? "1 failed" : `${failed} failed`,
|
|
487
|
+
tone: "text-destructive",
|
|
488
|
+
shine: null,
|
|
489
|
+
};
|
|
490
|
+
if (unread > 0)
|
|
491
|
+
return {
|
|
492
|
+
text: unread === 1 ? "1 new answer" : `${unread} new answers`,
|
|
493
|
+
tone: WAITING_INK,
|
|
494
|
+
shine: null,
|
|
484
495
|
};
|
|
485
496
|
if (busy > 0)
|
|
486
497
|
return {
|
|
487
498
|
text: busy === 1 ? "working" : `${busy} running`,
|
|
488
499
|
tone: "text-muted-foreground",
|
|
489
|
-
shine:
|
|
500
|
+
shine: "muted",
|
|
490
501
|
};
|
|
491
502
|
if (count > 0)
|
|
492
|
-
return { text: "all done", tone: "text-muted-foreground", shine:
|
|
493
|
-
return { text: "no jobs yet", tone: "text-muted-foreground", shine:
|
|
503
|
+
return { text: "all done", tone: "text-muted-foreground", shine: null };
|
|
504
|
+
return { text: "no jobs yet", tone: "text-muted-foreground", shine: null };
|
|
494
505
|
}
|
|
495
506
|
|
|
496
507
|
/**
|
|
@@ -520,6 +531,8 @@ function Chip({
|
|
|
520
531
|
count,
|
|
521
532
|
busy,
|
|
522
533
|
pending,
|
|
534
|
+
unread,
|
|
535
|
+
failed,
|
|
523
536
|
composing,
|
|
524
537
|
onCompose,
|
|
525
538
|
onCloseCompose,
|
|
@@ -535,13 +548,15 @@ function Chip({
|
|
|
535
548
|
count: number;
|
|
536
549
|
busy: number;
|
|
537
550
|
pending: number;
|
|
551
|
+
unread: number;
|
|
552
|
+
failed: number;
|
|
538
553
|
composing: boolean;
|
|
539
554
|
onCompose: () => void;
|
|
540
555
|
onCloseCompose: () => void;
|
|
541
556
|
onPick: (id: string) => void;
|
|
542
557
|
onOpen: () => void;
|
|
543
558
|
}) {
|
|
544
|
-
const state = restingState({ count, busy, pending });
|
|
559
|
+
const state = restingState({ count, busy, pending, unread, failed });
|
|
545
560
|
const grown = composing || pending > 0;
|
|
546
561
|
|
|
547
562
|
return (
|
|
@@ -550,8 +565,10 @@ function Chip({
|
|
|
550
565
|
// Not `overflow-hidden`: a hand-off bubble stands above the row, outside
|
|
551
566
|
// this box. The growing part clips itself instead.
|
|
552
567
|
"pointer-events-auto w-fit max-w-full bg-background/78 ring-1 ring-border/50 backdrop-blur-md transition-shadow duration-300",
|
|
568
|
+
// A card with questions in it keeps the room's width: only the resting
|
|
569
|
+
// row grows with the corner, and a reply's long lines would stretch it.
|
|
553
570
|
grown
|
|
554
|
-
? "min-w-96 rounded-3xl shadow-lg shadow-black/8"
|
|
571
|
+
? "max-w-[min(33rem,100%)] min-w-96 rounded-3xl shadow-lg shadow-black/8"
|
|
555
572
|
: "rounded-full shadow-sm shadow-black/3",
|
|
556
573
|
)}
|
|
557
574
|
>
|
|
@@ -607,18 +624,12 @@ function Chip({
|
|
|
607
624
|
the right. `ml-auto` keeps it there when the crew says nothing. */}
|
|
608
625
|
<span className="ml-auto flex h-7 shrink-0 items-center gap-1.5">
|
|
609
626
|
{state.shine ? (
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
speed={2.6}
|
|
617
|
-
color="var(--rest)"
|
|
618
|
-
shineColor="var(--shine)"
|
|
619
|
-
className="truncate text-[14px] leading-5 tracking-[-0.15px]"
|
|
620
|
-
/>
|
|
621
|
-
</span>
|
|
627
|
+
<ShinyText
|
|
628
|
+
text={state.text}
|
|
629
|
+
tone={state.shine}
|
|
630
|
+
speed={2.6}
|
|
631
|
+
className="block truncate text-[14px] leading-5 tracking-[-0.15px]"
|
|
632
|
+
/>
|
|
622
633
|
) : (
|
|
623
634
|
<span
|
|
624
635
|
key={state.text}
|
|
@@ -633,12 +644,14 @@ function Chip({
|
|
|
633
644
|
{/* Always 16px, empty or not: a glyph that comes and goes moves the
|
|
634
645
|
sentence's right end even when the sentence has not changed. */}
|
|
635
646
|
<span className="grid size-4 shrink-0 place-items-center">
|
|
636
|
-
{pending === 0 && busy > 0 && (
|
|
647
|
+
{pending === 0 && unread === 0 && busy > 0 && (
|
|
637
648
|
<Loader2 className="size-4 animate-spin text-muted-foreground/70" />
|
|
638
649
|
)}
|
|
639
|
-
{pending === 0 &&
|
|
640
|
-
|
|
641
|
-
|
|
650
|
+
{pending === 0 &&
|
|
651
|
+
failed === 0 &&
|
|
652
|
+
(unread > 0 || (busy === 0 && count > 0)) && (
|
|
653
|
+
<Check className="size-4 text-muted-foreground/60" />
|
|
654
|
+
)}
|
|
642
655
|
</span>
|
|
643
656
|
</span>
|
|
644
657
|
</button>
|
|
@@ -702,8 +715,13 @@ function Compose({ bots, onDone }: { bots?: Bot[]; onDone: () => void }) {
|
|
|
702
715
|
});
|
|
703
716
|
|
|
704
717
|
// A fresh install has no rows and still has a worker (bot.schema DEFAULT_BOT).
|
|
718
|
+
// Switched-off bots are left out for the same reason no model is shown one —
|
|
719
|
+
// but the fallback answers "no rows", not "every row off", so switching them
|
|
720
|
+
// all off leaves nothing to pick rather than conjuring a worker.
|
|
705
721
|
const roster: BotRef[] = bots?.length
|
|
706
|
-
? bots
|
|
722
|
+
? bots
|
|
723
|
+
.filter((bot) => !bot.disabled)
|
|
724
|
+
.map((bot) => ({ name: bot.name, icon: bot.icon }))
|
|
707
725
|
: [{ name: DEFAULT_BOT.name, icon: DEFAULT_BOT.icon }];
|
|
708
726
|
|
|
709
727
|
const send = () => {
|
|
@@ -833,6 +851,9 @@ const GHOSTS: CrewFace[] = ["alto", "brio", "cinder", "delta"].map(
|
|
|
833
851
|
/** A single face reads as one worker, not as a crew; below this the row is padded out. */
|
|
834
852
|
const FLOOR = 3;
|
|
835
853
|
|
|
854
|
+
/** The awake halo, in the mark's own view-box units: about 2px of blur at 28px. */
|
|
855
|
+
const AWAKE_GLOW = 20;
|
|
856
|
+
|
|
836
857
|
/**
|
|
837
858
|
* The crew, and what each of them is doing.
|
|
838
859
|
*
|
|
@@ -872,25 +893,12 @@ function Crew({
|
|
|
872
893
|
face.standIn && "opacity-35",
|
|
873
894
|
face.awake && "-translate-y-0.5 scale-110",
|
|
874
895
|
)}
|
|
875
|
-
style={{
|
|
876
|
-
zIndex: crew.length - index,
|
|
877
|
-
color: face.icon?.color ?? undefined,
|
|
878
|
-
// The glow is the bot's own colour, so who is moving reads before
|
|
879
|
-
// any word does. currentColor keeps it right when nobody chose one.
|
|
880
|
-
filter: face.awake
|
|
881
|
-
? "drop-shadow(0 0 5px color-mix(in srgb, currentColor 55%, transparent))"
|
|
882
|
-
: undefined,
|
|
883
|
-
}}
|
|
896
|
+
style={{ zIndex: crew.length - index }}
|
|
884
897
|
>
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
color={face.icon?.color}
|
|
890
|
-
shape={face.icon?.shape}
|
|
891
|
-
outline={face.icon?.outline}
|
|
892
|
-
notify={face.waiting}
|
|
893
|
-
/>
|
|
898
|
+
{/* The halo is the mark's own (bot-mark `glow`), not a filter on
|
|
899
|
+
this box: a filter here also lands on the bubble above, which
|
|
900
|
+
came out tinted in the bot's colour and wearing its blur. */}
|
|
901
|
+
<CrewMark face={face} />
|
|
894
902
|
{bubble && <HandoffBubble handoff={bubble} />}
|
|
895
903
|
</span>
|
|
896
904
|
{face.word && (
|
|
@@ -900,8 +908,6 @@ function Crew({
|
|
|
900
908
|
<ShinyText
|
|
901
909
|
text={face.word}
|
|
902
910
|
speed={2.6}
|
|
903
|
-
color="var(--muted-foreground)"
|
|
904
|
-
shineColor="var(--foreground)"
|
|
905
911
|
className="truncate text-[13px] leading-5 tracking-[-0.1px]"
|
|
906
912
|
/>
|
|
907
913
|
</span>
|
|
@@ -926,6 +932,30 @@ function Crew({
|
|
|
926
932
|
);
|
|
927
933
|
}
|
|
928
934
|
|
|
935
|
+
/**
|
|
936
|
+
* One crew face. Awake, it wears a halo in its own colour, so who is moving
|
|
937
|
+
* reads before any word does; the options object is memoized because a new one
|
|
938
|
+
* every render re-derives the silhouette behind it.
|
|
939
|
+
*/
|
|
940
|
+
function CrewMark({ face }: { face: CrewFace }) {
|
|
941
|
+
const glow = useMemo(
|
|
942
|
+
() => (face.awake ? { glow: AWAKE_GLOW } : undefined),
|
|
943
|
+
[face.awake],
|
|
944
|
+
);
|
|
945
|
+
return (
|
|
946
|
+
<BotMark
|
|
947
|
+
size={28}
|
|
948
|
+
seed={face.name}
|
|
949
|
+
vary={face.name}
|
|
950
|
+
color={face.icon?.color}
|
|
951
|
+
shape={face.icon?.shape}
|
|
952
|
+
outline={face.icon?.outline}
|
|
953
|
+
notify={face.waiting}
|
|
954
|
+
options={glow}
|
|
955
|
+
/>
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
|
|
929
959
|
/**
|
|
930
960
|
* A hand-off, over the face it landed on. The mark at its head is whoever gave
|
|
931
961
|
* it away — Thursday, another bot, or nobody at all when it was you.
|
|
@@ -1100,7 +1130,7 @@ const STATE_LOOK: Record<TaskViewStatus, string> = {
|
|
|
1100
1130
|
|
|
1101
1131
|
function State({ task }: { task: TaskView }) {
|
|
1102
1132
|
const look =
|
|
1103
|
-
task.status === "done" && task.
|
|
1133
|
+
task.status === "done" && task.seen
|
|
1104
1134
|
? "text-muted-foreground"
|
|
1105
1135
|
: STATE_LOOK[task.status];
|
|
1106
1136
|
|
|
@@ -1109,8 +1139,6 @@ function State({ task }: { task: TaskView }) {
|
|
|
1109
1139
|
<ShinyText
|
|
1110
1140
|
text="working"
|
|
1111
1141
|
speed={2.2}
|
|
1112
|
-
color="var(--muted-foreground)"
|
|
1113
|
-
shineColor="var(--foreground)"
|
|
1114
1142
|
className="shrink-0 font-mono text-[10px]"
|
|
1115
1143
|
/>
|
|
1116
1144
|
);
|
|
@@ -1224,18 +1252,17 @@ function TaskList({
|
|
|
1224
1252
|
|
|
1225
1253
|
function TaskRow({ task, onPick }: { task: TaskView; onPick: () => void }) {
|
|
1226
1254
|
const attention = needsYou(task);
|
|
1227
|
-
// secondLine runs plainText over the whole
|
|
1255
|
+
// secondLine runs plainText over the whole answer. Every sync rebuilds each TaskView
|
|
1228
1256
|
// (task.store), so depend on the fields that change the line, not on `task`.
|
|
1229
1257
|
const last = task.lines.at(-1);
|
|
1230
1258
|
const line = useMemo(
|
|
1231
1259
|
() => secondLine(task),
|
|
1232
|
-
[task.status, task.outcome, task.
|
|
1260
|
+
[task.status, task.outcome, task.seen, task.ask, last?.id],
|
|
1233
1261
|
);
|
|
1234
1262
|
const [answer, answering] = useAnswerTask();
|
|
1235
1263
|
const [sending, setSending] = useState<string | null>(null);
|
|
1236
1264
|
// Options are answered inline, without opening the thread.
|
|
1237
1265
|
const options = task.status === "waiting" ? (task.ask?.options ?? []) : [];
|
|
1238
|
-
const budget = isBudgetAsk(task.ask);
|
|
1239
1266
|
|
|
1240
1267
|
return (
|
|
1241
1268
|
// The row is not itself a button: the option buttons cannot nest inside one.
|
|
@@ -1287,8 +1314,6 @@ function TaskRow({ task, onPick }: { task: TaskView; onPick: () => void }) {
|
|
|
1287
1314
|
<ShinyText
|
|
1288
1315
|
text={line.text}
|
|
1289
1316
|
speed={2.2}
|
|
1290
|
-
color="var(--muted-foreground)"
|
|
1291
|
-
shineColor="var(--foreground)"
|
|
1292
1317
|
className={cn(
|
|
1293
1318
|
"min-w-0 flex-1 truncate text-[12px] leading-4",
|
|
1294
1319
|
line.tone,
|
|
@@ -1322,21 +1347,12 @@ function TaskRow({ task, onPick }: { task: TaskView; onPick: () => void }) {
|
|
|
1322
1347
|
await answer(task, option);
|
|
1323
1348
|
setSending(null);
|
|
1324
1349
|
}}
|
|
1325
|
-
className=
|
|
1326
|
-
"h-7 gap-1.5 rounded-full bg-background px-3 text-[12px]",
|
|
1327
|
-
// A budget stop is not a question, so it does not take the waiting colour.
|
|
1328
|
-
!budget && "border-amber-500/35",
|
|
1329
|
-
)}
|
|
1350
|
+
className="h-7 gap-1.5 rounded-full border-amber-500/35 bg-background px-3 text-[12px]"
|
|
1330
1351
|
>
|
|
1331
|
-
{
|
|
1352
|
+
{option === TASK_CONTINUE && (
|
|
1332
1353
|
<ChevronsRight className="size-3.5 text-muted-foreground" />
|
|
1333
1354
|
)}
|
|
1334
1355
|
{option}
|
|
1335
|
-
{budget && option === TASK_CONTINUE && (
|
|
1336
|
-
<span className="font-mono text-[10px] text-muted-foreground">
|
|
1337
|
-
+{BOT_RUN.steps} steps
|
|
1338
|
-
</span>
|
|
1339
|
-
)}
|
|
1340
1356
|
</Button>
|
|
1341
1357
|
))}
|
|
1342
1358
|
</div>
|
|
@@ -1348,29 +1364,28 @@ function TaskRow({ task, onPick }: { task: TaskView; onPick: () => void }) {
|
|
|
1348
1364
|
/** Second row of a task line: the question, the outcome, or the bot's last step. */
|
|
1349
1365
|
function secondLine(task: TaskView): { text: string; tone: string } {
|
|
1350
1366
|
if (task.status === "waiting" && task.ask) {
|
|
1351
|
-
//
|
|
1352
|
-
|
|
1353
|
-
return {
|
|
1354
|
-
text: plainText(task.outcome ?? task.ask.question),
|
|
1355
|
-
tone: "text-muted-foreground",
|
|
1356
|
-
};
|
|
1357
|
-
}
|
|
1367
|
+
// A budget stop is not a question, but it waits on the user exactly as one
|
|
1368
|
+
// does, so it carries the waiting colour too; only the words differ.
|
|
1358
1369
|
return {
|
|
1359
|
-
text: task.ask
|
|
1370
|
+
text: isAppStop(task.ask)
|
|
1371
|
+
? plainText(task.outcome ?? task.ask.question)
|
|
1372
|
+
: task.ask.question,
|
|
1360
1373
|
tone: WAITING_INK,
|
|
1361
1374
|
};
|
|
1362
1375
|
}
|
|
1363
1376
|
// Reports are markdown; keep only the text.
|
|
1377
|
+
// An ending the user has opened steps back; red stays red, only quieter.
|
|
1378
|
+
const had = task.seen;
|
|
1364
1379
|
if (task.status === "failed") {
|
|
1365
1380
|
return {
|
|
1366
1381
|
text: plainText(task.outcome ?? "Failed"),
|
|
1367
|
-
tone: "text-destructive",
|
|
1382
|
+
tone: had ? "text-destructive/70" : "text-destructive",
|
|
1368
1383
|
};
|
|
1369
1384
|
}
|
|
1370
1385
|
if (task.status === "done") {
|
|
1371
1386
|
return {
|
|
1372
1387
|
text: plainText(task.outcome ?? "Done"),
|
|
1373
|
-
tone:
|
|
1388
|
+
tone: had ? "text-muted-foreground" : "text-foreground",
|
|
1374
1389
|
};
|
|
1375
1390
|
}
|
|
1376
1391
|
const last = lastSaid(task);
|
|
@@ -1434,20 +1449,37 @@ export function Conversation({
|
|
|
1434
1449
|
<Group key={item.key} group={item.group} task={task} />
|
|
1435
1450
|
),
|
|
1436
1451
|
)}
|
|
1437
|
-
{task.status === "working" && task
|
|
1438
|
-
<ShinyText
|
|
1439
|
-
text={`${task.bot.name} is taking it on…`}
|
|
1440
|
-
speed={2.2}
|
|
1441
|
-
color="var(--muted-foreground)"
|
|
1442
|
-
shineColor="var(--foreground)"
|
|
1443
|
-
className="block px-1 font-mono text-[10px]"
|
|
1444
|
-
/>
|
|
1445
|
-
)}
|
|
1452
|
+
{task.status === "working" && <NextMove task={task} />}
|
|
1446
1453
|
</div>
|
|
1447
1454
|
</FileViewer>
|
|
1448
1455
|
);
|
|
1449
1456
|
}
|
|
1450
1457
|
|
|
1458
|
+
/**
|
|
1459
|
+
* The foot of a running thread while nothing on it is moving: the bot is
|
|
1460
|
+
* writing its next step. A tool mid-call already shines on its own row, so this
|
|
1461
|
+
* steps aside for it.
|
|
1462
|
+
*/
|
|
1463
|
+
function NextMove({ task }: { task: TaskView }) {
|
|
1464
|
+
if (task.lines.some((line) => line.tool && line.tool.results === undefined)) {
|
|
1465
|
+
return null;
|
|
1466
|
+
}
|
|
1467
|
+
const last = task.lines.at(-1);
|
|
1468
|
+
// After a hand-off, in either direction, the move is the receiver's
|
|
1469
|
+
const who = last?.kind === "ask" && last.to ? last.to : last?.bot;
|
|
1470
|
+
return (
|
|
1471
|
+
<ShinyText
|
|
1472
|
+
text={
|
|
1473
|
+
who
|
|
1474
|
+
? `${who.name} is on the next step…`
|
|
1475
|
+
: `${task.bot.name} is taking it on…`
|
|
1476
|
+
}
|
|
1477
|
+
speed={2.2}
|
|
1478
|
+
className="block px-1 font-mono text-[10px]"
|
|
1479
|
+
/>
|
|
1480
|
+
);
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1451
1483
|
/** The delegated request, folded to three lines (FoldedText). */
|
|
1452
1484
|
function Request({ task }: { task: TaskView }) {
|
|
1453
1485
|
return (
|
|
@@ -1544,7 +1576,7 @@ function Turn({
|
|
|
1544
1576
|
return (
|
|
1545
1577
|
<div className={cn("flex gap-2.5", side === "end" && "flex-row-reverse")}>
|
|
1546
1578
|
{mark}
|
|
1547
|
-
{/* One cap on the turn's column, not one per block inside it:
|
|
1579
|
+
{/* One cap on the turn's column, not one per block inside it: an answer and
|
|
1548
1580
|
a one-line remark from the same bot then end on the same edge. The
|
|
1549
1581
|
answering side hugs that edge, so the two sides face each other. */}
|
|
1550
1582
|
<div
|
|
@@ -1601,6 +1633,8 @@ function Group({ group, task }: { group: ChatterGroup; task: TaskView }) {
|
|
|
1601
1633
|
{runs(group.lines).map((run) =>
|
|
1602
1634
|
run.kind === "tools" ? (
|
|
1603
1635
|
<Steps key={run.key} lines={run.lines} taskId={task.id} />
|
|
1636
|
+
) : run.kind === "stops" ? (
|
|
1637
|
+
<Stops key={run.key} lines={run.lines} />
|
|
1604
1638
|
) : (
|
|
1605
1639
|
run.lines.map((line) => (
|
|
1606
1640
|
<Line key={line.id} line={line} taskId={task.id} />
|
|
@@ -1636,7 +1670,7 @@ function Line({ line, taskId }: { line: Chatter; taskId: string }) {
|
|
|
1636
1670
|
);
|
|
1637
1671
|
}
|
|
1638
1672
|
|
|
1639
|
-
// Passing remarks are muted; the
|
|
1673
|
+
// Passing remarks are muted; the answer is the one thing here at full weight.
|
|
1640
1674
|
if (!isOutcome(line)) {
|
|
1641
1675
|
return (
|
|
1642
1676
|
<p className="px-1 text-[12.5px] leading-relaxed break-keep text-muted-foreground">
|
|
@@ -1669,7 +1703,7 @@ function Line({ line, taskId }: { line: Chatter; taskId: string }) {
|
|
|
1669
1703
|
const failed = line.kind === "error";
|
|
1670
1704
|
|
|
1671
1705
|
return (
|
|
1672
|
-
// The
|
|
1706
|
+
// The answer is not a card. It sits in a thread that is already in a box,
|
|
1673
1707
|
// in a section that is another: a fourth border reads as a second chat
|
|
1674
1708
|
// window. What tells it from a passing remark is that it is the only prose
|
|
1675
1709
|
// here at foreground weight, plus the files it names — and its copy button
|
|
@@ -1690,7 +1724,7 @@ function Line({ line, taskId }: { line: Chatter; taskId: string }) {
|
|
|
1690
1724
|
{line.text}
|
|
1691
1725
|
</Markdown>
|
|
1692
1726
|
{/* The files it names, and the copy — one row, because the end of the
|
|
1693
|
-
|
|
1727
|
+
answer is where a reader is when they want either. */}
|
|
1694
1728
|
<div className="mt-2 flex items-center gap-2">
|
|
1695
1729
|
<PathChips text={line.text} className="min-w-0" />
|
|
1696
1730
|
{!failed && (
|
|
@@ -1703,7 +1737,7 @@ function Line({ line, taskId }: { line: Chatter; taskId: string }) {
|
|
|
1703
1737
|
);
|
|
1704
1738
|
}
|
|
1705
1739
|
|
|
1706
|
-
/** Copies the
|
|
1740
|
+
/** Copies the answer. The icon confirms; a toast only reports failure. */
|
|
1707
1741
|
function CopyReport({ text }: { text: string }) {
|
|
1708
1742
|
const [copied, setCopied] = useState(false);
|
|
1709
1743
|
const back = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -1718,7 +1752,7 @@ function CopyReport({ text }: { text: string }) {
|
|
|
1718
1752
|
return (
|
|
1719
1753
|
<button
|
|
1720
1754
|
type="button"
|
|
1721
|
-
aria-label="Copy the
|
|
1755
|
+
aria-label="Copy the answer"
|
|
1722
1756
|
onClick={async () => {
|
|
1723
1757
|
try {
|
|
1724
1758
|
await navigator.clipboard.writeText(text);
|
|
@@ -1728,7 +1762,7 @@ function CopyReport({ text }: { text: string }) {
|
|
|
1728
1762
|
} catch (cause) {
|
|
1729
1763
|
toast.add({
|
|
1730
1764
|
type: "error",
|
|
1731
|
-
title: "Could not copy the
|
|
1765
|
+
title: "Could not copy the answer",
|
|
1732
1766
|
description: errorToString(cause),
|
|
1733
1767
|
});
|
|
1734
1768
|
}
|
|
@@ -1764,17 +1798,65 @@ function Steps({ lines, taskId }: { lines: Chatter[]; taskId: string }) {
|
|
|
1764
1798
|
);
|
|
1765
1799
|
}
|
|
1766
1800
|
|
|
1767
|
-
/**
|
|
1801
|
+
/**
|
|
1802
|
+
* Where the app stopped the run (bot.runner parkTask): a failed model call, a
|
|
1803
|
+
* restart, a closed browser. Muted and in the bot's turn, since the bot goes on
|
|
1804
|
+
* from here. The same reason in a row is one line with a count; opening it lists
|
|
1805
|
+
* each stop by the time it happened.
|
|
1806
|
+
*/
|
|
1807
|
+
function Stops({ lines }: { lines: Chatter[] }) {
|
|
1808
|
+
return (
|
|
1809
|
+
<details className="group min-w-0 px-1 text-muted-foreground">
|
|
1810
|
+
<summary className="flex cursor-pointer list-none items-center gap-1.5 text-[12.5px] leading-relaxed outline-none [&::-webkit-details-marker]:hidden">
|
|
1811
|
+
<RotateCw className="size-3 shrink-0" />
|
|
1812
|
+
<span className="min-w-0 truncate">{leadOf(lines[0].text)}</span>
|
|
1813
|
+
{lines.length > 1 && (
|
|
1814
|
+
<span className="shrink-0 font-mono text-[10px] text-muted-foreground/70">
|
|
1815
|
+
×{lines.length}
|
|
1816
|
+
</span>
|
|
1817
|
+
)}
|
|
1818
|
+
<ChevronDown className="size-2.5 shrink-0 text-muted-foreground/70 transition-transform group-open:rotate-180" />
|
|
1819
|
+
</summary>
|
|
1820
|
+
<div className="mt-1 space-y-1 pl-4.5 text-[11px] leading-relaxed">
|
|
1821
|
+
{lines.map((line) => (
|
|
1822
|
+
<p key={line.id} className="flex gap-2 break-keep">
|
|
1823
|
+
{line.at && (
|
|
1824
|
+
<span className="shrink-0 font-mono text-muted-foreground/70 tabular-nums">
|
|
1825
|
+
{format(toDate(line.at), "HH:mm:ss")}
|
|
1826
|
+
</span>
|
|
1827
|
+
)}
|
|
1828
|
+
<span className="min-w-0">{line.text}</span>
|
|
1829
|
+
</p>
|
|
1830
|
+
))}
|
|
1831
|
+
</div>
|
|
1832
|
+
</details>
|
|
1833
|
+
);
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
/** What stopped it, without the words behind it: a stop names those in parentheses (bot.runner parkTask). */
|
|
1837
|
+
const leadOf = (text: string) => text.split(" (")[0].replace(/\.$/, "");
|
|
1838
|
+
|
|
1839
|
+
/** Splits one speaker's lines into runs of tool calls, of stops, and of everything else. */
|
|
1768
1840
|
type Run =
|
|
1769
1841
|
| { kind: "tools"; key: string; lines: Chatter[] }
|
|
1842
|
+
| { kind: "stops"; key: string; lines: Chatter[] }
|
|
1770
1843
|
| { kind: "said"; key: string; lines: Chatter[] };
|
|
1771
1844
|
|
|
1772
1845
|
function runs(lines: Chatter[]): Run[] {
|
|
1773
1846
|
const out: Run[] = [];
|
|
1774
1847
|
for (const line of lines) {
|
|
1775
|
-
const kind =
|
|
1848
|
+
const kind =
|
|
1849
|
+
line.kind === "tool" && line.tool
|
|
1850
|
+
? "tools"
|
|
1851
|
+
: line.kind === "stop"
|
|
1852
|
+
? "stops"
|
|
1853
|
+
: "said";
|
|
1776
1854
|
const open = out.at(-1);
|
|
1777
|
-
|
|
1855
|
+
// Stops fold only while the reason repeats; another reason is a line of its own
|
|
1856
|
+
const same =
|
|
1857
|
+
open?.kind === kind &&
|
|
1858
|
+
(kind !== "stops" || leadOf(open.lines[0].text) === leadOf(line.text));
|
|
1859
|
+
if (open && same) open.lines.push(line);
|
|
1778
1860
|
else out.push({ kind, key: line.id, lines: [line] });
|
|
1779
1861
|
}
|
|
1780
1862
|
return out;
|