thursday-agent 0.4.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 +6 -5
- 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 +5 -5
- 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 +13 -13
- 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 +10 -11
- 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 -4
- 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_0r28-sm._.js → node_modules_consola_dist_chunks_prompt_mjs_0a7-pbw._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0v_7drq._.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 -89
- 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/{_1gd8q8l._.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/{_1-_etts._.js → _1anqots._.js} +2 -2
- 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/{_0n3toaw._.js → _1k0spz7._.js} +2 -2
- package/.next/server/chunks/ssr/_1rgtxhr._.js +5 -0
- package/.next/server/chunks/ssr/_1slp25y._.js +3 -0
- package/.next/server/chunks/ssr/{_1fojd41._.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_0cxaxk9._.js → node_modules_00_51_v._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_04jf_m8._.js → node_modules_022sipm._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0g7fzk3._.js → node_modules_0332gw4._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1cx_ql6._.js → node_modules_04vxchl._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1vh5ntv._.js → node_modules_0746rzi._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0yugy6m._.js → node_modules_0d5uzof._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_09q35v_._.js → node_modules_0exkwcm._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_08dhkiq._.js → node_modules_0fr-ml8._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_14q6g4n._.js → node_modules_0mxvg8h._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0arus10._.js → node_modules_0qapgjr._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1eg7m6c._.js → node_modules_0qbfyjh._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1cz2hle._.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_1efrqxi._.js → node_modules_0vsxbzp._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0_-_a--._.js → node_modules_0vv0-fg._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1gdh31p._.js → node_modules_0wsvp00._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1hpopmo._.js → node_modules_1-urho9._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1_pc9kq._.js → node_modules_16pi_dd._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_00etblx._.js → node_modules_1d53yiq._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1aaxuef._.js → node_modules_1g1eihe._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_198nmll._.js → node_modules_1gpednh._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0pvd7q-._.js → node_modules_1gu1pph._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0b__sgl._.js → node_modules_1he1w8_._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1qpjvy5._.js → node_modules_1lnjapm._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0940ns5._.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_14om4ar._.js → node_modules_1u6w1pb._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0had7xd._.js → node_modules_1xn6saw._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1b748ic._.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_1z4hm5e._.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_06mk8id._.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/{15m575979un5f.js → 1i-u2wzub_to1.js} +2 -2
- 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/{3akmqm77muj4-.js → 1wlo979mx-y3w.js} +1 -1
- package/.next/static/chunks/26ql4y-43xwhp.js +1 -0
- package/.next/static/chunks/{0fl3gwe4-l6tz.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 +36 -14
- 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 +299 -636
- package/features/bot/bot.runner.ts +468 -844
- 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 +103 -50
- 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 +17 -6
- 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]__01dkp4a._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__02va5wz._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__02xjoto._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__04q--0f._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0bl-e63._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0ffbg85._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0jq4ohy._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0ls6_8y._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0ncs9uu._.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]__12cabg9._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1339jnv._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__18_teo8._.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]__1ccon1w._.js +0 -10
- package/.next/server/chunks/[root-of-the-server]__1fizn31._.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]__1wa1k7r._.js +0 -8
- package/.next/server/chunks/_0-73of8._.js +0 -55
- package/.next/server/chunks/_0-fjql4._.js +0 -26
- package/.next/server/chunks/_00xh_q0._.js +0 -25
- package/.next/server/chunks/_03a0897._.js +0 -3
- package/.next/server/chunks/_051qh8u._.js +0 -3
- package/.next/server/chunks/_05sovvj._.js +0 -3
- package/.next/server/chunks/_0fzqt2y._.js +0 -134
- package/.next/server/chunks/_0mecv0f._.js +0 -26
- package/.next/server/chunks/_0mh8j4m._.js +0 -3
- package/.next/server/chunks/_0obojvv._.js +0 -3
- package/.next/server/chunks/_0sb7tlz._.js +0 -3
- package/.next/server/chunks/_0sbynis._.js +0 -3
- package/.next/server/chunks/_0u10wmw._.js +0 -55
- package/.next/server/chunks/_0u4aiy2._.js +0 -3
- 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/_1_9mjx-._.js +0 -3
- package/.next/server/chunks/_1c78vw5._.js +0 -229
- 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/_1zjrdag._.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 -3
- package/.next/server/chunks/features_bot_0zt92oh._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1xoq2rl._.js +0 -3
- package/.next/server/chunks/ssr/[externals]__0dizgek._.js +0 -3
- 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]__0s9dq5u._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0s9l2sv._.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]__0xsog8n._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +0 -61
- package/.next/server/chunks/ssr/[root-of-the-server]__1gtlw6v._.js +0 -43
- package/.next/server/chunks/ssr/[root-of-the-server]__1ox7hbk._.js +0 -4
- package/.next/server/chunks/ssr/[root-of-the-server]__202p40z._.js +0 -3
- package/.next/server/chunks/ssr/_001_ms1._.js +0 -28
- package/.next/server/chunks/ssr/_01n3o0m._.js +0 -3
- package/.next/server/chunks/ssr/_0fz4mf_._.js +0 -3
- package/.next/server/chunks/ssr/_0gb4gmf._.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/_0ilna52._.js +0 -42
- 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/_13fke0x._.js +0 -3
- package/.next/server/chunks/ssr/_18cymkq._.js +0 -3
- package/.next/server/chunks/ssr/_1b2mjwr._.js +0 -3
- package/.next/server/chunks/ssr/_1f-dg-6._.js +0 -3
- package/.next/server/chunks/ssr/_1h0rw11._.js +0 -3
- package/.next/server/chunks/ssr/_1jhd09t._.js +0 -3
- package/.next/server/chunks/ssr/_1nnsk7z._.js +0 -3
- package/.next/server/chunks/ssr/_1ov37if._.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/00rd4-v8r7axp.js +0 -1
- package/.next/static/chunks/08qe4as2q428z.js +0 -3
- package/.next/static/chunks/0gnqdjn2lvdad.js +0 -2
- package/.next/static/chunks/0hwap1-p0m5sa.js +0 -1
- package/.next/static/chunks/0r5qcctujhxli.js +0 -1
- package/.next/static/chunks/0w52rrrmuj9r9.js +0 -1
- package/.next/static/chunks/0wcprt5ot5she.js +0 -1
- package/.next/static/chunks/10teww7wt-f6h.js +0 -1
- package/.next/static/chunks/17p6tk6k88dq6.js +0 -1
- package/.next/static/chunks/18a96rkhi4_yd.js +0 -1
- package/.next/static/chunks/1dkjg87pxk0n9.js +0 -28
- package/.next/static/chunks/1jd09sxcjddu1.js +0 -1
- package/.next/static/chunks/1w73ece_6bheu.js +0 -18
- package/.next/static/chunks/214ya3n5gxeih.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/2t4vhi3m8ahya.js +0 -1
- package/.next/static/chunks/2tigdtz3dpcy8.js +0 -1
- package/.next/static/chunks/2u7xt6mxg44lf.js +0 -1
- package/.next/static/chunks/3786h5vayt80-.js +0 -28
- package/.next/static/chunks/39j0fvpybzabl.js +0 -40
- package/.next/static/chunks/3cq5g494yuke8.css +0 -1
- package/.next/static/chunks/3hibbjnt85-k6.js +0 -1
- package/.next/static/chunks/3woj-xd7ki5_i.js +0 -1
- package/.next/static/chunks/3xk7yqgomx7yq.js +0 -1
- package/.next/static/chunks/3zmcsnuo25zvq.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 -976
- package/features/bot/task.store.ts +0 -489
- 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/{kaTO0UHqF1bMnWgCDik2f → 0qzGoKn2wTERVZtblX1tp}/_buildManifest.js +0 -0
- /package/.next/static/{kaTO0UHqF1bMnWgCDik2f → 0qzGoKn2wTERVZtblX1tp}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{kaTO0UHqF1bMnWgCDik2f → 0qzGoKn2wTERVZtblX1tp}/_ssgManifest.js +0 -0
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import type { RealtimeAudio } from "./realtime.session";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* PCM16 microphone capture, playback and base64 codec for the WebSocket
|
|
5
|
-
* transport. WebRTC handles audio as tracks and uses none of this.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/** Both providers are configured with this value. */
|
|
9
|
-
export const PCM_SAMPLE_RATE = 24000;
|
|
10
|
-
|
|
11
|
-
export type PcmPlayer = ReturnType<typeof createPcmPlayer>;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Plays PCM chunks scheduled against a moving play head; chunks arrive faster
|
|
15
|
-
* than they play. A play head that fell behind is pushed forward.
|
|
16
|
-
*/
|
|
17
|
-
export function createPcmPlayer(
|
|
18
|
-
audio: RealtimeAudio,
|
|
19
|
-
/** Called when the queue empties. */
|
|
20
|
-
onDrained: () => void,
|
|
21
|
-
) {
|
|
22
|
-
const { context, analyser } = audio.speaker();
|
|
23
|
-
let playHead = 0;
|
|
24
|
-
const scheduled = new Set<AudioBufferSourceNode>();
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
/** Queue one little-endian PCM16 chunk at PCM_SAMPLE_RATE. */
|
|
28
|
-
push(samples: Int16Array) {
|
|
29
|
-
if (samples.length === 0) return;
|
|
30
|
-
|
|
31
|
-
const buffer = context.createBuffer(1, samples.length, PCM_SAMPLE_RATE);
|
|
32
|
-
const channel = buffer.getChannelData(0);
|
|
33
|
-
for (let i = 0; i < samples.length; i++) channel[i] = samples[i] / 32768;
|
|
34
|
-
|
|
35
|
-
const source = context.createBufferSource();
|
|
36
|
-
source.buffer = buffer;
|
|
37
|
-
source.connect(analyser);
|
|
38
|
-
source.onended = () => {
|
|
39
|
-
scheduled.delete(source);
|
|
40
|
-
if (scheduled.size === 0) onDrained();
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// Slightly ahead of now so scheduling jitter never lands in the past.
|
|
44
|
-
playHead = Math.max(playHead, context.currentTime + 0.06);
|
|
45
|
-
source.start(playHead);
|
|
46
|
-
playHead += buffer.duration;
|
|
47
|
-
scheduled.add(source);
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
/** Barge-in: drop everything queued but not yet heard. */
|
|
51
|
-
stop() {
|
|
52
|
-
for (const source of scheduled) {
|
|
53
|
-
source.onended = null;
|
|
54
|
-
try {
|
|
55
|
-
source.stop();
|
|
56
|
-
} catch {
|
|
57
|
-
// Already finished.
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
scheduled.clear();
|
|
61
|
-
playHead = 0;
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
get speaking() {
|
|
65
|
-
return scheduled.size > 0;
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export type Microphone = Awaited<ReturnType<typeof openMicrophone>>;
|
|
71
|
-
|
|
72
|
-
/** Echo cancellation is required or the model hears itself and interrupts its own turn. */
|
|
73
|
-
export const MICROPHONE_CONSTRAINTS: MediaTrackConstraints = {
|
|
74
|
-
echoCancellation: true,
|
|
75
|
-
noiseSuppression: true,
|
|
76
|
-
autoGainControl: true,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
/** Opens the mic as PCM16 chunks; the AudioContext resamples to PCM_SAMPLE_RATE. */
|
|
80
|
-
export async function openMicrophone(onChunk: (samples: Int16Array) => void) {
|
|
81
|
-
const stream = await navigator.mediaDevices.getUserMedia({
|
|
82
|
-
audio: MICROPHONE_CONSTRAINTS,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// The mic is on from here and only this scope holds it: a failure below must
|
|
86
|
-
// release it itself or the recording indicator stays lit.
|
|
87
|
-
const context = new AudioContext({ sampleRate: PCM_SAMPLE_RATE });
|
|
88
|
-
try {
|
|
89
|
-
await context.audioWorklet.addModule(captureWorkletUrl());
|
|
90
|
-
const source = context.createMediaStreamSource(stream);
|
|
91
|
-
const capture = new AudioWorkletNode(context, CAPTURE_PROCESSOR);
|
|
92
|
-
|
|
93
|
-
capture.port.onmessage = (event: MessageEvent<Float32Array>) => {
|
|
94
|
-
const frame = event.data;
|
|
95
|
-
const samples = new Int16Array(frame.length);
|
|
96
|
-
for (let i = 0; i < frame.length; i++) {
|
|
97
|
-
const clamped = Math.max(-1, Math.min(1, frame[i]));
|
|
98
|
-
samples[i] = clamped < 0 ? clamped * 0x8000 : clamped * 0x7fff;
|
|
99
|
-
}
|
|
100
|
-
onChunk(samples);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
source.connect(capture);
|
|
104
|
-
// A worklet with nothing downstream can be garbage collected; a silent gain keeps it alive.
|
|
105
|
-
const silence = context.createGain();
|
|
106
|
-
silence.gain.value = 0;
|
|
107
|
-
capture.connect(silence).connect(context.destination);
|
|
108
|
-
await context.resume();
|
|
109
|
-
|
|
110
|
-
return microphone(stream, context, capture);
|
|
111
|
-
} catch (cause) {
|
|
112
|
-
for (const track of stream.getTracks()) track.stop();
|
|
113
|
-
void context.close();
|
|
114
|
-
throw cause;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function microphone(
|
|
119
|
-
stream: MediaStream,
|
|
120
|
-
context: AudioContext,
|
|
121
|
-
capture: AudioWorkletNode,
|
|
122
|
-
) {
|
|
123
|
-
return {
|
|
124
|
-
/** The raw stream, for level metering. */
|
|
125
|
-
stream,
|
|
126
|
-
/** Mutes at the track so the browser's recording indicator goes out too. */
|
|
127
|
-
setMuted(muted: boolean) {
|
|
128
|
-
for (const track of stream.getAudioTracks()) track.enabled = !muted;
|
|
129
|
-
},
|
|
130
|
-
close() {
|
|
131
|
-
capture.port.onmessage = null;
|
|
132
|
-
for (const track of stream.getTracks()) track.stop();
|
|
133
|
-
void context.close();
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const CAPTURE_PROCESSOR = "voice-capture";
|
|
139
|
-
|
|
140
|
-
/** Samples per message (about 43ms); posting every 128-sample block would flood the socket. */
|
|
141
|
-
const CAPTURE_FRAME = 1024;
|
|
142
|
-
|
|
143
|
-
const CAPTURE_WORKLET = `
|
|
144
|
-
class VoiceCapture extends AudioWorkletProcessor {
|
|
145
|
-
constructor() {
|
|
146
|
-
super();
|
|
147
|
-
this.frame = new Float32Array(${CAPTURE_FRAME});
|
|
148
|
-
this.filled = 0;
|
|
149
|
-
}
|
|
150
|
-
process(inputs) {
|
|
151
|
-
const input = inputs[0] && inputs[0][0];
|
|
152
|
-
if (!input) return true;
|
|
153
|
-
for (let i = 0; i < input.length; i++) {
|
|
154
|
-
this.frame[this.filled++] = input[i];
|
|
155
|
-
if (this.filled === this.frame.length) {
|
|
156
|
-
this.port.postMessage(this.frame.slice());
|
|
157
|
-
this.filled = 0;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return true;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
registerProcessor("${CAPTURE_PROCESSOR}", VoiceCapture);
|
|
164
|
-
`;
|
|
165
|
-
|
|
166
|
-
let workletUrl: string | null = null;
|
|
167
|
-
|
|
168
|
-
/** Inline blob URL so the processor lives next to the code reading its messages. */
|
|
169
|
-
function captureWorkletUrl() {
|
|
170
|
-
workletUrl ??= URL.createObjectURL(
|
|
171
|
-
new Blob([CAPTURE_WORKLET], { type: "application/javascript" }),
|
|
172
|
-
);
|
|
173
|
-
return workletUrl;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/** PCM16 to base64. Chunked: spreading a whole buffer into String.fromCharCode overflows the stack. */
|
|
177
|
-
export function encodePcm(samples: Int16Array): string {
|
|
178
|
-
const bytes = new Uint8Array(
|
|
179
|
-
samples.buffer,
|
|
180
|
-
samples.byteOffset,
|
|
181
|
-
samples.byteLength,
|
|
182
|
-
);
|
|
183
|
-
let binary = "";
|
|
184
|
-
for (let i = 0; i < bytes.length; i += 0x8000) {
|
|
185
|
-
binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
|
|
186
|
-
}
|
|
187
|
-
return btoa(binary);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export function decodePcm(base64: string): Int16Array {
|
|
191
|
-
const binary = atob(base64);
|
|
192
|
-
const bytes = new Uint8Array(binary.length);
|
|
193
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
194
|
-
// Drop a trailing half sample.
|
|
195
|
-
return new Int16Array(bytes.buffer, 0, bytes.length >> 1);
|
|
196
|
-
}
|
|
@@ -1,489 +0,0 @@
|
|
|
1
|
-
import { logger } from "@/lib/logger";
|
|
2
|
-
import { errorToString } from "@/lib/utils";
|
|
3
|
-
import type {
|
|
4
|
-
RealtimeFunctionTool,
|
|
5
|
-
RealtimeResponse,
|
|
6
|
-
RealtimeServerEvent,
|
|
7
|
-
SessionUpdateEvent,
|
|
8
|
-
} from "./realtime.protocol";
|
|
9
|
-
import type { RealtimeCredential, ToolManifest } from "./realtime.schema";
|
|
10
|
-
import type {
|
|
11
|
-
RealtimeActivity,
|
|
12
|
-
RealtimeAudio,
|
|
13
|
-
RealtimeSessionFactory,
|
|
14
|
-
RealtimeSessionSetup,
|
|
15
|
-
RealtimeTurn,
|
|
16
|
-
} from "./realtime.session";
|
|
17
|
-
import type { RealtimeTransport, TransportEvents } from "./realtime.transport";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Session driver for the OpenAI Realtime protocol, which xAI's API also speaks.
|
|
21
|
-
* A RealtimeDialect (openai, xai) supplies only the transport and the
|
|
22
|
-
* `session.update` payload.
|
|
23
|
-
*
|
|
24
|
-
* Turns are ordered by item announcement, not by word arrival: the user's
|
|
25
|
-
* transcript can land after the assistant's answer started. Tool outputs are
|
|
26
|
-
* sent as each finishes; the follow-up `response.create` goes out once, after
|
|
27
|
-
* all outputs are in and playback ended. `say()` text is queued until the line
|
|
28
|
-
* is quiet, since the API refuses a second response while one runs.
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
export type RealtimeDialect = {
|
|
32
|
-
/** Open the wire with this credential. */
|
|
33
|
-
transport(options: {
|
|
34
|
-
credential: RealtimeCredential;
|
|
35
|
-
setup: RealtimeSessionSetup;
|
|
36
|
-
audio: RealtimeAudio;
|
|
37
|
-
on: TransportEvents;
|
|
38
|
-
}): RealtimeTransport;
|
|
39
|
-
/** What the session should be, in the shape sent the moment the wire opens. */
|
|
40
|
-
sessionUpdate(setup: RealtimeSessionSetup): SessionUpdateEvent;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/** Function-tool shape for `session.update`; schemas pass through untouched. */
|
|
44
|
-
export const toFunctionTools = (
|
|
45
|
-
tools: ToolManifest[],
|
|
46
|
-
): RealtimeFunctionTool[] =>
|
|
47
|
-
tools.map(({ name, description, parameters }) => ({
|
|
48
|
-
type: "function",
|
|
49
|
-
name,
|
|
50
|
-
description,
|
|
51
|
-
parameters,
|
|
52
|
-
}));
|
|
53
|
-
|
|
54
|
-
/** Longest wait for `session.updated` before the session counts as open. */
|
|
55
|
-
const SESSION_ACK_MS = 5000;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* After speech stops the server creates its own response; a `response.create`
|
|
59
|
-
* in that gap is refused as a duplicate. Wait this long for it to appear.
|
|
60
|
-
*/
|
|
61
|
-
const SERVER_TURN_MS = 1500;
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* A sent `response.create` counts as active until `response.created` or
|
|
65
|
-
* `error`. If neither arrives within this, the claim is dropped so `say()` is
|
|
66
|
-
* not blocked for the rest of the call.
|
|
67
|
-
*/
|
|
68
|
-
const RESPONSE_ACK_MS = 5000;
|
|
69
|
-
|
|
70
|
-
type Turn = {
|
|
71
|
-
id: string;
|
|
72
|
-
role: RealtimeTurn["role"];
|
|
73
|
-
tool?: string;
|
|
74
|
-
text: string;
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export function realtimeSession(
|
|
78
|
-
dialect: RealtimeDialect,
|
|
79
|
-
): RealtimeSessionFactory {
|
|
80
|
-
return ({ credential, setup, audio, on }) => {
|
|
81
|
-
let hungUp = false;
|
|
82
|
-
/** Pending while waiting for `session.updated`. Null once the session is open. */
|
|
83
|
-
let opening: {
|
|
84
|
-
resolve: () => void;
|
|
85
|
-
reject: (cause: Error) => void;
|
|
86
|
-
} | null = null;
|
|
87
|
-
let ackTimer: ReturnType<typeof setTimeout> | null = null;
|
|
88
|
-
|
|
89
|
-
/** Event types this session has already noted as unhandled (see `default`). */
|
|
90
|
-
const seenUnhandled = new Set<string>();
|
|
91
|
-
|
|
92
|
-
const turns: Turn[] = [];
|
|
93
|
-
const slot = new Map<string, number>();
|
|
94
|
-
const finalized = new Set<string>();
|
|
95
|
-
|
|
96
|
-
/** Claims an item's place the moment it is announced. */
|
|
97
|
-
const reserve = (id: string, role: Turn["role"]) => {
|
|
98
|
-
if (slot.has(id)) return;
|
|
99
|
-
slot.set(id, turns.length);
|
|
100
|
-
turns.push({ id, role, text: "" });
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const report = (index: number, done: boolean) => {
|
|
104
|
-
const turn = turns[index];
|
|
105
|
-
// An item with no words yet is a place, not a turn
|
|
106
|
-
if (!turn.text.trim()) return;
|
|
107
|
-
on.turn({ ...turn, seq: index, done });
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const write = (
|
|
111
|
-
id: string,
|
|
112
|
-
role: Turn["role"],
|
|
113
|
-
text: string,
|
|
114
|
-
how: "append" | "replace",
|
|
115
|
-
) => {
|
|
116
|
-
reserve(id, role);
|
|
117
|
-
const index = slot.get(id) as number;
|
|
118
|
-
const was = turns[index].text;
|
|
119
|
-
const now = how === "append" ? was + text : text;
|
|
120
|
-
if (now === was) return;
|
|
121
|
-
turns[index] = { ...turns[index], text: now };
|
|
122
|
-
if (!finalized.has(id)) report(index, false);
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Reports unfinalized user turns as `done` once without marking them final.
|
|
127
|
-
* `input_audio_transcription.completed` does not always arrive, and `close`
|
|
128
|
-
* does not run on a refreshed tab; a later `completed` re-reports the same
|
|
129
|
-
* seq and the store upserts over it.
|
|
130
|
-
*/
|
|
131
|
-
const flushSpoken = () => {
|
|
132
|
-
for (const [index, turn] of turns.entries()) {
|
|
133
|
-
if (turn.role !== "user" || finalized.has(turn.id)) continue;
|
|
134
|
-
report(index, true);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
/** Reports the turn once as `done` and marks it final. */
|
|
139
|
-
const finish = (id: string) => {
|
|
140
|
-
const index = slot.get(id);
|
|
141
|
-
if (index === undefined || finalized.has(id)) return;
|
|
142
|
-
if (!turns[index].text.trim()) return;
|
|
143
|
-
finalized.add(id);
|
|
144
|
-
report(index, true);
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
let playing = false;
|
|
148
|
-
let userSpeaking = false;
|
|
149
|
-
/** From `response.created` to `response.done`, or from our unconfirmed `response.create`. */
|
|
150
|
-
let responseActive = false;
|
|
151
|
-
/** We asked for the active response and have not seen created yet. */
|
|
152
|
-
let requested = false;
|
|
153
|
-
/** Set while the server is expected to create its own response (SERVER_TURN_MS). */
|
|
154
|
-
let serverTurn: ReturnType<typeof setTimeout> | null = null;
|
|
155
|
-
/** Armed while a `response.create` is unconfirmed (RESPONSE_ACK_MS). */
|
|
156
|
-
let requestAck: ReturnType<typeof setTimeout> | null = null;
|
|
157
|
-
/** Tool calls announced but not yet answered with an output. call_id → name. */
|
|
158
|
-
const outstanding = new Map<string, string>();
|
|
159
|
-
/** How many outputs have been sent since the last follow-up was asked for. */
|
|
160
|
-
let answered = 0;
|
|
161
|
-
/** A follow-up was asked for and the model has not started it yet. */
|
|
162
|
-
let awaiting = false;
|
|
163
|
-
/** Tool names in the current episode; kept until the follow-up starts so activity does not blink. */
|
|
164
|
-
let episode: string[] = [];
|
|
165
|
-
/** What say() queued for the next quiet gap. */
|
|
166
|
-
const queue: string[] = [];
|
|
167
|
-
let shown = "";
|
|
168
|
-
|
|
169
|
-
const clearServerTurn = () => {
|
|
170
|
-
if (serverTurn) clearTimeout(serverTurn);
|
|
171
|
-
serverTurn = null;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
const expectServerTurn = () => {
|
|
175
|
-
clearServerTurn();
|
|
176
|
-
serverTurn = setTimeout(() => {
|
|
177
|
-
serverTurn = null;
|
|
178
|
-
settle();
|
|
179
|
-
}, SERVER_TURN_MS);
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
/** Stops waiting for confirmation of our `response.create`. */
|
|
183
|
-
const clearRequestAck = () => {
|
|
184
|
-
if (requestAck) clearTimeout(requestAck);
|
|
185
|
-
requestAck = null;
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
/** Drops the optimistic claim if no confirmation arrives (RESPONSE_ACK_MS). */
|
|
189
|
-
const expectRequestAck = () => {
|
|
190
|
-
clearRequestAck();
|
|
191
|
-
requestAck = setTimeout(() => {
|
|
192
|
-
requestAck = null;
|
|
193
|
-
if (!requested) return;
|
|
194
|
-
requested = false;
|
|
195
|
-
responseActive = false;
|
|
196
|
-
on.warn("The voice API never answered a response we asked for.");
|
|
197
|
-
settle();
|
|
198
|
-
}, RESPONSE_ACK_MS);
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
/** Reports changed activity and, when the line is quiet, sends what is pending. */
|
|
202
|
-
const settle = () => {
|
|
203
|
-
if (hungUp) return;
|
|
204
|
-
|
|
205
|
-
// `answered > 0` keeps the episode alive between a tool output and the
|
|
206
|
-
// follow-up request, when nothing is outstanding or awaited yet.
|
|
207
|
-
const busy = outstanding.size > 0 || awaiting || answered > 0;
|
|
208
|
-
const activity: RealtimeActivity = {
|
|
209
|
-
speaking: playing,
|
|
210
|
-
hearing: userSpeaking,
|
|
211
|
-
tools: busy ? episode : [],
|
|
212
|
-
};
|
|
213
|
-
const key = JSON.stringify(activity);
|
|
214
|
-
if (key !== shown) {
|
|
215
|
-
shown = key;
|
|
216
|
-
on.activity(activity);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Nothing is requested while anyone speaks, a response runs, or a tool is out.
|
|
220
|
-
if (
|
|
221
|
-
userSpeaking ||
|
|
222
|
-
responseActive ||
|
|
223
|
-
serverTurn ||
|
|
224
|
-
playing ||
|
|
225
|
-
outstanding.size > 0
|
|
226
|
-
) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
const continuing = answered > 0;
|
|
230
|
-
if (!continuing && queue.length === 0) return;
|
|
231
|
-
|
|
232
|
-
for (const text of queue.splice(0)) {
|
|
233
|
-
transport.send({
|
|
234
|
-
type: "conversation.item.create",
|
|
235
|
-
item: {
|
|
236
|
-
type: "message",
|
|
237
|
-
role: "system",
|
|
238
|
-
content: [{ type: "input_text", text }],
|
|
239
|
-
},
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
answered = 0;
|
|
243
|
-
awaiting = continuing;
|
|
244
|
-
// Counted as active until confirmed or refused.
|
|
245
|
-
responseActive = true;
|
|
246
|
-
requested = true;
|
|
247
|
-
expectRequestAck();
|
|
248
|
-
transport.send({ type: "response.create" });
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
const onToolCall = (call: {
|
|
252
|
-
call_id: string;
|
|
253
|
-
name: string;
|
|
254
|
-
arguments: string;
|
|
255
|
-
}) => {
|
|
256
|
-
// A new episode does not inherit the last one's names.
|
|
257
|
-
if (outstanding.size === 0 && !awaiting) episode = [];
|
|
258
|
-
episode = [...episode, call.name];
|
|
259
|
-
outstanding.set(call.call_id, call.name);
|
|
260
|
-
|
|
261
|
-
void on
|
|
262
|
-
.runTool({
|
|
263
|
-
id: call.call_id,
|
|
264
|
-
name: call.name,
|
|
265
|
-
arguments: call.arguments,
|
|
266
|
-
})
|
|
267
|
-
// A throwing runner must not stall the session.
|
|
268
|
-
.catch((cause) => `Error: ${errorToString(cause)}`)
|
|
269
|
-
.then((output) => {
|
|
270
|
-
if (hungUp) return;
|
|
271
|
-
// Sent immediately; only the follow-up waits.
|
|
272
|
-
transport.send({
|
|
273
|
-
type: "conversation.item.create",
|
|
274
|
-
item: {
|
|
275
|
-
type: "function_call_output",
|
|
276
|
-
call_id: call.call_id,
|
|
277
|
-
output,
|
|
278
|
-
},
|
|
279
|
-
});
|
|
280
|
-
outstanding.delete(call.call_id);
|
|
281
|
-
answered += 1;
|
|
282
|
-
settle();
|
|
283
|
-
});
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const handle = (event: RealtimeServerEvent) => {
|
|
287
|
-
switch (event.type) {
|
|
288
|
-
case "session.updated":
|
|
289
|
-
opening?.resolve();
|
|
290
|
-
break;
|
|
291
|
-
|
|
292
|
-
case "error": {
|
|
293
|
-
const message =
|
|
294
|
-
event.error?.message ?? "The voice API reported an error";
|
|
295
|
-
// Whatever was refused, our response request is no longer pending.
|
|
296
|
-
if (requested) {
|
|
297
|
-
requested = false;
|
|
298
|
-
responseActive = false;
|
|
299
|
-
clearRequestAck();
|
|
300
|
-
}
|
|
301
|
-
if (opening) opening.reject(new Error(message));
|
|
302
|
-
else on.warn(message);
|
|
303
|
-
break;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
case "input_audio_buffer.speech_started":
|
|
307
|
-
userSpeaking = true;
|
|
308
|
-
clearServerTurn();
|
|
309
|
-
break;
|
|
310
|
-
|
|
311
|
-
case "input_audio_buffer.speech_stopped":
|
|
312
|
-
userSpeaking = false;
|
|
313
|
-
expectServerTurn();
|
|
314
|
-
break;
|
|
315
|
-
|
|
316
|
-
case "input_audio_buffer.committed":
|
|
317
|
-
reserve(event.item_id, "user");
|
|
318
|
-
break;
|
|
319
|
-
|
|
320
|
-
case "conversation.item.added":
|
|
321
|
-
case "conversation.item.created":
|
|
322
|
-
if (event.item.type === "message" && event.item.role !== "system") {
|
|
323
|
-
reserve(event.item.id, event.item.role);
|
|
324
|
-
}
|
|
325
|
-
break;
|
|
326
|
-
|
|
327
|
-
case "response.output_item.added":
|
|
328
|
-
if (event.item.type === "message") {
|
|
329
|
-
reserve(event.item.id, "assistant");
|
|
330
|
-
} else if (event.item.type === "function_call") {
|
|
331
|
-
// A tool call holds a turn slot too (arguments instead of words).
|
|
332
|
-
reserve(event.item.id, "tool");
|
|
333
|
-
}
|
|
334
|
-
break;
|
|
335
|
-
|
|
336
|
-
case "conversation.item.input_audio_transcription.delta":
|
|
337
|
-
write(event.item_id, "user", event.delta ?? "", "append");
|
|
338
|
-
break;
|
|
339
|
-
|
|
340
|
-
case "conversation.item.input_audio_transcription.updated":
|
|
341
|
-
write(event.item_id, "user", event.transcript, "replace");
|
|
342
|
-
break;
|
|
343
|
-
|
|
344
|
-
case "conversation.item.input_audio_transcription.completed":
|
|
345
|
-
write(event.item_id, "user", event.transcript ?? "", "replace");
|
|
346
|
-
// Not always the end of the turn. xAI sends this while the user is
|
|
347
|
-
// still speaking, each time with a longer transcript and `in_progress`
|
|
348
|
-
// on it; finishing on the first froze the turn at its opening words
|
|
349
|
-
// and every later transcript was written but never reported (`write`
|
|
350
|
-
// reports only what is not finalized). A provider that sends it once
|
|
351
|
-
// omits the field, so anything but `in_progress` ends the turn.
|
|
352
|
-
if (event.status !== "in_progress") finish(event.item_id);
|
|
353
|
-
break;
|
|
354
|
-
|
|
355
|
-
// A turn nobody could read. Without this the item simply never gets
|
|
356
|
-
// words, and an item with no words is not reported at all (`report`) —
|
|
357
|
-
// the turn disappears from the transcript, and every reader downstream
|
|
358
|
-
// sees a conversation the user did not have.
|
|
359
|
-
case "conversation.item.input_audio_transcription.failed":
|
|
360
|
-
on.warn(
|
|
361
|
-
event.error?.message
|
|
362
|
-
? `That turn could not be transcribed: ${event.error.message}`
|
|
363
|
-
: "That turn could not be transcribed.",
|
|
364
|
-
);
|
|
365
|
-
break;
|
|
366
|
-
|
|
367
|
-
case "response.output_audio_transcript.delta":
|
|
368
|
-
write(event.item_id, "assistant", event.delta, "append");
|
|
369
|
-
break;
|
|
370
|
-
|
|
371
|
-
case "response.output_audio_transcript.done":
|
|
372
|
-
// Replace with the full transcript in case a delta was lost.
|
|
373
|
-
if (event.transcript) {
|
|
374
|
-
write(event.item_id, "assistant", event.transcript, "replace");
|
|
375
|
-
}
|
|
376
|
-
finish(event.item_id);
|
|
377
|
-
break;
|
|
378
|
-
|
|
379
|
-
case "response.created":
|
|
380
|
-
responseActive = true;
|
|
381
|
-
requested = false;
|
|
382
|
-
clearRequestAck();
|
|
383
|
-
clearServerTurn();
|
|
384
|
-
break;
|
|
385
|
-
|
|
386
|
-
case "response.done":
|
|
387
|
-
responseActive = false;
|
|
388
|
-
awaiting = false;
|
|
389
|
-
if (event.response.status === "failed") {
|
|
390
|
-
on.warn(describeFailure(event.response));
|
|
391
|
-
}
|
|
392
|
-
// An interrupted answer never gets its transcript `done`.
|
|
393
|
-
for (const item of event.response.output ?? []) {
|
|
394
|
-
if (item.type === "message") finish(item.id);
|
|
395
|
-
}
|
|
396
|
-
flushSpoken();
|
|
397
|
-
break;
|
|
398
|
-
|
|
399
|
-
case "response.function_call_arguments.done":
|
|
400
|
-
// Complete arguments make the tool turn final.
|
|
401
|
-
reserve(event.item_id, "tool");
|
|
402
|
-
{
|
|
403
|
-
const index = slot.get(event.item_id) as number;
|
|
404
|
-
turns[index] = {
|
|
405
|
-
...turns[index],
|
|
406
|
-
tool: event.name,
|
|
407
|
-
text: event.arguments || "{}",
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
finish(event.item_id);
|
|
411
|
-
onToolCall(event);
|
|
412
|
-
break;
|
|
413
|
-
|
|
414
|
-
default:
|
|
415
|
-
// Providers speak this protocol with their own additions, and a case
|
|
416
|
-
// that is missing here is invisible: the event is dropped and the
|
|
417
|
-
// conversation quietly loses whatever it carried. Once per type per
|
|
418
|
-
// session, so a busy stream cannot drown the log.
|
|
419
|
-
if (!seenUnhandled.has(event.type)) {
|
|
420
|
-
seenUnhandled.add(event.type);
|
|
421
|
-
logger.debug(`realtime: no case for ${event.type}`);
|
|
422
|
-
}
|
|
423
|
-
break;
|
|
424
|
-
}
|
|
425
|
-
settle();
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
const transport = dialect.transport({
|
|
429
|
-
credential,
|
|
430
|
-
setup,
|
|
431
|
-
audio,
|
|
432
|
-
on: {
|
|
433
|
-
event: handle,
|
|
434
|
-
playing: (next) => {
|
|
435
|
-
playing = next;
|
|
436
|
-
if (next) awaiting = false;
|
|
437
|
-
settle();
|
|
438
|
-
},
|
|
439
|
-
dropped: (message) => {
|
|
440
|
-
if (opening) opening.reject(new Error(message));
|
|
441
|
-
else on.failed(message);
|
|
442
|
-
},
|
|
443
|
-
},
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
return {
|
|
447
|
-
async connect() {
|
|
448
|
-
await transport.connect();
|
|
449
|
-
if (hungUp) throw new Error("Hung up before the session opened.");
|
|
450
|
-
|
|
451
|
-
transport.send(dialect.sessionUpdate(setup));
|
|
452
|
-
await new Promise<void>((resolve, reject) => {
|
|
453
|
-
opening = { resolve, reject };
|
|
454
|
-
// A server that never acknowledges is let through.
|
|
455
|
-
ackTimer = setTimeout(resolve, SESSION_ACK_MS);
|
|
456
|
-
}).finally(() => {
|
|
457
|
-
opening = null;
|
|
458
|
-
if (ackTimer) clearTimeout(ackTimer);
|
|
459
|
-
ackTimer = null;
|
|
460
|
-
});
|
|
461
|
-
},
|
|
462
|
-
|
|
463
|
-
close() {
|
|
464
|
-
// Finalize whatever is still open.
|
|
465
|
-
for (const turn of turns) finish(turn.id);
|
|
466
|
-
hungUp = true;
|
|
467
|
-
clearServerTurn();
|
|
468
|
-
clearRequestAck();
|
|
469
|
-
opening?.reject(new Error("Hung up before the session opened."));
|
|
470
|
-
transport.close();
|
|
471
|
-
},
|
|
472
|
-
|
|
473
|
-
mute: (muted) => transport.mute(muted),
|
|
474
|
-
|
|
475
|
-
say(text) {
|
|
476
|
-
if (hungUp) return;
|
|
477
|
-
queue.push(text);
|
|
478
|
-
settle();
|
|
479
|
-
},
|
|
480
|
-
};
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
function describeFailure(response: RealtimeResponse) {
|
|
485
|
-
return (
|
|
486
|
-
response.status_details?.error?.message ??
|
|
487
|
-
"The model could not finish answering"
|
|
488
|
-
);
|
|
489
|
-
}
|