thursday-agent 0.5.0 → 0.7.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 +11 -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]__0-06t3f._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__02846fb._.js +8 -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]__06l05n_._.js +3 -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]__0btqrct._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0c9fgca._.js +5 -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]__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/_1gnjfli._.js +3 -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_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]__0-e011f._.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]__0lyi8i2._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0pd8yr7._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__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]__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]__1vdmfbe._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1waa3rc._.js +85 -0
- package/.next/server/chunks/ssr/_0-2qsxo._.js +3 -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/_05yghx6._.js +3 -0
- package/.next/server/chunks/ssr/_07nbwap._.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/{_0m2lsd1._.js → _0b6_jv-._.js} +2 -2
- package/.next/server/chunks/ssr/_0evkpto._.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/_0no7i1o._.js +3 -0
- package/.next/server/chunks/ssr/_0tzg--b._.js +3 -0
- 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/_114ylv7._.js +7 -0
- package/.next/server/chunks/ssr/_123y-ah._.js +3 -0
- package/.next/server/chunks/ssr/_12c-iwh._.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/_167hchk._.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/_1_krfph._.js +3 -0
- package/.next/server/chunks/ssr/{_0rzucul._.js → _1_x5spz._.js} +3 -3
- package/.next/server/chunks/ssr/_1a61fc9._.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/_1rgtxhr._.js +5 -0
- package/.next/server/chunks/ssr/_1slp25y._.js +3 -0
- package/.next/server/chunks/ssr/_1w_t7h7._.js +101 -0
- package/.next/server/chunks/ssr/{_0s99bgb._.js → _1wyfaq_._.js} +9 -3
- package/.next/server/chunks/ssr/_200gt-m._.js +102 -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/features_workspace_00jz2hu._.js +8 -0
- package/.next/server/chunks/ssr/{_1-teee5._.js → lib_logger_ts_0-olsze._.js} +2 -7
- package/.next/server/chunks/ssr/{node_modules_05-n6dz._.js → node_modules_02ai7br._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1chvq5f._.js → node_modules_02deexj._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0m383r2._.js → node_modules_07za262._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_07dsgkx._.js → node_modules_0_s9get._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1a0kmjl._.js → node_modules_0n3c7h0._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0zeg3x_._.js → node_modules_0od6jwr._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1y79i83._.js → node_modules_0rdt7pk._.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_04sksn9._.js → node_modules_0w1z7kz._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1uyk91w._.js → node_modules_0wdupfz._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0ifp389._.js → node_modules_1720w0a._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0u9da1h._.js → node_modules_18lsg7d._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1k6n600._.js → node_modules_1b94fxf._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_20c28js._.js → node_modules_1ecdo1s._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0fkeku3._.js → node_modules_1fa9ag7._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1j8j4pt._.js → node_modules_1fv-_si._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0-dr_o7._.js → node_modules_1hf461g._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1lz0oxc._.js → node_modules_1m71ta-._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1t77e4n._.js → node_modules_1n93n-g._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_16mkxuo._.js → node_modules_1n9lqu9._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1k7z2j6._.js → node_modules_1npnsvd._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_056qgf-._.js → node_modules_1rn2r0n._.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_0bvopy2._.js → node_modules_1vq-mfk._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0iur59s._.js → node_modules_1vzyw1t._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1k8j8n0._.js → node_modules_1w359w4._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1x0ztf4._.js → node_modules_1yajbl6._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1-y7nni._.js → node_modules_20eqhy8._.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_019sbis._.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_0s6piq3._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@vercel_oidc_dist_1o553h-._.js → node_modules_@vercel_oidc_dist_05itbb1._.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/07vqbk_9t4em4.js +2 -0
- package/.next/static/chunks/08krja1zx7nqg.js +1 -0
- package/.next/static/chunks/0g4b348l0pve7.js +1 -0
- package/.next/static/chunks/0qcuwdk132jjt.js +1 -0
- package/.next/static/chunks/0vlgzqo9ka90v.js +1 -0
- package/.next/static/chunks/{11r2yp_yh9_qn.js → 0z69gvysmave7.js} +1 -1
- package/.next/static/chunks/0zrupxgci5gqc.js +1 -0
- package/.next/static/chunks/12fvz1w5ows75.js +1 -0
- package/.next/static/chunks/14t03ned286iu.js +1 -0
- package/.next/static/chunks/156xxbkrz5lzu.js +18 -0
- package/.next/static/chunks/1fz14reod4lft.js +1 -0
- package/.next/static/chunks/1g23dbabl-vkr.js +1 -0
- package/.next/static/chunks/1ohslk4568tm3.js +1 -0
- package/.next/static/chunks/1qy_rc3oxfxok.js +1 -0
- package/.next/static/chunks/1sbmwswc9k2-1.js +1 -0
- package/.next/static/chunks/1vqezbhjm3goq.js +1 -0
- package/.next/static/chunks/1zea7qdl-7365.js +1 -0
- package/.next/static/chunks/1zvqumkg7kmo0.css +1 -0
- package/.next/static/chunks/26hpqt3y6bogl.js +12 -0
- package/.next/static/chunks/2_j5mqm6d-z18.js +99 -0
- package/.next/static/chunks/2dt6tu7a22svs.js +1 -0
- package/.next/static/chunks/2h5ls3d86kya6.js +1 -0
- package/.next/static/chunks/2wc6y1ht6dfuy.js +1 -0
- package/.next/static/chunks/{435atsnhs7ksu.js → 2xr0zpll7thyi.js} +2 -2
- package/.next/static/chunks/31jztc-yq30m7.js +1 -0
- package/.next/static/chunks/391af0i8eljzk.js +1 -0
- package/.next/static/chunks/3bfwpww3m3x4u.js +1 -0
- package/.next/static/chunks/{38gweqdo4jpfj.js → 3izg0a3k87q1-.js} +5 -5
- package/.next/static/chunks/3p2s2cjokx1aa.js +5 -0
- package/.next/static/chunks/{408ueu4hfvcg7.js → 41s3fml5oivsa.js} +1 -1
- package/README.md +45 -193
- 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 +40 -35
- package/docs/images/keeps-going.png +0 -0
- package/docs/images/two-minds.png +0 -0
- package/docs/live-calls.md +236 -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 +152 -79
- 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 +169 -0
- package/features/ai/prompts/prompt-helper.ts +92 -32
- package/features/ai/prompts/thursday.prompt.ts +164 -190
- package/features/ai/tools/bot.tool.ts +38 -145
- package/features/ai/tools/call.tool.ts +33 -5
- 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 +3 -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 +463 -864
- 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/ascii.const.ts +74 -0
- package/features/thursday/components/ascii-field.tsx +24 -44
- package/features/thursday/components/ascii-orb.tsx +525 -381
- package/features/thursday/components/call-log.tsx +46 -44
- package/features/thursday/components/face.tsx +40 -10
- package/features/thursday/components/side-captions.tsx +273 -0
- package/features/thursday/components/tab-state.tsx +14 -6
- package/features/thursday/components/thursday-mark.tsx +1 -0
- package/features/thursday/components/thursday-setting.tsx +633 -333
- package/features/thursday/components/thursday.tsx +315 -274
- package/features/thursday/components/voice-picker.tsx +255 -0
- package/features/thursday/face.store.ts +5 -0
- package/features/thursday/thursday.action.ts +96 -72
- package/features/thursday/thursday.query.ts +49 -30
- package/features/thursday/thursday.schema.ts +37 -35
- package/features/thursday/thursday.store.ts +14 -7
- package/features/thursday/tool-call.ts +3 -3
- package/features/thursday/tool-line.ts +5 -3
- package/features/thursday/use-thursday.ts +801 -457
- package/features/workspace/file-kind.ts +9 -0
- package/features/workspace/workspace.query.ts +17 -0
- package/features/workspace/workspace.ts +82 -36
- package/hooks/use-hotkey.ts +3 -2
- package/lib/live/live.schema.ts +26 -0
- package/lib/live/live.server.ts +153 -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 +38 -0
- package/scripts/bot-context.test.mts +1408 -0
- package/scripts/live-history.test.mts +115 -0
- package/scripts/live-session.test.mts +938 -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/_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 → yyRVBc0xxYQsh3GpbQX9b}/_buildManifest.js +0 -0
- /package/.next/static/{G6-gNoyGDEcgAsq-L4PE1 → yyRVBc0xxYQsh3GpbQX9b}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{G6-gNoyGDEcgAsq-L4PE1 → yyRVBc0xxYQsh3GpbQX9b}/_ssgManifest.js +0 -0
package/docs/how-it-works.md
CHANGED
|
@@ -1,63 +1,68 @@
|
|
|
1
1
|
# How it works
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
What each part does, so you can guess what will happen before you say it.
|
|
4
4
|
|
|
5
5
|
## The call
|
|
6
6
|
|
|
7
|
-
A call
|
|
7
|
+
A call runs on two models: **GPT-Live 1** holds the conversation, and a Responses model (**GPT-5.6 Luna** by default) thinks and uses tools behind it. The voice keeps listening while the backend works.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+

