thursday-agent 0.5.0 → 0.6.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 +3 -2
- package/.next/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/required-server-files.json +8 -1
- package/.next/routes-manifest.json +18 -6
- 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.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 +13 -13
- package/.next/server/app/_not-found.segments/_full.segment.rsc +13 -13
- 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 +10 -6
- package/.next/server/app/api/artifact/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/files/route.js +5 -4
- package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/route.js +8 -8
- package/.next/server/app/api/bot/memory/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/route.js +8 -8
- package/.next/server/app/api/bot/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/thread/[id]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/bot/thread/[id]/route.js +15 -0
- package/.next/server/app/api/bot/thread/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/bot/thread/[id]/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/bot/thread/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/bot/thread/route.js +15 -0
- package/.next/server/app/api/bot/thread/route.js.nft.json +1 -0
- package/.next/server/app/api/bot/thread/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/config/route.js +7 -7
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/events/route.js +3 -3
- package/.next/server/app/api/events/route.js.nft.json +1 -1
- package/.next/server/app/api/file/[...path]/route.js +4 -4
- package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/catalog/route.js +8 -8
- package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/credits/route.js +8 -8
- package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/route.js +8 -8
- package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/subscription/route.js +8 -8
- package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/[name]/route.js +6 -6
- package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/oauth/callback/route.js +4 -4
- package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/route.js +6 -6
- package/.next/server/app/api/mcp/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/tools/route.js +6 -6
- package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/memory/edit/route.js +15 -15
- package/.next/server/app/api/memory/edit/route.js.nft.json +1 -1
- package/.next/server/app/api/memory/route.js +7 -6
- package/.next/server/app/api/memory/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/[source]/[name]/route.js +6 -6
- package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/route.js +6 -6
- package/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/call/route.js +10 -11
- package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/skills/route.js +9 -10
- package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/tool-call/route.js +15 -15
- package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
- package/.next/server/app/api/workspace/missing/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/workspace/missing/route/build-manifest.json +12 -0
- package/.next/server/app/api/workspace/missing/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/workspace/missing/route.js +12 -0
- package/.next/server/app/api/workspace/missing/route.js.map +5 -0
- package/.next/server/app/api/workspace/missing/route.js.nft.json +1 -0
- package/.next/server/app/api/workspace/missing/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/workspace/route.js +5 -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 +4 -3
- 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/page/server-reference-manifest.json +67 -45
- package/.next/server/app/page.js +10 -9
- 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 +3 -2
- package/.next/server/chunks/[root-of-the-server]__02846fb._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__049f521._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__05luceg._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__06--3q3._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__07bnah_._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__08eae20._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0_ue8oe._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0c9fgca._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__0g-ueei._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0h_x6q6._.js +5 -0
- package/.next/server/chunks/{[root-of-the-server]__0pa2n68._.js → [root-of-the-server]__0kxrvxf._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__0q0vvt2._.js → [root-of-the-server]__0ov3iir._.js} +2 -2
- package/.next/server/chunks/[root-of-the-server]__0qwtlmx._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0sm5xvm._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0ye3da2._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0zp35ul._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__144u9d_._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__18-2tsq._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1e-ci13._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1e2365e._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__1fix932._.js +8 -0
- package/.next/server/chunks/{[root-of-the-server]__0ce8nf8._.js → [root-of-the-server]__1g3t7vn._.js} +3 -3
- package/.next/server/chunks/[root-of-the-server]__1kp-83u._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1kv8p3e._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1orn-5b._.js +2 -3
- package/.next/server/chunks/_02szwk8._.js +5 -0
- package/.next/server/chunks/_05h2cii._.js +1 -1
- package/.next/server/chunks/_06c9kie._.js +216 -0
- package/.next/server/chunks/{_1x6kd1r._.js → _07y2gj-._.js} +1 -1
- package/.next/server/chunks/_0a43a-0._.js +3 -0
- package/.next/server/chunks/_0bujjey._.js +5 -0
- package/.next/server/chunks/_0c9j6rb._.js +1 -1
- package/.next/server/chunks/_0dkd549._.js +3 -0
- package/.next/server/chunks/_0ej1kvv._.js +3 -0
- package/.next/server/chunks/_0f6ts7z._.js +3 -0
- package/.next/server/chunks/_0gm9hyv._.js +55 -0
- package/.next/server/chunks/_0i55en5._.js +25 -0
- package/.next/server/chunks/_0k50n27._.js +18 -0
- package/.next/server/chunks/_0khihjk._.js +3 -3
- package/.next/server/chunks/_0n74zsf._.js +5 -5
- package/.next/server/chunks/_0nvm9ef._.js +3 -0
- package/.next/server/chunks/_0p56fn0._.js +3 -0
- package/.next/server/chunks/_0recufk._.js +1 -1
- package/.next/server/chunks/_0xbkz10._.js +3 -0
- package/.next/server/chunks/_10tkr26._.js +3 -0
- package/.next/server/chunks/{_0ioz3nd._.js → _11u2kp7._.js} +1 -1
- package/.next/server/chunks/_11ujpya._.js +3 -0
- package/.next/server/chunks/_127nx_p._.js +5 -0
- package/.next/server/chunks/_17l5ygt._.js +1 -1
- package/.next/server/chunks/_19uauj6._.js +3 -0
- package/.next/server/chunks/_1_5mnq4._.js +5 -5
- package/.next/server/chunks/_1abl6t9._.js +55 -0
- package/.next/server/chunks/_1d0j961._.js +3 -3
- package/.next/server/chunks/_1dbixxz._.js +3 -0
- package/.next/server/chunks/_1dc_d1q._.js +98 -0
- package/.next/server/chunks/_1drgfx4._.js +5 -5
- package/.next/server/chunks/_1e48czp._.js +3 -3
- package/.next/server/chunks/_1f31u5x._.js +5 -0
- package/.next/server/chunks/_1kg70wc._.js +3 -3
- package/.next/server/chunks/_1klbcft._.js +5 -0
- package/.next/server/chunks/_1krd9rf._.js +4 -1
- package/.next/server/chunks/_1kwmzab._.js +3 -0
- package/.next/server/chunks/{_1pf4qe-._.js → _1oxj9fa._.js} +1 -1
- package/.next/server/chunks/{_1f46eie._.js → _1pcmdbb._.js} +1 -1
- package/.next/server/chunks/_1qgix-j._.js +3 -0
- package/.next/server/chunks/{lib_logger_ts_1exwjut._.js → _1rpchta._.js} +5 -5
- package/.next/server/chunks/_1vsej-s._.js +5 -0
- package/.next/server/chunks/_1yx0p_s._.js +5 -0
- package/.next/server/chunks/{_0rnf-6n._.js → _20fsr_z._.js} +6 -6
- package/.next/server/chunks/_2128hkj._.js +5 -0
- package/.next/server/chunks/_next-internal_server_app_api_bot_thread_[id]_route_actions_1fstjn2.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_bot_thread_route_actions_003ccso.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_workspace_missing_route_actions_1fidi6p.js +3 -0
- package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
- package/.next/server/chunks/features_0-cnt0l._.js +4 -0
- package/.next/server/chunks/features_0hdaci0._.js +4 -0
- package/.next/server/chunks/features_1e39j7-._.js +8 -0
- package/.next/server/chunks/features_bot_bot_query_ts_12mgkl2._.js +1 -1
- package/.next/server/chunks/features_memory_1uqvksn._.js +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0v_7drq._.js → node_modules_consola_dist_chunks_prompt_mjs_0a7-pbw._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_17k8irj._.js → node_modules_consola_dist_chunks_prompt_mjs_0gzvgfv._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0i7cvml._.js → node_modules_consola_dist_chunks_prompt_mjs_107pxfn._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0icqaqw._.js → node_modules_consola_dist_chunks_prompt_mjs_15hbel8._.js} +1 -1
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_18i-23e._.js +3 -0
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1bewgf3._.js +3 -0
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1kipdeo._.js +3 -0
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1nlww1m._.js +3 -0
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1q77nfx._.js +3 -0
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1xqdzx_._.js +3 -0
- package/.next/server/chunks/{node_modules_zod_v4_1801ax7._.js → node_modules_zod_v4_0lkux5-._.js} +2 -2
- package/.next/server/chunks/{node_modules_zod_v4_1cha_bw._.js → node_modules_zod_v4_1jmr9cq._.js} +2 -2
- package/.next/server/chunks/{node_modules_zod_v4_0ubdflj._.js → node_modules_zod_v4_1yrxmek._.js} +2 -2
- package/.next/server/chunks/node_modules_zod_v4_classic_errors_0tp0y-q.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]__0bxsfyn._.js +101 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0lyi8i2._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__172cq4x._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__18dthbp._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__18e68w8._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1fll8dc._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__1nygfik._.js +5 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1sdphb0._.js +8 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1waa3rc._.js +100 -0
- package/.next/server/chunks/ssr/_00rehl_._.js +3 -0
- package/.next/server/chunks/ssr/{_1lz_cq2._.js → _02oc_h5._.js} +76 -97
- package/.next/server/chunks/ssr/_03_928f._.js +3 -0
- package/.next/server/chunks/ssr/_05yghx6._.js +3 -0
- package/.next/server/chunks/ssr/_08c4z-9._.js +3 -0
- package/.next/server/chunks/ssr/_0_qfdlw._.js +4 -0
- package/.next/server/chunks/ssr/_0c9e5w6._.js +9 -0
- package/.next/server/chunks/ssr/{_0s99bgb._.js → _0dh2e1j._.js} +9 -3
- package/.next/server/chunks/ssr/_0dr-ddg._.js +3 -0
- package/.next/server/chunks/ssr/_0eaog6_._.js +3 -0
- package/.next/server/chunks/ssr/_0evkpto._.js +3 -0
- package/.next/server/chunks/ssr/_0g_rlog._.js +3 -0
- package/.next/server/chunks/ssr/_0geg212._.js +3 -0
- package/.next/server/chunks/ssr/{_1jdgjv9._.js → _0hxt2ul._.js} +2 -2
- package/.next/server/chunks/ssr/_0i_6q1w._.js +2 -2
- package/.next/server/chunks/ssr/_0lu1n_x._.js +1 -1
- package/.next/server/chunks/ssr/{_15j2_8f._.js → _0wzaht-._.js} +2 -2
- package/.next/server/chunks/ssr/_0z-g0uy._.js +3 -0
- package/.next/server/chunks/ssr/_123ttsf._.js +3 -0
- package/.next/server/chunks/ssr/_123y-ah._.js +3 -0
- package/.next/server/chunks/ssr/_12w42gi._.js +3 -0
- package/.next/server/chunks/ssr/_161kqav._.js +3 -0
- package/.next/server/chunks/ssr/{_0ap2fzn._.js → _16c6_xm._.js} +2 -2
- package/.next/server/chunks/ssr/_18opah7._.js +3 -0
- package/.next/server/chunks/ssr/_18xqmny._.js +3 -0
- package/.next/server/chunks/ssr/_1_krfph._.js +3 -0
- package/.next/server/chunks/ssr/_1anqots._.js +3 -0
- package/.next/server/chunks/ssr/_1ey7qn-._.js +70 -0
- package/.next/server/chunks/ssr/_1g9vs7q._.js +3 -0
- package/.next/server/chunks/ssr/_1jmz33w._.js +3 -0
- package/.next/server/chunks/ssr/_1k0spz7._.js +3 -0
- package/.next/server/chunks/ssr/_1rgtxhr._.js +5 -0
- package/.next/server/chunks/ssr/_1slp25y._.js +3 -0
- package/.next/server/chunks/ssr/{_0rzucul._.js → _1x9pskj._.js} +3 -3
- package/.next/server/chunks/ssr/_1y6b5mr._.js +101 -0
- package/.next/server/chunks/ssr/_1ztk7p6._.js +7 -0
- package/.next/server/chunks/ssr/components_ui_tabs_tsx_0ej40b4._.js +3 -0
- package/.next/server/chunks/ssr/features_bot_thread_query_ts_023eklt._.js +4 -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/{_1-teee5._.js → lib_logger_ts_0-olsze._.js} +2 -7
- package/.next/server/chunks/ssr/{node_modules_1y79i83._.js → node_modules_00_51_v._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0m383r2._.js → node_modules_022sipm._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_05-n6dz._.js → node_modules_0332gw4._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0zeg3x_._.js → node_modules_04vxchl._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_07dsgkx._.js → node_modules_0746rzi._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0fkeku3._.js → node_modules_0d5uzof._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1k6n600._.js → node_modules_0exkwcm._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_16mkxuo._.js → node_modules_0fr-ml8._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0iur59s._.js → node_modules_0mxvg8h._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1j8j4pt._.js → node_modules_0qapgjr._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_20c28js._.js → node_modules_0qbfyjh._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1k7z2j6._.js → node_modules_0t-9nup._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_17bwo43._.js → node_modules_0tusx4d._.js} +3 -3
- package/.next/server/chunks/ssr/{node_modules_1chvq5f._.js → node_modules_0vsxbzp._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_04sksn9._.js → node_modules_0vv0-fg._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1k8j8n0._.js → node_modules_0wsvp00._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1lz0oxc._.js → node_modules_1-urho9._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1-y7nni._.js → node_modules_16pi_dd._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1uyk91w._.js → node_modules_1d53yiq._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0bvopy2._.js → node_modules_1g1eihe._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1a0kmjl._.js → node_modules_1gpednh._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0u9da1h._.js → node_modules_1gu1pph._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_056qgf-._.js → node_modules_1he1w8_._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0-dr_o7._.js → node_modules_1lnjapm._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1t77e4n._.js → node_modules_1lynj9m._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0x3-ply._.js → node_modules_1seuurl._.js} +2 -2
- package/.next/server/chunks/ssr/{node_modules_0ifp389._.js → node_modules_1u6w1pb._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1x0ztf4._.js → node_modules_1xn6saw._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0bkwd0u._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_067_exa._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0p9a9su._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0nrrdaq._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@vercel_oidc_dist_1o553h-._.js → node_modules_@vercel_oidc_dist_21a5haa._.js} +1 -1
- package/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_trash_mjs_0px2gzr._.js +3 -0
- 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 +68 -46
- package/.next/static/chunks/0dr16v67vj4n7.js +2 -0
- package/.next/static/chunks/0g4b348l0pve7.js +1 -0
- package/.next/static/chunks/0joan-69kbspd.js +1 -0
- package/.next/static/chunks/0vlgzqo9ka90v.js +1 -0
- package/.next/static/chunks/0zrupxgci5gqc.js +1 -0
- package/.next/static/chunks/10k2xvap03z20.css +1 -0
- package/.next/static/chunks/18mkhstgiqcbt.js +1 -0
- package/.next/static/chunks/{435atsnhs7ksu.js → 1i-u2wzub_to1.js} +7 -7
- package/.next/static/chunks/1kp5nfp06nj9h.js +5 -0
- package/.next/static/chunks/1ohslk4568tm3.js +1 -0
- package/.next/static/chunks/1sbmwswc9k2-1.js +1 -0
- package/.next/static/chunks/1t9qms5pwwa3n.js +1 -0
- package/.next/static/chunks/1vj_5bnbxx84e.js +1 -0
- package/.next/static/chunks/1vqezbhjm3goq.js +1 -0
- package/.next/static/chunks/{408ueu4hfvcg7.js → 1wlo979mx-y3w.js} +1 -1
- package/.next/static/chunks/26ql4y-43xwhp.js +1 -0
- package/.next/static/chunks/{11r2yp_yh9_qn.js → 2_pnccjp6j1ca.js} +1 -1
- package/.next/static/chunks/2a51-ywz9b2a3.js +1 -0
- package/.next/static/chunks/2fvdgxih7x7hr.js +1 -0
- package/.next/static/chunks/2jlz8zp4jax_m.js +18 -0
- package/.next/static/chunks/2nvepds1fu2ux.js +1 -0
- package/.next/static/chunks/3addj3i4-izma.js +1 -0
- package/.next/static/chunks/3bfwpww3m3x4u.js +1 -0
- package/.next/static/chunks/3gfh7nxwusbt0.js +1 -0
- package/.next/static/chunks/3gwa44cvz4qoi.js +1 -0
- package/.next/static/chunks/{38gweqdo4jpfj.js → 3izg0a3k87q1-.js} +5 -5
- package/.next/static/chunks/3zk6q3-3f9swq.js +99 -0
- package/.next/static/chunks/3zkg5iup3v4a2.js +12 -0
- package/.next/static/chunks/405m0bqtoihev.js +1 -0
- package/.next/static/chunks/42wcg3wfg_m_p.js +1 -0
- package/README.md +27 -216
- package/app/api/events/app-event.ts +6 -4
- package/app/api/query-key.ts +25 -16
- package/bin/database.mjs +37 -0
- package/bin/thursday.mjs +44 -28
- package/components/ui/custom-icon.tsx +0 -60
- package/components/ui/radio-group.tsx +37 -0
- package/components/ui/shiny-text.tsx +33 -6
- package/database/migrations/{20260910173049_numerous_spirit → 20260916145701_clever_multiple_man}/migration.sql +80 -24
- package/database/migrations/{20260910173049_numerous_spirit → 20260916145701_clever_multiple_man}/snapshot.json +689 -110
- package/database/migrations/20260916160713_thread_cancelled/migration.sql +2 -0
- package/database/migrations/{20260911030320_opposite_jack_power → 20260916160713_thread_cancelled}/snapshot.json +706 -84
- package/docs/how-it-works.md +39 -36
- package/docs/images/keeps-going.png +0 -0
- package/docs/images/two-minds.png +0 -0
- package/docs/live-calls.md +231 -0
- package/docs/thread-rooms.md +71 -0
- package/features/ai/chatgpt.ts +1 -2
- package/features/ai/live.schema.ts +128 -0
- package/features/ai/load-tools.ts +148 -77
- package/features/ai/model.schema.ts +2 -120
- package/features/ai/model.ts +52 -88
- package/features/ai/prompts/bot.prompt.ts +91 -214
- package/features/ai/prompts/live.prompt.ts +265 -0
- package/features/ai/prompts/prompt-helper.ts +91 -32
- package/features/ai/prompts/thursday.prompt.ts +125 -172
- package/features/ai/tools/bot.tool.ts +38 -145
- package/features/ai/tools/call.tool.ts +1 -1
- package/features/ai/tools/connected.ts +5 -3
- package/features/ai/tools/mcp.tool.ts +7 -4
- package/features/ai/tools/memory.tool.ts +35 -31
- package/features/ai/tools/skills.tool.ts +11 -6
- package/features/ai/tools/studio.tool.ts +26 -21
- package/features/ai/tools/tool-name.ts +2 -5
- package/features/ai/tools/workspace.tool.ts +33 -10
- package/features/artifact/artifact.action.ts +2 -2
- package/features/artifact/artifact.query.ts +112 -61
- package/features/artifact/artifact.schema.ts +8 -6
- package/features/artifact/components/artifact-setting.tsx +83 -33
- package/features/bot/bot.action.ts +43 -36
- package/features/bot/bot.memory.ts +137 -20
- package/features/bot/bot.query.ts +28 -11
- package/features/bot/bot.run.ts +296 -744
- package/features/bot/bot.runner.ts +461 -862
- package/features/bot/bot.schema.ts +93 -82
- package/features/bot/bot.seed.ts +141 -64
- package/features/bot/components/bot-mark.tsx +324 -232
- package/features/bot/components/bot-room.tsx +1613 -697
- package/features/bot/components/bot-roster.tsx +8 -13
- package/features/bot/components/bot-setting.tsx +58 -42
- package/features/bot/components/bot-tool.tsx +55 -87
- package/features/bot/components/mark-palette.tsx +35 -32
- package/features/bot/components/path-chips.tsx +33 -3
- package/features/bot/components/thread-badge.tsx +34 -0
- package/features/bot/components/thread-reply.tsx +639 -0
- package/features/bot/components/thread-setting.tsx +674 -0
- package/features/bot/mark.const.ts +79 -31
- package/features/bot/room.query.ts +889 -0
- package/features/bot/room.schema.ts +64 -0
- package/features/bot/seed-bots.ts +2 -1
- package/features/bot/thread.query.ts +971 -0
- package/features/bot/thread.store.ts +587 -0
- package/features/config/components/voice-key.tsx +113 -88
- package/features/config/config.const.ts +5 -9
- package/features/connectors/mcp.schema.ts +0 -2
- package/features/intro/components/intro.tsx +169 -139
- package/features/memory/components/memory-setting.tsx +2 -7
- package/features/memory/memory.schema.ts +14 -23
- package/features/settings/components/setting-ui.tsx +0 -44
- package/features/settings/components/settings.tsx +12 -12
- package/features/settings/settings.alert.ts +3 -3
- package/features/settings/settings.store.ts +1 -1
- package/features/skills/skills.schema.ts +0 -2
- package/features/thursday/components/ascii-field.tsx +24 -44
- package/features/thursday/components/ascii-orb.tsx +359 -358
- package/features/thursday/components/call-log.tsx +46 -44
- package/features/thursday/components/face.tsx +35 -10
- package/features/thursday/components/tab-state.tsx +3 -3
- package/features/thursday/components/thursday-mark.tsx +1 -0
- package/features/thursday/components/thursday-setting.tsx +631 -332
- package/features/thursday/components/thursday.tsx +106 -41
- package/features/thursday/components/voice-picker.tsx +255 -0
- package/features/thursday/thursday.action.ts +94 -68
- package/features/thursday/thursday.query.ts +49 -30
- package/features/thursday/thursday.schema.ts +27 -30
- package/features/thursday/thursday.store.ts +11 -7
- package/features/thursday/tool-call.ts +3 -3
- package/features/thursday/tool-line.ts +5 -3
- package/features/thursday/use-thursday.ts +725 -450
- package/features/workspace/workspace.query.ts +17 -0
- package/features/workspace/workspace.ts +82 -36
- package/lib/live/live.schema.ts +47 -0
- package/lib/live/live.server.ts +155 -0
- package/lib/live/live.session.ts +574 -0
- package/lib/{realtime/realtime.tap.ts → live/live.tap.ts} +41 -12
- package/lib/live/live.transport.ts +152 -0
- package/lib/protocol/use-server-pages.ts +9 -5
- package/lib/utils.ts +21 -20
- package/package.json +2 -2
- package/public/voices/alloy.ogg +0 -0
- package/public/voices/ash.ogg +0 -0
- package/public/voices/ballad.ogg +0 -0
- package/public/voices/beacon.ogg +0 -0
- package/public/voices/bossa.ogg +0 -0
- package/public/voices/cedar.ogg +0 -0
- package/public/voices/cinder.ogg +0 -0
- package/public/voices/coral.ogg +0 -0
- package/public/voices/delta.ogg +0 -0
- package/public/voices/echo.ogg +0 -0
- package/public/voices/gleam.ogg +0 -0
- package/public/voices/marin.ogg +0 -0
- package/public/voices/meridian.ogg +0 -0
- package/public/voices/quartz.ogg +0 -0
- package/public/voices/ripple.ogg +0 -0
- package/public/voices/sage.ogg +0 -0
- package/public/voices/shimmer.ogg +0 -0
- package/public/voices/stone.ogg +0 -0
- package/public/voices/tempo.ogg +0 -0
- package/public/voices/verse.ogg +0 -0
- package/public/voices/vesper.ogg +0 -0
- package/public/voices/willow.ogg +0 -0
- package/scripts/artifact-paths.test.mts +25 -0
- package/scripts/bot-context.test.mts +1408 -0
- package/scripts/live-history.test.mts +115 -0
- package/scripts/live-session.test.mts +948 -0
- package/server.js +1 -1
- package/skills/browser/SKILL.md +11 -1
- package/skills/computer/SKILL.md +1 -1
- package/skills/find-skills/SKILL.md +3 -8
- package/skills/interactive-page/SKILL.md +12 -7
- package/skills/interactive-page/references/diagram.md +89 -0
- package/skills/interactive-page/scripts/archify/LICENSE +22 -0
- package/skills/interactive-page/scripts/archify/README.md +25 -0
- package/skills/interactive-page/scripts/archify/assets/JetBrainsMono-OFL.txt +93 -0
- package/skills/interactive-page/scripts/archify/assets/template.html +14934 -0
- package/skills/interactive-page/scripts/archify/bin/archify.mjs +2126 -0
- package/skills/interactive-page/scripts/archify/bin/open-artifact.mjs +86 -0
- package/skills/interactive-page/scripts/archify/bin/preview.mjs +653 -0
- package/skills/interactive-page/scripts/archify/bin/visual-check.mjs +829 -0
- package/skills/interactive-page/scripts/archify/delta/architecture-delta.mjs +1223 -0
- package/skills/interactive-page/scripts/archify/examples/agent-run.lifecycle.json +60 -0
- package/skills/interactive-page/scripts/archify/examples/agent-tool-call.workflow.json +94 -0
- package/skills/interactive-page/scripts/archify/examples/async-job-roundtrip.sequence.json +61 -0
- package/skills/interactive-page/scripts/archify/examples/cache-miss-request.sequence.json +82 -0
- package/skills/interactive-page/scripts/archify/examples/checkout-platform.base.architecture.json +31 -0
- package/skills/interactive-page/scripts/archify/examples/checkout-platform.head.architecture.json +31 -0
- package/skills/interactive-page/scripts/archify/examples/deployment-release.lifecycle.json +49 -0
- package/skills/interactive-page/scripts/archify/examples/event-stream.dataflow.json +57 -0
- package/skills/interactive-page/scripts/archify/examples/incident-response.workflow.json +64 -0
- package/skills/interactive-page/scripts/archify/examples/product-analytics.dataflow.json +76 -0
- package/skills/interactive-page/scripts/archify/examples/production-deployment.architecture.json +71 -0
- package/skills/interactive-page/scripts/archify/examples/release-delivery.workflow.json +62 -0
- package/skills/interactive-page/scripts/archify/examples/web-app.architecture.json +46 -0
- package/skills/interactive-page/scripts/archify/migrations/workflow-v2.mjs +279 -0
- package/skills/interactive-page/scripts/archify/recipes/scenarios.mjs +284 -0
- package/skills/interactive-page/scripts/archify/references/authoring-contract.md +243 -0
- package/skills/interactive-page/scripts/archify/references/delivery-contract.md +120 -0
- package/skills/interactive-page/scripts/archify/references/viewer-runtime.md +45 -0
- package/skills/interactive-page/scripts/archify/renderers/architecture/grid.mjs +62 -0
- package/skills/interactive-page/scripts/archify/renderers/architecture/render-architecture.mjs +1078 -0
- package/skills/interactive-page/scripts/archify/renderers/dataflow/README.md +104 -0
- package/skills/interactive-page/scripts/archify/renderers/dataflow/render-dataflow.mjs +483 -0
- package/skills/interactive-page/scripts/archify/renderers/lifecycle/README.md +115 -0
- package/skills/interactive-page/scripts/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
- package/skills/interactive-page/scripts/archify/renderers/sequence/README.md +114 -0
- package/skills/interactive-page/scripts/archify/renderers/sequence/render-sequence.mjs +464 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/brand-marks.mjs +563 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/cli.mjs +218 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/desktop-readability.mjs +26 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/diagnostics.mjs +127 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/engineering-profiles.mjs +157 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/generated-brand-marks.mjs +3 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/generated-validators.mjs +13 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/geometry.mjs +1423 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/i18n.mjs +595 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/layout-report.mjs +40 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/legend.mjs +217 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/output-path.mjs +340 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/repository-evidence.mjs +238 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/repository-location.mjs +58 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/text-fit.mjs +49 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/utils.mjs +232 -0
- package/skills/interactive-page/scripts/archify/renderers/shared/validator.mjs +86 -0
- package/skills/interactive-page/scripts/archify/renderers/workflow/README.md +223 -0
- package/skills/interactive-page/scripts/archify/renderers/workflow/render-workflow.mjs +35 -0
- package/skills/interactive-page/scripts/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
- package/skills/interactive-page/scripts/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
- package/skills/interactive-page/scripts/archify/schemas/README.md +211 -0
- package/skills/interactive-page/scripts/archify/schemas/architecture.schema.json +178 -0
- package/skills/interactive-page/scripts/archify/schemas/common.schema.json +115 -0
- package/skills/interactive-page/scripts/archify/schemas/dataflow.schema.json +243 -0
- package/skills/interactive-page/scripts/archify/schemas/lifecycle.schema.json +266 -0
- package/skills/interactive-page/scripts/archify/schemas/sequence.schema.json +223 -0
- package/skills/interactive-page/scripts/archify/schemas/workflow.schema.json +428 -0
- package/skills/interactive-page/scripts/archify/scripts/check-render-output.mjs +916 -0
- package/skills/interactive-page/scripts/archify/scripts/render-examples.mjs +26 -0
- package/skills/interactive-page/scripts/bundle-artifact.sh +9 -8
- package/skills/skill-creator/SKILL.md +4 -5
- package/.next/server/app/api/bot/task/[id]/route/app-paths-manifest.json +0 -3
- package/.next/server/app/api/bot/task/[id]/route.js +0 -16
- package/.next/server/app/api/bot/task/[id]/route.js.nft.json +0 -1
- package/.next/server/app/api/bot/task/[id]/route_client-reference-manifest.js +0 -3
- package/.next/server/app/api/bot/task/route/app-paths-manifest.json +0 -3
- package/.next/server/app/api/bot/task/route.js +0 -16
- package/.next/server/app/api/bot/task/route.js.nft.json +0 -1
- package/.next/server/app/api/bot/task/route_client-reference-manifest.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__026u77e._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__02va5wz._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__050zri4._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0bg9710._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0ffbg85._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0in-d5s._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0ncs9uu._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0pa9k-f._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0qi_m0e._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0tq0m_k._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0xep6j_._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1-ga0kh._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__11n256_._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__144l7qt._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1anc1p9._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1fizn31._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1jg8t86._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1lldzy9._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1llj3-b._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1p8m3f4._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1peqvsi._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1w8gm5h._.js +0 -10
- package/.next/server/chunks/[root-of-the-server]__1xt39nn._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1zb8mfo._.js +0 -8
- package/.next/server/chunks/_0-73of8._.js +0 -55
- package/.next/server/chunks/_0-fjql4._.js +0 -31
- package/.next/server/chunks/_00xh_q0._.js +0 -25
- package/.next/server/chunks/_051qh8u._.js +0 -3
- package/.next/server/chunks/_05sovvj._.js +0 -3
- package/.next/server/chunks/_091bi8d._.js +0 -3
- package/.next/server/chunks/_0fzqt2y._.js +0 -142
- package/.next/server/chunks/_0lr92vd._.js +0 -3
- package/.next/server/chunks/_0mecv0f._.js +0 -31
- package/.next/server/chunks/_0mh8j4m._.js +0 -3
- package/.next/server/chunks/_0sb7tlz._.js +0 -3
- package/.next/server/chunks/_0si7xzn._.js +0 -3
- package/.next/server/chunks/_0u10wmw._.js +0 -55
- package/.next/server/chunks/_0wp4le3._.js +0 -3
- package/.next/server/chunks/_0y5fg-x._.js +0 -3
- package/.next/server/chunks/_1230wbx._.js +0 -10
- package/.next/server/chunks/_12nheja._.js +0 -3
- package/.next/server/chunks/_13510xh._.js +0 -3
- package/.next/server/chunks/_15hq89o._.js +0 -3
- package/.next/server/chunks/_18-1wcc._.js +0 -55
- package/.next/server/chunks/_18d7-5p._.js +0 -3
- package/.next/server/chunks/_1c78vw5._.js +0 -237
- package/.next/server/chunks/_1h5_8sk._.js +0 -3
- package/.next/server/chunks/_1hdnxb7._.js +0 -3
- package/.next/server/chunks/_1j8k_j5._.js +0 -3
- package/.next/server/chunks/_1nula3v._.js +0 -3
- package/.next/server/chunks/_1php4eq._.js +0 -3
- package/.next/server/chunks/_1yuv4vp._.js +0 -3
- package/.next/server/chunks/_1zkfbaa._.js +0 -3
- package/.next/server/chunks/_next-internal_server_app_api_bot_task_[id]_route_actions_1_k_8u3.js +0 -3
- package/.next/server/chunks/_next-internal_server_app_api_bot_task_route_actions_0xln6ra.js +0 -3
- package/.next/server/chunks/features_0rpfxbk._.js +0 -3
- package/.next/server/chunks/features_1qf3cei._.js +0 -8
- package/.next/server/chunks/features_bot_0zt92oh._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1jidylq._.js +0 -3
- package/.next/server/chunks/ssr/[externals]__0dizgek._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0-nob52._.js +0 -4
- package/.next/server/chunks/ssr/[root-of-the-server]__092knlj._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0mz33a7._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0s4wb56._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0s9dq5u._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0sd3izg._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0vnmv-s._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1-13tcn._.js +0 -43
- package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +0 -61
- package/.next/server/chunks/ssr/[root-of-the-server]__1zidpfl._.js +0 -3
- package/.next/server/chunks/ssr/_001_ms1._.js +0 -33
- package/.next/server/chunks/ssr/_01n3o0m._.js +0 -3
- package/.next/server/chunks/ssr/_04z2c7b._.js +0 -3
- package/.next/server/chunks/ssr/_06tssji._.js +0 -3
- package/.next/server/chunks/ssr/_0fk4c7d._.js +0 -3
- package/.next/server/chunks/ssr/_0h42fze._.js +0 -3
- package/.next/server/chunks/ssr/_0h7zdni._.js +0 -3
- package/.next/server/chunks/ssr/_0m2lsd1._.js +0 -3
- package/.next/server/chunks/ssr/_0mggveb._.js +0 -3
- package/.next/server/chunks/ssr/_0nbpc_8._.js +0 -3
- package/.next/server/chunks/ssr/_0q0zan6._.js +0 -70
- package/.next/server/chunks/ssr/_0zcjrbg._.js +0 -3
- package/.next/server/chunks/ssr/_0zhoc3r._.js +0 -3
- package/.next/server/chunks/ssr/_11j92tu._.js +0 -3
- package/.next/server/chunks/ssr/_13fke0x._.js +0 -3
- package/.next/server/chunks/ssr/_18cymkq._.js +0 -3
- package/.next/server/chunks/ssr/_1ebxla1._.js +0 -3
- package/.next/server/chunks/ssr/_1nj4niv._.js +0 -42
- package/.next/server/chunks/ssr/_1ov37if._.js +0 -3
- package/.next/server/chunks/ssr/_1ovmc9s._.js +0 -3
- package/.next/server/chunks/ssr/_1sji22n._.js +0 -3
- package/.next/server/chunks/ssr/_1vi_uo7._.js +0 -3
- package/.next/server/chunks/ssr/_1vyd1ji._.js +0 -3
- package/.next/server/chunks/ssr/_1xx4zlb._.js +0 -3
- package/.next/server/chunks/ssr/components_ui_1y1l7yj._.js +0 -3
- package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +0 -3
- package/.next/server/chunks/ssr/lib_realtime_12wg_dd._.js +0 -27
- package/.next/server/chunks/ssr/lib_realtime_15h_v1v._.js +0 -27
- package/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0npjf8-._.js +0 -3
- package/.next/static/chunks/0n3jle9kbqfr2.js +0 -40
- package/.next/static/chunks/0r5qcctujhxli.js +0 -1
- package/.next/static/chunks/10teww7wt-f6h.js +0 -1
- package/.next/static/chunks/126fj4pga_72k.js +0 -1
- package/.next/static/chunks/159udiexf6dom.js +0 -2
- package/.next/static/chunks/18a96rkhi4_yd.js +0 -1
- package/.next/static/chunks/18gi7o2ibrgh8.js +0 -3
- package/.next/static/chunks/1dkjg87pxk0n9.js +0 -28
- package/.next/static/chunks/1q9z1tohil7xn.js +0 -1
- package/.next/static/chunks/1sjgfets224re.js +0 -1
- package/.next/static/chunks/1wszsr83t01gh.js +0 -1
- package/.next/static/chunks/22_zkas21rpna.js +0 -1
- package/.next/static/chunks/2fh4-3z_q8b_w.js +0 -1
- package/.next/static/chunks/2h0sd2vumhb15.js +0 -1
- package/.next/static/chunks/2szintyibu0s5.js +0 -1
- package/.next/static/chunks/2t4vhi3m8ahya.js +0 -1
- package/.next/static/chunks/2tigdtz3dpcy8.js +0 -1
- package/.next/static/chunks/3-b6b7entqazs.js +0 -1
- package/.next/static/chunks/3786h5vayt80-.js +0 -28
- package/.next/static/chunks/3cq5g494yuke8.css +0 -1
- package/.next/static/chunks/3dmbhsv2u_8kj.js +0 -1
- package/.next/static/chunks/3hibbjnt85-k6.js +0 -1
- package/.next/static/chunks/3i0a5px-oufgc.js +0 -1
- package/.next/static/chunks/3wexk9qo8zuj3.js +0 -18
- package/.next/static/chunks/3xk7yqgomx7yq.js +0 -1
- package/.next/static/chunks/3xre8bu_pk1p_.js +0 -1
- package/.next/static/chunks/3zv6t3i77xhr_.js +0 -1
- package/database/migrations/20260911030320_opposite_jack_power/migration.sql +0 -1
- package/docs/images/task-thread.png +0 -0
- package/features/bot/components/task-badge.tsx +0 -42
- package/features/bot/components/task-reply.tsx +0 -328
- package/features/bot/components/task-setting.tsx +0 -524
- package/features/bot/task.query.ts +0 -1079
- package/features/bot/task.store.ts +0 -487
- package/lib/realtime/client-secret.ts +0 -86
- package/lib/realtime/open-session.ts +0 -31
- package/lib/realtime/openai.ts +0 -35
- package/lib/realtime/realtime.audio.ts +0 -196
- package/lib/realtime/realtime.driver.ts +0 -489
- package/lib/realtime/realtime.protocol.ts +0 -393
- package/lib/realtime/realtime.schema.ts +0 -37
- package/lib/realtime/realtime.session.ts +0 -106
- package/lib/realtime/realtime.transport.ts +0 -384
- package/lib/realtime/xai.ts +0 -39
- /package/.next/server/app/api/bot/{task → thread}/[id]/route/build-manifest.json +0 -0
- /package/.next/server/app/api/bot/{task → thread}/[id]/route/server-reference-manifest.json +0 -0
- /package/.next/server/app/api/bot/{task → thread}/[id]/route.js.map +0 -0
- /package/.next/server/app/api/bot/{task → thread}/route/build-manifest.json +0 -0
- /package/.next/server/app/api/bot/{task → thread}/route/server-reference-manifest.json +0 -0
- /package/.next/server/app/api/bot/{task → thread}/route.js.map +0 -0
- /package/.next/static/{G6-gNoyGDEcgAsq-L4PE1 → 0qzGoKn2wTERVZtblX1tp}/_buildManifest.js +0 -0
- /package/.next/static/{G6-gNoyGDEcgAsq-L4PE1 → 0qzGoKn2wTERVZtblX1tp}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{G6-gNoyGDEcgAsq-L4PE1 → 0qzGoKn2wTERVZtblX1tp}/_ssgManifest.js +0 -0
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useEffect, useId, useMemo, useRef } from "react";
|
|
4
|
-
import { createVoiceFollower } from "@/lib/
|
|
5
|
-
import {
|
|
4
|
+
import { createVoiceFollower, SPECTRUM_BANDS } from "@/lib/live/live.tap";
|
|
5
|
+
import {
|
|
6
|
+
MARK_PAINTS,
|
|
7
|
+
type MarkPaint,
|
|
8
|
+
type MarkPaintLook,
|
|
9
|
+
type MarkPaintSpec,
|
|
10
|
+
type MarkShape,
|
|
11
|
+
} from "../mark.const";
|
|
6
12
|
|
|
7
13
|
// Procedural bot avatar: a generated silhouette with two eyes, animated per frame from refs.
|
|
8
14
|
|
|
@@ -121,6 +127,22 @@ function polyOutline(sides: number, cornerRatio: number, rotDeg: number): Pt[] {
|
|
|
121
127
|
return out;
|
|
122
128
|
}
|
|
123
129
|
|
|
130
|
+
/** The classic heart curve, a little taller than wide. */
|
|
131
|
+
function heartOutline(): Pt[] {
|
|
132
|
+
const out: Pt[] = [];
|
|
133
|
+
for (let i = 0; i < 400; i++) {
|
|
134
|
+
const t = (i / 400) * TAU;
|
|
135
|
+
const x = 16 * Math.sin(t) ** 3;
|
|
136
|
+
const y =
|
|
137
|
+
13 * Math.cos(t) -
|
|
138
|
+
5 * Math.cos(2 * t) -
|
|
139
|
+
2 * Math.cos(3 * t) -
|
|
140
|
+
Math.cos(4 * t);
|
|
141
|
+
out.push([CENTER + x * 6.6, CENTER - (y + 2.2) * 7.26]);
|
|
142
|
+
}
|
|
143
|
+
return out;
|
|
144
|
+
}
|
|
145
|
+
|
|
124
146
|
function sub(a: Pt, b: Pt): Pt {
|
|
125
147
|
return [a[0] - b[0], a[1] - b[1]];
|
|
126
148
|
}
|
|
@@ -266,38 +288,23 @@ export type MarkOptions = {
|
|
|
266
288
|
stretch: number;
|
|
267
289
|
idle: boolean;
|
|
268
290
|
liveliness: number;
|
|
269
|
-
glance: number;
|
|
270
291
|
float: number;
|
|
271
292
|
breathe: number;
|
|
272
293
|
speed: number;
|
|
273
294
|
blink: boolean;
|
|
274
295
|
|
|
275
|
-
/** Peak opacity of the soft shadow that swells under the mark while thinking, percent. 0 disables. */
|
|
276
|
-
shadow: number;
|
|
277
|
-
/** Soft halo around the silhouette, cut out of the head; blur radius in view-box units. 0 disables. */
|
|
278
|
-
glow: number;
|
|
279
|
-
/** Aura color. null follows the mark color. */
|
|
280
|
-
glowColor: string | null;
|
|
281
|
-
/** Aura opacity, percent. */
|
|
282
|
-
glowStrength: number;
|
|
283
|
-
/** Border around the silhouette so it still reads on a same-colored background. 0 disables. */
|
|
284
|
-
rim: number;
|
|
285
|
-
/** Defaults to the theme text color, the one color guaranteed to differ from the background. */
|
|
286
|
-
rimColor: string;
|
|
287
|
-
|
|
288
296
|
notify: boolean;
|
|
289
297
|
notifyAngle: number;
|
|
290
298
|
notifyDist: number;
|
|
291
299
|
notifyR: number;
|
|
292
300
|
notifyRing: number;
|
|
293
|
-
notifyColor: string;
|
|
294
301
|
};
|
|
295
302
|
|
|
296
303
|
const MARK_DEFAULTS: MarkOptions = {
|
|
297
304
|
shape: "blob",
|
|
298
305
|
sides: 3,
|
|
299
306
|
corner: 0.74,
|
|
300
|
-
rotation:
|
|
307
|
+
rotation: 0,
|
|
301
308
|
squircle: 4.6,
|
|
302
309
|
wobble: 0.2,
|
|
303
310
|
seed: 113,
|
|
@@ -328,53 +335,18 @@ const MARK_DEFAULTS: MarkOptions = {
|
|
|
328
335
|
stretch: 15,
|
|
329
336
|
idle: true,
|
|
330
337
|
liveliness: 55,
|
|
331
|
-
glance: 22,
|
|
332
338
|
float: 7,
|
|
333
339
|
breathe: 3.7,
|
|
334
340
|
speed: 1.7,
|
|
335
341
|
blink: true,
|
|
336
342
|
|
|
337
|
-
shadow: 16,
|
|
338
|
-
glow: 0,
|
|
339
|
-
glowColor: null,
|
|
340
|
-
glowStrength: 55,
|
|
341
|
-
rim: 0,
|
|
342
|
-
rimColor: "currentColor",
|
|
343
|
-
|
|
344
343
|
notify: false,
|
|
345
344
|
notifyAngle: 41,
|
|
346
345
|
notifyDist: 109,
|
|
347
346
|
notifyR: 25,
|
|
348
347
|
notifyRing: 11,
|
|
349
|
-
notifyColor: "#FF3B30",
|
|
350
348
|
};
|
|
351
349
|
|
|
352
|
-
/* Per-instance variation: shape and color stay, only the values inside the shape roll
|
|
353
|
-
* from a seed the caller picks (task id for one face per task, bot name for one per bot). */
|
|
354
|
-
const VARY = {
|
|
355
|
-
/** Blob depth. The seed already changes the whole silhouette, so keep this slight. */
|
|
356
|
-
wobble: [0.8, 1.35],
|
|
357
|
-
/** Poly. Below 0.45 it rounds into a circle. */
|
|
358
|
-
corner: [0.45, 0.77],
|
|
359
|
-
rotation: [-180, 180],
|
|
360
|
-
/** Squircle. 4 is nearly square, 12 nearly round. */
|
|
361
|
-
squircle: [4, 12],
|
|
362
|
-
} as const satisfies Record<string, readonly [number, number]>;
|
|
363
|
-
|
|
364
|
-
/** Roll order defines what a seed means; reordering changes every bot's face. */
|
|
365
|
-
function varyOptions(cfg: MarkOptions, seed: number): MarkOptions {
|
|
366
|
-
if (!seed) return cfg;
|
|
367
|
-
const rnd = mulberry32(seed);
|
|
368
|
-
const pick = ([lo, hi]: readonly [number, number]) => lo + rnd() * (hi - lo);
|
|
369
|
-
return {
|
|
370
|
-
...cfg,
|
|
371
|
-
wobble: cfg.wobble * pick(VARY.wobble),
|
|
372
|
-
corner: pick(VARY.corner),
|
|
373
|
-
rotation: pick(VARY.rotation),
|
|
374
|
-
squircle: pick(VARY.squircle),
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
|
|
378
350
|
/** Silhouettes are scaled to the area of the circle of radius R so they read the same size,
|
|
379
351
|
* capped so sharp corners stay inside the view box. */
|
|
380
352
|
const FIT_LIMIT = 130;
|
|
@@ -400,7 +372,7 @@ function fitRadii(radii: number[]): number[] {
|
|
|
400
372
|
const WARP = 0.035;
|
|
401
373
|
|
|
402
374
|
/** Bends a ruled outline by a few slow waves. Blob outlines already wobble and are left alone. */
|
|
403
|
-
function warpRadii(radii: number[], seed: number): number[] {
|
|
375
|
+
function warpRadii(radii: number[], seed: number, depth = WARP): number[] {
|
|
404
376
|
const rnd = mulberry32(seed ^ 0x2f6b);
|
|
405
377
|
const waves = [2, 3, 5].map((k) => ({
|
|
406
378
|
k,
|
|
@@ -414,7 +386,33 @@ function warpRadii(radii: number[], seed: number): number[] {
|
|
|
414
386
|
return d;
|
|
415
387
|
});
|
|
416
388
|
const peak = Math.max(...offsets.map(Math.abs)) || 1;
|
|
417
|
-
return radii.map((r, i) => r * (1 + (
|
|
389
|
+
return radii.map((r, i) => r * (1 + (depth * offsets[i]) / peak));
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* A true heart has the only sharp tip and deep notch of any mark. Averaging the
|
|
394
|
+
* radii blunts both, then it bends and leans by the seed like poly and squircle
|
|
395
|
+
* do, a little more.
|
|
396
|
+
*/
|
|
397
|
+
function softenHeart(radii: number[], seed: number): number[] {
|
|
398
|
+
let soft = radii;
|
|
399
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
400
|
+
const prev = soft;
|
|
401
|
+
soft = prev.map((_, i) => {
|
|
402
|
+
let sum = 0;
|
|
403
|
+
for (let k = -3; k <= 3; k++) sum += prev[(i + k + RES) % RES];
|
|
404
|
+
return sum / 7;
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
const mean = soft.reduce((sum, r) => sum + r, 0) / RES;
|
|
408
|
+
const bent = warpRadii(
|
|
409
|
+
soft.map((r) => r * 0.95 + mean * 0.05),
|
|
410
|
+
seed,
|
|
411
|
+
0.05,
|
|
412
|
+
);
|
|
413
|
+
// A few degrees of lean, one sample at a time.
|
|
414
|
+
const lean = Math.round((mulberry32(seed ^ 0x51f1)() * 2 - 1) * 3);
|
|
415
|
+
return lean ? bent.map((_, i) => bent[(i - lean + RES * 2) % RES]) : bent;
|
|
418
416
|
}
|
|
419
417
|
|
|
420
418
|
const radiiCache = new Map<string, number[]>();
|
|
@@ -426,12 +424,19 @@ function radiiFor(cfg: MarkOptions, shape: MarkShape, seed: number): number[] {
|
|
|
426
424
|
? `poly|${cfg.sides}|${cfg.corner}|${cfg.rotation}|${seed}`
|
|
427
425
|
: shape === "squircle"
|
|
428
426
|
? `squircle|${cfg.squircle}|${seed}`
|
|
429
|
-
:
|
|
427
|
+
: shape === "heart"
|
|
428
|
+
? `heart|${seed}`
|
|
429
|
+
: `blob|${cfg.wobble}|${seed}`
|
|
430
430
|
}|${cfg.autofit}`;
|
|
431
431
|
const hit = radiiCache.get(key);
|
|
432
432
|
if (hit) return hit;
|
|
433
433
|
const traced = toRadii(outlineFor(cfg, shape, seed));
|
|
434
|
-
const raw =
|
|
434
|
+
const raw =
|
|
435
|
+
shape === "blob"
|
|
436
|
+
? traced
|
|
437
|
+
: shape === "heart"
|
|
438
|
+
? softenHeart(traced, seed)
|
|
439
|
+
: warpRadii(traced, seed);
|
|
435
440
|
const radii = cfg.autofit ? fitRadii(raw) : raw;
|
|
436
441
|
if (radiiCache.size > 400) radiiCache.clear();
|
|
437
442
|
radiiCache.set(key, radii);
|
|
@@ -441,9 +446,82 @@ function radiiFor(cfg: MarkOptions, shape: MarkShape, seed: number): number[] {
|
|
|
441
446
|
function outlineFor(cfg: MarkOptions, shape: MarkShape, seed: number): Pt[] {
|
|
442
447
|
if (shape === "squircle") return squircleOutline(cfg.squircle);
|
|
443
448
|
if (shape === "poly") return polyOutline(cfg.sides, cfg.corner, cfg.rotation);
|
|
449
|
+
if (shape === "heart") return heartOutline();
|
|
444
450
|
return blobOutline(seed, cfg.wobble);
|
|
445
451
|
}
|
|
446
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Where a mark sits between the smallest the app draws (14px, 0) and the bot
|
|
455
|
+
* page's 112px (1). The SVG scales evenly, but a small face has fewer pixels for
|
|
456
|
+
* each band, so paints and a crossed-out X are drawn denser as this falls.
|
|
457
|
+
*/
|
|
458
|
+
const growOf = (size: number) => clamp((size - 14) / 98, 0, 1);
|
|
459
|
+
|
|
460
|
+
/** One run of the sliding rainbow: shorter on small marks, so more of its colours fit. */
|
|
461
|
+
const spanOf = (grow: number) => 345 * (0.7 + 0.3 * grow);
|
|
462
|
+
|
|
463
|
+
/** Where each look's gradient runs, in the 240-unit box. */
|
|
464
|
+
function paintAxis(
|
|
465
|
+
look: MarkPaintLook,
|
|
466
|
+
grow: number,
|
|
467
|
+
): Pick<
|
|
468
|
+
React.SVGProps<SVGLinearGradientElement>,
|
|
469
|
+
"gradientUnits" | "x1" | "y1" | "x2" | "y2" | "spreadMethod"
|
|
470
|
+
> {
|
|
471
|
+
if (look === "flow") {
|
|
472
|
+
return {
|
|
473
|
+
gradientUnits: "userSpaceOnUse",
|
|
474
|
+
x1: 0,
|
|
475
|
+
y1: 0,
|
|
476
|
+
x2: spanOf(grow),
|
|
477
|
+
y2: 0,
|
|
478
|
+
spreadMethod: "repeat",
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
// In box units like the rest, so the wider blurred layer wears the same ramp as the head.
|
|
482
|
+
return {
|
|
483
|
+
gradientUnits: "userSpaceOnUse",
|
|
484
|
+
x1: 0,
|
|
485
|
+
y1: 0,
|
|
486
|
+
x2: look === "duo" ? BOX : 0,
|
|
487
|
+
y2: BOX,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/** A paint's stops. Aurora's gradient is only its night. */
|
|
492
|
+
function paintStops({
|
|
493
|
+
look,
|
|
494
|
+
colors,
|
|
495
|
+
}: MarkPaintSpec): { offset: number; color: string }[] {
|
|
496
|
+
const used = look === "aurora" ? colors.slice(0, 2) : colors;
|
|
497
|
+
return used.map((color, i) => ({ offset: i / (used.length - 1), color }));
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/** Aurora's curtains: where each hangs, how far it sways and how long one sway takes (s). */
|
|
501
|
+
const CURTAINS = [
|
|
502
|
+
{ cx: 42, sway: 40, period: 5 },
|
|
503
|
+
{ cx: 134, sway: -35, period: 6.5 },
|
|
504
|
+
{ cx: 209, sway: 29, period: 4.5 },
|
|
505
|
+
];
|
|
506
|
+
const CURTAIN_Y = 91;
|
|
507
|
+
/** Curtains grow broader and softer on small marks, so they read as a glow, not a stripe. */
|
|
508
|
+
const curtainRxOf = (grow: number) => 60 - 29 * grow;
|
|
509
|
+
const curtainBlurOf = (grow: number) => 34 - 12 * grow;
|
|
510
|
+
|
|
511
|
+
/** Below this relative luminance a body sinks into a dark page. */
|
|
512
|
+
const DARK_BODY = 0.06;
|
|
513
|
+
|
|
514
|
+
/** Relative luminance of a #rrggbb colour; null for anything else (currentColor follows the theme). */
|
|
515
|
+
function luminance(color: string): number | null {
|
|
516
|
+
const hex = /^#([0-9a-f]{6})$/i.exec(color);
|
|
517
|
+
if (!hex) return null;
|
|
518
|
+
const channel = (at: number) => {
|
|
519
|
+
const c = Number.parseInt(hex[1].slice(at, at + 2), 16) / 255;
|
|
520
|
+
return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
|
521
|
+
};
|
|
522
|
+
return 0.2126 * channel(0) + 0.7152 * channel(2) + 0.0722 * channel(4);
|
|
523
|
+
}
|
|
524
|
+
|
|
447
525
|
/* Idle beats: small unrelated motions picked at random, weighted by state. Each returns
|
|
448
526
|
* per-frame channel offsets for progress p in 0..1 and a direction. `eyeLen`/`eyeWid`
|
|
449
527
|
* scale along the eye's own axis, so they still mean shorter/wider when the eye is tilted. */
|
|
@@ -762,8 +840,6 @@ type StateShape = {
|
|
|
762
840
|
/** Constant gaze offset, box units, on top of pointer tracking and drift. */
|
|
763
841
|
gazeX: number;
|
|
764
842
|
gazeY: number;
|
|
765
|
-
/** 1 lets the shadow through, 0 blocks it; eased like the other channels. */
|
|
766
|
-
shadow: number;
|
|
767
843
|
};
|
|
768
844
|
|
|
769
845
|
/** Resting-pose targets per state. */
|
|
@@ -777,7 +853,6 @@ const STATE_SHAPE: Record<MarkState, StateShape> = {
|
|
|
777
853
|
breathe: 1,
|
|
778
854
|
float: 1,
|
|
779
855
|
blink: 1,
|
|
780
|
-
shadow: 0,
|
|
781
856
|
lean: 0,
|
|
782
857
|
aspect: 1,
|
|
783
858
|
gazeX: 0,
|
|
@@ -792,7 +867,6 @@ const STATE_SHAPE: Record<MarkState, StateShape> = {
|
|
|
792
867
|
breathe: 2.2,
|
|
793
868
|
float: 0.6,
|
|
794
869
|
blink: 0.6,
|
|
795
|
-
shadow: 0,
|
|
796
870
|
lean: 0,
|
|
797
871
|
aspect: 1.03,
|
|
798
872
|
gazeX: 0,
|
|
@@ -807,7 +881,6 @@ const STATE_SHAPE: Record<MarkState, StateShape> = {
|
|
|
807
881
|
breathe: 0.45,
|
|
808
882
|
float: 0.35,
|
|
809
883
|
blink: 1.8,
|
|
810
|
-
shadow: 0,
|
|
811
884
|
lean: 0,
|
|
812
885
|
aspect: 0.97,
|
|
813
886
|
gazeX: 0,
|
|
@@ -822,7 +895,6 @@ const STATE_SHAPE: Record<MarkState, StateShape> = {
|
|
|
822
895
|
breathe: 1.3,
|
|
823
896
|
float: 1.4,
|
|
824
897
|
blink: 0.8,
|
|
825
|
-
shadow: 1,
|
|
826
898
|
lean: 7,
|
|
827
899
|
aspect: 1.04,
|
|
828
900
|
gazeX: -9,
|
|
@@ -837,7 +909,6 @@ const STATE_SHAPE: Record<MarkState, StateShape> = {
|
|
|
837
909
|
breathe: 0.6,
|
|
838
910
|
float: 0.5,
|
|
839
911
|
blink: 1.3,
|
|
840
|
-
shadow: 0,
|
|
841
912
|
lean: -6,
|
|
842
913
|
aspect: 1,
|
|
843
914
|
gazeX: 15,
|
|
@@ -854,7 +925,6 @@ const STATE_SHAPE: Record<MarkState, StateShape> = {
|
|
|
854
925
|
breathe: 0.4,
|
|
855
926
|
float: 0.5,
|
|
856
927
|
blink: 1.2,
|
|
857
|
-
shadow: 0,
|
|
858
928
|
lean: 0,
|
|
859
929
|
aspect: 1,
|
|
860
930
|
gazeX: 0,
|
|
@@ -863,7 +933,7 @@ const STATE_SHAPE: Record<MarkState, StateShape> = {
|
|
|
863
933
|
};
|
|
864
934
|
|
|
865
935
|
/** What the follower reads while the mark is not speaking. */
|
|
866
|
-
const SILENT: number[] = new Array<number>(
|
|
936
|
+
const SILENT: number[] = new Array<number>(SPECTRUM_BANDS).fill(0);
|
|
867
937
|
|
|
868
938
|
/**
|
|
869
939
|
* Milliseconds to the next blink, irregular the way a person's are: mostly a
|
|
@@ -902,23 +972,19 @@ export type BotMarkProps = {
|
|
|
902
972
|
seed?: number | string;
|
|
903
973
|
color?: string;
|
|
904
974
|
shape?: MarkShape;
|
|
905
|
-
/**
|
|
906
|
-
* Nudges this instance's silhouette (VARY) while keeping shape and color. A value is
|
|
907
|
-
* the seed (task id or bot name); `true` uses useId so server and client agree.
|
|
908
|
-
*/
|
|
909
|
-
vary?: boolean | number | string;
|
|
910
975
|
/** Stroke instead of fill; same as `options.fill: false`. */
|
|
911
976
|
outline?: boolean;
|
|
977
|
+
/** A paint (MARK_PAINTS) worn in place of `color`. */
|
|
978
|
+
paint?: MarkPaint;
|
|
912
979
|
notify?: boolean;
|
|
980
|
+
/** Eyes crossed out: a stopped thread, or a call that failed. */
|
|
981
|
+
crossed?: boolean;
|
|
913
982
|
state?: MarkState;
|
|
914
|
-
/**
|
|
915
|
-
getLevel?: () => number;
|
|
916
|
-
/** MARK_BANDS values in 0..1, low frequencies first, read once per frame. Where the energy sits sets the shape, how much sets the size. */
|
|
983
|
+
/** SPECTRUM_BANDS values in 0..1, low frequencies first, read once per frame. Where the energy sits sets the shape, how much sets the size. */
|
|
917
984
|
getSpectrum?: () => ArrayLike<number>;
|
|
918
985
|
/** Per-instance overrides; omitted keys fall back to MARK_DEFAULTS. Pass a stable object, a new literal each render re-derives the silhouette. */
|
|
919
986
|
options?: Partial<MarkOptions>;
|
|
920
987
|
className?: string;
|
|
921
|
-
svgRef?: React.RefObject<SVGSVGElement | null>;
|
|
922
988
|
};
|
|
923
989
|
|
|
924
990
|
/** Cheap string hash so a name or id can seed the mark. */
|
|
@@ -936,62 +1002,56 @@ export function BotMark({
|
|
|
936
1002
|
seed,
|
|
937
1003
|
color,
|
|
938
1004
|
shape,
|
|
939
|
-
vary,
|
|
940
1005
|
outline,
|
|
1006
|
+
paint,
|
|
941
1007
|
notify,
|
|
1008
|
+
crossed,
|
|
942
1009
|
state = "idle",
|
|
943
|
-
getLevel,
|
|
944
1010
|
getSpectrum,
|
|
945
1011
|
options,
|
|
946
1012
|
className,
|
|
947
|
-
svgRef,
|
|
948
1013
|
}: BotMarkProps) {
|
|
949
1014
|
const clipId = useId();
|
|
950
|
-
// 0 means no variation. `true` falls back to useId, the only per-instance value
|
|
951
|
-
// server and client agree on.
|
|
952
|
-
const varySeed = useMemo(() => {
|
|
953
|
-
if (vary === undefined || vary === false) return 0;
|
|
954
|
-
return hashSeed(vary === true ? clipId : vary) || 1;
|
|
955
|
-
}, [vary, clipId]);
|
|
956
1015
|
const cfg = useMemo(
|
|
957
1016
|
() =>
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
varySeed,
|
|
965
|
-
),
|
|
966
|
-
[options, outline, varySeed],
|
|
1017
|
+
({
|
|
1018
|
+
...MARK_DEFAULTS,
|
|
1019
|
+
...options,
|
|
1020
|
+
...(outline === undefined ? {} : { fill: !outline }),
|
|
1021
|
+
}) as MarkOptions,
|
|
1022
|
+
[options, outline],
|
|
967
1023
|
);
|
|
968
|
-
const glowId = `${clipId}-glow`;
|
|
969
|
-
const haloId = `${clipId}-halo`;
|
|
970
1024
|
const maskId = `${clipId}-mask`;
|
|
971
|
-
const
|
|
1025
|
+
const paintId = `${clipId}-paint`;
|
|
1026
|
+
const curtainId = `${clipId}-curtain`;
|
|
972
1027
|
const lifeRef = useRef<SVGGElement>(null);
|
|
973
1028
|
const eyesRef = useRef<SVGGElement>(null);
|
|
974
1029
|
const headRef = useRef<SVGPathElement>(null);
|
|
975
1030
|
const clipRef = useRef<SVGPathElement>(null);
|
|
976
1031
|
const eyeLRef = useRef<SVGGElement>(null);
|
|
977
1032
|
const eyeRRef = useRef<SVGGElement>(null);
|
|
978
|
-
const glowRef = useRef<SVGPathElement>(null);
|
|
979
|
-
const haloHeadRef = useRef<SVGPathElement>(null);
|
|
980
|
-
const shadowRef = useRef<SVGPathElement>(null);
|
|
981
1033
|
const maskHeadRef = useRef<SVGPathElement>(null);
|
|
982
|
-
const
|
|
983
|
-
const
|
|
984
|
-
const
|
|
985
|
-
|
|
986
|
-
const
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
const shapeSeed =
|
|
990
|
-
? ((theSeed ^ Math.imul(varySeed, 0x9e3779b1)) >>> 0) % 10000
|
|
991
|
-
: theSeed;
|
|
1034
|
+
const paintRef = useRef<SVGLinearGradientElement>(null);
|
|
1035
|
+
const curtainRefs = useRef<(SVGEllipseElement | null)[]>([]);
|
|
1036
|
+
const inkEyesRef = useRef<SVGGElement>(null);
|
|
1037
|
+
const inkEyeLRef = useRef<SVGGElement>(null);
|
|
1038
|
+
const inkEyeRRef = useRef<SVGGElement>(null);
|
|
1039
|
+
const svgRef = useRef<SVGSVGElement>(null);
|
|
1040
|
+
|
|
1041
|
+
const shapeSeed = seed === undefined ? cfg.seed : hashSeed(seed);
|
|
992
1042
|
const theShape = shape ?? cfg.shape;
|
|
993
1043
|
const theFg = color ?? cfg.color;
|
|
994
1044
|
const notifying = notify ?? cfg.notify;
|
|
1045
|
+
const spec = paint ? MARK_PAINTS[paint] : null;
|
|
1046
|
+
const grow = growOf(size);
|
|
1047
|
+
// A dark body draws its eyes: as holes they show the dark page it sinks into.
|
|
1048
|
+
const edge = spec
|
|
1049
|
+
? "edge" in spec
|
|
1050
|
+
? spec.edge
|
|
1051
|
+
: null
|
|
1052
|
+
: (luminance(theFg) ?? 1) < DARK_BODY
|
|
1053
|
+
? "dark"
|
|
1054
|
+
: null;
|
|
995
1055
|
|
|
996
1056
|
// While deforming, the head is redrawn per frame; memo only seeds the initial `d`.
|
|
997
1057
|
const radii = useMemo(
|
|
@@ -1031,8 +1091,28 @@ export function BotMark({
|
|
|
1031
1091
|
// the tree at 60 fps. `radii` and `shapeSeed` go through the ref rather than the
|
|
1032
1092
|
// effect deps: the loop mounts once, and restarting it on a seed change (the create
|
|
1033
1093
|
// form retypes the name) would snap the eyes and reset the blink and breath phase.
|
|
1034
|
-
const
|
|
1035
|
-
|
|
1094
|
+
const look = spec?.look ?? null;
|
|
1095
|
+
const eyesOut = Boolean(crossed);
|
|
1096
|
+
const live = useRef({
|
|
1097
|
+
cfg,
|
|
1098
|
+
state,
|
|
1099
|
+
getSpectrum,
|
|
1100
|
+
radii,
|
|
1101
|
+
shapeSeed,
|
|
1102
|
+
look,
|
|
1103
|
+
crossed: eyesOut,
|
|
1104
|
+
grow,
|
|
1105
|
+
});
|
|
1106
|
+
live.current = {
|
|
1107
|
+
cfg,
|
|
1108
|
+
state,
|
|
1109
|
+
getSpectrum,
|
|
1110
|
+
radii,
|
|
1111
|
+
shapeSeed,
|
|
1112
|
+
look,
|
|
1113
|
+
crossed: eyesOut,
|
|
1114
|
+
grow,
|
|
1115
|
+
};
|
|
1036
1116
|
|
|
1037
1117
|
useEffect(() => {
|
|
1038
1118
|
bindPointer();
|
|
@@ -1050,20 +1130,18 @@ export function BotMark({
|
|
|
1050
1130
|
// STATE_SHAPE values are targets, eased over about 0.6 s.
|
|
1051
1131
|
const shape = { ...STATE_SHAPE.idle };
|
|
1052
1132
|
const SHAPE_KEYS = Object.keys(shape) as (keyof StateShape)[];
|
|
1053
|
-
//
|
|
1054
|
-
// ~1 s to know speech is ongoing.
|
|
1133
|
+
// Two time scales: ~50 ms to catch a syllable, ~1 s to know speech is ongoing.
|
|
1055
1134
|
let fastLvl = 0;
|
|
1056
|
-
let midLvl = 0;
|
|
1057
1135
|
let lvl = 0;
|
|
1058
1136
|
let bright = 0.5;
|
|
1059
1137
|
// Syllable-kicked spring; its own frequency caps how fast the mark can move.
|
|
1060
1138
|
let bob = 0;
|
|
1061
1139
|
let bobVel = 0;
|
|
1062
1140
|
let lastOnset = 0;
|
|
1063
|
-
const band = new Array<number>(
|
|
1141
|
+
const band = new Array<number>(SPECTRUM_BANDS).fill(0);
|
|
1064
1142
|
// Each harmonic rotates at its own speed, alternating direction, so the deformation
|
|
1065
1143
|
// never settles into a standing wave.
|
|
1066
|
-
const bandPhase = Array.from({ length:
|
|
1144
|
+
const bandPhase = Array.from({ length: SPECTRUM_BANDS }, (_, k) => k * 1.7);
|
|
1067
1145
|
// Integrated, never `time * speed`: `churnSpeed` eases between states, and
|
|
1068
1146
|
// phase = elapsed * speed would sweep the whole elapsed time on every speed change.
|
|
1069
1147
|
let churnPhase = 0;
|
|
@@ -1097,7 +1175,7 @@ export function BotMark({
|
|
|
1097
1175
|
// still; each band inside its own recent range moves with the words.
|
|
1098
1176
|
const heard = voice.read(spec ?? SILENT, dt);
|
|
1099
1177
|
let specSum = 0;
|
|
1100
|
-
for (let k = 0; k <
|
|
1178
|
+
for (let k = 0; k < SPECTRUM_BANDS; k++) {
|
|
1101
1179
|
const target = heard.bands[k];
|
|
1102
1180
|
// Bands set the shape, so smooth hard; faster and small marks shimmer.
|
|
1103
1181
|
band[k] += (target - band[k]) * c.bandEase;
|
|
@@ -1105,21 +1183,14 @@ export function BotMark({
|
|
|
1105
1183
|
specSum += target;
|
|
1106
1184
|
}
|
|
1107
1185
|
|
|
1108
|
-
const
|
|
1109
|
-
const want = st === "speaking" ? clamp(given ?? heard.level, 0, 1) : 0;
|
|
1186
|
+
const want = st === "speaking" ? clamp(heard.level, 0, 1) : 0;
|
|
1110
1187
|
|
|
1111
1188
|
fastLvl += (want - fastLvl) * 0.3;
|
|
1112
|
-
midLvl += (want - midLvl) * 0.055;
|
|
1113
1189
|
lvl += (want - lvl) * 0.016;
|
|
1114
1190
|
|
|
1115
|
-
// A syllable is
|
|
1116
|
-
// spectrum, this one's for a bare level. The gap must exceed the spring
|
|
1191
|
+
// A syllable is the follower's onset. The gap must exceed the spring
|
|
1117
1192
|
// period or kicks pile up into a tremble.
|
|
1118
|
-
|
|
1119
|
-
given === undefined
|
|
1120
|
-
? heard.onset > 0
|
|
1121
|
-
: fastLvl > midLvl * 1.25 + 0.03 && fastLvl > 0.09;
|
|
1122
|
-
if (syllable && now - lastOnset > 340) {
|
|
1193
|
+
if (heard.onset > 0 && now - lastOnset > 340) {
|
|
1123
1194
|
lastOnset = now;
|
|
1124
1195
|
// Slower springs integrate each impulse longer, so scale the kick with stiffness.
|
|
1125
1196
|
bobVel -= c.punch * Math.min(1, fastLvl * 1.6) * c.bobRate;
|
|
@@ -1133,8 +1204,8 @@ export function BotMark({
|
|
|
1133
1204
|
// that changes per phoneme reads as flicker.
|
|
1134
1205
|
if (specSum > 0.04) {
|
|
1135
1206
|
let weighted = 0;
|
|
1136
|
-
for (let k = 0; k <
|
|
1137
|
-
bright += (weighted / specSum / (
|
|
1207
|
+
for (let k = 0; k < SPECTRUM_BANDS; k++) weighted += band[k] * k;
|
|
1208
|
+
bright += (weighted / specSum / (SPECTRUM_BANDS - 1) - bright) * 0.04;
|
|
1138
1209
|
} else {
|
|
1139
1210
|
bright += (0.5 - bright) * 0.03;
|
|
1140
1211
|
}
|
|
@@ -1172,14 +1243,6 @@ export function BotMark({
|
|
|
1172
1243
|
}
|
|
1173
1244
|
}
|
|
1174
1245
|
|
|
1175
|
-
if (shadowRef.current) {
|
|
1176
|
-
const swell = 0.5 - 0.5 * Math.cos(t * 0.55);
|
|
1177
|
-
shadowRef.current.setAttribute(
|
|
1178
|
-
"opacity",
|
|
1179
|
-
f((shape.shadow * swell * c.shadow) / 100).toString(),
|
|
1180
|
-
);
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
1246
|
if (lifeRef.current) {
|
|
1184
1247
|
const amp = (c.breathe * shape.breathe) / 100;
|
|
1185
1248
|
const swell = (lvl * c.pulse) / 300 - bob * 0.05;
|
|
@@ -1208,6 +1271,28 @@ export function BotMark({
|
|
|
1208
1271
|
);
|
|
1209
1272
|
}
|
|
1210
1273
|
|
|
1274
|
+
// Paints run on plain seconds, not `c.speed`: they are surface, not mood.
|
|
1275
|
+
const paintLook = live.current.look;
|
|
1276
|
+
if (paintLook) {
|
|
1277
|
+
const secs = now / 1000;
|
|
1278
|
+
const grow = live.current.grow;
|
|
1279
|
+
if (paintLook === "flow") {
|
|
1280
|
+
// Slanted and sliding one run every 3.6 s, so the colours meet at no point.
|
|
1281
|
+
paintRef.current?.setAttribute(
|
|
1282
|
+
"gradientTransform",
|
|
1283
|
+
`rotate(-35 ${CENTER} ${CENTER}) translate(${f(-((secs / 3.6) % 1) * spanOf(grow))} 0)`,
|
|
1284
|
+
);
|
|
1285
|
+
} else if (paintLook === "aurora") {
|
|
1286
|
+
for (const [i, curtain] of CURTAINS.entries()) {
|
|
1287
|
+
const e = 0.5 - 0.5 * Math.cos((secs / curtain.period) * TAU);
|
|
1288
|
+
curtainRefs.current[i]?.setAttribute(
|
|
1289
|
+
"transform",
|
|
1290
|
+
`translate(${f(curtain.sway * e)} 0) translate(${curtain.cx} ${CURTAIN_Y}) skewX(${f(20 * e - 10)}) scale(1 ${f(1 + 0.18 * e)}) translate(${-curtain.cx} ${-CURTAIN_Y})`,
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1211
1296
|
// Eight bands folded into three, driving harmonics 2..4 only; higher harmonics on
|
|
1212
1297
|
// an already bumpy silhouette read as noise.
|
|
1213
1298
|
const lowE = (band[0] + band[1] + band[2]) / 3;
|
|
@@ -1241,18 +1326,14 @@ export function BotMark({
|
|
|
1241
1326
|
const d = radiiToPath(next);
|
|
1242
1327
|
headRef.current.setAttribute("d", d);
|
|
1243
1328
|
clipRef.current?.setAttribute("d", d);
|
|
1244
|
-
glowRef.current?.setAttribute("d", d);
|
|
1245
|
-
haloHeadRef.current?.setAttribute("d", d);
|
|
1246
|
-
shadowRef.current?.setAttribute("d", d);
|
|
1247
|
-
rimRef.current?.setAttribute("d", d);
|
|
1248
1329
|
maskHeadRef.current?.setAttribute("d", d);
|
|
1249
1330
|
}
|
|
1250
1331
|
|
|
1251
1332
|
if (eyesRef.current) {
|
|
1252
1333
|
let tgx = 0;
|
|
1253
1334
|
let tgy = 0;
|
|
1254
|
-
if (c.follow && pointer.live &&
|
|
1255
|
-
const r =
|
|
1335
|
+
if (c.follow && pointer.live && svgRef.current) {
|
|
1336
|
+
const r = svgRef.current.getBoundingClientRect();
|
|
1256
1337
|
if (r.width > 0) {
|
|
1257
1338
|
tgx =
|
|
1258
1339
|
clamp(
|
|
@@ -1278,7 +1359,8 @@ export function BotMark({
|
|
|
1278
1359
|
0.38 * Math.sin(t * 0.47 + phase * 2.1));
|
|
1279
1360
|
|
|
1280
1361
|
let sy = 1;
|
|
1281
|
-
|
|
1362
|
+
// Crossed-out eyes do not blink.
|
|
1363
|
+
if (blinkStart === 0 && !live.current.crossed) {
|
|
1282
1364
|
if (queuedBlink > 0 && now >= queuedBlink) {
|
|
1283
1365
|
blinkStart = now;
|
|
1284
1366
|
queuedBlink = 0;
|
|
@@ -1297,10 +1379,9 @@ export function BotMark({
|
|
|
1297
1379
|
sy = 1 - Math.sin(Math.PI * p) * 0.94;
|
|
1298
1380
|
}
|
|
1299
1381
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
);
|
|
1382
|
+
const eyesAt = `translate(${f(gx + act.eyeX + shape.gazeX)} ${f(gy + drift + act.eyeY + shape.gazeY)}) translate(${CENTER} ${c.eyeY}) scale(1 ${sy.toFixed(3)}) translate(${-CENTER} ${-c.eyeY})`;
|
|
1383
|
+
eyesRef.current.setAttribute("transform", eyesAt);
|
|
1384
|
+
inkEyesRef.current?.setAttribute("transform", eyesAt);
|
|
1304
1385
|
|
|
1305
1386
|
// Each eye scales about its own center; scaling both together widens the gap instead.
|
|
1306
1387
|
const eyeWid = act.eyeWid * (1 - lvl * 0.13) * shape.eyes;
|
|
@@ -1315,9 +1396,11 @@ export function BotMark({
|
|
|
1315
1396
|
const tilt = i === 0 ? c.eyeTilt : c.eyeTilt + c.eyeSkew;
|
|
1316
1397
|
const len = eyeLen.toFixed(3);
|
|
1317
1398
|
const wid = eyeWid.toFixed(3);
|
|
1318
|
-
|
|
1399
|
+
const eyeAt = `translate(${f(cx)} ${c.eyeY}) rotate(${f(tilt)}) scale(${len} ${wid}) rotate(${f(-tilt)}) translate(${f(-cx)} ${-c.eyeY})`;
|
|
1400
|
+
ref.current.setAttribute("transform", eyeAt);
|
|
1401
|
+
(i === 0 ? inkEyeLRef : inkEyeRRef).current?.setAttribute(
|
|
1319
1402
|
"transform",
|
|
1320
|
-
|
|
1403
|
+
eyeAt,
|
|
1321
1404
|
);
|
|
1322
1405
|
}
|
|
1323
1406
|
}
|
|
@@ -1325,13 +1408,29 @@ export function BotMark({
|
|
|
1325
1408
|
|
|
1326
1409
|
raf = requestAnimationFrame(tick);
|
|
1327
1410
|
return () => cancelAnimationFrame(raf);
|
|
1328
|
-
}, [
|
|
1411
|
+
}, []);
|
|
1329
1412
|
|
|
1330
1413
|
const nAngle = (cfg.notifyAngle * Math.PI) / 180;
|
|
1414
|
+
const ink = spec ? `url(#${paintId})` : "var(--fg)";
|
|
1415
|
+
// Smaller marks get a thicker, wider X: at 18px the 112px stroke is under a pixel.
|
|
1416
|
+
const xHalf = f(18 - 3 * grow);
|
|
1417
|
+
const xStroke = f(22 - 9 * grow);
|
|
1418
|
+
const eye = (d: string, cx: number, color: string) =>
|
|
1419
|
+
eyesOut ? (
|
|
1420
|
+
<path
|
|
1421
|
+
d={`M${cx - xHalf} ${cfg.eyeY - xHalf}L${cx + xHalf} ${cfg.eyeY + xHalf}M${cx + xHalf} ${cfg.eyeY - xHalf}L${cx - xHalf} ${cfg.eyeY + xHalf}`}
|
|
1422
|
+
fill="none"
|
|
1423
|
+
stroke={color}
|
|
1424
|
+
strokeWidth={xStroke}
|
|
1425
|
+
strokeLinecap="round"
|
|
1426
|
+
/>
|
|
1427
|
+
) : (
|
|
1428
|
+
<path d={d} fill={color} />
|
|
1429
|
+
);
|
|
1331
1430
|
|
|
1332
1431
|
return (
|
|
1333
1432
|
<svg
|
|
1334
|
-
ref={
|
|
1433
|
+
ref={svgRef}
|
|
1335
1434
|
data-slot="bot-mark"
|
|
1336
1435
|
aria-hidden="true"
|
|
1337
1436
|
className={className}
|
|
@@ -1352,10 +1451,10 @@ export function BotMark({
|
|
|
1352
1451
|
<g clipPath={`url(#${clipId})`}>
|
|
1353
1452
|
<g ref={eyesRef}>
|
|
1354
1453
|
<g ref={eyeLRef}>
|
|
1355
|
-
|
|
1454
|
+
{eye(eyeL, CENTER - cfg.eyeGap / 2, "#000")}
|
|
1356
1455
|
</g>
|
|
1357
1456
|
<g ref={eyeRRef}>
|
|
1358
|
-
|
|
1457
|
+
{eye(eyeR, CENTER + cfg.eyeGap / 2, "#000")}
|
|
1359
1458
|
</g>
|
|
1360
1459
|
</g>
|
|
1361
1460
|
</g>
|
|
@@ -1369,114 +1468,107 @@ export function BotMark({
|
|
|
1369
1468
|
)}
|
|
1370
1469
|
</mask>
|
|
1371
1470
|
)}
|
|
1372
|
-
{
|
|
1373
|
-
<
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
width="220%"
|
|
1378
|
-
height="220%"
|
|
1379
|
-
colorInterpolationFilters="sRGB"
|
|
1471
|
+
{spec && (
|
|
1472
|
+
<linearGradient
|
|
1473
|
+
ref={paintRef}
|
|
1474
|
+
id={paintId}
|
|
1475
|
+
{...paintAxis(spec.look, grow)}
|
|
1380
1476
|
>
|
|
1381
|
-
|
|
1382
|
-
|
|
1477
|
+
{paintStops(spec).map((stop) => (
|
|
1478
|
+
<stop
|
|
1479
|
+
key={`${stop.offset}-${stop.color}`}
|
|
1480
|
+
offset={stop.offset}
|
|
1481
|
+
stopColor={stop.color}
|
|
1482
|
+
/>
|
|
1483
|
+
))}
|
|
1484
|
+
</linearGradient>
|
|
1383
1485
|
)}
|
|
1384
|
-
{
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
<mask
|
|
1389
|
-
id={haloId}
|
|
1390
|
-
maskUnits="userSpaceOnUse"
|
|
1391
|
-
// The default region is the view box; the blur reaches past it.
|
|
1486
|
+
{spec?.look === "aurora" && (
|
|
1487
|
+
<filter
|
|
1488
|
+
id={curtainId}
|
|
1489
|
+
filterUnits="userSpaceOnUse"
|
|
1392
1490
|
x={-PAD * 4}
|
|
1393
1491
|
y={-PAD * 4}
|
|
1394
1492
|
width={BOX + PAD * 8}
|
|
1395
1493
|
height={BOX + PAD * 8}
|
|
1396
|
-
>
|
|
1397
|
-
<rect
|
|
1398
|
-
x={-PAD * 4}
|
|
1399
|
-
y={-PAD * 4}
|
|
1400
|
-
width={BOX + PAD * 8}
|
|
1401
|
-
height={BOX + PAD * 8}
|
|
1402
|
-
fill="#fff"
|
|
1403
|
-
/>
|
|
1404
|
-
<path ref={haloHeadRef} d={headPath} fill="#000" />
|
|
1405
|
-
</mask>
|
|
1406
|
-
)}
|
|
1407
|
-
{cfg.glow > 0 && (
|
|
1408
|
-
<filter
|
|
1409
|
-
id={glowId}
|
|
1410
|
-
x="-60%"
|
|
1411
|
-
y="-60%"
|
|
1412
|
-
width="220%"
|
|
1413
|
-
height="220%"
|
|
1414
1494
|
colorInterpolationFilters="sRGB"
|
|
1415
1495
|
>
|
|
1416
|
-
<feGaussianBlur stdDeviation={
|
|
1496
|
+
<feGaussianBlur stdDeviation={f(curtainBlurOf(grow))} />
|
|
1417
1497
|
</filter>
|
|
1418
1498
|
)}
|
|
1419
1499
|
</defs>
|
|
1420
1500
|
<g ref={lifeRef}>
|
|
1421
|
-
{cfg.
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
d={headPath}
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1501
|
+
{cfg.fill ? (
|
|
1502
|
+
// Everything the body wears shares its one mask, so a paint's layers keep the eyes cut.
|
|
1503
|
+
<g mask={`url(#${maskId})`}>
|
|
1504
|
+
<path ref={headRef} d={headPath} fill={ink} />
|
|
1505
|
+
{spec?.look === "aurora" && (
|
|
1506
|
+
// Blurred on a layer wider than the face, so the curtains melt into the night
|
|
1507
|
+
// while the mask keeps the outline and the eyes sharp.
|
|
1508
|
+
<g filter={`url(#${curtainId})`}>
|
|
1509
|
+
<rect
|
|
1510
|
+
x={-PAD * 4}
|
|
1511
|
+
y={-PAD * 4}
|
|
1512
|
+
width={BOX + PAD * 8}
|
|
1513
|
+
height={BOX + PAD * 8}
|
|
1514
|
+
fill={ink}
|
|
1515
|
+
/>
|
|
1516
|
+
{CURTAINS.map((curtain, i) => (
|
|
1517
|
+
<ellipse
|
|
1518
|
+
key={curtain.cx}
|
|
1519
|
+
ref={(node) => {
|
|
1520
|
+
curtainRefs.current[i] = node;
|
|
1521
|
+
}}
|
|
1522
|
+
cx={curtain.cx}
|
|
1523
|
+
cy={CURTAIN_Y}
|
|
1524
|
+
rx={f(curtainRxOf(grow))}
|
|
1525
|
+
ry={138}
|
|
1526
|
+
fill={spec.colors[2 + i]}
|
|
1527
|
+
style={{ mixBlendMode: "screen" }}
|
|
1528
|
+
/>
|
|
1529
|
+
))}
|
|
1530
|
+
</g>
|
|
1531
|
+
)}
|
|
1532
|
+
</g>
|
|
1533
|
+
) : (
|
|
1443
1534
|
<path
|
|
1444
|
-
ref={
|
|
1535
|
+
ref={headRef}
|
|
1445
1536
|
d={headPath}
|
|
1446
1537
|
fill="none"
|
|
1447
|
-
stroke={
|
|
1448
|
-
strokeWidth={cfg.
|
|
1538
|
+
stroke={ink}
|
|
1539
|
+
strokeWidth={cfg.strokeWidth}
|
|
1449
1540
|
strokeLinejoin="round"
|
|
1450
1541
|
/>
|
|
1451
1542
|
)}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1543
|
+
{cfg.fill && edge === "dark" && (
|
|
1544
|
+
// Eye holes show the page, and a dark body on a dark page swallows them.
|
|
1545
|
+
<g clipPath={`url(#${clipId})`} opacity={0.92}>
|
|
1546
|
+
<g ref={inkEyesRef}>
|
|
1547
|
+
<g ref={inkEyeLRef}>
|
|
1548
|
+
{eye(eyeL, CENTER - cfg.eyeGap / 2, "#fff")}
|
|
1549
|
+
</g>
|
|
1550
|
+
<g ref={inkEyeRRef}>
|
|
1551
|
+
{eye(eyeR, CENTER + cfg.eyeGap / 2, "#fff")}
|
|
1552
|
+
</g>
|
|
1553
|
+
</g>
|
|
1554
|
+
</g>
|
|
1555
|
+
)}
|
|
1461
1556
|
{/* Outlined marks have no silhouette to cut into, so the eyes are drawn. */}
|
|
1462
1557
|
{!cfg.fill && (
|
|
1463
1558
|
<g clipPath={`url(#${clipId})`}>
|
|
1464
1559
|
<g ref={eyesRef}>
|
|
1465
|
-
<g ref={eyeLRef}>
|
|
1466
|
-
|
|
1467
|
-
</g>
|
|
1468
|
-
<g ref={eyeRRef}>
|
|
1469
|
-
<path d={eyeR} fill="var(--fg)" />
|
|
1470
|
-
</g>
|
|
1560
|
+
<g ref={eyeLRef}>{eye(eyeL, CENTER - cfg.eyeGap / 2, ink)}</g>
|
|
1561
|
+
<g ref={eyeRRef}>{eye(eyeR, CENTER + cfg.eyeGap / 2, ink)}</g>
|
|
1471
1562
|
</g>
|
|
1472
1563
|
</g>
|
|
1473
1564
|
)}
|
|
1474
1565
|
{notifying && (
|
|
1566
|
+
// The dot waits on the user, so it wears amber in NavBadge's shades.
|
|
1475
1567
|
<circle
|
|
1476
1568
|
cx={f(CENTER + Math.cos(nAngle) * cfg.notifyDist)}
|
|
1477
1569
|
cy={f(CENTER + Math.sin(nAngle) * cfg.notifyDist)}
|
|
1478
1570
|
r={cfg.notifyR}
|
|
1479
|
-
fill
|
|
1571
|
+
className="fill-amber-600 dark:fill-amber-400"
|
|
1480
1572
|
/>
|
|
1481
1573
|
)}
|
|
1482
1574
|
</g>
|