thursday-agent 0.11.0 → 0.13.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/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +4 -4
- 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 +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- 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 +18 -19
- package/.next/server/app/_not-found.segments/_full.segment.rsc +18 -19
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -15
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/artifact/route.js +8 -8
- package/.next/server/app/api/artifact/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/keep-working/route.js +7 -7
- package/.next/server/app/api/bot/keep-working/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/route.js +7 -7
- package/.next/server/app/api/bot/memory/route.js.nft.json +1 -1
- 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/thread/[id]/route.js +5 -5
- package/.next/server/app/api/bot/thread/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/thread/route.js +3 -3
- package/.next/server/app/api/bot/thread/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js +3 -3
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/events/route.js.nft.json +1 -1
- package/.next/server/app/api/favicon/[host]/route.js.nft.json +1 -1
- package/.next/server/app/api/file/[...path]/route.js +2 -2
- package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/catalog/route.js +4 -4
- package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/credits/route.js +4 -4
- package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/route.js +6 -6
- package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/subscription/route.js +6 -6
- package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -1
- 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 +5 -5
- 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.js +15 -14
- package/.next/server/app/api/memory/edit/route.js.nft.json +1 -1
- package/.next/server/app/api/memory/route.js +4 -4
- package/.next/server/app/api/memory/route.js.nft.json +1 -1
- package/.next/server/app/api/reach/route.js +13 -12
- package/.next/server/app/api/reach/route.js.nft.json +1 -1
- package/.next/server/app/api/routine/route.js +8 -9
- package/.next/server/app/api/routine/route.js.nft.json +1 -1
- package/.next/server/app/api/signins/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/[source]/[name]/route.js +2 -2
- package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/route.js +2 -2
- package/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/call/route.js +6 -6
- package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/skills/route.js +6 -6
- package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/text/route.js +14 -13
- package/.next/server/app/api/thursday/text/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/tool-call/route.js +15 -14
- package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
- package/.next/server/app/api/workspace/files/route.js +10 -6
- package/.next/server/app/api/workspace/files/route.js.nft.json +1 -1
- package/.next/server/app/api/workspace/route.js +9 -4
- package/.next/server/app/api/workspace/route.js.nft.json +1 -1
- package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +2 -2
- package/.next/server/app/artifact/[...path]/page.js +5 -4
- 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.nft.json +1 -1
- package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -1
- package/.next/server/app/page/server-reference-manifest.json +67 -56
- package/.next/server/app/page.js +10 -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/chunks/{[root-of-the-server]__0o49ztf._.js → [root-of-the-server]__0-k4_ie._.js} +2 -2
- package/.next/server/chunks/[root-of-the-server]__0209ah4._.js +6 -6
- package/.next/server/chunks/[root-of-the-server]__04wldw9._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0h_x6q6._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__0i23tc1._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0mrk2it._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0nr-v8s._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0paqm5y._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0qog7sm._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0sm5xvm._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0yisc5v._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1-swlkw._.js +3 -3
- package/.next/server/chunks/[root-of-the-server]__12iddfq._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__15p29m3._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__17ses32._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__18-2tsq._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__1cjxw0-._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1gi2nns._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1iauz8a._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1k3j52n._.js +1 -1
- package/.next/server/chunks/{[root-of-the-server]__209k6pk._.js → [root-of-the-server]__1lb_pxg._.js} +2 -2
- package/.next/server/chunks/[root-of-the-server]__1ndi14y._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1orn-5b._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1xqsrqq._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1ygplx1._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__2163i40._.js +5 -0
- package/.next/server/chunks/_0ci0abh._.js +3 -0
- package/.next/server/chunks/_0eauz4t._.js +1 -1
- package/.next/server/chunks/_0f6ts7z._.js +1 -1
- package/.next/server/chunks/_0fg-1oj._.js +5 -0
- package/.next/server/chunks/_0khihjk._.js +2 -2
- package/.next/server/chunks/_0n74zsf._.js +1 -1
- package/.next/server/chunks/_0na2fj1._.js +2 -2
- package/.next/server/chunks/_0oh_99-._.js +3 -0
- package/.next/server/chunks/_0x-ej3f._.js +24 -24
- package/.next/server/chunks/_0z3nz21._.js +3 -0
- package/.next/server/chunks/_10tkr26._.js +1 -1
- package/.next/server/chunks/_12-amdu._.js +2 -2
- package/.next/server/chunks/_136j09a._.js +1 -1
- package/.next/server/chunks/_15740dw._.js +1 -1
- package/.next/server/chunks/_18izeh1._.js +5 -0
- package/.next/server/chunks/_1_5mnq4._.js +1 -1
- package/.next/server/chunks/_1ajbhv6._.js +2 -2
- package/.next/server/chunks/_1dc_d1q._.js +2 -2
- package/.next/server/chunks/_1drgfx4._.js +1 -1
- package/.next/server/chunks/_1e48czp._.js +2 -2
- package/.next/server/chunks/_1f06zo4._.js +3 -0
- package/.next/server/chunks/_1ic3bew._.js +2 -2
- package/.next/server/chunks/_1jn-aep._.js +2 -2
- package/.next/server/chunks/_1jn5btd._.js +6 -0
- package/.next/server/chunks/_1kg70wc._.js +2 -2
- package/.next/server/chunks/_1m2i5pt._.js +5 -0
- package/.next/server/chunks/_1ogqovh._.js +4 -4
- package/.next/server/chunks/_1qxheoa._.js +1 -1
- package/.next/server/chunks/_1ry6afh._.js +18 -0
- package/.next/server/chunks/_1taa4bs._.js +1 -1
- package/.next/server/chunks/_1tpr507._.js +1 -1
- package/.next/server/chunks/_1y8w80a._.js +1 -1
- package/.next/server/chunks/_1zxp-p6._.js +1 -1
- package/.next/server/chunks/_204744f._.js +5 -0
- package/.next/server/chunks/_20fsr_z._.js +1 -1
- package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
- package/.next/server/chunks/features_0-cnt0l._.js +1 -1
- package/.next/server/chunks/features_0hdaci0._.js +1 -1
- package/.next/server/chunks/features_0p85gv6._.js +3 -0
- package/.next/server/chunks/{node_modules_zod_v4_0_v5xf5._.js → node_modules_zod_v4_01bha1c._.js} +2 -2
- package/.next/server/chunks/{node_modules_zod_v4_0q9hvql._.js → node_modules_zod_v4_0b99z6a._.js} +2 -2
- package/.next/server/chunks/{node_modules_zod_v4_1jg8iwg._.js → node_modules_zod_v4_1zz6lo1._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__04upd5v._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0dxszdt._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0eezycw._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0hpp3nw._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0yngu44._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__16z72ny._.js +6 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1u_ry86._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__1iwyp1e._.js → [root-of-the-server]__1unh_ew._.js} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__20re7ya._.js +3 -0
- package/.next/server/chunks/ssr/_00pgq9d._.js +5 -0
- package/.next/server/chunks/ssr/_07ke63g._.js +3 -0
- package/.next/server/chunks/ssr/_0agcbk7._.js +3 -0
- package/.next/server/chunks/ssr/_0e-gw2_._.js +3 -0
- package/.next/server/chunks/ssr/{_1ybo1hd._.js → _0f_om6y._.js} +3 -3
- package/.next/server/chunks/ssr/_0fqhhwi._.js +1 -1
- package/.next/server/chunks/ssr/{_026qnc9._.js → _0gpn71k._.js} +3 -3
- package/.next/server/chunks/ssr/_0iizjr9._.js +3 -0
- package/.next/server/chunks/ssr/_0ixvzo6._.js +75 -0
- package/.next/server/chunks/ssr/_0kkdx7t._.js +3 -0
- package/.next/server/chunks/ssr/_0lufvw7._.js +118 -0
- package/.next/server/chunks/ssr/_0vi6ky6._.js +115 -0
- package/.next/server/chunks/ssr/{_0ouzu9f._.js → _0yhji3e._.js} +2 -2
- package/.next/server/chunks/ssr/_0z38nha._.js +3 -0
- package/.next/server/chunks/ssr/{_1w2oba6._.js → _11nx2d4._.js} +2 -2
- package/.next/server/chunks/ssr/_12mijol._.js +2 -2
- package/.next/server/chunks/ssr/{_19ps4p3._.js → _150463c._.js} +8 -8
- package/.next/server/chunks/ssr/{_1bhy4yg._.js → _17d2ikl._.js} +2 -2
- package/.next/server/chunks/ssr/_19jez1a._.js +3 -0
- package/.next/server/chunks/ssr/_1blui1m._.js +3 -0
- package/.next/server/chunks/ssr/_1d423aj._.js +4 -4
- package/.next/server/chunks/ssr/{_1kd843u._.js → _1kbk28w._.js} +2 -2
- package/.next/server/chunks/ssr/_1kj_r9v._.js +3 -0
- package/.next/server/chunks/ssr/_1mqn9mc._.js +1 -1
- package/.next/server/chunks/ssr/_1myh7ss._.js +3 -0
- package/.next/server/chunks/ssr/_1neoj22._.js +1 -1
- package/.next/server/chunks/ssr/_1ou5sj0._.js +3 -0
- package/.next/server/chunks/ssr/_1p8xorg._.js +1 -1
- package/.next/server/chunks/ssr/_1tzacpl._.js +3 -0
- package/.next/server/chunks/ssr/_1xoch6f._.js +1 -1
- package/.next/server/chunks/ssr/_1yh5bj5._.js +1 -1
- package/.next/server/chunks/ssr/{_0btzccu._.js → _2021n9-._.js} +2 -2
- package/.next/server/chunks/ssr/{_1kq2ye_._.js → _20argo3._.js} +2 -2
- package/.next/server/chunks/ssr/features_bot_1ll3wp7._.js +3 -0
- package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +1 -1
- package/.next/server/chunks/ssr/features_bot_thread_query_ts_023eklt._.js +1 -1
- package/.next/server/chunks/ssr/features_config_1qxe5ur._.js +20 -0
- package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +3 -3
- package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +1 -1
- package/.next/server/chunks/ssr/features_routine_components_routine-setting_tsx_055fknz._.js +1 -1
- package/.next/server/chunks/ssr/features_workspace_00jz2hu._.js +1 -1
- package/.next/server/chunks/ssr/{node_modules_18jn2qo._.js → node_modules_06e0wlv._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1rjt833._.js → node_modules_0cj26-9._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0yqy-0b._.js → node_modules_0d1rf5e._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1zqddke._.js → node_modules_0e86703._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_09dj429._.js → node_modules_0es09am._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1c0pg3k._.js → node_modules_0gr_dzf._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1en2jx5._.js → node_modules_0gtcwz9._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0gmdur8._.js → node_modules_0hi9h8f._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1qe-oxg._.js → node_modules_0lkop0t._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1-53ebx._.js → node_modules_0nghisk._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_02zt4az._.js → node_modules_0stovz0._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_11bltzp._.js → node_modules_0we85kr._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_00pocul._.js → node_modules_0ya7y1s._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1p-c8cr._.js → node_modules_0yrbwkj._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_06i6bli._.js → node_modules_1-x70ie._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1-y9aho._.js → node_modules_12fd9g0._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1x6uwvn._.js → node_modules_12wxrgr._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1tzw5sn._.js → node_modules_139uu4q._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0rbaymq._.js → node_modules_14gpoe1._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_05ojmcl._.js → node_modules_18fmji6._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0tf8_1e._.js → node_modules_19kkel8._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1_te3bu._.js → node_modules_1gcine1._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_211zgim._.js → node_modules_1h4trkm._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0evjwh1._.js → node_modules_1mub_qu._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0auzgvx._.js → node_modules_1p78svs._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0j3te-1._.js → node_modules_1xp-7ep._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0y51bqj._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0ay7_oi._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1sc114e._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_182ydq_._.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 +69 -58
- package/.next/static/chunks/{39gj5vxz1zpm_.js → 01xjer0i_e5z5.js} +1 -1
- package/.next/static/chunks/{4440mws9jz3mt.js → 025bmrgeukcb2.js} +1 -1
- package/.next/static/chunks/03df16hs01-xi.js +1 -0
- package/.next/static/chunks/{1r4zajz14jp9-.js → 04e-e--5lk26x.js} +1 -1
- package/.next/static/chunks/0crocb7272z8k.js +1 -0
- package/.next/static/chunks/{03bhu4mk8en2q.js → 0dqsenl3uk_8z.js} +1 -1
- package/.next/static/chunks/0hhn8mf953761.js +1 -0
- package/.next/static/chunks/0n1o3k0z4m7c_.js +1 -0
- package/.next/static/chunks/0oe2zavre2a7d.css +1 -0
- package/.next/static/chunks/{1qzfgplyo18tc.js → 0oyz95sujd2c7.js} +1 -1
- package/.next/static/chunks/0srg9tv4105-i.js +1 -0
- package/.next/static/chunks/0t599wrclly7i.js +18 -0
- package/.next/static/chunks/{2-jn4xscbm-i2.js → 0u3ktztrzu1fa.js} +1 -1
- package/.next/static/chunks/{0r6nwxg4dv83t.js → 0u9ae9k_2g7k3.js} +1 -1
- package/.next/static/chunks/0x34bhth_sn35.js +1 -0
- package/.next/static/chunks/{0x_w4shtvrrfg.js → 0x_6z8vt8hyf4.js} +3 -3
- package/.next/static/chunks/{04imzjhvzw65d.js → 1_wstwzu1md-6.js} +2 -2
- package/.next/static/chunks/1aughn81slf90.js +1 -0
- package/.next/static/chunks/1g1j03h_l-e67.js +1 -0
- package/.next/static/chunks/1lp02y2nmddxg.js +1 -0
- package/.next/static/chunks/{35wdx3wt7cg4a.js → 1u5i-jti87jbo.js} +1 -1
- package/.next/static/chunks/211s4xjtecj2l.js +1 -0
- package/.next/static/chunks/2244-cat2jlvd.js +1 -0
- package/.next/static/chunks/{12scesro428m7.js → 2eev_i93slion.js} +1 -1
- package/.next/static/chunks/{3x6pggb-2kyrk.js → 2gocl3dq0_h1s.js} +1 -1
- package/.next/static/chunks/{3tz4dr0_8pq1-.js → 2m267diam_vib.js} +1 -1
- package/.next/static/chunks/{0hzbj7f48cmx0.js → 2o4dndk0d68do.js} +1 -1
- package/.next/static/chunks/{0ympuji_ufypd.js → 2sdwbfs1x5skp.js} +1 -1
- package/.next/static/chunks/2sjq4gsimlfqr.js +113 -0
- package/.next/static/chunks/{39vrqy1r_00jc.js → 2uleilh8ph06-.js} +1 -1
- package/.next/static/chunks/{0gljzv9fz1g7d.js → 2zchsg03a1pdp.js} +1 -1
- package/.next/static/chunks/32tmfirfjpulv.js +1 -0
- package/.next/static/chunks/{26-eblxwnykck.js → 337g9g_ux2gj-.js} +1 -1
- package/.next/static/chunks/376-s_i83irs-.js +1 -0
- package/.next/static/chunks/3blk-kpn39xr-.js +1 -0
- package/.next/static/chunks/3eieehp7wquyu.js +1 -0
- package/.next/static/chunks/3kc-e7pcj50ae.js +1 -0
- package/.next/static/chunks/3rwpyuo9nrrop.js +17 -0
- package/.next/static/chunks/3sf4l25l353ja.js +1 -0
- package/.next/static/chunks/{0zmrz4zfzm4dt.js → 3t9huugh-5_ps.js} +1 -1
- package/.next/static/chunks/3vz7m1w688juj.js +3 -0
- package/.next/static/chunks/{2kzwhbuobpkw3.js → 43q9cgbuw8krx.js} +2 -2
- package/.next/static/chunks/43skgt0h9woyu.js +1 -0
- package/app/api/events/app-event.client.ts +8 -2
- package/app/api/events/app-event.server.ts +7 -5
- package/app/api/events/app-event.ts +19 -8
- package/app/api/query-key.ts +13 -5
- package/bin/database.mjs +21 -11
- package/bin/thursday.mjs +5 -2
- package/components/ui/shiny-text.tsx +2 -2
- package/database/migrations/20260920024909_messy_baron_strucker/migration.sql +1 -0
- package/database/migrations/20260920024909_messy_baron_strucker/snapshot.json +1937 -0
- package/features/ai/components/model-picker.tsx +8 -2
- package/features/ai/model.schema.ts +26 -0
- package/features/artifact/components/artifact-setting.tsx +18 -24
- package/features/bot/bot.action.ts +3 -0
- package/features/bot/bot.runner.ts +25 -3
- package/features/bot/bot.seed.ts +98 -22
- package/features/bot/components/bot-badge.tsx +2 -2
- package/features/bot/components/bot-mark.tsx +12 -3
- package/features/bot/components/bot-room.tsx +36 -16
- package/features/bot/components/bot-setting.tsx +88 -34
- package/features/bot/components/crew-motion.ts +161 -0
- package/features/bot/components/mark-palette.tsx +3 -3
- package/features/bot/components/room-conversation.tsx +13 -8
- package/features/bot/components/room-list.tsx +9 -5
- package/features/bot/components/room-pill.tsx +171 -94
- package/features/bot/components/thread-badge.tsx +4 -4
- package/features/bot/components/thread-setting.tsx +58 -19
- package/features/bot/mark.const.ts +24 -0
- package/features/bot/thread.query.ts +32 -14
- package/features/bot/thread.store.ts +19 -16
- package/features/config/components/config-badge.tsx +7 -1
- package/features/config/components/config-setting.tsx +83 -214
- package/features/config/components/models-badge.tsx +5 -7
- package/features/config/components/voice-key.tsx +24 -1
- package/features/config/config.const.ts +9 -1
- package/features/connectors/components/mcp-setting.tsx +60 -29
- package/features/intro/components/intro.tsx +4 -18
- package/features/memory/components/memory-setting.tsx +11 -7
- package/features/reach/channel.ts +9 -1
- package/features/reach/components/reach-guide.tsx +606 -105
- package/features/reach/discord.ts +18 -3
- package/features/reach/reach.schema.ts +6 -0
- package/features/reach/reach.ts +55 -2
- package/features/reach/slack.ts +2 -1
- package/features/reach/telegram.ts +5 -1
- package/features/routine/components/routine-setting.tsx +46 -18
- package/features/settings/components/setting-ui.tsx +16 -58
- package/features/settings/components/settings.tsx +7 -4
- package/features/settings/settings.alert.ts +10 -9
- package/features/skills/components/skills-setting.tsx +78 -12
- package/features/skills/skills.action.ts +12 -0
- package/features/skills/skills.query.ts +24 -0
- package/features/thursday/components/call-log.tsx +19 -14
- package/features/thursday/components/side-captions.tsx +3 -2
- package/features/thursday/components/tab-state.tsx +5 -2
- package/features/thursday/components/thursday-setting.tsx +5 -6
- package/features/thursday/components/thursday.tsx +60 -29
- package/features/thursday/components/write-line.tsx +19 -5
- package/features/thursday/thursday.action.ts +4 -0
- package/features/thursday/thursday.query.ts +3 -2
- package/features/thursday/thursday.schema.ts +5 -0
- package/features/thursday/use-call-ring.ts +6 -1
- package/features/thursday/use-text-call.ts +25 -10
- package/features/thursday/use-thursday.ts +10 -1
- package/features/workspace/components/artifact-view.tsx +42 -33
- package/features/workspace/components/file-thumb.tsx +8 -4
- package/features/workspace/components/file-view.tsx +25 -2
- package/features/workspace/components/workspace-setting.tsx +27 -23
- package/features/workspace/workspace.query.ts +20 -1
- package/features/workspace/workspace.ts +14 -0
- package/guide/bots.md +27 -4
- package/guide/calls.md +7 -4
- package/guide/phone.md +23 -12
- package/guide/setup.md +24 -6
- package/guide/trouble.md +1 -1
- package/hooks/use-theme.ts +14 -0
- package/lib/protocol/events.client.ts +56 -14
- package/lib/protocol/events.server.ts +41 -12
- package/lib/utils.ts +1 -1
- package/package.json +1 -1
- package/scripts/reach-channels.test.mts +15 -2
- package/seed-skills/brief/daily-brief/SKILL.md +39 -0
- package/seed-skills/brief/daily-brief/page/brief.css +406 -0
- package/seed-skills/brief/daily-brief/references/brief.md +106 -0
- package/seed-skills/brief/daily-brief/references/preferences.md +67 -0
- package/seed-skills/brief/daily-brief/scripts/glance.mjs +128 -0
- package/seed-skills/brief/daily-brief/scripts/lib.mjs +182 -0
- package/seed-skills/brief/daily-brief/scripts/news.mjs +320 -0
- package/seed-skills/brief/daily-brief/scripts/page.mjs +322 -0
- package/seed-skills/brief/daily-brief/scripts/story.mjs +265 -0
- package/seed-skills/digest/README.md +20 -0
- package/seed-skills/digest/media-digest/SKILL.md +32 -0
- package/seed-skills/digest/media-digest/references/no-captions.md +20 -0
- package/seed-skills/digest/media-digest/references/page.md +56 -0
- package/seed-skills/digest/media-digest/references/reading.md +56 -0
- package/seed-skills/digest/media-digest/scripts/audio.mjs +232 -0
- package/seed-skills/digest/media-digest/scripts/digest.mjs +379 -0
- package/seed-skills/digest/media-digest/scripts/lib.mjs +284 -0
- package/seed-skills/digest/media-digest/scripts/part.mjs +16 -0
- package/seed-skills/digest/media-digest/scripts/text.mjs +287 -0
- package/seed-skills/digest/media-digest/scripts/yt.mjs +487 -0
- package/seed-skills/docs/README.md +32 -0
- package/seed-skills/docs/documents/SKILL.md +34 -0
- package/seed-skills/docs/documents/kit/package-lock.json +1596 -0
- package/seed-skills/docs/documents/kit/package.json +17 -0
- package/seed-skills/docs/documents/references/deck.md +63 -0
- package/seed-skills/docs/documents/references/invoice.md +64 -0
- package/seed-skills/docs/documents/references/pdf.md +59 -0
- package/seed-skills/docs/documents/references/print.md +43 -0
- package/seed-skills/docs/documents/references/sheets.md +49 -0
- package/seed-skills/docs/documents/references/translate.md +37 -0
- package/seed-skills/docs/documents/references/word.md +45 -0
- package/seed-skills/docs/documents/scripts/doc.mjs +123 -0
- package/seed-skills/docs/documents/scripts/lib/browser.mjs +259 -0
- package/seed-skills/docs/documents/scripts/lib/deck-chart.mjs +150 -0
- package/seed-skills/docs/documents/scripts/lib/deck.mjs +1132 -0
- package/seed-skills/docs/documents/scripts/lib/invoice.mjs +505 -0
- package/seed-skills/docs/documents/scripts/lib/kit.mjs +244 -0
- package/seed-skills/docs/documents/scripts/lib/pdf.mjs +645 -0
- package/seed-skills/docs/documents/scripts/lib/report.mjs +38 -0
- package/seed-skills/docs/documents/scripts/lib/sheet.mjs +523 -0
- package/seed-skills/docs/documents/scripts/lib/templates.mjs +34 -0
- package/seed-skills/docs/documents/scripts/lib/translate.mjs +691 -0
- package/seed-skills/docs/documents/scripts/lib/word.mjs +678 -0
- package/seed-skills/docs/documents/templates/letter.html +56 -0
- package/seed-skills/docs/documents/templates/print.css +219 -0
- package/seed-skills/docs/documents/templates/report.html +47 -0
- package/seed-skills/docs/documents/templates/resume.html +61 -0
- package/seed-skills/insta/instagram/references/post.md +31 -7
- package/seed-skills/trip/README.md +11 -0
- package/seed-skills/trip/travel/SKILL.md +40 -0
- package/seed-skills/trip/travel/page/itinerary.css +488 -0
- package/seed-skills/trip/travel/references/itinerary.md +70 -0
- package/seed-skills/trip/travel/references/plan.md +75 -0
- package/seed-skills/trip/travel/references/watch-and-book.md +39 -0
- package/seed-skills/trip/travel/scripts/flights.mjs +374 -0
- package/seed-skills/trip/travel/scripts/fx.mjs +57 -0
- package/seed-skills/trip/travel/scripts/hotels.mjs +356 -0
- package/seed-skills/trip/travel/scripts/itinerary.mjs +482 -0
- package/seed-skills/trip/travel/scripts/lib.mjs +120 -0
- package/seed-skills/trip/travel/scripts/selectors.mjs +78 -0
- package/seed-skills/trip/travel/scripts/watch.mjs +147 -0
- package/seed-skills/trip/travel/scripts/weather.mjs +150 -0
- package/seed-skills/tutor/picture-book/SKILL.md +6 -0
- package/seed-skills/tutor/picture-book/references/picture-book.md +22 -2
- package/.next/server/chunks/[root-of-the-server]__014ydvq._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__01d285y._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__04r4h-2._.js +0 -7
- package/.next/server/chunks/[root-of-the-server]__0ayldfn._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0cfszwn._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0npn_pn._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0rqgb17._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__17weeeg._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1ai5lme._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1tg5got._.js +0 -3
- package/.next/server/chunks/_05v8k21._.js +0 -7
- package/.next/server/chunks/_0k6qjcf._.js +0 -5
- package/.next/server/chunks/_1d_enhu._.js +0 -3
- package/.next/server/chunks/_1jc5g4p._.js +0 -6
- package/.next/server/chunks/_1nfr-75._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0md6j0x._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_14ih1vy._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1d6ez5-._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0m7u9j-._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0tzekbl._.js +0 -68
- package/.next/server/chunks/ssr/[root-of-the-server]__1756892._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1cz2rz5._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1nqw56a._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1w9hqq8._.js +0 -8
- package/.next/server/chunks/ssr/_05pl_u8._.js +0 -3
- package/.next/server/chunks/ssr/_097-ljd._.js +0 -4
- package/.next/server/chunks/ssr/_0evkpto._.js +0 -3
- package/.next/server/chunks/ssr/_0hjzb5o._.js +0 -3
- package/.next/server/chunks/ssr/_0lu1n_x._.js +0 -3
- package/.next/server/chunks/ssr/_0u7ko71._.js +0 -3
- package/.next/server/chunks/ssr/_0wd_o8-._.js +0 -3
- package/.next/server/chunks/ssr/_0ya0cb0._.js +0 -3
- package/.next/server/chunks/ssr/_10yyqtk._.js +0 -67
- package/.next/server/chunks/ssr/_12eyown._.js +0 -5
- package/.next/server/chunks/ssr/_132qkfz._.js +0 -5
- package/.next/server/chunks/ssr/_15zqt-t._.js +0 -3
- package/.next/server/chunks/ssr/_184327j._.js +0 -3
- package/.next/server/chunks/ssr/_1q683w8._.js +0 -20
- package/.next/server/chunks/ssr/_1tawxu2._.js +0 -3
- package/.next/server/chunks/ssr/_1xx4zlb._.js +0 -3
- package/.next/server/chunks/ssr/features_bot_0s11m4r._.js +0 -3
- package/.next/static/chunks/03-724sj0nk_z.js +0 -3
- package/.next/static/chunks/0c_g4-11sha-1.js +0 -1
- package/.next/static/chunks/0h0lythv1ql93.js +0 -1
- package/.next/static/chunks/0lwunwbl7u7pt.js +0 -1
- package/.next/static/chunks/0rn9nbg6aif9f.js +0 -17
- package/.next/static/chunks/0vlgzqo9ka90v.js +0 -1
- package/.next/static/chunks/11tlxkr7a_rpc.js +0 -1
- package/.next/static/chunks/16s2fx3890_jd.js +0 -65
- package/.next/static/chunks/1g9yyvculuxj2.js +0 -1
- package/.next/static/chunks/1s6m4cmbn7htf.js +0 -1
- package/.next/static/chunks/1wl9t1-3i-q8p.css +0 -1
- package/.next/static/chunks/2-asot3p1j3yg.js +0 -1
- package/.next/static/chunks/22h9gvclqtx_2.js +0 -1
- package/.next/static/chunks/23nfu5g4vl_m7.js +0 -1
- package/.next/static/chunks/2m6jd3586ijb-.js +0 -1
- package/.next/static/chunks/2ndw4w4u2x51r.js +0 -1
- package/.next/static/chunks/304q9p54tcgm1.js +0 -1
- package/.next/static/chunks/37unh9460im7v.js +0 -18
- package/.next/static/chunks/3dipmu0mptqum.js +0 -1
- package/.next/static/chunks/3gki-squw28yu.js +0 -1
- package/.next/static/chunks/3nnzdl_te20hv.js +0 -1
- package/features/reach/components/reach-state.tsx +0 -71
- /package/.next/static/{En1vUPazxcYjPjnnahcN5 → fiNGsQfna8qldl8wU8wqr}/_buildManifest.js +0 -0
- /package/.next/static/{En1vUPazxcYjPjnnahcN5 → fiNGsQfna8qldl8wU8wqr}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{En1vUPazxcYjPjnnahcN5 → fiNGsQfna8qldl8wU8wqr}/_ssgManifest.js +0 -0
|
@@ -20,7 +20,11 @@ import type {
|
|
|
20
20
|
MediaKind,
|
|
21
21
|
TextModelProviderId,
|
|
22
22
|
} from "../model.schema";
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
canMakeKind,
|
|
25
|
+
MEDIA_MODEL_PROVIDERS,
|
|
26
|
+
TEXT_MODEL_PROVIDERS,
|
|
27
|
+
} from "../model.schema";
|
|
24
28
|
import { ChatGptSignIn } from "./chatgpt-sign-in";
|
|
25
29
|
import { ModelBrowser } from "./model-browser";
|
|
26
30
|
import { ProviderIcon } from "./provider-icon";
|
|
@@ -312,7 +316,9 @@ function AskForKey({
|
|
|
312
316
|
<Input
|
|
313
317
|
value={value}
|
|
314
318
|
onChange={(event) => setValue(event.target.value)}
|
|
315
|
-
placeholder={
|
|
319
|
+
placeholder={
|
|
320
|
+
TEXT_MODEL_PROVIDERS[provider.id].keyLooks ?? "Paste the key"
|
|
321
|
+
}
|
|
316
322
|
spellCheck={false}
|
|
317
323
|
type="password"
|
|
318
324
|
/>
|
|
@@ -378,12 +378,18 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
378
378
|
apiKeyName: string;
|
|
379
379
|
/** Reached by signing in to an account rather than a pasted key; `apiKeyName` is where the sign-in is kept. */
|
|
380
380
|
signIn?: true;
|
|
381
|
+
/** Where a key is made: the link beside its field. */
|
|
382
|
+
keysAt?: string;
|
|
383
|
+
/** How a key begins, shown in its empty field in place of the setting's name. */
|
|
384
|
+
keyLooks?: string;
|
|
381
385
|
suggestModels: SuggestModel[];
|
|
382
386
|
}
|
|
383
387
|
> = {
|
|
384
388
|
openai: {
|
|
385
389
|
label: "Open AI",
|
|
386
390
|
apiKeyName: "OPENAI_API_KEY",
|
|
391
|
+
keysAt: "https://platform.openai.com/api-keys",
|
|
392
|
+
keyLooks: "sk-…",
|
|
387
393
|
suggestModels: [
|
|
388
394
|
{
|
|
389
395
|
id: "gpt-5.6-luna",
|
|
@@ -450,6 +456,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
450
456
|
anthropic: {
|
|
451
457
|
label: "Claude",
|
|
452
458
|
apiKeyName: "ANTHROPIC_API_KEY",
|
|
459
|
+
keysAt: "https://platform.claude.com/settings/keys",
|
|
460
|
+
keyLooks: "sk-ant-…",
|
|
453
461
|
suggestModels: [
|
|
454
462
|
{ id: "claude-haiku-4-5", label: "Haiku 4.5", tier: "small" },
|
|
455
463
|
{
|
|
@@ -470,6 +478,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
470
478
|
google: {
|
|
471
479
|
label: "Gemini",
|
|
472
480
|
apiKeyName: "GOOGLE_GENERATIVE_AI_API_KEY",
|
|
481
|
+
keysAt: "https://aistudio.google.com/apikey",
|
|
482
|
+
keyLooks: "AIza…",
|
|
473
483
|
suggestModels: [
|
|
474
484
|
{
|
|
475
485
|
id: "gemini-3.5-flash-lite",
|
|
@@ -488,6 +498,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
488
498
|
xai: {
|
|
489
499
|
label: "xAI",
|
|
490
500
|
apiKeyName: "XAI_API_KEY",
|
|
501
|
+
keysAt: "https://console.x.ai",
|
|
502
|
+
keyLooks: "xai-…",
|
|
491
503
|
suggestModels: [
|
|
492
504
|
{ id: "grok-4.6", label: "Grok 4.6", tier: "large", context: 500_000 },
|
|
493
505
|
],
|
|
@@ -499,6 +511,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
499
511
|
"vercel-ai-gateway": {
|
|
500
512
|
label: "Vercel AI GateWay",
|
|
501
513
|
apiKeyName: "AI_GATEWAY_API_KEY",
|
|
514
|
+
keysAt:
|
|
515
|
+
"https://vercel.com/docs/ai-gateway/authentication-and-byok/authentication",
|
|
502
516
|
suggestModels: [
|
|
503
517
|
{ id: "zai/glm-5.3-flash", label: "GLM 5.3 Flash", tier: "small" },
|
|
504
518
|
{
|
|
@@ -554,6 +568,7 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
554
568
|
mistral: {
|
|
555
569
|
label: "Mistral",
|
|
556
570
|
apiKeyName: "MISTRAL_API_KEY",
|
|
571
|
+
keysAt: "https://console.mistral.ai/api-keys",
|
|
557
572
|
suggestModels: [
|
|
558
573
|
{ id: "ministral-8b-latest", label: "Ministral 8B", tier: "small" },
|
|
559
574
|
{ id: "mistral-small-latest", label: "Small", tier: "mid" },
|
|
@@ -564,6 +579,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
564
579
|
deepseek: {
|
|
565
580
|
label: "DeepSeek",
|
|
566
581
|
apiKeyName: "DEEPSEEK_API_KEY",
|
|
582
|
+
keysAt: "https://platform.deepseek.com/api_keys",
|
|
583
|
+
keyLooks: "sk-…",
|
|
567
584
|
suggestModels: [
|
|
568
585
|
{
|
|
569
586
|
id: "deepseek-flash",
|
|
@@ -583,6 +600,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
583
600
|
groq: {
|
|
584
601
|
label: "Groq",
|
|
585
602
|
apiKeyName: "GROQ_API_KEY",
|
|
603
|
+
keysAt: "https://console.groq.com/keys",
|
|
604
|
+
keyLooks: "gsk_…",
|
|
586
605
|
suggestModels: [
|
|
587
606
|
{
|
|
588
607
|
id: "openai/gpt-oss-20b",
|
|
@@ -608,6 +627,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
608
627
|
cerebras: {
|
|
609
628
|
label: "Cerebras",
|
|
610
629
|
apiKeyName: "CEREBRAS_API_KEY",
|
|
630
|
+
keysAt: "https://cloud.cerebras.ai",
|
|
631
|
+
keyLooks: "csk-…",
|
|
611
632
|
suggestModels: [
|
|
612
633
|
{
|
|
613
634
|
id: "qwen-3.8-27b",
|
|
@@ -626,6 +647,7 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
626
647
|
togetherai: {
|
|
627
648
|
label: "Together",
|
|
628
649
|
apiKeyName: "TOGETHER_AI_API_KEY",
|
|
650
|
+
keysAt: "https://api.together.ai/settings/api-keys",
|
|
629
651
|
suggestModels: [
|
|
630
652
|
{
|
|
631
653
|
id: "Qwen/Qwen3.5-9B",
|
|
@@ -668,6 +690,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
668
690
|
fireworks: {
|
|
669
691
|
label: "Fireworks",
|
|
670
692
|
apiKeyName: "FIREWORKS_API_KEY",
|
|
693
|
+
keysAt: "https://app.fireworks.ai/account/api-keys",
|
|
694
|
+
keyLooks: "fw_…",
|
|
671
695
|
suggestModels: [
|
|
672
696
|
{
|
|
673
697
|
id: "accounts/fireworks/models/glm-5p3-flash",
|
|
@@ -704,6 +728,7 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
704
728
|
deepinfra: {
|
|
705
729
|
label: "DeepInfra",
|
|
706
730
|
apiKeyName: "DEEPINFRA_API_KEY",
|
|
731
|
+
keysAt: "https://deepinfra.com/dash/api_keys",
|
|
707
732
|
suggestModels: [
|
|
708
733
|
{
|
|
709
734
|
id: "deepseek-ai/DeepSeek-V4-Flash-0731",
|
|
@@ -740,6 +765,7 @@ export const TEXT_MODEL_PROVIDERS: Record<
|
|
|
740
765
|
cohere: {
|
|
741
766
|
label: "Cohere",
|
|
742
767
|
apiKeyName: "COHERE_API_KEY",
|
|
768
|
+
keysAt: "https://dashboard.cohere.com/api-keys",
|
|
743
769
|
suggestModels: [
|
|
744
770
|
{
|
|
745
771
|
id: "command-r7b-12-2024",
|
|
@@ -23,6 +23,7 @@ import type {
|
|
|
23
23
|
import type { Bot } from "@/features/bot/bot.schema";
|
|
24
24
|
import { BotMark } from "@/features/bot/components/bot-mark";
|
|
25
25
|
import {
|
|
26
|
+
PICKED_ROW,
|
|
26
27
|
SettingError,
|
|
27
28
|
SettingFilter,
|
|
28
29
|
SettingPanes,
|
|
@@ -90,7 +91,7 @@ export function ArtifactSetting() {
|
|
|
90
91
|
<>
|
|
91
92
|
<SettingRailNote>
|
|
92
93
|
<span className="font-mono">
|
|
93
|
-
<span className="font-medium text-foreground">
|
|
94
|
+
<span className="font-medium text-foreground">finished</span>
|
|
94
95
|
{` · ${countLine(entries, total, data?.files ?? 0)}`}
|
|
95
96
|
</span>
|
|
96
97
|
</SettingRailNote>
|
|
@@ -109,7 +110,7 @@ export function ArtifactSetting() {
|
|
|
109
110
|
<SettingFilter
|
|
110
111
|
value={filter}
|
|
111
112
|
onChange={setFilter}
|
|
112
|
-
placeholder="Filter
|
|
113
|
+
placeholder="Filter files"
|
|
113
114
|
className="mx-2 mb-1.5 w-auto"
|
|
114
115
|
/>
|
|
115
116
|
|
|
@@ -177,7 +178,7 @@ export function ArtifactSetting() {
|
|
|
177
178
|
onPick={(row) => setReading({ row, file: null })}
|
|
178
179
|
/>
|
|
179
180
|
) : (
|
|
180
|
-
<Nothing empty={total === 0}
|
|
181
|
+
<Nothing empty={total === 0} />
|
|
181
182
|
)
|
|
182
183
|
}
|
|
183
184
|
/>
|
|
@@ -211,13 +212,13 @@ function markOf(name: string, bots?: Bot[]) {
|
|
|
211
212
|
};
|
|
212
213
|
}
|
|
213
214
|
|
|
214
|
-
/** `4
|
|
215
|
+
/** `4 results · 34 files`, and what is not on screen. Counts rows, so it is free. */
|
|
215
216
|
function countLine(shown: Artifact[], total: number, files: number): string {
|
|
216
217
|
if (total === 0) return "empty";
|
|
217
218
|
const head =
|
|
218
219
|
total > shown.length
|
|
219
|
-
? `${shown.length} of ${total.toLocaleString("en")}
|
|
220
|
-
: `${total} ${total === 1 ? "
|
|
220
|
+
? `${shown.length} of ${total.toLocaleString("en")} results`
|
|
221
|
+
: `${total} ${total === 1 ? "result" : "results"}`;
|
|
221
222
|
return files > total ? `${head} · ${files.toLocaleString("en")} files` : head;
|
|
222
223
|
}
|
|
223
224
|
|
|
@@ -242,7 +243,7 @@ function BotRow({
|
|
|
242
243
|
className={cn(
|
|
243
244
|
"mx-2 flex h-9 items-center gap-2 rounded-md px-2 text-left text-[13px] outline-none focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:ring-inset",
|
|
244
245
|
active
|
|
245
|
-
? "
|
|
246
|
+
? cn(PICKED_ROW, "font-medium")
|
|
246
247
|
: "text-muted-foreground hover:bg-muted/60 hover:text-foreground",
|
|
247
248
|
)}
|
|
248
249
|
>
|
|
@@ -341,12 +342,13 @@ function Reader({
|
|
|
341
342
|
>
|
|
342
343
|
<FolderOpen />
|
|
343
344
|
</Button>
|
|
345
|
+
{/* set apart from Reveal beside it, and red on the way in: the file goes from disk */}
|
|
344
346
|
<Button
|
|
345
347
|
size="icon-sm"
|
|
346
348
|
variant="ghost"
|
|
347
349
|
aria-label="Delete"
|
|
348
350
|
loading={removing}
|
|
349
|
-
className="text-muted-foreground"
|
|
351
|
+
className="ml-1.5 text-muted-foreground hover:text-destructive"
|
|
350
352
|
onClick={() => confirmRemove(open?.path ?? row.path)}
|
|
351
353
|
>
|
|
352
354
|
<Trash2 />
|
|
@@ -433,7 +435,7 @@ function Thumb({ file }: { file: ArtifactFile }) {
|
|
|
433
435
|
path={file.path}
|
|
434
436
|
bytes={file.bytes}
|
|
435
437
|
glyph="size-5"
|
|
436
|
-
className="aspect-4/3 w-full rounded-xl"
|
|
438
|
+
className="aspect-4/3 w-full rounded-xl ring-1 ring-foreground/5 ring-inset"
|
|
437
439
|
/>
|
|
438
440
|
);
|
|
439
441
|
}
|
|
@@ -487,13 +489,15 @@ function Shelf({
|
|
|
487
489
|
path={row.path}
|
|
488
490
|
bytes={row.bytes}
|
|
489
491
|
glyph="size-5"
|
|
490
|
-
className="aspect-4/3 w-full rounded-xl"
|
|
492
|
+
className="aspect-4/3 w-full rounded-xl ring-1 ring-foreground/5 ring-inset"
|
|
491
493
|
/>
|
|
492
494
|
)}
|
|
493
495
|
<span className="min-w-0 space-y-0.5 px-0.5">
|
|
494
496
|
<span className="block truncate text-[13px]">{row.name}</span>
|
|
495
497
|
<span className="block truncate font-mono text-[10.5px] text-muted-foreground">
|
|
496
|
-
{row.kind === "set"
|
|
498
|
+
{row.kind === "set"
|
|
499
|
+
? `${row.count} ${row.count === 1 ? "file" : "files"} · `
|
|
500
|
+
: ""}
|
|
497
501
|
{shortAgo(row.at)}
|
|
498
502
|
</span>
|
|
499
503
|
</span>
|
|
@@ -506,25 +510,15 @@ function Shelf({
|
|
|
506
510
|
);
|
|
507
511
|
}
|
|
508
512
|
|
|
509
|
-
/** The right pane with nothing to show: what lands here, and where it comes from. */
|
|
510
|
-
function Nothing({
|
|
511
|
-
empty,
|
|
512
|
-
onReveal,
|
|
513
|
-
}: {
|
|
514
|
-
empty: boolean;
|
|
515
|
-
onReveal: () => void;
|
|
516
|
-
}) {
|
|
513
|
+
/** The right pane with nothing to show: what lands here, and where it comes from. Reveal folder is the footer's. */
|
|
514
|
+
function Nothing({ empty }: { empty: boolean }) {
|
|
517
515
|
return (
|
|
518
|
-
<div className="
|
|
516
|
+
<div className="p-8">
|
|
519
517
|
<p className="max-w-lg text-sm leading-relaxed text-muted-foreground">
|
|
520
518
|
{empty
|
|
521
519
|
? "Nothing finished yet. When a bot ends a job with something to hand over — a page, a report, a set of pictures — it lands here."
|
|
522
520
|
: "Pick something on the left. Each bot's work is under its face; a folder it filled is one row, and opens as a sheet."}
|
|
523
521
|
</p>
|
|
524
|
-
<Button variant="outline" onClick={onReveal}>
|
|
525
|
-
<FolderOpen />
|
|
526
|
-
Reveal folder
|
|
527
|
-
</Button>
|
|
528
522
|
</div>
|
|
529
523
|
);
|
|
530
524
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { textModelProviderSchema } from "@/features/ai/model.schema";
|
|
5
5
|
import { giveSeedSkills } from "@/features/skills/skills.discover";
|
|
6
|
+
import { removeBotFolder } from "@/features/workspace/workspace";
|
|
6
7
|
import { serverAction } from "@/lib/protocol/server-action";
|
|
7
8
|
import { publicError } from "@/lib/public-error";
|
|
8
9
|
import {
|
|
@@ -82,6 +83,8 @@ export const createSeedBotsAction = serverAction(async (picks: unknown) => {
|
|
|
82
83
|
|
|
83
84
|
export const deleteBotAction = serverAction(async (name: string) => {
|
|
84
85
|
if (!(await deleteBot(name))) publicError("Bot not found");
|
|
86
|
+
// The row is not the whole bot: what it kept is on disk under its name
|
|
87
|
+
await removeBotFolder(name);
|
|
85
88
|
});
|
|
86
89
|
|
|
87
90
|
/** Switched off, no bot is shown its own memory. What is already written stays on disk. */
|
|
@@ -252,10 +252,15 @@ async function drive(work: RoomWork, signal: AbortSignal) {
|
|
|
252
252
|
await finishRoomWork(work, final.text);
|
|
253
253
|
const thread = await findThread(work.threadId);
|
|
254
254
|
if (thread?.status === "done") {
|
|
255
|
+
// An answer is written for the screen; what says it elsewhere says it as words
|
|
256
|
+
const words = plainText(thread.outcome ?? "").slice(
|
|
257
|
+
0,
|
|
258
|
+
FINISHED_NOTICE.words,
|
|
259
|
+
);
|
|
255
260
|
// With a page open the page tells it (artifact-view): a notification it shows brings
|
|
256
261
|
// Thursday forward when pressed, where the OS one opens the script runner behind it
|
|
257
262
|
if (!presence.watching && !(await isAnyCallLive()))
|
|
258
|
-
desktopNotify(thread.label,
|
|
263
|
+
desktopNotify(thread.label, words);
|
|
259
264
|
const files = await filesOnDisk(pathsIn(thread.outcome ?? ""), null);
|
|
260
265
|
// A page to read leads the notice; the rest follow in the order they were written.
|
|
261
266
|
const lead = files.findIndex(opensOnFinish);
|
|
@@ -264,7 +269,7 @@ async function drive(work: RoomWork, signal: AbortSignal) {
|
|
|
264
269
|
threadId: thread.id,
|
|
265
270
|
label: thread.label,
|
|
266
271
|
bot: thread.bot,
|
|
267
|
-
words
|
|
272
|
+
words,
|
|
268
273
|
paths:
|
|
269
274
|
lead > 0
|
|
270
275
|
? [files[lead], ...files.filter((_, at) => at !== lead)]
|
|
@@ -507,13 +512,30 @@ async function removeLockedThread(id: string) {
|
|
|
507
512
|
return removed;
|
|
508
513
|
}
|
|
509
514
|
|
|
510
|
-
|
|
515
|
+
/**
|
|
516
|
+
* Removes jobs that are over, with everything they held. With `endedBefore` only
|
|
517
|
+
* the ones that ended before then go, which is how the app clears by age
|
|
518
|
+
* (instrumentation, config HISTORY_KEEP); without it, all of them, which is the
|
|
519
|
+
* user pressing Clear finished. A job is taken under its lock and read again
|
|
520
|
+
* inside it, so one picked back up in that moment is left alone.
|
|
521
|
+
*/
|
|
522
|
+
export async function removeFinishedThreads(
|
|
523
|
+
endedBefore?: Date,
|
|
524
|
+
): Promise<number> {
|
|
525
|
+
const cutoff = endedBefore?.getTime();
|
|
526
|
+
// The same age a job's files are judged by (sweepJobFiles): a thread is only
|
|
527
|
+
// stamped `endedAt` on done and cancelled, so `updatedAt` stands in for the rest.
|
|
528
|
+
const over = (thread: { endedAt: Date | null; updatedAt: Date }) =>
|
|
529
|
+
cutoff === undefined ||
|
|
530
|
+
(thread.endedAt ?? thread.updatedAt).getTime() < cutoff;
|
|
511
531
|
let removed = 0;
|
|
512
532
|
for (const thread of await listThreadFolders()) {
|
|
513
533
|
if (thread.status !== "done" && thread.status !== "cancelled") continue;
|
|
534
|
+
if (!over(thread)) continue;
|
|
514
535
|
await threadLock(thread.id, async () => {
|
|
515
536
|
const current = await findThread(thread.id);
|
|
516
537
|
if (current?.status !== "done" && current?.status !== "cancelled") return;
|
|
538
|
+
if (!over(current)) return;
|
|
517
539
|
if (await removeLockedThread(thread.id)) removed += 1;
|
|
518
540
|
});
|
|
519
541
|
}
|
package/features/bot/bot.seed.ts
CHANGED
|
@@ -48,27 +48,6 @@ export const BOT_SEEDS: BotSeed[] = [
|
|
|
48
48
|
hint: "Takes whatever nobody else is for",
|
|
49
49
|
systemPrompt: "",
|
|
50
50
|
},
|
|
51
|
-
{
|
|
52
|
-
name: "Planner",
|
|
53
|
-
description:
|
|
54
|
-
"Any job that needs a team — decides what done means, assigns the parts, checks them, signs off",
|
|
55
|
-
hint: "Runs the job: assigns, checks, decides",
|
|
56
|
-
systemPrompt: `You run the team the way a chief executive runs a company: accountable for the result, not the one who produces it. A job comes in as a request and goes out as one finished result. Between the two you decide what done means, give each part to whoever on Bots is best placed for it, hold every part to what it was asked for, and make the calls nobody else can. A part is yours only when nobody on Bots fits it.
|
|
57
|
-
|
|
58
|
-
**Decide what done means, first.** Before anything is handed out, send Thursday one \`${TOOL_NAMES.send_message}\` question holding everything only the user can decide — which one, how much, by when, in what form — with options where they fit. What you can find out, or the request already says, is not asked. After that, a doubt a reasonable choice settles is yours: decide, write \`Ruling: <what> — <why>\` in the plan, and keep going. Only what cannot be undone goes back to Thursday.
|
|
59
|
-
|
|
60
|
-
**Staff it to its size.** A job one bot can do goes whole to that bot. Split only where parts run at the same time or need different strengths, and never let two parts write the same file at once.
|
|
61
|
-
|
|
62
|
-
**The plan is the one record.** \`plan.md\` in the job's scratch folder holds the goal; the facts every part needs (the user's answers, names, dates, units); one line per part, \`- [ ] <what exists when done, and how it will be checked> — <who> → <path>\`; then rulings and misses. Read it before every decision and update it as each part lands. Send the checklist to Thursday as a \`message\` once it is written.
|
|
63
|
-
|
|
64
|
-
**A brief is an assignment finished without asking you.** The goal and how it will be judged; the facts from \`plan.md\` it needs; the files to read; where to write — the part's own folder in scratch, the bot's own folder under \`artifacts/\` for what the user opens, \`projects/\` for code that outlives the job; what not to touch because another part owns it; what to send back — a few lines and the paths. Send every part that waits on nothing in the same step; a part that needs another's output goes out once that file exists.
|
|
65
|
-
|
|
66
|
-
**Judge the work, not the report.** Open what a part wrote and test it against its line — values, units, names and dates agreeing across parts — then tick it. Short or wrong: back to the same bot once, saying exactly what. Short again: another bot or another way, never the same brief twice. A third miss stops that part: ask Thursday how to go on, with what was tried. Every miss goes in the plan.
|
|
67
|
-
|
|
68
|
-
**Your memory is how the team gets better.** Keep a file for each: which bot did which kind of part well or badly; briefs that worked; jobs that come back and where their results live. Date each line, merge rather than add, delete what proved wrong. Never a job's contents — those stay in its files. The team changes: a bot you remember may be gone, so staff from Bots as it is now.
|
|
69
|
-
|
|
70
|
-
**Sign off on one result.** Put the deliverable together from the part files. Your final text says what was done, where it is, who did which part, the rulings you made, and what is unverified and why.`,
|
|
71
|
-
},
|
|
72
51
|
{
|
|
73
52
|
name: "Analyst",
|
|
74
53
|
description:
|
|
@@ -106,6 +85,25 @@ Your final text gives the answer with its numbers, what is not solid, and the pa
|
|
|
106
85
|
**Start where they are.** Your memory keeps what the user already knows and how they liked being taught: the level, a picture style, how many pages. Read it before the story, and after a book keep what this one showed, dated.
|
|
107
86
|
|
|
108
87
|
Your final text gives the path, and in one sentence the idea the book leaves them with.`,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "Docs",
|
|
91
|
+
description:
|
|
92
|
+
"Office files — PDFs, invoices and quotes, decks, Word and Excel; fills, signs and translates them",
|
|
93
|
+
hint: "Makes and reads PDF, Word, PowerPoint, Excel",
|
|
94
|
+
systemPrompt: `Office documents are yours — making them, and working on the ones people send. A PDF to print or send (a letter, a report, a resume, a one-pager), an invoice, a quote or a receipt, a slide deck, a Word file, a spreadsheet; a PDF, Word, PowerPoint or Excel file read, filled in, signed, merged, split or translated. It ends as the file itself in your folder under \`artifacts/\`. Load your own \`documents\` skill before any step: its one script does the layout, the sums, the fitting and the pictures, and it names the reference to read for each kind of document.
|
|
95
|
+
|
|
96
|
+
**The format follows the use.** What is sent, printed or signed is a PDF; a deck to present is a .pptx; text someone will go on editing is a .docx; numbers someone will work with are an .xlsx. A format the request names wins. A .pptx or .docx comes with its PDF twin, which is what the app shows.
|
|
97
|
+
|
|
98
|
+
**Real details only.** Names, addresses, prices, tax and bank details, and every fact and figure a document states, come from the request, a file you were given, what you kept in your memory, or a page you read on this job — never recalled, never made up. A detail you do not have stays a visible blank like \`[bank account]\`, named in your answer. When what is missing is the document itself — who is billed and for what, what the deck must argue — send Thursday one \`${TOOL_NAMES.send_message}\` question holding all of it, and stop.
|
|
99
|
+
|
|
100
|
+
**Words first, then layout.** Write for the reader: a title that says the point, the answer before the detail, short lines, one idea a slide. A translation reads as if it were written in that language, with numbers, names and codes untouched.
|
|
101
|
+
|
|
102
|
+
**Look before you hand it back.** Every command that makes a page leaves a picture of it. Look at the overview once, fix what is wrong — text that overflows or shrank, a nearly empty last page, a wrong figure — and look once more after the fix: two rounds at most. Run the steps of one build in one bash call.
|
|
103
|
+
|
|
104
|
+
**Keep what repeats.** The user's own business details the first time they give them — name, address, tax ID, how they are paid, their logo's path, paper size, how invoices are numbered and the last number used — go in your memory, dated, and are reused without asking.
|
|
105
|
+
|
|
106
|
+
Your final text gives each file's path, the PDF first, with what matters in it: an invoice's total, the page or slide count, and any blank left to fill.`,
|
|
109
107
|
},
|
|
110
108
|
{
|
|
111
109
|
name: "Marketer",
|
|
@@ -133,7 +131,7 @@ Sign in once, and into an account made for this rather than their own — the se
|
|
|
133
131
|
|
|
134
132
|
Settle a post in one question. Ask only what the request leaves open — the topic, how many slides — in a single \`${TOOL_NAMES.send_message}\` question to Thursday. Told to decide yourself: \`${TOOL_NAMES.web_search}\` for what is current on the topic. Never ask twice for one round.
|
|
135
133
|
|
|
136
|
-
**Copy what already works
|
|
134
|
+
**Copy what already works, and look at it first.** For a niche you hold no pattern for, ask Thursday in the same first question whether they will name the accounts to build it after, open one on their screen for you, or leave it to you. Then study how those accounts post — and look at their covers, not only the numbers a script prints: a pattern written from counts alone comes out as a slide deck. Keep it in your memory with the accounts and the date, and build every post in that niche to it until the user says otherwise.
|
|
137
135
|
|
|
138
136
|
**A picture tells the truth about what it is.** A post about something that happened uses the real picture — the person in the story, the article's own image, a frame from the source — with the source named on the slide. A post about an idea or a mood can use a drawn one: \`${STUDIO_TOOLS.generate_image}\` through \`${TOOL_NAMES.tool_call}\` on \`${STUDIO_SERVER}\`, the whole picture in \`prompt\` and the same look repeated in each. A drawn picture is never passed off as the event, and one that looks real goes up with the AI label. \`${STUDIO_TOOLS.generate_image}\` not coming back from \`${TOOL_NAMES.tool_search}\`, or a call answering that the model cannot make images, means there is no image model: go on when real pictures make the post; when it needs a drawn one, send Thursday a \`${TOOL_NAMES.send_message}\` question saying to pick an image model in Settings › Models, and end your turn.
|
|
139
137
|
|
|
@@ -147,6 +145,84 @@ Messages are read without being opened: list the inbox first and open only the t
|
|
|
147
145
|
|
|
148
146
|
Answer with the post's url and the file paths, or with what the messages say and what they need.`,
|
|
149
147
|
},
|
|
148
|
+
{
|
|
149
|
+
name: "Trip",
|
|
150
|
+
description:
|
|
151
|
+
"Travel — flights, places to stay, weather, exchange rates, a day-by-day plan, price watches, booking",
|
|
152
|
+
hint: "Plans the trip: flights, stay, days, costs",
|
|
153
|
+
systemPrompt: `Travel is yours — a flight, a place to stay, what the weather will be, what things cost in another currency, a whole trip planned day by day, a price worth watching, a booking. Load the \`${BROWSER_SKILL}\` skill and your own \`travel\` skill before any step: its scripts read flight and hotel search pages in a dozen lines where a snapshot costs a hundred thousand characters, so run them first, chain every search a step needs in one bash call, and snapshot only when a script says the layout changed.
|
|
154
|
+
|
|
155
|
+
**Size the answer to the ask.** A fare, a forecast or a rate is your final text and nothing more. A trip — somewhere, for some days — is the skill's itinerary page in your folder under \`artifacts/\`: the flights, the stay, the weather, the days with a real photo and a map link per stop, and the costs.
|
|
156
|
+
|
|
157
|
+
**Settle what only the user can, once.** When the request leaves open something that changes the answer — where from, which dates, how many people, the budget — send Thursday one \`${TOOL_NAMES.send_message}\` question holding all of it, with options where they fit. A relative date ("next month", "a weekend") is yours to make real: pick dates and say which. Your memory keeps what the user told you before — the home airport, who travels with them, the currency they think in, seats, how they like to travel; read it before asking, and keep what a trip taught you, dated.
|
|
158
|
+
|
|
159
|
+
**Real prices, never remembered ones.** Every fare, room price and rate comes from a script's output or a page you opened, in the user's currency, with the date you saw it; a price is a quote until it is booked. Compare like with like: a round trip against a round trip, a private room against a private room, taxes in or out said.
|
|
160
|
+
|
|
161
|
+
**Choose like a careful friend.** A cheaper flight that lands at midnight or leaves before dawn is not cheaper; the cheapest room can be a dormitory bed, and a rating from a few reviews is not a rating. Say why the pick beats the next one.
|
|
162
|
+
|
|
163
|
+
**A plan that can be walked.** Three to five stops a day in an order that makes sense on a map, the first and last days shaped around the flights, rain moved indoors. What is current — a closure, a festival on those dates, entry rules for their passport — comes from one \`${TOOL_NAMES.web_search}\`, not memory.
|
|
164
|
+
|
|
165
|
+
**Watching a price is the user's to start.** You cannot schedule anything. Run the skill's watch once so it is known to work, then hand back the exact request a daily routine would carry, and say Thursday can set it up.
|
|
166
|
+
|
|
167
|
+
**A payment is theirs to press.** Take a booking to the last screen before money moves, in a window on their screen, and stop there. Traveller details they did not give you are asked for, never invented.
|
|
168
|
+
|
|
169
|
+
Your final text leads with the answer — the flights with times and price, the stay with its nightly price and why, the total against the budget — then the page's path and the booking links, and what you could not confirm.`,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "Brief",
|
|
173
|
+
description:
|
|
174
|
+
"A daily news brief on the user's topics — fresh stories, real photos, one page, a minute to hear",
|
|
175
|
+
hint: "Your news each morning, on your topics",
|
|
176
|
+
systemPrompt: `The news brief is yours — each day, or whenever asked, the stories that matter to this user on the topics they chose, as one page they read in two minutes and a version they can hear in one. It ends as a page in your folder under \`artifacts/\`. Load your own \`daily-brief\` skill before any step: its scripts gather the stories, fetch each one's own words and photo, and lay out the page, so your work is choosing and writing.
|
|
177
|
+
|
|
178
|
+
**Their taste is the brief.** What they read — topics, the language and country of their news, how many stories, a city's weather and the markets they watch, sources to prefer or avoid, audio or not, the time it should be ready — lives in \`preferences.md\` in your own memory. Read it before gathering. With none yet, look in Thursday's memory of the user for what it already says, then send Thursday one \`${TOOL_NAMES.send_message}\` question holding everything else, with a default for each part and the options \`Use the defaults\` / \`I'll tell you\`, write the file from the answer, and never ask again. When they react to a brief — "less crypto", "shorter", "not that site" — change the file the same turn, so the next brief already follows it.
|
|
179
|
+
|
|
180
|
+
**True, from the page itself.** A summary says only what the publisher's own words say, with its number or name; a headline tells the news, never teases it. A photo is the one the publisher shared, credited on the page — never a drawn picture in its place. What you could not read is left out or marked, not filled in.
|
|
181
|
+
|
|
182
|
+
**Four bash calls.** Gather every topic and the glance in one, read the chosen stories in the next, write \`brief.json\`, lay out the page and render it in the last. Look at the page once, and only once, with \`${TOOL_NAMES.look_at}\`, for photos that are wrong.
|
|
183
|
+
|
|
184
|
+
**Audio only when they want it:** \`${STUDIO_TOOLS.generate_speech}\` through \`${TOOL_NAMES.tool_call}\` on \`${STUDIO_SERVER}\`, the spoken version as its text. No speech model means the page alone today, said in one line.
|
|
185
|
+
|
|
186
|
+
**What starts by itself is theirs to set up.** After a brief no routine opened, offer it in your final text: the time they gave, and the words to ask Thursday for a daily routine with.
|
|
187
|
+
|
|
188
|
+
Your final text gives the page's path, then the spoken version exactly as written — Thursday may read it aloud — then one line on anything left out.`,
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: "Digest",
|
|
192
|
+
description:
|
|
193
|
+
"Summarizes YouTube videos, podcasts, articles and PDFs — key points with timestamps, which to watch",
|
|
194
|
+
hint: "Watches and reads the long stuff for you",
|
|
195
|
+
systemPrompt: `Anything long is yours to make short — a YouTube video, a podcast, a talk, an article, a PDF — and finding which videos on a topic are worth watching. The user would rather listen than scroll: you watch and read so they don't have to. Load your own \`media-digest\` skill before any step: its scripts read a video's transcript, chapters and details in about a second, search YouTube, and pull an article or a PDF into a file, where a browser would spend a snapshot on each screen. Run them first, and batch every command a step needs into one bash call.
|
|
196
|
+
|
|
197
|
+
**Read all of it, then say it short.** A summary rests on the whole source, read part by part, never on the title, the description or the first ten minutes. A question about one thing is a search in the transcript first, then only the parts it hits. When it is not in there, say so.
|
|
198
|
+
|
|
199
|
+
**Every claim points at its moment.** A point about a video carries the time it is said, taken from the transcript line it rests on, so a tap on the page opens the video there; a point about a PDF carries its page. A quote is copied exactly. Automatic captions mishear names and numbers: check those against the title, the description or the web before repeating them, and mark what you could not.
|
|
200
|
+
|
|
201
|
+
**Say what they said, not what you think of it.** The speaker's claims are theirs — "she argues", "he estimates" — and your own judgement, when it is asked for, is marked as yours. Which video to watch is a judgement you make from reading them: pick one, say why and where to start.
|
|
202
|
+
|
|
203
|
+
**Size the answer to the ask.** Your final text opens with the answer as you would say it aloud — a few plain sentences, no list — because it is often read to them. More than a few points goes on one page in your folder under \`artifacts/\`, drawn by your skill's page script: the key points with clickable moments, a watch list, or notes. When they want to listen, the answer is also an audio file: \`${STUDIO_TOOLS.generate_speech}\` through \`${TOOL_NAMES.tool_call}\` on \`${STUDIO_SERVER}\`, written for the ear. Answer in the user's language, whatever language the source is in.
|
|
204
|
+
|
|
205
|
+
**What cannot be read, say.** A video with no captions has its audio transcribed when a transcription model is picked; with none, or a site that will not open, answer from what you could reach and name what you could not.
|
|
206
|
+
|
|
207
|
+
Your final text is the spoken answer, then the page's path and the audio's when there are any.`,
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: "Designer",
|
|
211
|
+
description:
|
|
212
|
+
"Designs screens and pages — the options side by side on one canvas to pick from",
|
|
213
|
+
hint: "Draws the options side by side to pick from",
|
|
214
|
+
systemPrompt: `Anything that has to be looked at before it is built is yours — a screen, a page, a poster, a layout, the shape of a flow. It ends as a canvas in your folder under \`artifacts/\`: the options side by side on one surface that pans and zooms, each with a note on what it is for and what it costs, and a picture of every board beside it. Load the \`${BROWSER_SKILL}\` skill and your own \`design-canvas\` skill before any step: one script writes the canvas and shoots the boards, and the shooting needs the browser.
|
|
215
|
+
|
|
216
|
+
**Offer a real choice.** Two to four options, each exploring an axis you can name — everything at once against one thing at a time, dense against roomy — never five shades of one, which is no choice at all. Every option gets an honest case and the thing it costs: a set where only your favourite has a case made for it is a rigged vote. Mark the one you would carry forward. Once an option is B it stays B, whatever is dropped before it.
|
|
217
|
+
|
|
218
|
+
**Root it in what is already there.** Read the real thing first — the code, its stylesheet, the pages, the brand, a file you were given — and lift its exact colours, type, spacing, radii and control sizes rather than inventing a look; say in one line what you matched. You cannot open a running app to see today's screen: when the options need it beside them, ask for a picture of it, because a "today" drawn from memory makes every comparison on the canvas a guess.
|
|
219
|
+
|
|
220
|
+
**Settle the direction before the detail.** When the request leaves open what only the user can answer — who it is for, which of two directions, how much may change — send Thursday one \`${TOOL_NAMES.send_message}\` question holding all of it, with the options named. Rough boards are enough to settle a direction; the chosen one is drawn out afterwards.
|
|
221
|
+
|
|
222
|
+
**The pictures are how you check your own work.** Shoot them, fix every board the renderer refuses or the canvas marks as cut, and shoot once more: two rounds at most. Run the steps of one round in one bash call.
|
|
223
|
+
|
|
224
|
+
Your final text gives the canvas's path and every picture's path, then the axis each option explores, the one you would lead with, and what that one costs.`,
|
|
225
|
+
},
|
|
150
226
|
];
|
|
151
227
|
|
|
152
228
|
export const findBotSeed = (name: string) =>
|
|
@@ -13,9 +13,9 @@ import { useServerRoute } from "@/lib/protocol/use-server-route";
|
|
|
13
13
|
*/
|
|
14
14
|
export function useBotAlert(): SectionAlert {
|
|
15
15
|
const { data } = useServerRoute<Bot[]>(queryKey.bot);
|
|
16
|
-
return data && data.length === 0 ? "
|
|
16
|
+
return data && data.length === 0 ? "brand" : null;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export function BotBadge() {
|
|
20
|
-
return useBotAlert() ? <NavBadge tone="
|
|
20
|
+
return useBotAlert() ? <NavBadge tone="brand" /> : null;
|
|
21
21
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useEffect, useId, useMemo, useRef } from "react";
|
|
4
|
+
import { useIsDark } from "@/hooks/use-theme";
|
|
4
5
|
import { createVoiceFollower, SPECTRUM_BANDS } from "@/lib/live/live.tap";
|
|
5
6
|
import { cn } from "@/lib/utils";
|
|
6
7
|
import {
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
type MarkPaintLook,
|
|
10
11
|
type MarkPaintSpec,
|
|
11
12
|
type MarkShape,
|
|
13
|
+
markInk,
|
|
12
14
|
} from "../mark.const";
|
|
13
15
|
|
|
14
16
|
// Procedural bot avatar: a generated silhouette with two eyes, animated per frame from refs.
|
|
@@ -980,6 +982,11 @@ type BotMarkProps = {
|
|
|
980
982
|
outline?: boolean;
|
|
981
983
|
/** A paint (MARK_PAINTS) worn in place of `color`. */
|
|
982
984
|
paint?: MarkPaint;
|
|
985
|
+
/**
|
|
986
|
+
* The dot on the face: `true` waits on the user (amber), `"new"` is a result of its
|
|
987
|
+
* nobody has opened yet (brand blue, the user's pick). False draws none.
|
|
988
|
+
*/
|
|
989
|
+
/** A dot on the rim: something of this bot wants the user. */
|
|
983
990
|
notify?: boolean;
|
|
984
991
|
/** Eyes crossed out: a stopped thread, or a call that failed. */
|
|
985
992
|
crossed?: boolean;
|
|
@@ -1044,7 +1051,8 @@ export function BotMark({
|
|
|
1044
1051
|
|
|
1045
1052
|
const shapeSeed = seed === undefined ? cfg.seed : hashSeed(seed);
|
|
1046
1053
|
const theShape = shape ?? cfg.shape;
|
|
1047
|
-
|
|
1054
|
+
// The stored colour is the user's; the paper it lands on decides how it is drawn.
|
|
1055
|
+
const theFg = markInk(color ?? cfg.color, useIsDark());
|
|
1048
1056
|
const notifying = notify ?? cfg.notify;
|
|
1049
1057
|
const spec = paint ? MARK_PAINTS[paint] : null;
|
|
1050
1058
|
const grow = growOf(size);
|
|
@@ -1568,12 +1576,13 @@ export function BotMark({
|
|
|
1568
1576
|
</g>
|
|
1569
1577
|
)}
|
|
1570
1578
|
{notifying && (
|
|
1571
|
-
//
|
|
1579
|
+
// Waiting on the user wears amber in NavBadge's shades; a result nobody
|
|
1580
|
+
// has opened wears the brand blue its label does (room-list).
|
|
1572
1581
|
<circle
|
|
1573
1582
|
cx={f(CENTER + Math.cos(nAngle) * cfg.notifyDist)}
|
|
1574
1583
|
cy={f(CENTER + Math.sin(nAngle) * cfg.notifyDist)}
|
|
1575
1584
|
r={cfg.notifyR}
|
|
1576
|
-
className={cn("fill-
|
|
1585
|
+
className={cn("fill-waiting", NOTIFY_POP)}
|
|
1577
1586
|
/>
|
|
1578
1587
|
)}
|
|
1579
1588
|
</g>
|