|
|
10
10
|
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
11
|
+
- **Quick things, she answers herself.** She reads and writes your memory and runs one shell command at a time: open a file, check a folder, play something.
|
|
12
|
+
- **Everything else goes to a bot.** She hands it over and keeps talking. A speech model that ran a browser itself would go silent for minutes.
|
|
13
|
+
- **When a job comes back,** she tells you in a sentence. A file it made opens on your screen, and a question it asks shows up as buttons.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Settings › Thursday picks the voice, the backend model and its reasoning, web search, the wake word and hotkey, and whether she calls you when a job ends.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The voice is billed per active minute, silence included; the backend is billed per token. Both use your OpenAI API key, not a ChatGPT subscription.
|
|
18
18
|
|
|
19
19
|
## Bots
|
|
20
20
|
|
|
21
|
-
A bot
|
|
21
|
+

|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
- a **real browser** (Chromium through Playwright), headless until a sign-in or something you should see, and able to attach to the Chrome you already use
|
|
25
|
-
- the **filesystem**, read anywhere, written only inside the workspace and where you pointed it
|
|
26
|
-
- **skills** — written-down methods it reads before starting: the browser, this Mac, building a page, finding and writing skills
|
|
27
|
-
- **MCP servers** you connected, searched by name and called by schema, with OAuth handled
|
|
28
|
-
- a **studio** of image, video, speech and transcription models
|
|
29
|
-
- **each other**: a bot hands a part of its job to the bot that exists for it, and folds the answer into its own report
|
|
23
|
+
A bot is a text model from any provider you added, with:
|
|
30
24
|
|
|
31
|
-
|
|
25
|
+
- a **shell** in a workspace folder
|
|
26
|
+
- a **real browser** — its own, or the Chrome you already use
|
|
27
|
+
- **your files** — it reads anywhere and writes where your user can; only its file tool is kept out of the app and the workspace root ([SECURITY.md](../SECURITY.md))
|
|
28
|
+
- **skills**, methods it reads before it starts
|
|
29
|
+
- **MCP servers** you connected
|
|
30
|
+
- a **studio** for images, video, speech, and transcription
|
|
31
|
+
- **each other**, to hand off part of a job
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
The first run lets you pick a few starter bots; more are ready in Settings › Bots, or make your own with a name and one sentence about what it is for. That sentence is how Thursday decides who gets a job. Switch a bot off without deleting it.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
A job ends in the thing you asked for and a short report. Anything longer than a few lines is a file in `artifacts/`. When only you can do something — sign in, choose between two real options — the bot sets it up, asks, and waits. It never presses Pay: a purchase stops on the last screen, left open for you.
|
|
36
36
|
|
|
37
|
-
Each bot keeps its own memory as files
|
|
37
|
+
Each bot keeps its own memory as files you can open from its page.
|
|
38
38
|
|
|
39
39
|
## Jobs outlive the call
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+

