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,9 +1,20 @@
|
|
|
1
1
|
import type { AssistantContent, ModelMessage, ToolContent } from "ai";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
and,
|
|
4
|
+
desc,
|
|
5
|
+
eq,
|
|
6
|
+
inArray,
|
|
7
|
+
isNotNull,
|
|
8
|
+
isNull,
|
|
9
|
+
lt,
|
|
10
|
+
max,
|
|
11
|
+
sql,
|
|
12
|
+
} from "drizzle-orm";
|
|
3
13
|
import { appEvents } from "@/app/api/events/app-event.server";
|
|
14
|
+
import { INBOX_FINISHED } from "@/config";
|
|
4
15
|
import { database } from "@/database/db";
|
|
5
16
|
import { taskMessageTable, taskTable } from "@/database/tables";
|
|
6
|
-
import {
|
|
17
|
+
import { answerAccepted, isAnswerCall } from "@/features/ai/tools/bot.tool";
|
|
7
18
|
import { TOOL_NAMES } from "@/features/ai/tools/tool-name";
|
|
8
19
|
import { clip } from "@/lib/utils";
|
|
9
20
|
import {
|
|
@@ -11,6 +22,7 @@ import {
|
|
|
11
22
|
TASK_HISTORY_PAGE,
|
|
12
23
|
type Task,
|
|
13
24
|
type TaskLine,
|
|
25
|
+
type TaskPending,
|
|
14
26
|
type TaskStatus,
|
|
15
27
|
type TokenUsage,
|
|
16
28
|
} from "./bot.schema";
|
|
@@ -29,7 +41,7 @@ const taskView = {
|
|
|
29
41
|
status: taskTable.status,
|
|
30
42
|
outcome: taskTable.outcome,
|
|
31
43
|
pending: taskTable.pending,
|
|
32
|
-
|
|
44
|
+
seen: taskTable.seen,
|
|
33
45
|
inputTokens: taskTable.inputTokens,
|
|
34
46
|
outputTokens: taskTable.outputTokens,
|
|
35
47
|
contextTokens: taskTable.contextTokens,
|
|
@@ -45,8 +57,8 @@ type TaskRow = {
|
|
|
45
57
|
request: string;
|
|
46
58
|
status: TaskStatus;
|
|
47
59
|
outcome: string | null;
|
|
48
|
-
pending:
|
|
49
|
-
|
|
60
|
+
pending: TaskPending | null;
|
|
61
|
+
seen: boolean;
|
|
50
62
|
inputTokens: number;
|
|
51
63
|
outputTokens: number;
|
|
52
64
|
contextTokens: number;
|
|
@@ -55,12 +67,9 @@ type TaskRow = {
|
|
|
55
67
|
updatedAt: Date;
|
|
56
68
|
};
|
|
57
69
|
|
|
58
|
-
/** How many finished tasks the inbox keeps; the rest live in Settings > Tasks. */
|
|
59
|
-
const INBOX_RECENT_FINISHED = 3;
|
|
60
|
-
|
|
61
70
|
/**
|
|
62
71
|
* One row plus the thread's first message. `request` is what the screen shows;
|
|
63
|
-
* `opening` is what the model reads (
|
|
72
|
+
* `opening` is what the model reads (who is who, the job, the call it came from). The screen
|
|
64
73
|
* skips seq 0 and shows `request` instead (linesOf).
|
|
65
74
|
*/
|
|
66
75
|
export async function insertTask(input: {
|
|
@@ -68,7 +77,7 @@ export async function insertTask(input: {
|
|
|
68
77
|
label: string;
|
|
69
78
|
request: string;
|
|
70
79
|
callId?: string | null;
|
|
71
|
-
opening:
|
|
80
|
+
opening: Extract<ModelMessage, { role: "user" }>["content"];
|
|
72
81
|
}) {
|
|
73
82
|
const { opening, ...row } = input;
|
|
74
83
|
const [task] = await database
|
|
@@ -90,9 +99,11 @@ export async function updateTask(
|
|
|
90
99
|
patch: Partial<{
|
|
91
100
|
status: TaskStatus;
|
|
92
101
|
outcome: string | null;
|
|
93
|
-
pending:
|
|
94
|
-
|
|
102
|
+
pending: TaskPending | null;
|
|
103
|
+
seen: boolean;
|
|
95
104
|
endedAt: Date | null;
|
|
105
|
+
/** Where the job compacts from now on; also written at every step (addTaskUsage). */
|
|
106
|
+
contextBudget: number;
|
|
96
107
|
}>,
|
|
97
108
|
) {
|
|
98
109
|
await database
|
|
@@ -102,12 +113,12 @@ export async function updateTask(
|
|
|
102
113
|
changed();
|
|
103
114
|
}
|
|
104
115
|
|
|
105
|
-
/** Bypasses `updateTask` on purpose:
|
|
106
|
-
export async function
|
|
116
|
+
/** Bypasses `updateTask` on purpose: being seen is not movement and must not reorder the inbox by updatedAt. */
|
|
117
|
+
export async function markSeen(ids: string[]) {
|
|
107
118
|
if (ids.length === 0) return;
|
|
108
119
|
await database
|
|
109
120
|
.update(taskTable)
|
|
110
|
-
.set({
|
|
121
|
+
.set({ seen: true })
|
|
111
122
|
.where(inArray(taskTable.id, ids));
|
|
112
123
|
changed();
|
|
113
124
|
}
|
|
@@ -155,7 +166,7 @@ export async function findTask(id: string) {
|
|
|
155
166
|
return task ?? null;
|
|
156
167
|
}
|
|
157
168
|
|
|
158
|
-
/** Inbox: everything running or waiting plus the
|
|
169
|
+
/** Inbox: everything running or waiting plus the latest INBOX_FINISHED endings, newest first. `seen` is not a filter here. */
|
|
159
170
|
export async function listInboxTasks(): Promise<Task[]> {
|
|
160
171
|
const [open, finished] = await Promise.all([
|
|
161
172
|
database
|
|
@@ -168,7 +179,7 @@ export async function listInboxTasks(): Promise<Task[]> {
|
|
|
168
179
|
.from(taskTable)
|
|
169
180
|
.where(inArray(taskTable.status, ["done", "failed"]))
|
|
170
181
|
.orderBy(desc(taskTable.updatedAt))
|
|
171
|
-
.limit(
|
|
182
|
+
.limit(INBOX_FINISHED),
|
|
172
183
|
]);
|
|
173
184
|
const rows = [...open, ...finished].sort(
|
|
174
185
|
(a, b) => b.updatedAt.getTime() - a.updatedAt.getTime(),
|
|
@@ -226,9 +237,11 @@ export async function deleteFinishedTasks() {
|
|
|
226
237
|
const removed = await database
|
|
227
238
|
.delete(taskTable)
|
|
228
239
|
.where(inArray(taskTable.status, ["done", "failed"]))
|
|
229
|
-
|
|
240
|
+
// The label comes back too: a job's working folder is named for it and goes
|
|
241
|
+
// with the row (bot.runner removeFinishedTasks).
|
|
242
|
+
.returning({ id: taskTable.id, label: taskTable.label });
|
|
230
243
|
if (removed.length) changed();
|
|
231
|
-
return removed
|
|
244
|
+
return removed;
|
|
232
245
|
}
|
|
233
246
|
|
|
234
247
|
/** Every job, newest first. The caller stops each one before deleting it (bot.runner removeTask). */
|
|
@@ -249,6 +262,177 @@ export async function listRunningTaskIds() {
|
|
|
249
262
|
return rows.map((row) => row.id);
|
|
250
263
|
}
|
|
251
264
|
|
|
265
|
+
/** Every job with what names its folder and whether it still keeps it (bot.runner sweepJobFiles). */
|
|
266
|
+
export async function listTaskFolders() {
|
|
267
|
+
return await database
|
|
268
|
+
.select({
|
|
269
|
+
id: taskTable.id,
|
|
270
|
+
label: taskTable.label,
|
|
271
|
+
status: taskTable.status,
|
|
272
|
+
endedAt: taskTable.endedAt,
|
|
273
|
+
updatedAt: taskTable.updatedAt,
|
|
274
|
+
})
|
|
275
|
+
.from(taskTable);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** Jobs the app parked to pick back up by itself (bot.runner parkTask), and when each may go. */
|
|
279
|
+
export async function listAutoStoppedTasks() {
|
|
280
|
+
const rows = await database
|
|
281
|
+
.select({ id: taskTable.id, pending: taskTable.pending })
|
|
282
|
+
.from(taskTable)
|
|
283
|
+
.where(eq(taskTable.status, "waiting"));
|
|
284
|
+
return rows.flatMap((row) =>
|
|
285
|
+
row.pending?.auto
|
|
286
|
+
? [{ id: row.id, retryAt: row.pending.retryAt ?? 0 }]
|
|
287
|
+
: [],
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* How many times the app has stopped this job since a person last said anything
|
|
293
|
+
* to it: the notes it left in the thread — a break, a park — back to the last row
|
|
294
|
+
* a person wrote: the opening, an answer, a word to a running job. Read off the
|
|
295
|
+
* rows rather than kept as a count, so it cannot drift from what the thread shows.
|
|
296
|
+
*/
|
|
297
|
+
export async function countStopsSinceSpoken(taskId: string): Promise<number> {
|
|
298
|
+
const rows = await database
|
|
299
|
+
.select({
|
|
300
|
+
role: taskMessageTable.role,
|
|
301
|
+
bot: taskMessageTable.bot,
|
|
302
|
+
note: taskMessageTable.note,
|
|
303
|
+
compact: taskMessageTable.compact,
|
|
304
|
+
})
|
|
305
|
+
.from(taskMessageTable)
|
|
306
|
+
.where(
|
|
307
|
+
and(eq(taskMessageTable.taskId, taskId), isNull(taskMessageTable.parent)),
|
|
308
|
+
)
|
|
309
|
+
.orderBy(desc(taskMessageTable.seq));
|
|
310
|
+
let stops = 0;
|
|
311
|
+
for (const row of rows) {
|
|
312
|
+
if (row.note) {
|
|
313
|
+
if (!row.compact) stops += 1;
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
// A person: the opening and every answer are written with no bot, and a
|
|
317
|
+
// word to a running job is a user row in the bot's name
|
|
318
|
+
if (row.bot === null || row.role === "user") break;
|
|
319
|
+
}
|
|
320
|
+
return stops;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** How much of a cut-off borrowed bot's prose a resume carries: its last few paragraphs. */
|
|
324
|
+
const TAIL = { texts: 3, chars: 600 };
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* What each borrowed bot had written when its `ask_bot` call stopped, by that
|
|
328
|
+
* call's id: its last few paragraphs, and the tool it reached for after them. A
|
|
329
|
+
* resumed run reads it where the call's result never arrived (bot.run
|
|
330
|
+
* resumeThread), so a part cut off half-way is carried on, not asked for afresh.
|
|
331
|
+
*/
|
|
332
|
+
export async function listBorrowedTails(
|
|
333
|
+
taskId: string,
|
|
334
|
+
): Promise<Map<string, { bot: string; tail: string }>> {
|
|
335
|
+
const rows = await database
|
|
336
|
+
.select({
|
|
337
|
+
parent: taskMessageTable.parent,
|
|
338
|
+
bot: taskMessageTable.bot,
|
|
339
|
+
content: taskMessageTable.content,
|
|
340
|
+
})
|
|
341
|
+
.from(taskMessageTable)
|
|
342
|
+
.where(
|
|
343
|
+
and(
|
|
344
|
+
eq(taskMessageTable.taskId, taskId),
|
|
345
|
+
isNotNull(taskMessageTable.parent),
|
|
346
|
+
eq(taskMessageTable.role, "assistant"),
|
|
347
|
+
),
|
|
348
|
+
)
|
|
349
|
+
.orderBy(taskMessageTable.seq);
|
|
350
|
+
|
|
351
|
+
const calls = new Map<
|
|
352
|
+
string,
|
|
353
|
+
{ bot: string; texts: string[]; then: string | null }
|
|
354
|
+
>();
|
|
355
|
+
for (const row of rows) {
|
|
356
|
+
if (!row.parent) continue;
|
|
357
|
+
const call = calls.get(row.parent) ?? {
|
|
358
|
+
bot: row.bot ?? "",
|
|
359
|
+
texts: [],
|
|
360
|
+
then: null,
|
|
361
|
+
};
|
|
362
|
+
const content = row.content as AssistantContent;
|
|
363
|
+
const parts =
|
|
364
|
+
typeof content === "string"
|
|
365
|
+
? [{ type: "text" as const, text: content }]
|
|
366
|
+
: content;
|
|
367
|
+
for (const part of parts) {
|
|
368
|
+
if (part.type === "text" && part.text.trim()) {
|
|
369
|
+
call.texts.push(part.text.trim());
|
|
370
|
+
call.then = null;
|
|
371
|
+
} else if (part.type === "tool-call") {
|
|
372
|
+
call.then =
|
|
373
|
+
`${part.toolName} ${toolLine(part.toolName, part.input)}`.trim();
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
calls.set(row.parent, call);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const tails = new Map<string, { bot: string; tail: string }>();
|
|
380
|
+
for (const [id, call] of calls) {
|
|
381
|
+
const tail = [
|
|
382
|
+
...call.texts.slice(-TAIL.texts).map((text) => clip(text, TAIL.chars)),
|
|
383
|
+
call.then ? `Then: ${call.then}` : "",
|
|
384
|
+
]
|
|
385
|
+
.filter(Boolean)
|
|
386
|
+
.join("\n\n");
|
|
387
|
+
if (tail) tails.set(id, { bot: call.bot, tail });
|
|
388
|
+
}
|
|
389
|
+
return tails;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Paths a list of message contents gave `write_file`, oldest first and each once; a
|
|
394
|
+
* path written again moves to the end. A refused write is here too, so whoever shows
|
|
395
|
+
* them checks the disk (workspace.ts filesOnDisk).
|
|
396
|
+
*/
|
|
397
|
+
export function writtenPathsIn(contents: unknown[]): string[] {
|
|
398
|
+
const paths = new Set<string>();
|
|
399
|
+
for (const content of contents) {
|
|
400
|
+
if (!Array.isArray(content)) continue;
|
|
401
|
+
for (const part of content as {
|
|
402
|
+
type?: unknown;
|
|
403
|
+
toolName?: unknown;
|
|
404
|
+
input?: unknown;
|
|
405
|
+
}[]) {
|
|
406
|
+
if (
|
|
407
|
+
part.type !== "tool-call" ||
|
|
408
|
+
part.toolName !== TOOL_NAMES.write_file
|
|
409
|
+
) {
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const path = (part.input as { path?: unknown } | null)?.path;
|
|
413
|
+
if (typeof path !== "string" || !path.trim()) continue;
|
|
414
|
+
paths.delete(path.trim());
|
|
415
|
+
paths.add(path.trim());
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return [...paths];
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/** Every path this job gave `write_file`: its own bot and each bot it borrowed (writtenPathsIn). */
|
|
422
|
+
export async function listWrittenPaths(taskId: string): Promise<string[]> {
|
|
423
|
+
const rows = await database
|
|
424
|
+
.select({ content: taskMessageTable.content })
|
|
425
|
+
.from(taskMessageTable)
|
|
426
|
+
.where(
|
|
427
|
+
and(
|
|
428
|
+
eq(taskMessageTable.taskId, taskId),
|
|
429
|
+
eq(taskMessageTable.role, "assistant"),
|
|
430
|
+
),
|
|
431
|
+
)
|
|
432
|
+
.orderBy(taskMessageTable.seq);
|
|
433
|
+
return writtenPathsIn(rows.map((row) => row.content));
|
|
434
|
+
}
|
|
435
|
+
|
|
252
436
|
/**
|
|
253
437
|
* Finds a task by id or by exact label (case-insensitive). No looser matching:
|
|
254
438
|
* a miss returns null and the caller lists recent tasks instead.
|
|
@@ -275,6 +459,8 @@ export type TaskMessageInput = {
|
|
|
275
459
|
content: ModelMessage["content"];
|
|
276
460
|
/** Compaction summary row; `listThread` re-reads from here. */
|
|
277
461
|
compact?: boolean;
|
|
462
|
+
/** Drawn as the app's own line, not as something a person or a bot said. */
|
|
463
|
+
note?: boolean;
|
|
278
464
|
};
|
|
279
465
|
|
|
280
466
|
/**
|
|
@@ -288,13 +474,20 @@ export async function upsertMessage(
|
|
|
288
474
|
) {
|
|
289
475
|
await database
|
|
290
476
|
.insert(taskMessageTable)
|
|
291
|
-
.values({
|
|
477
|
+
.values({
|
|
478
|
+
taskId,
|
|
479
|
+
seq,
|
|
480
|
+
...message,
|
|
481
|
+
compact: message.compact ?? false,
|
|
482
|
+
note: message.note ?? false,
|
|
483
|
+
})
|
|
292
484
|
.onConflictDoUpdate({
|
|
293
485
|
target: [taskMessageTable.taskId, taskMessageTable.seq],
|
|
294
486
|
set: {
|
|
295
487
|
role: message.role,
|
|
296
488
|
content: message.content,
|
|
297
489
|
compact: message.compact ?? false,
|
|
490
|
+
note: message.note ?? false,
|
|
298
491
|
},
|
|
299
492
|
});
|
|
300
493
|
changed();
|
|
@@ -326,7 +519,8 @@ export async function lastSeq(taskId: string): Promise<number> {
|
|
|
326
519
|
/**
|
|
327
520
|
* The task's own thread as the model sees it: parent-less messages in order.
|
|
328
521
|
* What a borrowed bot said inside an `ask_bot` call is not here; its result is.
|
|
329
|
-
*
|
|
522
|
+
* After a compaction it is the opening, then the last compact row on: a summary
|
|
523
|
+
* replaces what came after the job and the call, never the job and the call.
|
|
330
524
|
*/
|
|
331
525
|
export async function listThread(taskId: string): Promise<ModelMessage[]> {
|
|
332
526
|
const rows = await database
|
|
@@ -341,9 +535,10 @@ export async function listThread(taskId: string): Promise<ModelMessage[]> {
|
|
|
341
535
|
)
|
|
342
536
|
.orderBy(taskMessageTable.seq);
|
|
343
537
|
const from = rows.findLastIndex((row) => row.compact);
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
538
|
+
const kept = from > 0 ? [rows[0], ...rows.slice(from)] : rows;
|
|
539
|
+
return kept.map(
|
|
540
|
+
(row) => ({ role: row.role, content: row.content }) as ModelMessage,
|
|
541
|
+
);
|
|
347
542
|
}
|
|
348
543
|
|
|
349
544
|
/** One row in the screen's shape; `pending` folds into `ask`. */
|
|
@@ -354,7 +549,11 @@ function viewOf(row: TaskRow, lines: TaskLine[]): Task {
|
|
|
354
549
|
...rest,
|
|
355
550
|
ask:
|
|
356
551
|
row.status === "waiting"
|
|
357
|
-
? {
|
|
552
|
+
? {
|
|
553
|
+
question: row.outcome ?? "",
|
|
554
|
+
options: pending?.options ?? [],
|
|
555
|
+
auto: pending?.auto === true,
|
|
556
|
+
}
|
|
358
557
|
: null,
|
|
359
558
|
tokens: { input: inputTokens, output: outputTokens },
|
|
360
559
|
lines,
|
|
@@ -417,8 +616,7 @@ function labelOf(args: Record<string, unknown>): string | null {
|
|
|
417
616
|
}
|
|
418
617
|
|
|
419
618
|
/**
|
|
420
|
-
* One tool call as one line
|
|
421
|
-
* re-read history (bot.run condenseThread). No per-tool summary table: the
|
|
619
|
+
* One tool call as one line, for the screen. No per-tool summary table: the
|
|
422
620
|
* label is model-written (bash `description`), other tools use the first
|
|
423
621
|
* telling argument, else the argument shape.
|
|
424
622
|
*/
|
|
@@ -512,8 +710,10 @@ function linesOf(message: StoredMessage, owner: string): TaskLine[] {
|
|
|
512
710
|
if (message.seq === 0) return [];
|
|
513
711
|
const text = typeof content === "string" ? content : textOf(content);
|
|
514
712
|
if (!text) return [];
|
|
515
|
-
//
|
|
516
|
-
|
|
713
|
+
// The app's own line — a compaction marker, or why a run stopped — never
|
|
714
|
+
// the user's words. `compact` is read too: rows written before `note` was.
|
|
715
|
+
if (message.note || message.compact)
|
|
716
|
+
return [{ ...base, id: id(0), kind: "note", text }];
|
|
517
717
|
return [{ ...base, id: id(0), kind: "user", text }];
|
|
518
718
|
}
|
|
519
719
|
|
|
@@ -547,8 +747,8 @@ function linesOf(message: StoredMessage, owner: string): TaskLine[] {
|
|
|
547
747
|
question: String(args.question ?? ""),
|
|
548
748
|
options: optionsOf(args.options),
|
|
549
749
|
});
|
|
550
|
-
} else if (part.toolName
|
|
551
|
-
// The
|
|
750
|
+
} else if (isAnswerCall(part.toolName)) {
|
|
751
|
+
// The answer is a tool call but draws as text: it is the last thing said
|
|
552
752
|
// in the thread, and taskFromRow promotes it to the result line
|
|
553
753
|
const text = String(args.result ?? "").trim();
|
|
554
754
|
if (text) lines.push({ ...base, id: id(index), kind: "text", text });
|
|
@@ -607,8 +807,8 @@ function linesOf(message: StoredMessage, owner: string): TaskLine[] {
|
|
|
607
807
|
const lines: TaskLine[] = [];
|
|
608
808
|
(message.content as ToolContent).forEach((part, index) => {
|
|
609
809
|
if (part.type !== "tool-result") return;
|
|
610
|
-
if (part.toolName
|
|
611
|
-
// An accepted
|
|
810
|
+
if (isAnswerCall(part.toolName) && answerAccepted(part.output)) {
|
|
811
|
+
// An accepted answer's result is only a confirmation; the answer itself
|
|
612
812
|
// was drawn from the call. A rejected one is drawn: it explains the next step
|
|
613
813
|
return;
|
|
614
814
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useSyncExternalStore } from "react";
|
|
3
|
+
import { useEffect, useRef, useSyncExternalStore } from "react";
|
|
4
|
+
import { queryKey } from "@/app/api/query-key";
|
|
5
|
+
import { toast } from "@/components/ui/toast";
|
|
6
|
+
import { markSeenAction } from "@/features/bot/bot.action";
|
|
4
7
|
import type {
|
|
5
8
|
Bot,
|
|
6
9
|
BotIcon,
|
|
@@ -8,7 +11,10 @@ import type {
|
|
|
8
11
|
Task,
|
|
9
12
|
TokenUsage,
|
|
10
13
|
} from "@/features/bot/bot.schema";
|
|
11
|
-
import type
|
|
14
|
+
import { type DateLike, toDate } from "@/lib/date-like";
|
|
15
|
+
import { unwrapResult } from "@/lib/protocol/result";
|
|
16
|
+
import { revalidate } from "@/lib/protocol/use-server-route";
|
|
17
|
+
import { errorToString } from "@/lib/utils";
|
|
12
18
|
|
|
13
19
|
/**
|
|
14
20
|
* Client mirror of tasks, keyed by task rather than as one message stream so
|
|
@@ -76,9 +82,9 @@ export type TaskView = {
|
|
|
76
82
|
/** Text it came back with; only after it returned. */
|
|
77
83
|
outcome: string | null;
|
|
78
84
|
/** What it is asking while `waiting`. */
|
|
79
|
-
ask:
|
|
80
|
-
/** Whether
|
|
81
|
-
|
|
85
|
+
ask: Task["ask"];
|
|
86
|
+
/** Whether the user has had the ending (Task `seen`). */
|
|
87
|
+
seen: boolean;
|
|
82
88
|
/** Burned so far. */
|
|
83
89
|
tokens: TokenUsage;
|
|
84
90
|
/** Context read on the last step and the compaction threshold; the header meter is their ratio. Both 0 means no step ran yet. */
|
|
@@ -219,9 +225,9 @@ export function taskFromRow(row: Task, bots?: Bot[]): TaskView {
|
|
|
219
225
|
}
|
|
220
226
|
}
|
|
221
227
|
|
|
222
|
-
// The ending lives on the row, not in the thread: the
|
|
228
|
+
// The ending lives on the row, not in the thread: the answer is the last text
|
|
223
229
|
// said, failure exists only here. `waiting` is treated like done: a job that
|
|
224
|
-
//
|
|
230
|
+
// the app stopped answered first, so that line is a result.
|
|
225
231
|
if (row.status === "failed" && row.outcome) {
|
|
226
232
|
lines.push({
|
|
227
233
|
id: `${row.id}-end`,
|
|
@@ -246,7 +252,7 @@ export function taskFromRow(row: Task, bots?: Bot[]): TaskView {
|
|
|
246
252
|
status: row.status === "running" ? "working" : row.status,
|
|
247
253
|
outcome: row.outcome,
|
|
248
254
|
ask: row.ask,
|
|
249
|
-
|
|
255
|
+
seen: row.seen,
|
|
250
256
|
tokens: row.tokens,
|
|
251
257
|
contextTokens: row.contextTokens,
|
|
252
258
|
contextBudget: row.contextBudget,
|
|
@@ -266,7 +272,7 @@ export function lastSaid(task: TaskView): Chatter | null {
|
|
|
266
272
|
/**
|
|
267
273
|
* What the screen did to a task. Announced so the call can hear it: a poll
|
|
268
274
|
* cannot tell a screen answer from a voice answer, and a cancel is never relayed
|
|
269
|
-
* (bot.runner cancelTask marks it
|
|
275
|
+
* (bot.runner cancelTask marks it seen).
|
|
270
276
|
*/
|
|
271
277
|
export type ScreenAct =
|
|
272
278
|
/** Answered a waiting task, interjected into a running one, or continued a finished one. */
|
|
@@ -424,3 +430,41 @@ export function latestPerBot(list: TaskView[]): BotLine[] {
|
|
|
424
430
|
|
|
425
431
|
return [...byBot.values()];
|
|
426
432
|
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Opening a job's detail is reading its ending: the thread in the room, a row
|
|
436
|
+
* expanded in Settings › Tasks. That is what clears its dot — a list scrolled
|
|
437
|
+
* past or a line heard on a call is not. Keyed by `updatedAt` as well, because a
|
|
438
|
+
* follow-up ends a job a second time and that ending is new again.
|
|
439
|
+
*/
|
|
440
|
+
export function useSeenOnDetail(
|
|
441
|
+
task:
|
|
442
|
+
| { id: string; status: string; seen: boolean; updatedAt: DateLike }
|
|
443
|
+
| null
|
|
444
|
+
| undefined,
|
|
445
|
+
) {
|
|
446
|
+
const sent = useRef(new Set<string>());
|
|
447
|
+
const id = task?.id ?? null;
|
|
448
|
+
const key = task ? `${task.id}@${toDate(task.updatedAt).getTime()}` : null;
|
|
449
|
+
const owed =
|
|
450
|
+
!!task &&
|
|
451
|
+
(task.status === "done" || task.status === "failed") &&
|
|
452
|
+
!task.seen;
|
|
453
|
+
|
|
454
|
+
useEffect(() => {
|
|
455
|
+
if (!id || !key || !owed || sent.current.has(key)) return;
|
|
456
|
+
sent.current.add(key);
|
|
457
|
+
void markSeenAction([id])
|
|
458
|
+
.then(unwrapResult)
|
|
459
|
+
.then(() => revalidate(queryKey.tasks))
|
|
460
|
+
.catch((cause) => {
|
|
461
|
+
// Released, so opening it again tries again
|
|
462
|
+
sent.current.delete(key);
|
|
463
|
+
toast.add({
|
|
464
|
+
type: "error",
|
|
465
|
+
title: "Could not mark the task as read",
|
|
466
|
+
description: errorToString(cause),
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
}, [id, key, owed]);
|
|
470
|
+
}
|