thursday-agent 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +5 -2
- package/.next/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +5 -5
- package/.next/routes-manifest.json +24 -6
- package/.next/server/app/_global-error/page.js +2 -2
- package/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +2 -2
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +2 -2
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +14 -14
- package/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/artifact/route.js +3 -3
- package/.next/server/app/api/artifact/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/files/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/bot/memory/files/route.js +10 -0
- package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -0
- package/.next/server/app/api/bot/memory/files/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/bot/memory/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/bot/memory/route.js +14 -0
- package/.next/server/app/api/bot/{notes → memory}/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/bot/route.js +6 -6
- package/.next/server/app/api/bot/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/task/[id]/route.js +8 -8
- package/.next/server/app/api/bot/task/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/task/route.js +8 -8
- package/.next/server/app/api/bot/task/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js +5 -5
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/events/route.js +4 -5
- package/.next/server/app/api/events/route.js.nft.json +1 -1
- package/.next/server/app/api/file/[...path]/route.js +3 -3
- package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/catalog/route.js +9 -8
- package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/credits/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/llm-model/credits/route/build-manifest.json +12 -0
- package/.next/server/app/api/llm-model/credits/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/llm-model/credits/route.js +16 -0
- package/.next/server/app/api/llm-model/credits/route.js.map +5 -0
- package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -0
- package/.next/server/app/api/llm-model/credits/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/llm-model/route.js +10 -8
- package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/subscription/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/llm-model/subscription/route/build-manifest.json +12 -0
- package/.next/server/app/api/llm-model/subscription/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/llm-model/subscription/route.js +15 -0
- package/.next/server/app/api/llm-model/subscription/route.js.map +5 -0
- package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -0
- package/.next/server/app/api/llm-model/subscription/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/mcp/[name]/route.js +4 -4
- package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/oauth/callback/route.js +5 -5
- package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/route.js +4 -4
- package/.next/server/app/api/mcp/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/tools/route.js +4 -4
- package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/memory/edit/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/memory/edit/route/build-manifest.json +12 -0
- package/.next/server/app/api/memory/edit/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/memory/edit/route.js +24 -0
- package/.next/server/app/api/memory/edit/route.js.map +5 -0
- package/.next/server/app/api/memory/edit/route.js.nft.json +1 -0
- package/.next/server/app/api/memory/{tidy → edit}/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/memory/route.js +6 -7
- package/.next/server/app/api/memory/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/[source]/[name]/route.js +3 -3
- package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/route.js +3 -3
- package/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/call/route.js +9 -7
- package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/skills/route.js +9 -7
- package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/tool-call/route.js +17 -15
- package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
- package/.next/server/app/api/workspace/route.js +4 -5
- package/.next/server/app/api/workspace/route.js.nft.json +1 -1
- package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +1 -1
- package/.next/server/app/artifact/[...path]/page.js +5 -6
- package/.next/server/app/artifact/[...path]/page.js.nft.json +1 -1
- package/.next/server/app/artifact/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/favicon.ico/route.js +3 -4
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/page/server-reference-manifest.json +57 -90
- package/.next/server/app/page.js +10 -10
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +5 -2
- package/.next/server/chunks/[externals]__0dzuk6_._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__01dkp4a._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__02va5wz._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__02xjoto._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__04q--0f._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0bl-e63._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0ce8nf8._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__0ffbg85._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0j7z0r3._.js +12 -0
- package/.next/server/chunks/[root-of-the-server]__0jq4ohy._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0ls6_8y._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__0ncs9uu._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0pa2n68._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0q0vvt2._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1-ga0kh._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__11n256_._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__12cabg9._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1339jnv._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__15bjnu5._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__18_teo8._.js +8 -0
- package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__1anc1p9._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1ccon1w._.js +5 -5
- package/.next/server/chunks/[root-of-the-server]__1fizn31._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1llj3-b._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1orn-5b._.js +12 -0
- package/.next/server/chunks/[root-of-the-server]__1p8m3f4._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1wa1k7r._.js +8 -0
- package/.next/server/chunks/_0-73of8._.js +5 -5
- package/.next/server/chunks/_0-fjql4._.js +26 -0
- package/.next/server/chunks/_00xh_q0._.js +25 -0
- package/.next/server/chunks/_051qh8u._.js +3 -0
- package/.next/server/chunks/{node_modules_next_04q-o58._.js → _05dla15._.js} +2 -2
- package/.next/server/chunks/_05h2cii._.js +1 -1
- package/.next/server/chunks/_0c9j6rb._.js +49 -0
- package/.next/server/chunks/_0fzqt2y._.js +134 -0
- package/.next/server/chunks/{_0vnutv9._.js → _0ioz3nd._.js} +1 -1
- package/.next/server/chunks/_0iwfby5._.js +3 -0
- package/.next/server/chunks/_0mecv0f._.js +26 -0
- package/.next/server/chunks/_0mh8j4m._.js +3 -0
- package/.next/server/chunks/_0n74zsf._.js +4 -4
- package/.next/server/chunks/_0obojvv._.js +3 -0
- package/.next/server/chunks/_0recufk._.js +49 -0
- package/.next/server/chunks/_0rnf-6n._.js +4 -4
- package/.next/server/chunks/_0sb7tlz._.js +3 -0
- package/.next/server/chunks/_0u10wmw._.js +5 -5
- package/.next/server/chunks/_0u4aiy2._.js +3 -0
- package/.next/server/chunks/_0wp4le3._.js +1 -1
- package/.next/server/chunks/_0y5fg-x._.js +1 -1
- package/.next/server/chunks/_1230wbx._.js +10 -0
- package/.next/server/chunks/_12nheja._.js +3 -0
- package/.next/server/chunks/_13510xh._.js +3 -0
- package/.next/server/chunks/_15hq89o._.js +1 -1
- package/.next/server/chunks/_17l5ygt._.js +49 -0
- package/.next/server/chunks/_18-1wcc._.js +5 -5
- package/.next/server/chunks/_1_5mnq4._.js +4 -4
- package/.next/server/chunks/_1_9mjx-._.js +3 -0
- package/.next/server/chunks/{_0pppbb5._.js → _1c78vw5._.js} +166 -37
- package/.next/server/chunks/_1d0j961._.js +6 -0
- package/.next/server/chunks/_1d5zmy8._.js +1 -1
- package/.next/server/chunks/_1drgfx4._.js +4 -4
- package/.next/server/chunks/_1f46eie._.js +3 -0
- package/.next/server/chunks/_1h5_8sk._.js +3 -0
- package/.next/server/chunks/_1hdnxb7._.js +3 -0
- package/.next/server/chunks/_1j8k_j5._.js +3 -0
- package/.next/server/chunks/_1krd9rf._.js +3 -0
- package/.next/server/chunks/_1nc0eui._.js +11 -0
- package/.next/server/chunks/_1nula3v._.js +3 -0
- package/.next/server/chunks/_1pf4qe-._.js +3 -0
- package/.next/server/chunks/_1php4eq._.js +1 -1
- package/.next/server/chunks/_1qxheoa._.js +3 -0
- package/.next/server/chunks/_1x6kd1r._.js +3 -0
- package/.next/server/chunks/_1yuv4vp._.js +1 -1
- package/.next/server/chunks/_1zjrdag._.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_bot_memory_files_route_actions_1_xd_8f.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_bot_memory_route_actions_1a8xfr7.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_llm-model_credits_route_actions_0v424pb.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_llm-model_subscription_route_actions_0-udcm5.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_memory_edit_route_actions_02sfnmr.js +3 -0
- package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
- package/.next/server/chunks/features_0rpfxbk._.js +3 -0
- package/.next/server/chunks/features_1qf3cei._.js +3 -0
- package/.next/server/chunks/features_bot_0zt92oh._.js +3 -0
- package/.next/server/chunks/features_bot_bot_query_ts_12mgkl2._.js +3 -0
- package/.next/server/chunks/features_memory_1uqvksn._.js +6 -0
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0a1rd09._.js → node_modules_consola_dist_chunks_prompt_mjs_0i7cvml._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_06067w6._.js → node_modules_consola_dist_chunks_prompt_mjs_0icqaqw._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_096ais_._.js → node_modules_consola_dist_chunks_prompt_mjs_0r28-sm._.js} +1 -1
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_02s3hjt._.js → node_modules_consola_dist_chunks_prompt_mjs_0v_7drq._.js} +1 -1
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1xoq2rl._.js +3 -0
- package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0tvkfgh._.js → node_modules_consola_dist_chunks_prompt_mjs_1y49572._.js} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__092knlj._.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]__0hg5gib._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0i8ie7f._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__0jsmmb-._.js → [root-of-the-server]__0mz33a7._.js} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0s9dq5u._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__0m1b5ky._.js → [root-of-the-server]__0s9l2sv._.js} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0tbkdlx._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0vnmv-s._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__0f6s48x._.js → [root-of-the-server]__0xpcv9w._.js} +3 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0xsog8n._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0xtssj3._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +61 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__15_uhip._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__1gtlw6v._.js +43 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__1ox7hbk._.js +4 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__1qfqvmg._.js → [root-of-the-server]__202p40z._.js} +2 -2
- package/.next/server/chunks/ssr/{_1mznrxk._.js → _001_ms1._.js} +3 -3
- package/.next/server/chunks/ssr/_01n3o0m._.js +3 -0
- package/.next/server/chunks/ssr/_0ap2fzn._.js +3 -0
- package/.next/server/chunks/ssr/_0fz4mf_._.js +3 -0
- package/.next/server/chunks/ssr/_0gb4gmf._.js +3 -0
- package/.next/server/chunks/ssr/_0h42fze._.js +3 -0
- package/.next/server/chunks/ssr/_0h7zdni._.js +1 -1
- package/.next/server/chunks/ssr/_0i_6q1w._.js +41 -0
- package/.next/server/chunks/ssr/_0ilna52._.js +42 -0
- package/.next/server/chunks/ssr/_0n3toaw._.js +3 -0
- package/.next/server/chunks/ssr/{_13punpm._.js → _0q0zan6._.js} +2 -2
- package/.next/server/chunks/ssr/{_077-g6s._.js → _0s99bgb._.js} +3 -3
- package/.next/server/chunks/ssr/_0zcjrbg._.js +3 -0
- package/.next/server/chunks/ssr/_0zhoc3r._.js +3 -0
- package/.next/server/chunks/ssr/{_1lip4th._.js → _1-_etts._.js} +2 -2
- package/.next/server/chunks/ssr/_1-teee5._.js +3 -3
- package/.next/server/chunks/ssr/_13fke0x._.js +3 -0
- package/.next/server/chunks/ssr/_15j2_8f._.js +3 -0
- package/.next/server/chunks/ssr/_1b2mjwr._.js +3 -0
- package/.next/server/chunks/ssr/{_09ja_w1._.js → _1f-dg-6._.js} +2 -2
- package/.next/server/chunks/ssr/_1fojd41._.js +4 -0
- package/.next/server/chunks/ssr/_1gd8q8l._.js +3 -0
- package/.next/server/chunks/ssr/{_1m3bsfr._.js → _1h0rw11._.js} +2 -2
- package/.next/server/chunks/ssr/_1jhd09t._.js +3 -0
- package/.next/server/chunks/ssr/{_040sk32._.js → _1lz_cq2._.js} +84 -88
- package/.next/server/chunks/ssr/_1nnsk7z._.js +3 -0
- package/.next/server/chunks/ssr/_1sji22n._.js +3 -0
- package/.next/server/chunks/ssr/{_0x_nu5e._.js → _1vi_uo7._.js} +2 -2
- package/.next/server/chunks/ssr/_1vyd1ji._.js +1 -1
- package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +3 -0
- package/.next/server/chunks/ssr/features_config_components_config-setting_tsx_0xfwqdg._.js +1 -1
- package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
- package/.next/server/chunks/ssr/{node_modules_0kxz4gt._.js → node_modules_00etblx._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_18_dk7_._.js → node_modules_04jf_m8._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0_n241r._.js → node_modules_08dhkiq._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0n1kj4p._.js → node_modules_0940ns5._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_17lrt3y._.js → node_modules_09q35v_._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1toafc-._.js → node_modules_0_-_a--._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0lrjk5t._.js → node_modules_0arus10._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_04n7mjs._.js → node_modules_0b__sgl._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0iz1rzd._.js → node_modules_0cxaxk9._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0ndvxub._.js → node_modules_0g7fzk3._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0kl7-tn._.js → node_modules_0had7xd._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_19dp7ko._.js → node_modules_0pvd7q-._.js} +1 -1
- package/.next/server/chunks/ssr/node_modules_0x3-ply._.js +3 -0
- package/.next/server/chunks/ssr/{node_modules_1dwguw_._.js → node_modules_0yugy6m._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_004qlr4._.js → node_modules_14om4ar._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1q0p85z._.js → node_modules_14q6g4n._.js} +1 -1
- package/.next/server/chunks/ssr/node_modules_17bwo43._.js +55 -0
- package/.next/server/chunks/ssr/{node_modules_1hd-5tv._.js → node_modules_198nmll._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0m93zeg._.js → node_modules_1_pc9kq._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1n5ygqe._.js → node_modules_1aaxuef._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_01qnv-a._.js → node_modules_1cx_ql6._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1zu988w._.js → node_modules_1cz2hle._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1xyd7ov._.js → node_modules_1efrqxi._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_13r44jq._.js → node_modules_1eg7m6c._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_08d8bke._.js → node_modules_1gdh31p._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1hn8z1f._.js → node_modules_1hpopmo._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_20yebtj._.js → node_modules_1qpjvy5._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_09xhur7._.js → node_modules_1vh5ntv._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0m9a4y0._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1b748ic._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_13w_wy9._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1z4hm5e._.js} +1 -1
- package/.next/server/chunks/ssr/node_modules_@vercel_oidc_dist_06mk8id._.js +3 -0
- package/.next/server/chunks/ssr/{node_modules_next_dist_0w6mzq5._.js → node_modules_next_dist_0drixxt._.js} +4 -4
- package/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +2 -2
- package/.next/server/instrumentation.js +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +58 -91
- package/.next/static/chunks/00rd4-v8r7axp.js +1 -0
- package/.next/static/chunks/08qe4as2q428z.js +3 -0
- package/.next/static/chunks/{31ttnjt6g35a0.js → 0ev4hyghq0mbb.js} +1 -1
- package/.next/static/chunks/0fl3gwe4-l6tz.js +1 -0
- package/.next/static/chunks/0gnqdjn2lvdad.js +2 -0
- package/.next/static/chunks/0hwap1-p0m5sa.js +1 -0
- package/.next/static/chunks/0r5qcctujhxli.js +1 -0
- package/.next/static/chunks/0w52rrrmuj9r9.js +1 -0
- package/.next/static/chunks/{07kl352c-lvcz.js → 0wcprt5ot5she.js} +1 -1
- package/.next/static/chunks/10teww7wt-f6h.js +1 -0
- package/.next/static/chunks/15m575979un5f.js +38 -0
- package/.next/static/chunks/17p6tk6k88dq6.js +1 -0
- package/.next/static/chunks/{3_h9txt3tq8t8.js → 1dkjg87pxk0n9.js} +1 -1
- package/.next/static/chunks/1jd09sxcjddu1.js +1 -0
- package/.next/static/chunks/1kq8h8wi_e0bc.js +53 -0
- package/.next/static/chunks/{18vhba44l1fc9.js → 1w73ece_6bheu.js} +1 -1
- package/.next/static/chunks/{3ard_noqapnw1.js → 214ya3n5gxeih.js} +1 -1
- package/.next/static/chunks/22_zkas21rpna.js +1 -0
- package/.next/static/chunks/2h0sd2vumhb15.js +1 -0
- package/.next/static/chunks/2t4vhi3m8ahya.js +1 -0
- package/.next/static/chunks/2tigdtz3dpcy8.js +1 -0
- package/.next/static/chunks/2u7xt6mxg44lf.js +1 -0
- package/.next/static/chunks/39j0fvpybzabl.js +40 -0
- package/.next/static/chunks/3akmqm77muj4-.js +1 -0
- package/.next/static/chunks/3cq5g494yuke8.css +1 -0
- package/.next/static/chunks/3woj-xd7ki5_i.js +1 -0
- package/.next/static/chunks/3xk7yqgomx7yq.js +1 -0
- package/.next/static/chunks/3zmcsnuo25zvq.js +1 -0
- package/.next/static/media/favicon.37o1pjldwi2uc.ico +0 -0
- package/README.md +47 -22
- package/app/api/bot/memory/files/route.ts +14 -0
- package/app/api/bot/memory/route.ts +5 -0
- package/app/api/events/app-event.ts +3 -7
- package/app/api/llm-model/credits/route.ts +11 -0
- package/app/api/llm-model/route.ts +6 -1
- package/app/api/llm-model/subscription/route.ts +11 -0
- package/app/api/memory/edit/route.ts +7 -0
- package/app/api/memory/route.ts +21 -0
- package/app/api/query-key.ts +19 -4
- package/bin/port.mjs +65 -0
- package/bin/thursday.mjs +5 -33
- package/components/ui/shiny-text.tsx +48 -134
- package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/migration.sql +24 -34
- package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/snapshot.json +71 -145
- package/database/migrations/20260911030320_opposite_jack_power/migration.sql +1 -0
- package/database/migrations/{20260909063821_bitter_tenebrous → 20260911030320_opposite_jack_power}/snapshot.json +57 -184
- package/docs/how-it-works.md +11 -7
- package/docs/images/face-dark.png +0 -0
- package/docs/images/face-light.png +0 -0
- package/docs/images/keeps-going.png +0 -0
- package/features/ai/chatgpt.ts +639 -0
- package/features/ai/components/chatgpt-sign-in.tsx +66 -0
- package/features/ai/components/model-picker.tsx +17 -1
- package/features/ai/components/provider-icon.tsx +1 -0
- package/features/ai/load-tools.ts +78 -56
- package/features/ai/model.schema.ts +232 -34
- package/features/ai/model.ts +169 -24
- package/features/ai/prompts/bot.prompt.ts +207 -114
- package/features/ai/prompts/memory-edit.prompt.ts +33 -0
- package/features/ai/prompts/prompt-helper.ts +45 -26
- package/features/ai/prompts/thursday.prompt.ts +57 -27
- package/features/ai/tools/bot.tool.ts +35 -52
- package/features/ai/tools/connected.ts +17 -4
- package/features/ai/tools/memory.tool.ts +181 -117
- package/features/ai/tools/search.tool.ts +136 -47
- package/features/ai/tools/tool-name.ts +2 -6
- package/features/ai/tools/workspace.tool.ts +5 -1
- package/features/bot/bot.action.ts +14 -19
- package/features/bot/bot.memory.ts +89 -0
- package/features/bot/bot.query.ts +37 -57
- package/features/bot/bot.run.ts +512 -242
- package/features/bot/bot.runner.ts +434 -120
- package/features/bot/bot.schema.ts +104 -19
- package/features/bot/bot.seed.ts +89 -16
- package/features/bot/components/bot-mark.tsx +122 -20
- package/features/bot/components/bot-room.tsx +214 -132
- package/features/bot/components/bot-setting.tsx +790 -402
- package/features/bot/components/bot-tool.tsx +2 -7
- package/features/bot/components/mark-palette.tsx +54 -0
- package/features/bot/components/path-chips.tsx +1 -1
- package/features/bot/components/task-badge.tsx +26 -6
- package/features/bot/components/task-reply.tsx +22 -33
- package/features/bot/components/task-setting.tsx +20 -17
- package/features/bot/task.query.ts +240 -34
- package/features/bot/task.store.ts +76 -13
- package/features/config/components/config-setting.tsx +265 -34
- package/features/config/components/models-badge.tsx +42 -0
- package/features/config/config.action.ts +12 -0
- package/features/config/config.const.ts +38 -2
- package/features/connectors/mcp.manager.ts +10 -2
- package/features/intro/components/intro.tsx +47 -46
- package/features/memory/components/memory-edit.tsx +340 -0
- package/features/memory/components/memory-setting.tsx +75 -77
- package/features/memory/memory.action.ts +3 -43
- package/features/memory/memory.edit.ts +87 -0
- package/features/memory/memory.query.ts +24 -42
- package/features/memory/memory.schema.ts +29 -106
- package/features/settings/components/settings.tsx +2 -0
- package/features/settings/settings.alert.ts +3 -1
- package/features/thursday/components/ascii-orb.tsx +106 -90
- package/features/thursday/components/boot.tsx +7 -0
- package/features/thursday/components/call-log.tsx +219 -92
- package/features/thursday/components/face.tsx +6 -4
- package/features/thursday/components/tab-state.tsx +97 -0
- package/features/thursday/components/thursday-mark.tsx +4 -1
- package/features/thursday/components/thursday-setting.tsx +17 -47
- package/features/thursday/components/thursday.tsx +208 -98
- package/features/thursday/thursday.action.ts +12 -17
- package/features/thursday/thursday.query.ts +61 -70
- package/features/thursday/thursday.schema.ts +20 -7
- package/features/thursday/tool-line.ts +85 -12
- package/features/thursday/use-thursday.ts +87 -60
- package/features/workspace/components/file-view.tsx +4 -2
- package/features/workspace/workspace.ts +110 -26
- package/lib/limits.ts +1 -1
- package/lib/oauth-page.ts +27 -0
- package/lib/realtime/openai.ts +2 -2
- package/lib/realtime/realtime.protocol.ts +1 -1
- package/lib/realtime/realtime.tap.ts +122 -0
- package/lib/sandbox.ts +59 -36
- package/package.json +1 -1
- package/skills/browser/SKILL.md +55 -34
- package/.next/server/app/api/bot/notes/route/app-paths-manifest.json +0 -3
- package/.next/server/app/api/bot/notes/route.js +0 -14
- package/.next/server/app/api/bot/notes/route_client-reference-manifest.js +0 -3
- package/.next/server/app/api/memory/tidy/route/app-paths-manifest.json +0 -3
- package/.next/server/app/api/memory/tidy/route.js +0 -22
- package/.next/server/app/api/memory/tidy/route.js.nft.json +0 -1
- package/.next/server/chunks/0d-b_next_dist_server_app-render_after-task-async-storage_external_0-exn7p.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0-npkh_._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__005var5._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__019dx9f._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__02_2sm-._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__04_8spk._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__05luceg._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__06t77t4._.js +0 -11
- package/.next/server/chunks/[root-of-the-server]__0bed6hu._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0cro2dz._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0dupqt7._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0emr6go._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0le4d-p._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0m8ywyo._.js +0 -10
- package/.next/server/chunks/[root-of-the-server]__0nfuugi._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__0p32jfz._.js +0 -12
- package/.next/server/chunks/[root-of-the-server]__0phdgco._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__0wvgrsl._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__10qshki._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__11j52t0._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1692zrv._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__16thabu._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__173nhwf._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1_aoyr9._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1bn73ih._.js +0 -10
- package/.next/server/chunks/[root-of-the-server]__1bqhuh9._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1cqizfq._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1e-ci13._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1fboj2j._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1lr7j9t._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1oli73c._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1txedx6._.js +0 -8
- package/.next/server/chunks/[root-of-the-server]__1untqv8._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__1zgpz1w._.js +0 -3
- package/.next/server/chunks/_00_584r._.js +0 -293
- package/.next/server/chunks/_012yhfm._.js +0 -39
- package/.next/server/chunks/_06mxlgn._.js +0 -3
- package/.next/server/chunks/_07rtlxv._.js +0 -3
- package/.next/server/chunks/_0a351g7._.js +0 -6
- package/.next/server/chunks/_0kjjmag._.js +0 -3
- package/.next/server/chunks/_0nn99o2._.js +0 -3
- package/.next/server/chunks/_0zuzmt_._.js +0 -39
- package/.next/server/chunks/_106co2o._.js +0 -3
- package/.next/server/chunks/_12bbv5i._.js +0 -100
- package/.next/server/chunks/_15q1pig._.js +0 -3
- package/.next/server/chunks/_19wg5yn._.js +0 -138
- package/.next/server/chunks/_1bt95p9._.js +0 -55
- package/.next/server/chunks/_1cbk7ms._.js +0 -26
- package/.next/server/chunks/_1drv2et._.js +0 -40
- package/.next/server/chunks/_1ic3bew._.js +0 -5
- package/.next/server/chunks/_1mxn_lb._.js +0 -3
- package/.next/server/chunks/_1rysr-r._.js +0 -10
- package/.next/server/chunks/_1u3rwbr._.js +0 -3
- package/.next/server/chunks/_1x7p319._.js +0 -6
- package/.next/server/chunks/_next-internal_server_app_api_bot_notes_route_actions_0qcsyu7.js +0 -3
- package/.next/server/chunks/_next-internal_server_app_api_memory_tidy_route_actions_0_cfuom.js +0 -3
- package/.next/server/chunks/features_bot_task_query_ts_11xuzl3._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0gzvgfv._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0vorg6w._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1tpvamf._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1vmaq9f._.js +0 -3
- package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1y9-wcr._.js +0 -3
- package/.next/server/chunks/ssr/[externals]_node_crypto_1kn79-7._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0iuoa-r._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0un-erv._.js +0 -4
- package/.next/server/chunks/ssr/[root-of-the-server]__1-mnhyd._.js +0 -92
- package/.next/server/chunks/ssr/[root-of-the-server]__1bww500._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1vcdast._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1xwnu-h._.js +0 -3
- package/.next/server/chunks/ssr/_0-mc7ro._.js +0 -3
- package/.next/server/chunks/ssr/_01p5r6-._.js +0 -3
- package/.next/server/chunks/ssr/_03webdr._.js +0 -3
- package/.next/server/chunks/ssr/_09-0k3z._.js +0 -3
- package/.next/server/chunks/ssr/_0f_b_9s._.js +0 -3
- package/.next/server/chunks/ssr/_0fafgvl._.js +0 -3
- package/.next/server/chunks/ssr/_0sf1isi._.js +0 -3
- package/.next/server/chunks/ssr/_0su6_08._.js +0 -3
- package/.next/server/chunks/ssr/_0ti51xc._.js +0 -3
- package/.next/server/chunks/ssr/_0w5bgak._.js +0 -3
- package/.next/server/chunks/ssr/_0y84qo6._.js +0 -3
- package/.next/server/chunks/ssr/_1ciyoo3._.js +0 -3
- package/.next/server/chunks/ssr/_1e-dgz0._.js +0 -4
- package/.next/server/chunks/ssr/_1fq7zgb._.js +0 -3
- package/.next/server/chunks/ssr/_1g6l4uj._.js +0 -3
- package/.next/server/chunks/ssr/_1ruzehw._.js +0 -3
- package/.next/server/chunks/ssr/features_bot_components_bot-setting_tsx_01ajft6._.js +0 -4
- package/.next/server/chunks/ssr/features_config_components_14jqgy4._.js +0 -3
- package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +0 -4
- package/.next/server/chunks/ssr/node_modules_zod_v4_classic_external_15fmmz3.js +0 -55
- package/.next/static/chunks/05b6nx_o3_f_n.js +0 -1
- package/.next/static/chunks/0dmns-gi0raa4.js +0 -1
- package/.next/static/chunks/0f9sq-7q_yxyl.js +0 -1
- package/.next/static/chunks/0oc4_xoia77dg.css +0 -1
- package/.next/static/chunks/0pheo8m3a-rzi.js +0 -1
- package/.next/static/chunks/19i8h2t-5evjx.js +0 -1
- package/.next/static/chunks/1c5fcj473025q.js +0 -1
- package/.next/static/chunks/1pi_hbmjw-f-z.js +0 -1
- package/.next/static/chunks/1twt6k09vg4np.js +0 -1
- package/.next/static/chunks/1ytnip8wdng93.js +0 -1
- package/.next/static/chunks/28gotuisldmom.js +0 -1
- package/.next/static/chunks/2998p0y7k1c8z.js +0 -3
- package/.next/static/chunks/29gyb3nubj51j.js +0 -53
- package/.next/static/chunks/2l233xfycjpd8.js +0 -1
- package/.next/static/chunks/2p5n7pa3c40t-.js +0 -2
- package/.next/static/chunks/2ru1q132af7h7.js +0 -1
- package/.next/static/chunks/2t8wqycwg3y04.js +0 -2
- package/.next/static/chunks/2uxum7qbyeyxd.js +0 -1
- package/.next/static/chunks/32z_ypgtchw48.js +0 -1
- package/.next/static/chunks/33pyjb3xd1iez.js +0 -1
- package/.next/static/chunks/3omud5xunrk1f.js +0 -1
- package/.next/static/chunks/42dnrkbph9e-1.js +0 -1
- package/.next/static/media/favicon.2vob68tjqpejf.ico +0 -0
- package/database/migrations/20260909063821_bitter_tenebrous/migration.sql +0 -1
- package/features/ai/prompts/memory-tidy.prompt.ts +0 -129
- package/features/ai/tools/tidy.tool.ts +0 -22
- package/features/bot/bot.notes.ts +0 -120
- package/features/memory/components/memory-tidy.tsx +0 -395
- package/features/memory/components/memory-view.tsx +0 -84
- package/features/memory/memory.tidy.ts +0 -332
- package/features/memory/tidy.query.ts +0 -135
- package/features/thursday/use-call-title.ts +0 -31
- /package/.next/server/app/api/bot/{notes → memory/files}/route/build-manifest.json +0 -0
- /package/.next/server/app/api/bot/{notes → memory/files}/route/server-reference-manifest.json +0 -0
- /package/.next/server/app/api/bot/{notes → memory/files}/route.js.map +0 -0
- /package/.next/server/app/api/{memory/tidy → bot/memory}/route/build-manifest.json +0 -0
- /package/.next/server/app/api/{memory/tidy → bot/memory}/route/server-reference-manifest.json +0 -0
- /package/.next/server/app/api/{memory/tidy → bot/memory}/route.js.map +0 -0
- /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → kaTO0UHqF1bMnWgCDik2f}/_buildManifest.js +0 -0
- /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → kaTO0UHqF1bMnWgCDik2f}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → kaTO0UHqF1bMnWgCDik2f}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="docs/images/hero.png" alt="Thursday" width="760">
|
|
3
|
+
<img src="docs/images/hero.png" alt="Thursday — an open-source voice agent with a face made of emoji" width="760">
|
|
4
4
|
|
|
5
5
|
### Everyone wanted Friday. This is Thursday.
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**An open-source voice agent that lives on your machine.** You talk. It works. You keep talking.
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/thursday-agent)
|
|
10
10
|
[](https://github.com/cgoinglove/thursday/actions/workflows/ci.yml)
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
npx thursday-agent
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
One API key, typed into the first screen. No `.env`, no account, no cloud. That is the whole setup.
|
|
24
|
+
One API key, typed into the first screen. Then say **"hey thursday."** No `.env`, no account, no cloud. That is the whole setup.
|
|
25
25
|
|
|
26
26
|
<br>
|
|
27
27
|
|
|
@@ -35,6 +35,21 @@ You never watched a spinner. You never stopped talking.
|
|
|
35
35
|
|
|
36
36
|
<br>
|
|
37
37
|
|
|
38
|
+
## She has a face, and it is made of emoji
|
|
39
|
+
|
|
40
|
+
<div align="center">
|
|
41
|
+
<picture>
|
|
42
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/images/face-dark.png">
|
|
43
|
+
<img src="docs/images/face-light.png" alt="Thursday's face: an orb of emoji that swells when she speaks" width="280">
|
|
44
|
+
</picture>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
Hundreds of them, packed into one orb. When she talks, the rim swells with her voice and every syllable shakes a few loose — you can tell she is speaking with the sound off.
|
|
48
|
+
|
|
49
|
+
Rather have letters, a sprinkle, or a plain mark with two eyes? Settings › Thursday.
|
|
50
|
+
|
|
51
|
+
<br>
|
|
52
|
+
|
|
38
53
|
## A harness you talk to
|
|
39
54
|
|
|
40
55
|
A **harness** is the layer around a model that decides what it sees, which tools it may call, where its commands run, and what survives the session. Claude Code, [OpenClaw](https://github.com/openclaw/openclaw) and [Hermes](https://github.com/NousResearch/hermes-agent) are harnesses, and they got very good this year.
|
|
@@ -64,7 +79,7 @@ The split is not new. OpenAI's own [realtime-agents](https://github.com/openai/o
|
|
|
64
79
|
|
|
65
80
|
They are frameworks and demonstrations: excellent parts for building a voice agent. What they hand the supervisor is a tool list.
|
|
66
81
|
|
|
67
|
-
Thursday hands it a machine — a shell,
|
|
82
|
+
Thursday hands it a machine — a shell, a real browser, skills, connectors, a workspace, and jobs that keep running after you hang up. It is a harness first, and speech is how you operate it. That is the whole difference, and it is the half that takes the work.
|
|
68
83
|
|
|
69
84
|
</details>
|
|
70
85
|
|
|
@@ -72,18 +87,19 @@ Thursday hands it a machine — a shell, the Chrome you are already signed into,
|
|
|
72
87
|
|
|
73
88
|
## What a bot actually has
|
|
74
89
|
|
|
75
|
-
Not an API sandbox. **Your computer
|
|
90
|
+
Not an API sandbox. **Your computer** — down to the Chrome you are already signed into, which no agent in someone else's cloud can borrow.
|
|
76
91
|
|
|
77
92
|
- **A shell** — real commands on your real files
|
|
78
|
-
- **A real browser** —
|
|
93
|
+
- **A real browser** — its own, or attached to your Chrome. When there is something for you to see — a checkout, a map, a sign-in — it opens a window on your screen and leaves it there
|
|
79
94
|
- **Skills** — the browser, this Mac, building a page; `npx skills add` for the rest
|
|
80
95
|
- **46 connectors** — Notion, GitHub, Linear, Slack, Figma, Stripe, Supabase… one click each
|
|
81
96
|
- **A studio** — image, video, speech, transcription
|
|
97
|
+
- **Its own memory** — what it learned doing the job, kept as files you can open on its page
|
|
82
98
|
- **Each other** — a bot hands a part of its job to the bot that exists for it
|
|
83
99
|
|
|
84
|
-

|
|
85
101
|
|
|
86
|
-
It signs in
|
|
102
|
+
It signs in the way you would let it: a session it kept, your own Chrome, you in the window it opened, or the login you gave it — after asking. And there is one button it never presses: **pay.** It takes the order to the last screen, leaves it open in front of you, and tells you what it buys and for how much.
|
|
87
103
|
|
|
88
104
|
<br>
|
|
89
105
|
|
|
@@ -93,23 +109,25 @@ It signs in where it has to, in a window you can watch, and stops at exactly one
|
|
|
93
109
|
|
|
94
110
|
Jarvis holds the job and decides neither half is his. Navigator opens six shops and reads them. Scribe builds the page out of what came back. It reaches you as one line, out loud — and the room is there to read if you ever want to know how.
|
|
95
111
|
|
|
112
|
+
Those three come with her. Two more are ready-made in Settings — **Insta** draws the post, writes the caption and puts it up once you say so; **Voyage** plans the trip with a map for each day — and one of your own takes a name and a sentence.
|
|
113
|
+
|
|
96
114
|
<br>
|
|
97
115
|
|
|
98
116
|
## Hang up. It keeps going.
|
|
99
117
|
|
|
100
|
-
The job is not in the call. It runs on the server and the screen is a projection of it — so hang up mid-sentence, open a new tab, come back in ten minutes. She tells you what came in, or rings you, if you let her.
|
|
118
|
+
The job is not in the call. It runs on the server and the screen is a projection of it — so hang up mid-sentence, open a new tab, come back in ten minutes. She tells you what came in, or rings you, if you let her. The tab says it too: `(2) Thursday` means two things are waiting on you.
|
|
101
119
|
|
|
102
120
|

|
|
103
121
|
|
|
104
|
-
Close the app
|
|
122
|
+
Close the app and it does the honest thing: ten seconds with no browser on it and every running job stops where it stands. **Nothing spends your keys while you are not looking.** Open it again and they pick themselves back up — the same after a restart, a `Ctrl+C`, or a model that went quiet for a minute.
|
|
105
123
|
|
|
106
124
|
<br>
|
|
107
125
|
|
|
108
126
|
## It remembers you, and you can read it
|
|
109
127
|
|
|
110
|
-
|
|
128
|
+
One fact per line, in the database on your disk. Open the Memory screen and read every one — where it came from, when it landed, whether it rides in every call — and delete any of them. Or type what changed, *"I moved to Busan"*, and watch the edit land.
|
|
111
129
|
|
|
112
|
-
|
|
130
|
+
Every fact remembers the call it was said in, so when one line is not enough she can go back and read the conversation.
|
|
113
131
|
|
|
114
132
|
<br>
|
|
115
133
|
|
|
@@ -117,10 +135,10 @@ And after every call a text model **re-reads what was actually said** and reconc
|
|
|
117
135
|
|
|
118
136
|
| | |
|
|
119
137
|
|---|---|
|
|
120
|
-
| **Your browser** | Bots attach to the Chrome already open on your desk
|
|
138
|
+
| **Your browser** | Bots drive a real browser on your machine — and can attach to the Chrome already open on your desk |
|
|
121
139
|
| **Your machine** | Real commands on real files. Not a VM with a copy |
|
|
122
140
|
| **Your keys** | A SQLite file on your disk, stripped from the shell a bot runs in |
|
|
123
|
-
| **Your memory** |
|
|
141
|
+
| **Your memory** | Facts in a database on your disk. Read, edit and delete them on the screen |
|
|
124
142
|
| **No account** | Nothing to sign up for. The "server" is a Node process on `127.0.0.1` |
|
|
125
143
|
|
|
126
144
|
**Honest caveat:** the *intelligence* is remote. There is no local realtime speech model worth putting a call on yet, so the audio goes to OpenAI or xAI. Everything else never leaves the machine. When a local voice model lands, this is the app that is ready for it.
|
|
@@ -141,7 +159,7 @@ It runs in the terminal you started it in, like `n8n`. There is no daemon and no
|
|
|
141
159
|
|
|
142
160
|
| | |
|
|
143
161
|
|---|---|
|
|
144
|
-
| **Stop it** | `Ctrl+C` |
|
|
162
|
+
| **Stop it** | `Ctrl+C` — running jobs are parked and pick up at the next start |
|
|
145
163
|
| **Start it again** | the same `npx thursday-agent` |
|
|
146
164
|
| **Close the terminal** | it stops with the terminal — nothing is left running |
|
|
147
165
|
| **Keep it up while you work** | run it in its own tab, or `npx thursday-agent &` |
|
|
@@ -153,7 +171,12 @@ It runs in the terminal you started it in, like `n8n`. There is no daemon and no
|
|
|
153
171
|
```
|
|
154
172
|
~/.thursday
|
|
155
173
|
├── local.db calls, memory, bots, jobs, keys
|
|
156
|
-
└── .ai-workspace
|
|
174
|
+
└── .ai-workspace
|
|
175
|
+
├── artifacts/ what the bots made for you
|
|
176
|
+
├── projects/ code they build
|
|
177
|
+
├── bots/ each bot's own memory and kept sign-ins
|
|
178
|
+
├── .agents/ skills you installed
|
|
179
|
+
└── scratch/ one folder per job, cleared three days after it ends
|
|
157
180
|
```
|
|
158
181
|
|
|
159
182
|
The first run also fetches the browser bots drive (~280 MB) in the background, once. That one lands in Playwright's own cache — `~/Library/Caches/ms-playwright`, or `~/.cache/ms-playwright` on Linux — so every run after it, and every upgrade, skips the download.
|
|
@@ -178,7 +201,7 @@ Node 22.18+ and pnpm 10+. The first run fetches the browser bots drive (~280 MB)
|
|
|
178
201
|
| | Providers |
|
|
179
202
|
|---|---|
|
|
180
203
|
| **Voice** (the call) | OpenAI Realtime · xAI Grok Voice |
|
|
181
|
-
| **Text** (the bots) | OpenAI · Anthropic · Google · xAI · Vercel AI Gateway — every model it carries, live |
|
|
204
|
+
| **Text** (the bots) | OpenAI · Anthropic · Google · xAI · Vercel AI Gateway — every model it carries, live · your ChatGPT plan, by signing in |
|
|
182
205
|
| **Studio** | OpenAI · Google · xAI · Vercel AI Gateway |
|
|
183
206
|
|
|
184
207
|
Every bot can run on its own model. Give the errand-runner something cheap and the planner something good.
|
|
@@ -190,12 +213,12 @@ Every bot can run on its own model. Give the errand-runner something cheap and t
|
|
|
190
213
|
|
|
191
214
|
- "What did I download this week?" — one command, run while you talk
|
|
192
215
|
- "Remember my sister's birthday is March 3rd." — saved the moment it lands
|
|
193
|
-
- "Anything from my landlord in my email?" —
|
|
194
|
-
- "
|
|
216
|
+
- "Anything from my landlord in my email?" — read in the Chrome you are signed into
|
|
217
|
+
- "Find the cheapest flight to Osaka on the 14th." — left at the pay button, on your screen
|
|
218
|
+
- "Plan three days in Kyoto, with a map for each day." — Voyage
|
|
219
|
+
- "Make a post about Friday's gig and put it on Instagram." — Insta, once you say so
|
|
195
220
|
- "Write up what we decided today as a one-pager." — opens as a document, not a chat bubble
|
|
196
|
-
- "Draw me a logo for a bakery called Crumb."
|
|
197
221
|
- "Go through my card statements and list every subscription I am paying for."
|
|
198
|
-
- "Book a table for four on Friday, somewhere my sister can actually eat."
|
|
199
222
|
- "Watch this page and tell me when the price drops."
|
|
200
223
|
- "Build me a page of thirty wedding pose photos."
|
|
201
224
|
|
|
@@ -215,7 +238,9 @@ Tell me what you said to her and where it stopped. That is the roadmap.
|
|
|
215
238
|
|
|
216
239
|
## The part where I am honest with you
|
|
217
240
|
|
|
218
|
-
She is a language model with a shell, a browser and your API keys. **That is the product, not an accident.** Keys
|
|
241
|
+
She is a language model with a shell, a browser and your API keys. **That is the product, not an accident.** Keys are stripped from the environment the shell runs in. The server is localhost-only. A login you gave a bot is asked about before it is used, and a payment is left for you to press — instructions a skill carries, not a lock the code holds.
|
|
242
|
+
|
|
243
|
+
The shell is not fenced, and it is not meant to be — a bot that cannot look around cannot do the job, and a command writes wherever you can. That includes the database your keys sit in.
|
|
219
244
|
|
|
220
245
|
It is not a sandbox and it does not pretend to be. → [SECURITY.md](SECURITY.md)
|
|
221
246
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { WORKSPACE_VIEW } from "@/config";
|
|
2
|
+
import { listBotMemory } from "@/features/bot/bot.memory";
|
|
3
|
+
import { serverRoute } from "@/lib/protocol/server-route";
|
|
4
|
+
import { publicError } from "@/lib/public-error";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* One bot's own memory, newest first. `?bot=` names it; read only — a file is
|
|
8
|
+
* deleted through workspace.action, like any file a bot wrote.
|
|
9
|
+
*/
|
|
10
|
+
export const GET = serverRoute(async (request) => {
|
|
11
|
+
const bot = new URL(request.url).searchParams.get("bot")?.trim();
|
|
12
|
+
if (!bot) publicError("Which bot?");
|
|
13
|
+
return listBotMemory(bot, WORKSPACE_VIEW.rows);
|
|
14
|
+
});
|
|
@@ -12,12 +12,8 @@ export type AppEvent =
|
|
|
12
12
|
| { type: "memory" }
|
|
13
13
|
/** Signal: a server was registered, removed, synced, or finished OAuth. */
|
|
14
14
|
| { type: "mcp" }
|
|
15
|
-
/** Signal: a
|
|
16
|
-
| { type: "
|
|
17
|
-
/** Data: a read-back ended on its own. `tally` is one line of what changed, or why it failed. */
|
|
18
|
-
| { type: "memory-tidied"; failed: boolean; tally: string }
|
|
19
|
-
/** Data: show this note on screen, or hide it when null (memory.tool). */
|
|
20
|
-
| { type: "memory-view"; path: string | null }
|
|
15
|
+
/** Signal: a sign-in was written away from the settings screen (ai/chatgpt's sign-in answer). */
|
|
16
|
+
| { type: "config" }
|
|
21
17
|
/** Data: a finished job produced a document; `path` is workspace-relative. */
|
|
22
18
|
| { type: "artifact"; taskId: string; label: string; path: string };
|
|
23
19
|
|
|
@@ -36,7 +32,7 @@ export const SIGNALS: Record<Signal, true> = {
|
|
|
36
32
|
tasks: true,
|
|
37
33
|
memory: true,
|
|
38
34
|
mcp: true,
|
|
39
|
-
|
|
35
|
+
config: true,
|
|
40
36
|
};
|
|
41
37
|
|
|
42
38
|
export const isSignal = (
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { readGatewayCredits } from "@/features/ai/model";
|
|
2
|
+
import type { GatewayCredits } from "@/features/ai/model.schema";
|
|
3
|
+
import { serverRoute } from "@/lib/protocol/server-route";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* What is left on the gateway key, null when none is set. Read by the gateway's
|
|
7
|
+
* row in Settings › Keys and its key dialog; the answer is built in ai/model.
|
|
8
|
+
*/
|
|
9
|
+
export const GET = serverRoute(
|
|
10
|
+
async (): Promise<GatewayCredits | null> => readGatewayCredits(),
|
|
11
|
+
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readChatGptPlan } from "@/features/ai/chatgpt";
|
|
1
2
|
import {
|
|
2
3
|
type AiProvider,
|
|
3
4
|
TEXT_MODEL_PROVIDER_LIST,
|
|
@@ -5,7 +6,7 @@ import {
|
|
|
5
6
|
import { readConfig } from "@/features/config/config.query";
|
|
6
7
|
import { serverRoute } from "@/lib/protocol/server-route";
|
|
7
8
|
|
|
8
|
-
/** Callable providers
|
|
9
|
+
/** Callable providers, whether each one's key is set, and the plan a sign-in is on. */
|
|
9
10
|
export const GET = serverRoute(async () =>
|
|
10
11
|
Promise.all(
|
|
11
12
|
TEXT_MODEL_PROVIDER_LIST.map(
|
|
@@ -15,6 +16,10 @@ export const GET = serverRoute(async () =>
|
|
|
15
16
|
apiKeyName: item.apiKeyName,
|
|
16
17
|
suggestModels: item.suggestModels,
|
|
17
18
|
hasKey: Boolean(await readConfig(item.apiKeyName)),
|
|
19
|
+
...(item.signIn && {
|
|
20
|
+
signIn: true as const,
|
|
21
|
+
plan: await readChatGptPlan(),
|
|
22
|
+
}),
|
|
18
23
|
}),
|
|
19
24
|
),
|
|
20
25
|
),
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { readChatGptUsage } from "@/features/ai/chatgpt";
|
|
2
|
+
import type { SubscriptionUsage } from "@/features/ai/model.schema";
|
|
3
|
+
import { serverRoute } from "@/lib/protocol/server-route";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* How much of the GPT Subscription plan is used, null when nobody is signed in. Read by its
|
|
7
|
+
* row in Settings › Keys and its sign-in dialog; the answer is built in ai/chatgpt.
|
|
8
|
+
*/
|
|
9
|
+
export const GET = serverRoute(
|
|
10
|
+
async (): Promise<SubscriptionUsage | null> => readChatGptUsage(),
|
|
11
|
+
);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { streamMemoryEdit } from "@/features/memory/memory.edit";
|
|
2
|
+
import { serverRoute } from "@/lib/protocol/server-route";
|
|
3
|
+
|
|
4
|
+
/** An edit from the memory screen, streamed as it runs (memory.edit). */
|
|
5
|
+
export const POST = serverRoute(async (request) =>
|
|
6
|
+
streamMemoryEdit(await request.json(), request.signal),
|
|
7
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { findAllNotes, findNoteByPath } from "@/features/memory/memory.query";
|
|
2
|
+
import { serverRoute } from "@/lib/protocol/server-route";
|
|
3
|
+
import { publicError } from "@/lib/public-error";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Read only; writes go through memory.action. One MemoryNote[] page, `?offset=`
|
|
7
|
+
* for the next. `?path=` returns one note: paths contain `/`, so not a segment.
|
|
8
|
+
*/
|
|
9
|
+
export const GET = serverRoute(async (request) => {
|
|
10
|
+
const params = new URL(request.url).searchParams;
|
|
11
|
+
|
|
12
|
+
const path = params.get("path");
|
|
13
|
+
if (path) {
|
|
14
|
+
const note = await findNoteByPath(path);
|
|
15
|
+
if (!note) publicError("Note not found");
|
|
16
|
+
return note;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const offset = Number(params.get("offset") ?? 0);
|
|
20
|
+
return findAllNotes({ offset: Number.isFinite(offset) ? offset : 0 });
|
|
21
|
+
});
|
package/app/api/query-key.ts
CHANGED
|
@@ -24,8 +24,6 @@ export const queryKey = {
|
|
|
24
24
|
/** One note with all facts, by path. Paths contain `/`, so it is a query, not a
|
|
25
25
|
* segment: pass the hook null instead of building this key when closed. */
|
|
26
26
|
notePath: (path: string) => ({ url: "/api/memory", query: { path } }),
|
|
27
|
-
/** MemoryTidyStatusView: settings, what is pending, the pass in progress and the last one. Under the memory prefix on purpose: a fact changing moves it too. */
|
|
28
|
-
memoryTidy: "/api/memory/tidy",
|
|
29
27
|
|
|
30
28
|
/** MCPServerSummary[] with tool counts, no tools */
|
|
31
29
|
mcp: "/api/mcp",
|
|
@@ -56,8 +54,13 @@ export const queryKey = {
|
|
|
56
54
|
*/
|
|
57
55
|
bot: "/api/bot",
|
|
58
56
|
|
|
59
|
-
/** boolean: whether bots keep their own
|
|
60
|
-
|
|
57
|
+
/** boolean: whether bots keep their own memory (Settings > Bots) */
|
|
58
|
+
botMemory: "/api/bot/memory",
|
|
59
|
+
/** BotMemory: one bot's own memory files, newest first (Settings > Bots) */
|
|
60
|
+
botMemoryFiles: (bot: string) => ({
|
|
61
|
+
url: "/api/bot/memory/files",
|
|
62
|
+
query: { bot },
|
|
63
|
+
}),
|
|
61
64
|
|
|
62
65
|
/**
|
|
63
66
|
* Inbox: Task[] newest first with threads, everything running or asking plus
|
|
@@ -136,9 +139,21 @@ export const queryKey = {
|
|
|
136
139
|
* {toolCallId, callId, name, input}; one JSON Result per call, abortable.
|
|
137
140
|
*/
|
|
138
141
|
toolCall: "/api/thursday/tool-call",
|
|
142
|
+
/** POST, an edit from the memory screen, streamed as it runs (memory.edit). */
|
|
143
|
+
memoryEdit: "/api/memory/edit",
|
|
139
144
|
|
|
140
145
|
/** Providers this app can call and whether each key is set */
|
|
141
146
|
llmModel: "/api/llm-model",
|
|
142
147
|
/** Models reachable with the AI Gateway key; gateway only */
|
|
143
148
|
modelCatalog: "/api/llm-model/catalog",
|
|
149
|
+
/**
|
|
150
|
+
* GatewayCredits | null: what is left on the gateway key, null without one.
|
|
151
|
+
* Under `llmModel`, so the key dialog's revalidate re-reads it after a save.
|
|
152
|
+
*/
|
|
153
|
+
gatewayCredits: "/api/llm-model/credits",
|
|
154
|
+
/**
|
|
155
|
+
* SubscriptionUsage | null: how much of the GPT Subscription plan is used, null when
|
|
156
|
+
* signed out. Under `llmModel`, so signing in or out re-reads it.
|
|
157
|
+
*/
|
|
158
|
+
subscriptionUsage: "/api/llm-model/subscription",
|
|
144
159
|
} as const;
|
package/bin/port.mjs
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Which port the app serves on. Plain JavaScript and no app imports: both
|
|
2
|
+
// starters run it before anything is built — `thursday` (bin/thursday.mjs) and
|
|
3
|
+
// `pnpm dev` (scripts/dev.mts).
|
|
4
|
+
|
|
5
|
+
import { createServer } from "node:net";
|
|
6
|
+
|
|
7
|
+
/** The port when none is asked for. */
|
|
8
|
+
const DEFAULT_PORT = 3000;
|
|
9
|
+
/** How far past it to look before giving up. */
|
|
10
|
+
const SEARCH = 20;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Every address a holder of the port may have bound. No single probe sees them
|
|
14
|
+
* all: on macOS a socket on 127.0.0.1 does not block `::`, and one on `::` does
|
|
15
|
+
* not block 127.0.0.1 — yet `localhost` reaches whichever answers first, so two
|
|
16
|
+
* servers "on 3000" each serve some of the page. Probed one at a time, since
|
|
17
|
+
* `0.0.0.0` and `::` block each other.
|
|
18
|
+
*/
|
|
19
|
+
const ADDRESSES = ["127.0.0.1", "::1", "0.0.0.0", "::"];
|
|
20
|
+
|
|
21
|
+
/** No IPv6 on this machine: nobody can hold that address either. */
|
|
22
|
+
const UNBINDABLE = new Set(["EADDRNOTAVAIL", "EAFNOSUPPORT"]);
|
|
23
|
+
|
|
24
|
+
const heldAt = (port, host) =>
|
|
25
|
+
new Promise((resolve) => {
|
|
26
|
+
const probe = createServer()
|
|
27
|
+
.once("error", (cause) => resolve(!UNBINDABLE.has(cause.code)))
|
|
28
|
+
.once("listening", () => probe.close(() => resolve(false)));
|
|
29
|
+
probe.listen(port, host);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/** Whether something already holds the port, on any address. */
|
|
33
|
+
async function taken(port) {
|
|
34
|
+
for (const host of ADDRESSES) {
|
|
35
|
+
if (await heldAt(port, host)) return true;
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 3000 is the most occupied port on a developer's machine. A port nobody asked
|
|
42
|
+
* for is ours to move; a port that was asked for (`--port`, `PORT`) is not, and
|
|
43
|
+
* saying so is more use than moving it quietly. Exits with the reason when no
|
|
44
|
+
* port will do.
|
|
45
|
+
*/
|
|
46
|
+
export async function freePort(asked) {
|
|
47
|
+
const wanted = asked?.trim() || undefined;
|
|
48
|
+
const from = Number(wanted ?? DEFAULT_PORT);
|
|
49
|
+
if (!Number.isInteger(from) || from < 1 || from > 65535) {
|
|
50
|
+
console.error(`\n Not a port: ${wanted}\n`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
if (!(await taken(from))) return from;
|
|
54
|
+
if (wanted !== undefined) {
|
|
55
|
+
console.error(
|
|
56
|
+
`\n Port ${from} is already in use.\n Try another: --port ${from + 1}\n`,
|
|
57
|
+
);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
for (let port = from + 1; port < from + SEARCH; port++) {
|
|
61
|
+
if (!(await taken(port))) return port;
|
|
62
|
+
}
|
|
63
|
+
console.error(`\n Nothing free between ${from} and ${from + SEARCH}.\n`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
package/bin/thursday.mjs
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
import { spawn } from "node:child_process";
|
|
7
7
|
import { existsSync, symlinkSync } from "node:fs";
|
|
8
8
|
import { readFile } from "node:fs/promises";
|
|
9
|
-
import { createServer } from "node:net";
|
|
10
9
|
import { homedir } from "node:os";
|
|
11
10
|
import { join, resolve } from "node:path";
|
|
11
|
+
import { freePort } from "./port.mjs";
|
|
12
12
|
import { ROOT, toolPath } from "./tools.mjs";
|
|
13
13
|
|
|
14
14
|
const { version, name } = JSON.parse(
|
|
@@ -34,7 +34,7 @@ if (has("-h", "--help")) {
|
|
|
34
34
|
$ thursday [options]
|
|
35
35
|
|
|
36
36
|
Options
|
|
37
|
-
--port <n> Port to serve on (default 3000)
|
|
37
|
+
--port <n> Port to serve on (default 3000, or the next free one)
|
|
38
38
|
--home <dir> Where your data lives (default ~/.thursday)
|
|
39
39
|
--no-open Do not open a browser
|
|
40
40
|
-v, --version Print the version
|
|
@@ -50,37 +50,6 @@ if (has("-v", "--version")) {
|
|
|
50
50
|
process.exit(0);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
/** Whether something already holds the port we are about to bind. */
|
|
54
|
-
const taken = (port) =>
|
|
55
|
-
new Promise((resolve) => {
|
|
56
|
-
const probe = createServer()
|
|
57
|
-
.once("error", () => resolve(true))
|
|
58
|
-
.once("listening", () => probe.close(() => resolve(false)))
|
|
59
|
-
.listen(port, "127.0.0.1");
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* 3000 is the most occupied port on a developer's machine, and the first thing
|
|
64
|
-
* `npx thursday-agent` does is bind it — so an untouched install used to end in
|
|
65
|
-
* an EADDRINUSE stack trace. A port nobody asked for is ours to move; a port
|
|
66
|
-
* that was asked for is not, and saying so is more use than moving it quietly.
|
|
67
|
-
*/
|
|
68
|
-
async function freePort(asked) {
|
|
69
|
-
const from = Number(asked ?? 3000);
|
|
70
|
-
if (!(await taken(from))) return from;
|
|
71
|
-
if (asked !== undefined) {
|
|
72
|
-
console.error(
|
|
73
|
-
`\n Port ${from} is already in use.\n Try another: thursday --port ${from + 1}\n`,
|
|
74
|
-
);
|
|
75
|
-
process.exit(1);
|
|
76
|
-
}
|
|
77
|
-
for (let port = from + 1; port < from + 20; port++) {
|
|
78
|
-
if (!(await taken(port))) return port;
|
|
79
|
-
}
|
|
80
|
-
console.error(`\n Nothing free between ${from} and ${from + 20}.\n`);
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
53
|
const asked = flag("port") ?? process.env.PORT;
|
|
85
54
|
const port = String(await freePort(asked));
|
|
86
55
|
const home = resolve(flag("home") || process.env.THURSDAY_HOME || DEFAULT_HOME);
|
|
@@ -138,6 +107,9 @@ const child = spawn(process.execPath, [join(APP, "server.js")], {
|
|
|
138
107
|
// This machine only. A voice agent with a shell is not a thing to expose.
|
|
139
108
|
HOSTNAME: process.env.HOSTNAME || "127.0.0.1",
|
|
140
109
|
NODE_ENV: "production",
|
|
110
|
+
// The server parks running jobs on a stop before it exits (instrumentation);
|
|
111
|
+
// without this, Next exits on the signal first
|
|
112
|
+
NEXT_MANUAL_SIG_HANDLE: "true",
|
|
141
113
|
},
|
|
142
114
|
});
|
|
143
115
|
|