|
|
42
42
|
|
|
43
|
-
A job
|
|
43
|
+
- A job runs on the local server, not in the call. Hang up and it keeps going.
|
|
44
|
+
- Every step is saved, so a job that stopped to ask picks up where it left off, and you can read the whole thread.
|
|
45
|
+
- Close the app, and after ten seconds running jobs pause. Open it again and they continue, so nothing spends your keys while you are away.
|
|
46
|
+
- A model call that fails is retried once. After that, the job waits for you.
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
## Memory
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
Memory is a set of notes about you, one fact per line: your name, your language, the people you mention, the rules you give her. A few notes go into every call.
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
Open any note in Settings › Memory to see exactly what she knows. To change it, type what changed and watch each edit land. Bots read your memory but never write it.
|
|
50
53
|
|
|
51
|
-
|
|
54
|
+
## Where your data lives
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
```text
|
|
57
|
+
~/.thursday
|
|
58
|
+
├── local.db calls, memory, bots, jobs, keys
|
|
59
|
+
└── .ai-workspace
|
|
60
|
+
├── artifacts/ finished work, a folder per bot
|
|
61
|
+
├── projects/ code and longer-lived projects
|
|
62
|
+
├── bots/ each bot's memory and saved sessions
|
|
63
|
+
└── .agents/ skills you installed
|
|
64
|
+
```
|
|
54
65
|
|
|
55
|
-
|
|
66
|
+
When you run from source, the same files live in the checkout. The server listens only on `127.0.0.1`, and there is no login — see [SECURITY.md](../SECURITY.md).
|
|
56
67
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
- **No cloud.** The server is the one on your machine; keys are stored locally and sent only to the provider you chose.
|
|
60
|
-
- **No account.** There is nothing to sign up for. There is also no login, which is why the server binds to `127.0.0.1` — see [SECURITY.md](../SECURITY.md).
|
|
61
|
-
- **No prompt engineering on your side.** The prompts are assembled from your data on every session; the one thing you can add is an instruction to her, and one to each bot, in settings.
|
|
62
|
-
|
|
63
|
-
For the code — which file owns what, and why — read [CLAUDE.md](../CLAUDE.md).
|
|
68
|
+
For contributors: [live calls](live-calls.md) and [thread rooms](thread-rooms.md) are the engine contracts, and [AGENTS.md](../AGENTS.md) maps the code.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Live calls
|
|
2
|
+
|
|
3
|
+
Thursday uses GPT-Live 1 for voice and Responses delegation for short reasoning and
|
|
4
|
+
tool use. The default backend is GPT-5.6 Luna. Background bots keep their own
|
|
5
|
+
models, prompts, durable threads, and execution budgets; the voice settings do not
|
|
6
|
+
change the text or media providers available to them.
|
|
7
|
+
|
|
8
|
+
This document is the implementation contract for calls. Keep it aligned with the
|
|
9
|
+
code when changing session events, settings, prompts, or persistence.
|
|
10
|
+
|
|
11
|
+
## Responsibilities
|
|
12
|
+
|
|
13
|
+
| Runtime | Context and instructions | Work |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| Live voice | `live.prompt`: who Thursday is; under `## Always` the ending rule, backchannel, interruption and a short delegation policy; profile and preferences with the note listing | Listen, speak, backchannel, handle interruptions, hand everything but conversation to the backend |
|
|
16
|
+
| Responses backend | `thursday.prompt`: who Thursday is, memory with ids, bot roster, threads and what bots can reach, this computer, what to return, earlier calls with their jobs; tool schemas | Recall, update and tidy memory, run short commands, ask before handing work over, route thread messages and cancellations, delegate long work |
|
|
17
|
+
| Background bots | `bot.prompt` and the stored participant transcript | Shell, browser, MCP, skills, and work that outlives a call |
|
|
18
|
+
| Application | Authoritative database and tool implementations | Validate actions, retain results, enforce thread limits, render progress, save call history |
|
|
19
|
+
|
|
20
|
+
Use Responses delegation because Live supplies conversation context and manages the
|
|
21
|
+
backend connection. Do not build a second transcript-to-thread orchestrator. Client
|
|
22
|
+
delegation is a different integration: its notification contains metadata, not thread
|
|
23
|
+
text, so the application would have to reconstruct the request and operate the backend.
|
|
24
|
+
|
|
25
|
+
The voice and the backend are one assistant. Both prompts open with the same identity
|
|
26
|
+
(`thursdayIdentity`) and the same rule for ending the call (`callEnding`), read the same
|
|
27
|
+
memory, and neither is told it is part of something else. The voice holds conversation and
|
|
28
|
+
memory only. Right under the identity, `## Always` groups what holds on every turn: the ending
|
|
29
|
+
rule (the only line marked `IMPORTANT`), the guide's starter backchannel and interruption
|
|
30
|
+
policies, and under the guide's `Delegation policy` label three lines — hand everything but
|
|
31
|
+
greetings, small talk and a brief clarification to the backend; hand over whatever the user says
|
|
32
|
+
about themselves, their people, their plans or how they want things done as they say it, unless
|
|
33
|
+
it is already written in the prompt; answer from what the backend returns without guessing while
|
|
34
|
+
waiting. Live decides by itself whether to delegate, so the rule stays even this short. It says
|
|
35
|
+
nothing else about how to speak; it sees no tool schema and no tool name but `end_call`, in the
|
|
36
|
+
ending rule. The backend prompt holds the work: memory (merging a fact that repeats or changes one
|
|
37
|
+
already kept, and tidying with the user past the limits), background work and threads, this
|
|
38
|
+
computer, what to return, and the earlier calls. Before handing work to a bot it returns one question — which bot, a new thread or
|
|
39
|
+
one already open — unless the user already said or left it to Thursday.
|
|
40
|
+
|
|
41
|
+
## Settings and upgrades
|
|
42
|
+
|
|
43
|
+
Voice uses the fixed `gpt-live-1` model. Settings › Thursday exposes a voice and
|
|
44
|
+
additional voice instructions; for the backend, a model,
|
|
45
|
+
optional reasoning effort, web search, and additional backend instructions. Both
|
|
46
|
+
instruction fields add to the app's prompts and never replace them. The model list
|
|
47
|
+
shows recent models; an older or custom ID can be typed and saved. Live accepts any
|
|
48
|
+
reasoning settings when the call opens and fails the backend's first response when the
|
|
49
|
+
model does not take one, so the server asks the token-count endpoint first
|
|
50
|
+
(`acceptedReasoning`), once per model and effort. A setting refused by name, the effort or
|
|
51
|
+
the summary, is dropped and not shown; a refused model or key still reaches the user when the
|
|
52
|
+
call opens. Auto reasoning sends no effort.
|
|
53
|
+
Web search adds the `web_search` tool only when switched on. Changes apply from the
|
|
54
|
+
next call.
|
|
55
|
+
|
|
56
|
+
Settings stay in the browser under the existing `thursday.settings` key, beside wake
|
|
57
|
+
word, shortcut, captions and call-back (`thursday.store`). `migrateLiveSettings`
|
|
58
|
+
upgrades stored values: an OpenAI voice and backend model carry over, a Grok voice is
|
|
59
|
+
retired without touching historical calls or xAI text and media keys, and the old
|
|
60
|
+
shared instruction is copied into both new instruction fields. Each field recovers on
|
|
61
|
+
its own, so one malformed value falls back to its default and leaves the rest.
|
|
62
|
+
|
|
63
|
+
Every call is kept on this machine. Live transcription needs no separate model or
|
|
64
|
+
request, so there is nothing to switch off to save cost. Keep `store: false` in the
|
|
65
|
+
provider request: local history is distinct from OpenAI session recording and fork
|
|
66
|
+
storage.
|
|
67
|
+
|
|
68
|
+
## Connection and opening
|
|
69
|
+
|
|
70
|
+
1. In the user's gesture, before anything awaits, prepare playback. Then request
|
|
71
|
+
microphone access and gather WebRTC ICE.
|
|
72
|
+
2. Send the SDP offer and the parsed settings to `openCallAction`. The browser sends
|
|
73
|
+
settings only; the server reads the key.
|
|
74
|
+
3. On the server, assemble both prompts and the current tool manifest. Create the
|
|
75
|
+
Live session with the fixed voice model, the chosen voice, voice instructions and
|
|
76
|
+
`delegation.responses` backend settings. No `input`: earlier calls are the backend's to read.
|
|
77
|
+
Insert the call row only after the provider accepts, so a refusal leaves no open row.
|
|
78
|
+
4. Apply the SDP answer and wait for `session.started`. Do not send Realtime startup
|
|
79
|
+
configuration, audio commits, or a voice `response.create`.
|
|
80
|
+
5. Send the opening as `session.instructions.append`, so she speaks first: a first call
|
|
81
|
+
(no profile facts) greets the user and asks what to call them, and any other call opens
|
|
82
|
+
with a short greeting.
|
|
83
|
+
Updates that arrived while connecting follow once she has voiced the opening.
|
|
84
|
+
For work that changed after the last call ended (a call tells what came up during it),
|
|
85
|
+
the page rings instead of opening a line (call-back): the user answers it like any
|
|
86
|
+
call, declines it, or lets it ring out after `CALL_BACK.ringMs`. An answered ring opens
|
|
87
|
+
with the fact that
|
|
88
|
+
she placed it, ahead of every other opening, and the first open work goes in as soon
|
|
89
|
+
as she has voiced that, without waiting for a quiet line: why she called is the first
|
|
90
|
+
thing asked. The opening names no bot text; the work itself follows as commentary.
|
|
91
|
+
|
|
92
|
+
A hang-up during startup invalidates that attempt, so a connection that finishes
|
|
93
|
+
later is closed rather than taking over the screen. Do not change machine trust,
|
|
94
|
+
certificate, or proxy configuration to hide connection errors.
|
|
95
|
+
|
|
96
|
+
## Tools and background updates
|
|
97
|
+
|
|
98
|
+
Live speech and backend work have independent lifecycles. Unwrap `response.event`
|
|
99
|
+
and associate its delegation with the response ID from `response.created`. Collect
|
|
100
|
+
complete function calls from `response.output_item.done`, deduplicate by call ID, and
|
|
101
|
+
run existing server handlers through the tool-call route. Terminal response snapshots
|
|
102
|
+
intentionally omit output items. Submit every function output with
|
|
103
|
+
`response.item.create`, then explicitly continue with one `response.create`. That
|
|
104
|
+
command continues backend work; it does not grant permission for Live to speak. A
|
|
105
|
+
response that ends incomplete after asking for tools is still continued once its outputs
|
|
106
|
+
are in, or the backend turn never finishes; a failed or cancelled response, or a second
|
|
107
|
+
incomplete in a row, only warns. A function call the output cap cuts off arrives as an
|
|
108
|
+
item with status `incomplete` and fragment arguments, and Live ends that handoff with a
|
|
109
|
+
top-level `error` instead of a terminal event: the call is not run and its response
|
|
110
|
+
counts as finished, though calls it completed before the cut still have their results
|
|
111
|
+
continued once. The backend is asked for `reasoning.summary: "auto"` unless the
|
|
112
|
+
effort is `none`. Each finished summary part (nested `response.reasoning_summary_text.done`,
|
|
113
|
+
only while the model reasons) is stored with its call in `call_thought` to look into
|
|
114
|
+
later; while the backend has the turn, the activity line shows the bold title of the latest
|
|
115
|
+
one, and nothing reads it back into a prompt. Tools are sent without `strict`, so each schema that allows it is
|
|
116
|
+
decoded to the schema; `strict: false` would let a model write arguments that are not
|
|
117
|
+
JSON, and `strict: true` is refused while any schema has optional fields. Live has no
|
|
118
|
+
`response.cancel`.
|
|
119
|
+
|
|
120
|
+
Long work enters the existing bot runner and returns a thread receipt immediately.
|
|
121
|
+
Background questions and results follow the existing durable relay queue. A voice
|
|
122
|
+
interruption never cancels a thread by itself. Route an explicit cancellation or
|
|
123
|
+
correction to the owning thread and report its actual outcome.
|
|
124
|
+
|
|
125
|
+
| Update | Live event |
|
|
126
|
+
| --- | --- |
|
|
127
|
+
| Opening, idle goodbye, other trusted behavior | `session.instructions.append` |
|
|
128
|
+
| Screen actions the voice should know but need not say | `session.thinking.append` |
|
|
129
|
+
| A bot's result or question to convey | `session.commentary.append` |
|
|
130
|
+
|
|
131
|
+
Bot output is never sent as instructions. Each append carries a required
|
|
132
|
+
`delegation_id`, `null` for application updates in Responses mode; a response ID is
|
|
133
|
+
not a client delegation ID. Appends are serialized and matched to their
|
|
134
|
+
acknowledgement by `client_event_id`. An update longer than one append is split at
|
|
135
|
+
word boundaries under 480 UTF-8 bytes, which keeps within the 500-token limit for any
|
|
136
|
+
script, and sent chunk by chunk. A rejected or unacknowledged chunk drops the rest of
|
|
137
|
+
its update, warns, and is never replayed. An acknowledgement is not proof of speech.
|
|
138
|
+
|
|
139
|
+
Live never speaks unprompted, so what waits on the user reaches them only when the page puts
|
|
140
|
+
it in. The relay clock (`useThursday` `relayOpenWork`) reads the inbox once a second and sends
|
|
141
|
+
open work only when neither side's words have been transcribed for `CALL_RELAY.quietMs` and
|
|
142
|
+
no backend work or tool is running: questions not answered, jobs stopped or finished and not
|
|
143
|
+
yet seen, and progress from jobs still running. Up to `CALL_RELAY.perTurn` items of one
|
|
144
|
+
kind go in one commentary append, most pressing first, so an ending never shares an append with
|
|
145
|
+
a question. The activity line carries the update from the moment
|
|
146
|
+
it goes out until her voice has finished it, and nothing else goes in until her voice has started
|
|
147
|
+
and stopped (at most `CALL_RELAY.readMs`). An item is handled when it is answered, marked seen
|
|
148
|
+
by the backend's `thread` `seen` once the user has been told enough, or opened on screen — the
|
|
149
|
+
backend's `thread` `open` opens it in the call screen's room (a `showThread` event). Each item
|
|
150
|
+
goes in once a call (`told`, in memory), and it stays in the inbox and on screen until handled.
|
|
151
|
+
One her voice carried stays out of later calls too while the page is open; one it did not (Live
|
|
152
|
+
refused it, she never spoke, the call ended first) goes in again on the next call, never in a
|
|
153
|
+
loop on this one. The key carries the job's last change, so a job that resumes and asks or ends
|
|
154
|
+
again is a new item, and a reload puts what is still open in once more. Nothing goes in while
|
|
155
|
+
the call is ending or a goodbye has been asked for. A relay is facts only, with no note
|
|
156
|
+
ahead of it.
|
|
157
|
+
|
|
158
|
+
A relay names the bot and the thread and, for a question, where its answer goes (thread,
|
|
159
|
+
recipient, `replyTo`). The backend reads relays in its conversation and routes the user's
|
|
160
|
+
answer from those facts, so a relay carries no instructions. Relay rows are accepted
|
|
161
|
+
(`acceptThreadRelaysAction`) once Live acknowledges the append; an ending also covers its
|
|
162
|
+
job's progress rows. Being put to her does not mark a result seen.
|
|
163
|
+
|
|
164
|
+
## Transcript and screen
|
|
165
|
+
|
|
166
|
+
Input and output transcript events contain `delta`, `start_ms`, and `end_ms`. They
|
|
167
|
+
have no authoritative completed-turn event. The session folds fragments into
|
|
168
|
+
revisable display groups by speaker and time, deduplicates them by event ID, and
|
|
169
|
+
checkpoints changed groups every `LIVE_CALL.transcriptSaveMs` with their exact
|
|
170
|
+
fragments. A late fragment revises its group, which is saved again. Never derive
|
|
171
|
+
actions or cancellations from the grouping. Backend text is not a transcript of spoken
|
|
172
|
+
audio and never becomes a caption.
|
|
173
|
+
|
|
174
|
+
`call_message.fragments` keeps the original fragments beside each saved group; a
|
|
175
|
+
revision replaces them and keeps the group's `seq`. Rows written before Live have no
|
|
176
|
+
fragments and remain readable.
|
|
177
|
+
|
|
178
|
+
Track playback and backend work independently, from her audio level and backend events.
|
|
179
|
+
The idle clock rewinds on new transcribed words, her voice and backend work, not on
|
|
180
|
+
microphone level alone, so a noisy room does not hold a call open, and not on an update she
|
|
181
|
+
voices on her own, so waiting results do not either. A sound the transcript writes in
|
|
182
|
+
brackets (`[sigh]`) is not words. After `CALL_IDLE.hangUpMs` the page hangs up without asking
|
|
183
|
+
for a goodbye, which would leave the ending to the model.
|
|
184
|
+
|
|
185
|
+
## Closing and recovery
|
|
186
|
+
|
|
187
|
+
The user wanting the call to end, however they say it, sets everything else aside: the
|
|
188
|
+
voice answers yes and hands it to the backend at once, and the backend runs `end_call`
|
|
189
|
+
without deliberating. The ending rule names `end_call` in the voice prompt too, the one tool
|
|
190
|
+
name it holds: without it, ending read as something to say rather than do.
|
|
191
|
+
The page does not close on `end_call` itself: it waits until her voice has been quiet
|
|
192
|
+
for `CALL_END.quietMs`, or `CALL_END.unsaidMs` when nothing was said, never past
|
|
193
|
+
`CALL_END.maxMs`. `end_call` and `emote` (a word of up to eight characters on her face,
|
|
194
|
+
offered only while the face is the ascii orb) are answered by the page, not the tool-call
|
|
195
|
+
route. A call the user did not end — quiet, `end_call`, Live closing the session, a dropped
|
|
196
|
+
connection — leaves the reason in the idle hint until the next call.
|
|
197
|
+
|
|
198
|
+
Stop accepting new work, send `session.close`, and keep the connection while waiting
|
|
199
|
+
for `session.closed`. Its reason and billed seconds are recorded on the call row
|
|
200
|
+
(`ended_reason`, `seconds`) next to the backend model. Without a confirmation within
|
|
201
|
+
`LIVE_CALL.closeMs`, the call warns and the seconds stay unknown. The screen shows
|
|
202
|
+
Ending until cleanup finishes and blocks a second call during that interval.
|
|
203
|
+
Background jobs follow existing presence rules and survive the call.
|
|
204
|
+
|
|
205
|
+
A new connection is a new session. Seed it with relevant saved history and current
|
|
206
|
+
thread state. Reconcile completed operations and suppress stale results; never replay
|
|
207
|
+
tools merely because the previous connection disappeared. Live charges active session
|
|
208
|
+
time, including silence and backend waits; backend tokens are separate.
|
|
209
|
+
|
|
210
|
+
## Validation
|
|
211
|
+
|
|
212
|
+
`pnpm test:live` covers tool continuation, including the one continuation after an
|
|
213
|
+
incomplete response, fragment grouping and late revision, closing with and without
|
|
214
|
+
confirmation, activity while speaking and working, append ordering, acknowledgement,
|
|
215
|
+
rejection and chunking, the provider request with optional reasoning and web search,
|
|
216
|
+
settings migration, both assembled call prompts and the identity they share, and fragment
|
|
217
|
+
persistence against a migrated database. Also run typecheck, lint, build and
|
|
218
|
+
`pnpm test:bot`, and read both assembled prompts.
|
|
219
|
+
|
|
220
|
+
Inspect settings on desktop and narrow screens. Real-call checks cover a first
|
|
221
|
+
greeting, overlapping speech, a short tool call, a bot
|
|
222
|
+
question answered during other work, correction, cancellation, a late result,
|
|
223
|
+
reconnect, and the recorded seconds. Count durable tool calls and thread
|
|
224
|
+
messages as well as listening to the actual audio.
|
|
225
|
+
|
|
226
|
+
## Official references
|
|
227
|
+
|
|
228
|
+
- [Getting started](https://developers.openai.com/api/docs/guides/live)
|
|
229
|
+
- [Voice prompting](https://developers.openai.com/api/docs/guides/live-prompting)
|
|
230
|
+
- [Sessions, transcripts, and closure](https://developers.openai.com/api/docs/guides/live-conversations)
|
|
231
|
+
- [Responses delegation and updates](https://developers.openai.com/api/docs/guides/live-delegation)
|
|
232
|
+
- [Migration](https://developers.openai.com/api/docs/guides/live-migration)
|
|
233
|
+
- [Partner integrations](https://developers.openai.com/api/docs/guides/live-partner-integrations)
|
|
234
|
+
|
|
235
|
+
Thursday uses direct browser WebRTC. LiveKit, Pipecat, and telephone integrations
|
|
236
|
+
are not required for this media path.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Thread rooms
|
|
2
|
+
|
|
3
|
+
A thread has one coordinator and a persistent participant for each canonical bot name. Thursday introduces the work to the coordinator. Bots exchange messages and run independently; the coordinator brings the results back to Thursday. A model invocation is one period of activity, not a new bot.
|
|
4
|
+
|
|
5
|
+
## Identity and context
|
|
6
|
+
|
|
7
|
+
A participant is identified by `(threadId, bot)`. Every continuation for that participant reads the same stored history, beginning with its original briefing and, after compaction, its latest summary. Requests from a different colleague do not create another context or browser identity. Browser session names derive from the thread and canonical bot name.
|
|
8
|
+
|
|
9
|
+
`parentId` identifies the conversation to which a continuation returns. It does not identify the participant. If A waits for B and B asks A a question, A handles that question in its own context, returns the answer to B, and keeps its original responsibility to report to Thursday. Only exchanged messages enter the other participant's context. The human can inspect all recorded activity; workspace files remain shared resources.
|
|
10
|
+
|
|
11
|
+
## Messages and turns
|
|
12
|
+
|
|
13
|
+
Bots use `send_message(to, text, kind?, options?, replyTo?)`. A send commits before returning a receipt. The sender can continue independent work or end its turn. A natural final message returns to the current correspondent; a silent ending is valid. There is no completion tool or required closing phrase.
|
|
14
|
+
|
|
15
|
+
An explicit `replyTo` routes a message to an open incoming exchange. An ordinary send to another bot opens a new exchange. For Thursday, `kind: "message"` (the default) sends an update without opening a question or delaying completion. Use `kind: "question"` for user input; it carries an addressable question ID and optional answer choices. Other participants continue while a question is open, but the question ends the asker's turn: until it is answered, that bot runs nothing, messages to it wait in its inbox, and words from the user side addressed to it answer the question. With several questions open and none named, an answer is refused with the list. The screen and the call's `thread` tool can direct an answer or a new message to a particular participant. An answer is words like any other: a question that offers `Continue` among its choices is answered by it, and only a stop the app made is resumed by that word.
|
|
16
|
+
|
|
17
|
+
The room and its participants have separate lifecycles:
|
|
18
|
+
|
|
19
|
+
| Continuation state | Meaning |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| `queued` | Ready for the scheduler. |
|
|
22
|
+
| `running` | Claimed by one live turn. |
|
|
23
|
+
| `waiting` | The turn ended with downstream work still open. |
|
|
24
|
+
| `external` | A message to Thursday awaits a user response. |
|
|
25
|
+
| `paused` | Interrupted work awaits a permitted resume. |
|
|
26
|
+
| `done` | The continuation has no unread messages or open downstream work. |
|
|
27
|
+
| `cancelled` | The user stopped the continuation. |
|
|
28
|
+
|
|
29
|
+
Incoming messages queue a waiting continuation. At completion, the engine checks the inbox and downstream work in the same transaction that releases the claim. A message racing with an ending is handled by the current turn or its successor.
|
|
30
|
+
|
|
31
|
+
The coordinator's normal final message completes the thread only when all work has settled. If activity settles without a coordinator report, the scheduler permits one wrap-up turn. An empty final turn leaves an idle, resumable room; it does not cause an automatic retry loop. A participant that already replied with `replyTo` and then ends silently sends nothing more; its reply is the answer.
|
|
32
|
+
|
|
33
|
+
## Durable state
|
|
34
|
+
|
|
35
|
+
`room.query.ts` owns transactional scheduling and messaging. `bot.runner.ts` holds live promises and abort controllers. `bot.run.ts` runs one `ToolLoopAgent` and persists events through the runner.
|
|
36
|
+
|
|
37
|
+
| Table | Responsibility |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `thread` | Room status, coordinator, reporting epoch, automatic turn budget. |
|
|
40
|
+
| `thread_work` | Continuations, return routes, claims and claim generations. |
|
|
41
|
+
| `thread_delivery` | Durable inbox and insertion acknowledgement. |
|
|
42
|
+
| `thread_message` | Model history and the human-visible activity projection. |
|
|
43
|
+
| `thread_relay` | Reports and questions awaiting delivery to Thursday. |
|
|
44
|
+
|
|
45
|
+
A partial unique index allows only one running continuation for a bot in a thread. Model execution never holds the room's command lock. Cancellation and manual resume share that lock; cancellation drains the old runs before a new run can start. Generation checks reject a stale run's attempts to send messages or settle work. Actual tool results received during shutdown are retained before the drain ends.
|
|
46
|
+
|
|
47
|
+
Message receipts use a stable key derived from the thread, sender and tool call ID. A repeated send returns the committed receipt. Recovery also reconstructs a known receipt when the send committed but its tool-result row did not. Inbox insertion and acknowledgement are transactional. Transcript sequence numbers are allocated at the database boundary, so different bots cannot overwrite each other's rows.
|
|
48
|
+
|
|
49
|
+
The SDK can prepare another model step before a streaming consumer finishes writing the previous step. A persistence barrier prevents that next step from starting early. Compaction is written before newly consumed inbox messages, preserving the same ordering on resume.
|
|
50
|
+
|
|
51
|
+
`BOT_RUN` in `config.ts` bounds concurrent participants, distinct participants, pending exchanges, steps per turn and automatic turns across the room. User messages and manual resumes reset the room's turn budget. Browser presence returning does not reset it.
|
|
52
|
+
|
|
53
|
+
## Interruption and recovery
|
|
54
|
+
|
|
55
|
+
Closing the last app browser pauses work; returning resumes only work paused for browser absence. A model call that breaks — a dropped or garbled stream, an overload, a model gone quiet, a context refused as too long — is tried once more from the stored conversation after a short wait, with a note saying why. A second break, a provider's refusal (the key, the credit, the model id), the content filter, a server restart, a resource limit such as the step limit, or a user stop waits for a person. The stored conversation and browser identity remain available. Browser processes, login state and element references may require inspection after a restart.
|
|
56
|
+
|
|
57
|
+
Before a local tool executes, its validated call is stored. Before another model step starts, its result is stored. On resume, a local call with no result receives an interruption result in the model projection: the outcome is unknown and the current state must be inspected before repeating the action. The original audit rows remain intact. Real results are preserved, malformed argument fragments do not become executable calls, and native provider operations without results become explicit interruption notes instead of fabricated local results.
|
|
58
|
+
|
|
59
|
+
This does not provide exactly-once execution against arbitrary external services. A server can disappear after a remote action succeeds and before its result is stored. The engine preserves that uncertainty and offers manual recovery rather than replaying external actions automatically.
|
|
60
|
+
|
|
61
|
+
A thread is created together with its coordinator's first continuation, so every thread is a room from its first row.
|
|
62
|
+
|
|
63
|
+
Thursday relays are persisted independently of whether a thread has been opened on screen. Unaccepted reports remain in the inbox beyond the usual finished-thread limit. Opening a thread, or Thursday marking it seen, settles its relays; so does a resume for the stop it picks up from, and new words for how it last stopped or ended. A call accepts a relay once Live acknowledges the update; this is not proof that the user heard the audio, and an update Live never acknowledged is relayed again on a later call. A question or ending she voiced is not presented again on a later call while the page stays open; it stays on screen until handled.
|
|
64
|
+
|
|
65
|
+
The screen keeps unanswered questions visible even while other participants work, and keeps unread endings until the user opens them. A thread reads as the conversation between its participants: every message as words, the open tab's bot's own work in full, and each other bot's work between its messages folded into a row that opens in place. It opens on its own bot's tab, which holds every participant; another bot's tab holds only what reached that bot's context. The collapsed thread panel shows both without relying on a call. Thursday's status tool returns up to ten threads, prioritizing open work and filling the remaining places with recent endings; naming a thread returns its full result and pending questions.
|
|
66
|
+
|
|
67
|
+
## Verification
|
|
68
|
+
|
|
69
|
+
`pnpm test:bot` runs the real scheduler, SQLite queries, tools, prompts and SDK loop against isolated temporary data and deterministic model streams. It checks continuity, private histories, routing, concurrent questions, completion races, interruption, cancellation, compaction and committed-message recovery. Provider adapter tests inspect serialized OpenAI, Anthropic and Google requests at a mocked HTTP boundary. They do not call live models.
|
|
70
|
+
|
|
71
|
+
Run `pnpm typecheck`, `pnpm lint` and `pnpm build` as well. Browser checks cover the thread screen, participant selection, separate drafts, Markdown and long URLs. TypeScript alone does not validate Next.js client/server directives or the rendered layout.
|
package/features/ai/chatgpt.ts
CHANGED
|
@@ -521,8 +521,7 @@ async function codexFetch(
|
|
|
521
521
|
/**
|
|
522
522
|
* A 429 is either a rate limit a moment fixes or the plan's usage spent until its window resets
|
|
523
523
|
* — hours, or on Free a month. The second becomes a 402 in the backend's words: the sdk does not
|
|
524
|
-
* retry it,
|
|
525
|
-
* minutes to be refused again.
|
|
524
|
+
* retry it, so a job fails with it at once instead of being refused again and again.
|
|
526
525
|
*/
|
|
527
526
|
async function usageLimitOf(response: Response): Promise<Response> {
|
|
528
527
|
const text = await response.text();
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { COMMON_VALIDATE } from "@/lib/limits";
|
|
3
|
+
import { LIVE_BACKEND_MODEL } from "@/lib/live/live.schema";
|
|
4
|
+
import { TEXT_MODEL_PROVIDERS } from "./model.schema";
|
|
5
|
+
|
|
6
|
+
export const LIVE_PROVIDER = {
|
|
7
|
+
id: "openai",
|
|
8
|
+
label: "OpenAI",
|
|
9
|
+
apiKeyName: TEXT_MODEL_PROVIDERS.openai.apiKeyName,
|
|
10
|
+
} as const;
|
|
11
|
+
|
|
12
|
+
/** Suggestions only: custom voices and older backend model IDs remain valid input. */
|
|
13
|
+
export const LIVE_VOICES = [
|
|
14
|
+
"marin",
|
|
15
|
+
"cedar",
|
|
16
|
+
"gleam",
|
|
17
|
+
"meridian",
|
|
18
|
+
"quartz",
|
|
19
|
+
"ripple",
|
|
20
|
+
"vesper",
|
|
21
|
+
"willow",
|
|
22
|
+
"stone",
|
|
23
|
+
"bossa",
|
|
24
|
+
"tempo",
|
|
25
|
+
"beacon",
|
|
26
|
+
"delta",
|
|
27
|
+
"cinder",
|
|
28
|
+
"alloy",
|
|
29
|
+
"ash",
|
|
30
|
+
"ballad",
|
|
31
|
+
"coral",
|
|
32
|
+
"echo",
|
|
33
|
+
"sage",
|
|
34
|
+
"shimmer",
|
|
35
|
+
"verse",
|
|
36
|
+
] as const;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Regional influence and presentation, as OpenAI documents them for the voices
|
|
40
|
+
* GPT-Live adds. The rest — marin, cedar and the voices shared with Realtime —
|
|
41
|
+
* have no documented character, and an invented one would read as fact.
|
|
42
|
+
*/
|
|
43
|
+
export const LIVE_VOICE_NOTE: Partial<
|
|
44
|
+
Record<(typeof LIVE_VOICES)[number], string>
|
|
45
|
+
> = {
|
|
46
|
+
gleam: "North American · feminine",
|
|
47
|
+
meridian: "North American · masculine",
|
|
48
|
+
quartz: "Australian · feminine",
|
|
49
|
+
ripple: "Australian · masculine",
|
|
50
|
+
vesper: "British · masculine",
|
|
51
|
+
willow: "Irish · feminine",
|
|
52
|
+
stone: "Irish · masculine",
|
|
53
|
+
bossa: "Portuguese · feminine",
|
|
54
|
+
tempo: "Portuguese · masculine",
|
|
55
|
+
beacon: "Filipino · masculine",
|
|
56
|
+
delta: "Southern U.S. · feminine",
|
|
57
|
+
cinder: "Southern U.S. · masculine",
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** A recorded line in this voice. Only the listed voices have one. */
|
|
61
|
+
export const voiceSamplePath = (voice: string) => `/voices/${voice}.ogg`;
|
|
62
|
+
|
|
63
|
+
export const LIVE_BACKEND_MODELS = TEXT_MODEL_PROVIDERS.openai.suggestModels;
|
|
64
|
+
export const LIVE_REASONING = [
|
|
65
|
+
"none",
|
|
66
|
+
"minimal",
|
|
67
|
+
"low",
|
|
68
|
+
"medium",
|
|
69
|
+
"high",
|
|
70
|
+
"xhigh",
|
|
71
|
+
] as const;
|
|
72
|
+
|
|
73
|
+
const instruction = z.string().max(COMMON_VALIDATE.prompt.max).default("");
|
|
74
|
+
|
|
75
|
+
export const LiveSettingsSchema = z.object({
|
|
76
|
+
voice: z.string().trim().min(1).max(128).default("marin"),
|
|
77
|
+
voicePrompt: instruction,
|
|
78
|
+
backendModel: z.string().trim().min(1).max(128).default(LIVE_BACKEND_MODEL),
|
|
79
|
+
backendPrompt: instruction,
|
|
80
|
+
/**
|
|
81
|
+
* A call waits out loud, so the backend reasons as little as the work allows.
|
|
82
|
+
* Null omits the parameter, for a model that only runs on its own default.
|
|
83
|
+
*/
|
|
84
|
+
reasoningEffort: z.enum(LIVE_REASONING).nullable().default("low"),
|
|
85
|
+
webSearch: z.boolean().default(false),
|
|
86
|
+
});
|
|
87
|
+
export type LiveSettings = z.infer<typeof LiveSettingsSchema>;
|
|
88
|
+
export const LIVE_DEFAULTS = LiveSettingsSchema.parse({});
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Settings stored before Live-only, or hand-edited, into valid ones. An OpenAI
|
|
92
|
+
* voice and backend model carry over; a Grok voice does not, since its names
|
|
93
|
+
* mean nothing to Live. The one shared instruction goes into both new fields so
|
|
94
|
+
* nothing the user wrote is lost. Each field recovers on its own: one bad value
|
|
95
|
+
* falls back to its default and leaves the rest as they were.
|
|
96
|
+
*/
|
|
97
|
+
export function migrateLiveSettings(value: unknown): Record<string, unknown> {
|
|
98
|
+
const stored =
|
|
99
|
+
value && typeof value === "object"
|
|
100
|
+
? (value as Record<string, unknown>)
|
|
101
|
+
: {};
|
|
102
|
+
const { model, systemPrompt, ...rest } = stored;
|
|
103
|
+
const legacy = z
|
|
104
|
+
.object({
|
|
105
|
+
provider: z.string(),
|
|
106
|
+
voice: z.string().nullish(),
|
|
107
|
+
backendModel: z.string().nullish(),
|
|
108
|
+
})
|
|
109
|
+
.safeParse(model);
|
|
110
|
+
const openai =
|
|
111
|
+
legacy.success && legacy.data.provider === "openai" ? legacy.data : null;
|
|
112
|
+
|
|
113
|
+
const candidate: Record<keyof LiveSettings, unknown> = {
|
|
114
|
+
voice: stored.voice ?? openai?.voice,
|
|
115
|
+
voicePrompt: stored.voicePrompt ?? systemPrompt,
|
|
116
|
+
backendModel: stored.backendModel ?? openai?.backendModel,
|
|
117
|
+
backendPrompt: stored.backendPrompt ?? systemPrompt,
|
|
118
|
+
reasoningEffort: stored.reasoningEffort,
|
|
119
|
+
webSearch: stored.webSearch,
|
|
120
|
+
};
|
|
121
|
+
const live = Object.fromEntries(
|
|
122
|
+
(Object.keys(candidate) as (keyof LiveSettings)[]).map((key) => {
|
|
123
|
+
const parsed = LiveSettingsSchema.shape[key].safeParse(candidate[key]);
|
|
124
|
+
return [key, parsed.success ? parsed.data : LIVE_DEFAULTS[key]];
|
|
125
|
+
}),
|
|
126
|
+
);
|
|
127
|
+
return { ...rest, ...live };
|
|
128
|
+
}
|