thursday-agent 0.18.0 → 0.19.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/routes-manifest.json +22 -12
- 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 +12 -12
- package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +11 -11
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/artifact/route.js +6 -6
- package/.next/server/app/api/artifact/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/files/route.js +1 -1
- package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/memory/route.js +3 -3
- package/.next/server/app/api/bot/memory/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/route.js +3 -3
- package/.next/server/app/api/bot/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/thread/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/thread/file/route.js +17 -17
- package/.next/server/app/api/bot/thread/file/route.js.nft.json +1 -1
- package/.next/server/app/api/bot/thread/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/events/route.js +2 -2
- package/.next/server/app/api/events/route.js.nft.json +1 -1
- package/.next/server/app/api/favicon/[host]/route.js.nft.json +1 -1
- package/.next/server/app/api/file/[...path]/route.js +2 -2
- package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/automatic/route.js +2 -2
- package/.next/server/app/api/llm-model/automatic/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/catalog/[provider]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/llm-model/catalog/{route.js → [provider]/route.js} +7 -7
- package/.next/server/app/api/llm-model/catalog/[provider]/route.js.nft.json +1 -0
- package/.next/server/app/api/llm-model/catalog/[provider]/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/llm-model/credits/[provider]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/llm-model/credits/{route.js → [provider]/route.js} +7 -7
- package/.next/server/app/api/llm-model/credits/[provider]/route.js.nft.json +1 -0
- package/.next/server/app/api/llm-model/credits/[provider]/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
- package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/memory/edit/route.js +12 -12
- package/.next/server/app/api/memory/edit/route.js.nft.json +1 -1
- package/.next/server/app/api/memory/route.js.nft.json +1 -1
- package/.next/server/app/api/reach/route.js +16 -16
- package/.next/server/app/api/reach/route.js.nft.json +1 -1
- package/.next/server/app/api/routine/route.js +5 -5
- package/.next/server/app/api/routine/route.js.nft.json +1 -1
- package/.next/server/app/api/running/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/running/route/build-manifest.json +12 -0
- package/.next/server/app/api/running/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/running/route.js +10 -0
- package/.next/server/app/api/running/route.js.map +5 -0
- package/.next/server/app/api/running/route.js.nft.json +1 -0
- package/.next/server/app/api/running/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/signins/route.js +4 -4
- package/.next/server/app/api/signins/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/end/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/settings/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/text/route.js +12 -12
- package/.next/server/app/api/thursday/text/route.js.nft.json +1 -1
- package/.next/server/app/api/thursday/tool-call/route.js +12 -12
- package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
- package/.next/server/app/api/workspace/files/route.js +6 -6
- package/.next/server/app/api/workspace/files/route.js.nft.json +1 -1
- 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 +11 -11
- package/.next/server/app/artifact/[...path]/page.js +7 -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.nft.json +1 -1
- package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -1
- package/.next/server/app/page/server-reference-manifest.json +63 -63
- package/.next/server/app/page.js +10 -9
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +3 -2
- package/.next/server/chunks/{[externals]__178rv3v._.js → [externals]__12stas-._.js} +1 -1
- package/.next/server/chunks/[root-of-the-server]__02ra64t._.js +1 -1
- package/.next/server/chunks/{[root-of-the-server]__05dp5tr._.js → [root-of-the-server]__06ky9of._.js} +2 -2
- package/.next/server/chunks/[root-of-the-server]__0b565-x._.js +7 -0
- package/.next/server/chunks/{[root-of-the-server]__1izes4_._.js → [root-of-the-server]__0bmtib_._.js} +2 -2
- package/.next/server/chunks/[root-of-the-server]__0bqveex._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0brmiv2._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__0eivkvk._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__0f7m79q._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0g38-aj._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__0gvdr2h._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0h656y-._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__0hm3tiq._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__0hzdqnv._.js +2 -2
- package/.next/server/chunks/{[root-of-the-server]__0my9geo._.js → [root-of-the-server]__0kzmxpg._.js} +1 -1
- package/.next/server/chunks/[root-of-the-server]__0mgyt8p._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__0mrk2it._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0o5s5-o._.js +5 -0
- package/.next/server/chunks/[root-of-the-server]__0p80i1n._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0qdoc_9._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0qzho69._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0sm5xvm._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0v_kuor._.js +1 -1
- package/.next/server/chunks/{[root-of-the-server]__1k2qs1m._.js → [root-of-the-server]__0ypkfbu._.js} +1 -1
- package/.next/server/chunks/[root-of-the-server]__1-18_pz._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__13hng6h._.js +1 -1
- package/.next/server/chunks/{[root-of-the-server]__01k3vi3._.js → [root-of-the-server]__14iga7p._.js} +1 -1
- package/.next/server/chunks/[root-of-the-server]__16gn7zn._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__18e65_-._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +2 -2
- package/.next/server/chunks/{[root-of-the-server]__0lvjz0b._.js → [root-of-the-server]__1_cgawk._.js} +2 -2
- package/.next/server/chunks/[root-of-the-server]__1ceammd._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1ckt1yj._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1cu5f3z._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1dth047._.js +1 -1
- package/.next/server/chunks/{[root-of-the-server]__061o2_x._.js → [root-of-the-server]__1fc6v12._.js} +1 -1
- package/.next/server/chunks/[root-of-the-server]__1hviq62._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__1m1q6u5._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__1m_dmf6._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1mys2c3._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1ndi14y._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1p0njle._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__1p47fbb._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1pugoq0._.js +1 -1
- package/.next/server/chunks/{[root-of-the-server]__0ts7ai0._.js → [root-of-the-server]__1trns9g._.js} +1 -1
- package/.next/server/chunks/[root-of-the-server]__1ygplx1._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1zn039k._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__20w_g71._.js +3 -0
- package/.next/server/chunks/_06hnfi8._.js +2 -2
- package/.next/server/chunks/_06u9yo-._.js +1 -1
- package/.next/server/chunks/_08_-9ay._.js +2 -2
- package/.next/server/chunks/_0bgjf07._.js +1 -1
- package/.next/server/chunks/_0c49lmw._.js +1 -1
- package/.next/server/chunks/_0hgvg55._.js +1 -1
- package/.next/server/chunks/_0s8ao8z._.js +1 -1
- package/.next/server/chunks/_0ucx1jv._.js +1 -1
- package/.next/server/chunks/_0uzj57i._.js +1 -1
- package/.next/server/chunks/_1-sk_q4._.js +1 -1
- package/.next/server/chunks/_1dxq827._.js +2 -2
- package/.next/server/chunks/_1e54wxa._.js +1 -1
- package/.next/server/chunks/_1frcwj1._.js +1 -1
- package/.next/server/chunks/_1gn2r2q._.js +4 -2
- package/.next/server/chunks/_1gxankq._.js +2 -2
- package/.next/server/chunks/_1i3uucm._.js +1 -1
- package/.next/server/chunks/_1jvy78-._.js +1 -1
- package/.next/server/chunks/_1lg0lsu._.js +53 -0
- package/.next/server/chunks/_1njolhx._.js +294 -0
- package/.next/server/chunks/_1q6e56i._.js +4 -2
- package/.next/server/chunks/_1wtb-77._.js +294 -0
- package/.next/server/chunks/_next-internal_server_app_api_llm-model_catalog_[provider]_route_actions_1i0449q.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_llm-model_credits_[provider]_route_actions_0iui9hz.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_running_route_actions_0o1g-aw.js +3 -0
- package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
- package/.next/server/chunks/features_bot_0zy_q8y._.js +7 -7
- package/.next/server/chunks/features_bot_1dfrdsb._.js +7 -7
- package/.next/server/chunks/{node_modules_1rosz79._.js → node_modules_035o7ku._.js} +1 -1
- package/.next/server/chunks/{node_modules_1er1u8w._.js → node_modules_0tn5t13._.js} +1 -1
- package/.next/server/chunks/{node_modules_103lpef._.js → node_modules_12oq3hr._.js} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__04upd5v._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0p0mv2u._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__1r7tj27._.js → [root-of-the-server]__0sk5enu._.js} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0xyaud4._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__128hnrd._.js → [root-of-the-server]__1-gi9sm._.js} +1 -1
- package/.next/server/chunks/ssr/{[root-of-the-server]__0h6jo0s._.js → [root-of-the-server]__16nn3pe._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__1867koj._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__1c8-7cw._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1tb5vve._.js +2 -1
- package/.next/server/chunks/ssr/_02cm0fr._.js +5 -0
- package/.next/server/chunks/ssr/_07nmtxo._.js +1 -1
- package/.next/server/chunks/ssr/_088vzgn._.js +1 -1
- package/.next/server/chunks/ssr/{_1oafxdu._.js → _0bg1u1j._.js} +2 -2
- package/.next/server/chunks/ssr/_0cv9tmv._.js +1 -1
- package/.next/server/chunks/ssr/_0f9hx5p._.js +1 -1
- package/.next/server/chunks/ssr/_0g9ula_._.js +3 -0
- package/.next/server/chunks/ssr/{_0wuvkqk._.js → _0irozu9._.js} +2 -2
- package/.next/server/chunks/ssr/_0iwsdp7._.js +3 -0
- package/.next/server/chunks/ssr/_0l7rjg5._.js +1 -1
- package/.next/server/chunks/ssr/{_0fo4552._.js → _0nk80t6._.js} +44 -5
- package/.next/server/chunks/ssr/_0pbav_w._.js +1 -1
- package/.next/server/chunks/ssr/{_1r4mc3i._.js → _0q-mdwv._.js} +8 -8
- package/.next/server/chunks/ssr/{_1w899wx._.js → _0s5_ahb._.js} +2 -2
- package/.next/server/chunks/ssr/{_1omom9y._.js → _0t5f2c3._.js} +2 -2
- package/.next/server/chunks/ssr/_0v9r8g2._.js +1 -1
- package/.next/server/chunks/ssr/_0x8ophf._.js +1 -1
- package/.next/server/chunks/ssr/_0x9f717._.js +1 -1
- package/.next/server/chunks/ssr/_107vtdk._.js +162 -0
- package/.next/server/chunks/ssr/{_0ixe3g3._.js → _12lql1x._.js} +3 -3
- package/.next/server/chunks/ssr/_165wnr4._.js +1 -1
- package/.next/server/chunks/ssr/_16_7zeo._.js +1 -1
- package/.next/server/chunks/ssr/_17komoi._.js +3 -0
- package/.next/server/chunks/ssr/{_0j9vh-8._.js → _190hjys._.js} +2 -2
- package/.next/server/chunks/ssr/_1bfrntd._.js +2 -2
- package/.next/server/chunks/ssr/{_1tx-2k7._.js → _1booff4._.js} +2 -2
- package/.next/server/chunks/ssr/{_12jv_41._.js → _1ew1j7l._.js} +2 -2
- package/.next/server/chunks/ssr/_1i2swyr._.js +1 -1
- package/.next/server/chunks/ssr/_1neoj22._.js +1 -1
- package/.next/server/chunks/ssr/{_0osvxkt._.js → _1qsa25k._.js} +2 -2
- package/.next/server/chunks/ssr/_1soynbw._.js +2 -2
- package/.next/server/chunks/ssr/_1vc2xmu._.js +3 -0
- package/.next/server/chunks/ssr/{_1_ogjze._.js → _1wq90j8._.js} +2 -2
- package/.next/server/chunks/ssr/{_1pgxh81._.js → _1zrhkf0._.js} +44 -5
- package/.next/server/chunks/ssr/{_0mpn6q0._.js → _21awrs2._.js} +2 -2
- package/.next/server/chunks/ssr/features_0796o8r._.js +1 -1
- package/.next/server/chunks/ssr/features_bot_1c56lew._.js +37 -0
- package/.next/server/chunks/ssr/{features_bot_18gqkr_._.js → features_bot_1fn_grf._.js} +2 -2
- package/.next/server/chunks/ssr/{features_config_1ond01n._.js → features_config_05zi68v._.js} +3 -3
- package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
- package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +1 -1
- package/.next/server/chunks/ssr/features_routine_components_routine-setting_tsx_055fknz._.js +1 -1
- package/.next/server/chunks/ssr/{node_modules_1-4q6is._.js → node_modules_0-sux1a._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_17o218r._.js → node_modules_01oezhb._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0f485jl._.js → node_modules_04m6ebg._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0upwx50._.js → node_modules_067jfov._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0i_v0-m._.js → node_modules_06ugby3._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0lxwg2v._.js → node_modules_07p51j3._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_16z7p8b._.js → node_modules_0995xyq._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_004qt-z._.js → node_modules_0_uecwx._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0lrn9ci._.js → node_modules_0dsyc90._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0v__o4h._.js → node_modules_0hli6s2._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1gpapfv._.js → node_modules_0m-bde_._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1tus4vi._.js → node_modules_0oqfdbr._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_09dy7tk._.js → node_modules_0tgy5s5._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1hdaxu9._.js → node_modules_1-kjmls._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0gbx70b._.js → node_modules_1-l3ka5._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_20448xv._.js → node_modules_1-w3ayh._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_06m6e97._.js → node_modules_133exgm._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1srjf5c._.js → node_modules_17xc5_k._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1tv_7lk._.js → node_modules_1_i_w30._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1hjvwkh._.js → node_modules_1a2cjfk._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0_hy3i2._.js → node_modules_1k752fe._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0n2-p5q._.js → node_modules_1lie7z8._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0pw13ww._.js → node_modules_1mv70-y._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_10mb0cv._.js → node_modules_1r611t2._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_0nj36zf._.js → node_modules_1vfd8dz._.js} +2 -2
- package/.next/server/chunks/ssr/{node_modules_0ppirau._.js → node_modules_1yaowd7._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_1j886a5._.js → node_modules_20a1wpo._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0lg9pkl._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1r8pxbe._.js} +1 -1
- package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1xgbf5j._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1siiu4h._.js} +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/middleware.js +1 -1
- 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 +64 -64
- package/.next/static/chunks/{1dpg1u4a16ujt.js → 088d3w5qxu19g.js} +2 -2
- package/.next/static/chunks/0bxekp4hnuk1g.js +1 -0
- package/.next/static/chunks/{17dx6w478vnb0.js → 0fw4u_s974j24.js} +1 -1
- package/.next/static/chunks/0hy2x7qhk8wgx.css +1 -0
- package/.next/static/chunks/{240nfv2dtidhc.js → 0n_eshmn_7wfn.js} +2 -2
- package/.next/static/chunks/0ulcp_u_y1u0b.js +15 -0
- package/.next/static/chunks/0vj93zo0yvix9.js +35 -0
- package/.next/static/chunks/{05uvci-bk-vgp.js → 10f98bh4hdmhe.js} +1 -1
- package/.next/static/chunks/{0ruf3dqs--3ve.js → 1b8bce_z_act0.js} +1 -1
- package/.next/static/chunks/1c32d2azsjaj_.js +1 -0
- package/.next/static/chunks/1fs829mz69pxz.js +1 -0
- package/.next/static/chunks/{2ug8q1x9e-_j6.js → 1lwlh4mo_vv8d.js} +1 -1
- package/.next/static/chunks/{3r7u1y9xjoh-v.js → 1po8fkg40peu-.js} +1 -1
- package/.next/static/chunks/{27l8qwnk1j66z.js → 1rg6b9l5fm1hj.js} +1 -1
- package/.next/static/chunks/{1pe7i5yu779ta.js → 26g3iwfuad-7p.js} +1 -1
- package/.next/static/chunks/2bjnmtke_q43c.js +1 -0
- package/.next/static/chunks/2c86k0o-1p9_w.js +1 -0
- package/.next/static/chunks/2gf4t0d76bvyv.js +1 -0
- package/.next/static/chunks/2rj3q_ahctv19.js +1 -0
- package/.next/static/chunks/{2lhc74urf3acr.js → 2x6-fpctvucte.js} +1 -1
- package/.next/static/chunks/{2gxfy__ef51n9.js → 2yicf7bky866n.js} +1 -1
- package/.next/static/chunks/{0oqviw3f55nfp.js → 350ws7svim7ij.js} +1 -1
- package/.next/static/chunks/3e1w_nwfb39j-.js +1 -0
- package/.next/static/chunks/3v3ooretb54ag.js +1 -0
- package/.next/static/chunks/{2lzg4zedtmyic.js → 44bcbnmup71so.js} +1 -1
- package/.next/static/chunks/{1h_6rh86q3i4p.js → 458dtbsemx996.js} +1 -1
- package/bin/background.mjs +995 -0
- package/bin/lock.mjs +64 -29
- package/bin/thursday.mjs +111 -42
- package/bin/tools.mjs +58 -4
- package/guide/calls.md +8 -0
- package/guide/setup.md +27 -13
- package/package.json +1 -1
- package/seed-skills/concierge/travel/references/itinerary.md +1 -1
- package/seed-skills/concierge/travel/scripts/itinerary.mjs +7 -2
- package/skills/artifact/references/book.md +3 -3
- package/.next/server/app/api/llm-model/catalog/route/app-paths-manifest.json +0 -3
- package/.next/server/app/api/llm-model/catalog/route.js.nft.json +0 -1
- package/.next/server/app/api/llm-model/catalog/route_client-reference-manifest.js +0 -3
- package/.next/server/app/api/llm-model/credits/route/app-paths-manifest.json +0 -3
- package/.next/server/app/api/llm-model/credits/route.js.nft.json +0 -1
- package/.next/server/app/api/llm-model/credits/route_client-reference-manifest.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__03xamry._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__04hhvpu._.js +0 -7
- package/.next/server/chunks/[root-of-the-server]__1-rmal0._.js +0 -5
- package/.next/server/chunks/[root-of-the-server]__10xnb7e._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1etbk64._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1v7x5ym._.js +0 -3
- package/.next/server/chunks/_07nxi75._.js +0 -255
- package/.next/server/chunks/_0srlnvd._.js +0 -16
- package/.next/server/chunks/_0xygcxs._.js +0 -255
- package/.next/server/chunks/_next-internal_server_app_api_llm-model_catalog_route_actions_1eu2y41.js +0 -3
- package/.next/server/chunks/_next-internal_server_app_api_llm-model_credits_route_actions_0v424pb.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__06knwl5._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__07ehpky._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1gzje-h._.js +0 -3
- package/.next/server/chunks/ssr/_0jstvlg._.js +0 -39
- package/.next/server/chunks/ssr/_1-41lck._.js +0 -3
- package/.next/server/chunks/ssr/_10jtmhl._.js +0 -3
- package/.next/server/chunks/ssr/_19jez1a._.js +0 -3
- package/.next/server/chunks/ssr/_1jd8rjm._.js +0 -3
- package/.next/server/chunks/ssr/_1mdjoak._.js +0 -162
- package/.next/static/chunks/09y_43y1cy5jw.js +0 -1
- package/.next/static/chunks/0vggwjufw2-6r.js +0 -1
- package/.next/static/chunks/0x4m9nj2fazl2.js +0 -35
- package/.next/static/chunks/1-1yfu34-3p2p.js +0 -1
- package/.next/static/chunks/10oyyypxn_cpx.js +0 -1
- package/.next/static/chunks/184-r80rv0xay.css +0 -1
- package/.next/static/chunks/1_hgdoungpm0o.js +0 -1
- package/.next/static/chunks/2kjwmo70judc2.js +0 -15
- package/.next/static/chunks/2uk8rdtr-pk58.js +0 -1
- package/.next/static/chunks/3vg1-oc-zgw_7.js +0 -1
- package/.next/static/chunks/3vrmcm31ih7gb.js +0 -1
- package/.next/static/chunks/41ztsnjn4qrn-.js +0 -1
- package/bin/autostart.mjs +0 -192
- /package/.next/server/app/api/llm-model/catalog/{route → [provider]/route}/build-manifest.json +0 -0
- /package/.next/server/app/api/llm-model/catalog/{route → [provider]/route}/server-reference-manifest.json +0 -0
- /package/.next/server/app/api/llm-model/catalog/{route.js.map → [provider]/route.js.map} +0 -0
- /package/.next/server/app/api/llm-model/credits/{route → [provider]/route}/build-manifest.json +0 -0
- /package/.next/server/app/api/llm-model/credits/{route → [provider]/route}/server-reference-manifest.json +0 -0
- /package/.next/server/app/api/llm-model/credits/{route.js.map → [provider]/route.js.map} +0 -0
- /package/.next/static/{-IBxB5oqr6e3RuOCCmYtL → YhaRHJqObuAcXZe5VLFs0}/_buildManifest.js +0 -0
- /package/.next/static/{-IBxB5oqr6e3RuOCCmYtL → YhaRHJqObuAcXZe5VLFs0}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{-IBxB5oqr6e3RuOCCmYtL → YhaRHJqObuAcXZe5VLFs0}/_ssgManifest.js +0 -0
package/bin/lock.mjs
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { spawnSync } from "node:child_process";
|
|
7
7
|
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import {
|
|
9
|
+
import { backgroundJob } from "./background.mjs";
|
|
10
10
|
import { thursdayCommand } from "./tools.mjs";
|
|
11
11
|
|
|
12
12
|
/** Beside the database, and named so a checkout never commits it (`*.local.*`). */
|
|
@@ -21,37 +21,70 @@ export function runningOn(home) {
|
|
|
21
21
|
return null;
|
|
22
22
|
}
|
|
23
23
|
if (!Number.isInteger(held?.pid) || held.pid === process.pid) return null;
|
|
24
|
-
|
|
25
|
-
// Signal 0 asks whether the process exists and sends nothing
|
|
26
|
-
process.kill(held.pid, 0);
|
|
27
|
-
} catch (error) {
|
|
28
|
-
// Someone else's process by that id is still a live one
|
|
29
|
-
if (error?.code !== "EPERM") return null;
|
|
30
|
-
}
|
|
31
|
-
// A lock left by a server that died without its exit (a kill -9, a power cut) names a pid
|
|
32
|
-
// another process may hold after a restart, which would refuse every start until the file
|
|
33
|
-
// was deleted by hand: the pid is this server only if it started when the lock says. Where
|
|
34
|
-
// `ps` cannot say (Windows), or the lock predates `started`, the live pid is all there is.
|
|
35
|
-
const started = startedAt(held.pid);
|
|
36
|
-
if (typeof held.started === "string" && started && started !== held.started)
|
|
37
|
-
return null;
|
|
24
|
+
if (!stillRuns(held)) return null;
|
|
38
25
|
return {
|
|
39
26
|
pid: held.pid,
|
|
40
27
|
url: String(held.url ?? ""),
|
|
41
28
|
// Null from `pnpm dev`, and from a server started before the lock said
|
|
42
29
|
version: typeof held.version === "string" ? held.version : null,
|
|
30
|
+
background: held.background === true,
|
|
43
31
|
};
|
|
44
32
|
}
|
|
45
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Whether the process a lock names is still the one that wrote it. A lock left by a process
|
|
36
|
+
* that died without its exit (a kill -9, a power cut) names a pid another process may hold
|
|
37
|
+
* after a restart, which would refuse every start until the file was deleted by hand: the pid
|
|
38
|
+
* is the writer only if it started when the lock says. Where `ps` cannot say (Windows), or the
|
|
39
|
+
* lock predates its start time, the live pid is all there is.
|
|
40
|
+
*/
|
|
41
|
+
export function stillRuns(held) {
|
|
42
|
+
try {
|
|
43
|
+
// Signal 0 asks whether the process exists and sends nothing
|
|
44
|
+
process.kill(held.pid, 0);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
// Someone else's process by that id is still a live one
|
|
47
|
+
if (error?.code !== "EPERM") return false;
|
|
48
|
+
}
|
|
49
|
+
// Compared in UTC: `ps` writes the reader's zone, and a server under launchd (no TZ), a
|
|
50
|
+
// terminal that exports one, or a Mac that moved zones since it started spelled one start
|
|
51
|
+
// two ways — the server read as gone, and a second one opened the same database. A lock
|
|
52
|
+
// written before `startedUtc` has `started` alone, in its writer's zone.
|
|
53
|
+
const [said, zone] =
|
|
54
|
+
typeof held.startedUtc === "string"
|
|
55
|
+
? [held.startedUtc, "UTC"]
|
|
56
|
+
: [held.started, undefined];
|
|
57
|
+
if (typeof said !== "string") return true;
|
|
58
|
+
const started = startedAt(held.pid, zone);
|
|
59
|
+
return !started || started === said;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Whether the server holding this folder is `pid`, or runs under it: launchd knows a job by the
|
|
64
|
+
* process it started, and a version manager's shim (Volta's) starts node as its child rather
|
|
65
|
+
* than becoming it.
|
|
66
|
+
*/
|
|
67
|
+
export function heldBy(running, pid) {
|
|
68
|
+
if (!running || !pid) return false;
|
|
69
|
+
return (
|
|
70
|
+
running.pid === pid ||
|
|
71
|
+
Number(ps(["-o", "ppid=", "-p", String(running.pid)])) === pid
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
46
75
|
// LC_ALL=C: a start time is compared as `ps` wrote it, so both reads spell it alike
|
|
47
|
-
const ps = (
|
|
76
|
+
const ps = (args, zone) =>
|
|
48
77
|
spawnSync("ps", args, {
|
|
49
78
|
encoding: "utf8",
|
|
50
|
-
env: { ...process.env, LC_ALL: "C" },
|
|
79
|
+
env: { ...process.env, LC_ALL: "C", ...(zone ? { TZ: zone } : {}) },
|
|
51
80
|
}).stdout?.trim() ?? "";
|
|
52
81
|
|
|
53
|
-
/**
|
|
54
|
-
|
|
82
|
+
/**
|
|
83
|
+
* When a process started, to the second, as `ps` has it in `zone` (the reader's own when none).
|
|
84
|
+
* Empty where it cannot say.
|
|
85
|
+
*/
|
|
86
|
+
export const startedAt = (pid, zone) =>
|
|
87
|
+
ps(["-o", "lstart=", "-p", String(pid)], zone);
|
|
55
88
|
|
|
56
89
|
/**
|
|
57
90
|
* Where a process runs, as `ps` has it: the terminal it is attached to (null when none), when
|
|
@@ -59,27 +92,27 @@ const startedAt = (pid) => ps("-o", "lstart=", "-p", String(pid));
|
|
|
59
92
|
* `npx thursday-agent`, not the Node process under it. Null where `ps` cannot say (Windows).
|
|
60
93
|
*/
|
|
61
94
|
function whereRuns(pid) {
|
|
62
|
-
const [tty, group, ...started] = ps(
|
|
95
|
+
const [tty, group, ...started] = ps([
|
|
63
96
|
"-o",
|
|
64
97
|
"tty=,pgid=,lstart=",
|
|
65
98
|
"-p",
|
|
66
99
|
String(pid),
|
|
67
|
-
).split(/\s+/);
|
|
100
|
+
]).split(/\s+/);
|
|
68
101
|
if (!tty || !group) return null;
|
|
69
102
|
return {
|
|
70
103
|
terminal: tty === "??" || tty === "?" ? null : tty,
|
|
71
104
|
group,
|
|
72
|
-
// "Fri Sep 25 20:55:51 2026" to the minute
|
|
105
|
+
// "Fri Sep 25 20:55:51 2026" to the minute, in the reader's zone: it is read, not compared
|
|
73
106
|
since: started.join(" ").replace(/:\d\d \d{4}$/, ""),
|
|
74
|
-
typed: ps("-o", "command=", "-p", group),
|
|
107
|
+
typed: ps(["-o", "command=", "-p", group]),
|
|
75
108
|
};
|
|
76
109
|
}
|
|
77
110
|
|
|
78
111
|
/**
|
|
79
112
|
* How to stop the server with this pid, said where it can be done. A person told only "stop
|
|
80
113
|
* it" looked for a terminal they could not find: the one it runs in is named, with a command
|
|
81
|
-
* that does the same from any terminal. One that
|
|
82
|
-
* launchd, so it is stopped by
|
|
114
|
+
* that does the same from any terminal. One that runs in the background is started again by
|
|
115
|
+
* launchd, so it is stopped by stopping that. Lines to print, without indent.
|
|
83
116
|
*/
|
|
84
117
|
export function stopLines(pid, home) {
|
|
85
118
|
const where = whereRuns(pid);
|
|
@@ -88,10 +121,8 @@ export function stopLines(pid, home) {
|
|
|
88
121
|
`It runs in a terminal (${where.terminal}${where.typed ? `, ${where.typed}` : ""}, since ${where.since}).`,
|
|
89
122
|
`Ctrl+C there, or from any terminal: kill -INT -${where.group}`,
|
|
90
123
|
];
|
|
91
|
-
if (
|
|
92
|
-
return [
|
|
93
|
-
`It starts with your Mac. To stop it: ${thursdayCommand()} autostart --off`,
|
|
94
|
-
];
|
|
124
|
+
if (backgroundJob()?.home === home)
|
|
125
|
+
return [`It runs in the background. To stop it: ${thursdayCommand()} stop`];
|
|
95
126
|
if (where) return [`It runs in the background. To stop it: kill ${pid}`];
|
|
96
127
|
return ["Ctrl+C where it runs."];
|
|
97
128
|
}
|
|
@@ -120,9 +151,13 @@ export function holdFolder(home, url, version) {
|
|
|
120
151
|
file,
|
|
121
152
|
`${JSON.stringify({
|
|
122
153
|
pid: process.pid,
|
|
154
|
+
startedUtc: startedAt(process.pid, "UTC") || undefined,
|
|
155
|
+
// What a starter from before `startedUtc` reads, in this process's zone
|
|
123
156
|
started: startedAt(process.pid) || undefined,
|
|
124
157
|
url,
|
|
125
158
|
version,
|
|
159
|
+
// Which one launchd started, so a stop can end it when launchd did not (background.mjs)
|
|
160
|
+
background: process.env.THURSDAY_BACKGROUND ? true : undefined,
|
|
126
161
|
})}\n`,
|
|
127
162
|
);
|
|
128
163
|
} catch {
|
package/bin/thursday.mjs
CHANGED
|
@@ -14,12 +14,19 @@ import {
|
|
|
14
14
|
symlinkSync,
|
|
15
15
|
} from "node:fs";
|
|
16
16
|
import { readFile } from "node:fs/promises";
|
|
17
|
-
import { homedir } from "node:os";
|
|
18
17
|
import { join, resolve } from "node:path";
|
|
18
|
+
import { backgroundJob, keepLogShort, offerBackground } from "./background.mjs";
|
|
19
19
|
import { askToSetDatabaseAside, MIGRATION_FAILED_EXIT } from "./database.mjs";
|
|
20
20
|
import { holdFolder, runningOn, stopLines } from "./lock.mjs";
|
|
21
21
|
import { freePort } from "./port.mjs";
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
commandFor,
|
|
24
|
+
DEFAULT_HOME,
|
|
25
|
+
openBrowser,
|
|
26
|
+
ROOT,
|
|
27
|
+
thursdayCommand,
|
|
28
|
+
toolPath,
|
|
29
|
+
} from "./tools.mjs";
|
|
23
30
|
|
|
24
31
|
const { version, name } = JSON.parse(
|
|
25
32
|
await readFile(join(ROOT, "package.json"), "utf8"),
|
|
@@ -39,8 +46,11 @@ if (has("-h", "--help")) {
|
|
|
39
46
|
${name} ${version}
|
|
40
47
|
|
|
41
48
|
Usage
|
|
42
|
-
$ ${command} [options]
|
|
43
|
-
$ ${command}
|
|
49
|
+
$ ${command} [options] Start it here, in this terminal
|
|
50
|
+
$ ${command} start [options] Keep it running in the background, and start it
|
|
51
|
+
when you log in (macOS)
|
|
52
|
+
$ ${command} stop Stop it in the background
|
|
53
|
+
$ ${command} status Whether it runs, where, and how to reach it
|
|
44
54
|
|
|
45
55
|
Options
|
|
46
56
|
--port <n> Port to serve on (default 4747, or the next free one)
|
|
@@ -72,62 +82,112 @@ if (!APP) {
|
|
|
72
82
|
process.exit(1);
|
|
73
83
|
}
|
|
74
84
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
* keeps them in the home folder, never inside the package — an upgrade replaces
|
|
78
|
-
* that. A checkout keeps them in the checkout, which is where `pnpm dev` already
|
|
79
|
-
* writes them (config.ts DATA_DIR): a build started here opens the data it was
|
|
80
|
-
* developed against, not a second, empty one beside it.
|
|
81
|
-
*/
|
|
82
|
-
const DEFAULT_HOME = APP === ROOT ? join(homedir(), ".thursday") : ROOT;
|
|
83
|
-
|
|
84
|
-
const asked = flag("port") ?? process.env.PORT;
|
|
85
|
+
// An exported `PORT=` with nothing in it asks for no port
|
|
86
|
+
const asked = flag("port") ?? (process.env.PORT?.trim() || undefined);
|
|
85
87
|
const home = resolve(flag("home") || process.env.THURSDAY_HOME || DEFAULT_HOME);
|
|
86
88
|
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
89
|
+
// The background (background.mjs): each is the whole command, and never goes on to serve.
|
|
90
|
+
// `autostart` and `autostart --off` are what earlier versions called start and stop.
|
|
91
|
+
const said =
|
|
92
|
+
argv[0] === "autostart" ? (has("--off") ? "stop" : "start") : argv[0];
|
|
93
|
+
const background = ["start", "stop", "status"].includes(said) ? said : null;
|
|
94
|
+
/** A start that could not run it in the background, and serves in this terminal instead. */
|
|
95
|
+
let fellBack = false;
|
|
96
|
+
if (background) {
|
|
97
|
+
const { printStatus, startInBackground, stopBackground } = await import(
|
|
98
|
+
"./background.mjs"
|
|
99
|
+
);
|
|
100
|
+
if (background === "status") {
|
|
101
|
+
printStatus({ home });
|
|
102
|
+
process.exit(0);
|
|
103
|
+
}
|
|
104
|
+
if (background === "stop")
|
|
105
|
+
process.exit((await stopBackground({ home })) ? 0 : 1);
|
|
106
|
+
const started = await startInBackground({
|
|
107
|
+
root: ROOT,
|
|
108
|
+
home,
|
|
109
|
+
port: asked,
|
|
110
|
+
open: !has("--no-open"),
|
|
111
|
+
version,
|
|
112
|
+
});
|
|
113
|
+
if (started === true) process.exit(0);
|
|
114
|
+
// A person at a terminal still gets it running, there, for as long as it stays open, as the
|
|
115
|
+
// first run's question does. "held" is a folder something else serves already; a script
|
|
116
|
+
// gets the failure
|
|
117
|
+
if (started === "held" || !process.stdin.isTTY || !process.stdout.isTTY)
|
|
118
|
+
process.exit(1);
|
|
119
|
+
fellBack = true;
|
|
103
120
|
}
|
|
104
121
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Leaves when this folder already has a server: a second one would take the next port, and
|
|
124
|
+
* serve the same calls, jobs and phone twice (lock.mjs). Run again, it is usually the app they
|
|
125
|
+
* came for — a second `npx` once its tab is closed — so that one opens instead. One of another
|
|
126
|
+
* version does not: they ran this one to have this one.
|
|
127
|
+
*/
|
|
128
|
+
function leaveToRunning() {
|
|
129
|
+
const running = runningOn(home);
|
|
130
|
+
if (!running) return;
|
|
111
131
|
const other =
|
|
112
132
|
running.version && running.version !== version ? running.version : null;
|
|
113
133
|
const opens = Boolean(running.url) && !other && !has("--no-open");
|
|
134
|
+
// The copy in the background moves to this version by starting it from this one: through
|
|
135
|
+
// npx pinned, since a bare `npx thursday-agent` is whichever version npm resolves that day
|
|
136
|
+
const command = thursdayCommand();
|
|
137
|
+
const moves =
|
|
138
|
+
other && backgroundJob()?.home === home
|
|
139
|
+
? ` To move it to ${version}: ${commandFor(
|
|
140
|
+
"start",
|
|
141
|
+
home,
|
|
142
|
+
command === "npx thursday-agent"
|
|
143
|
+
? `npx thursday-agent@${version}`
|
|
144
|
+
: command,
|
|
145
|
+
)}\n`
|
|
146
|
+
: null;
|
|
114
147
|
console.log(
|
|
115
148
|
`\n Thursday${other ? ` ${other}` : ""} is already running on this data folder${running.url ? `: ${running.url}` : ""}\n${
|
|
116
149
|
opens
|
|
117
150
|
? " Opened it in your browser.\n"
|
|
118
|
-
:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
151
|
+
: (moves ??
|
|
152
|
+
(other
|
|
153
|
+
? ` To run ${version} instead, stop that one and run this again.\n`
|
|
154
|
+
: ""))
|
|
155
|
+
}${
|
|
156
|
+
moves
|
|
157
|
+
? ""
|
|
158
|
+
: stopLines(running.pid, home)
|
|
159
|
+
.map((line) => ` ${line}\n`)
|
|
160
|
+
.join("")
|
|
161
|
+
}`,
|
|
124
162
|
);
|
|
125
163
|
if (opens) openBrowser(running.url);
|
|
126
164
|
process.exit(other ? 1 : 0);
|
|
127
165
|
}
|
|
166
|
+
|
|
167
|
+
// Before a port is picked
|
|
168
|
+
leaveToRunning();
|
|
169
|
+
|
|
170
|
+
if (fellBack) console.log(" Running it in this terminal instead.");
|
|
171
|
+
else {
|
|
172
|
+
// A first run in a terminal asks once whether to keep it running in the background; said
|
|
173
|
+
// yes, the background serves and this run is done
|
|
174
|
+
const chose = await offerBackground({
|
|
175
|
+
root: ROOT,
|
|
176
|
+
home,
|
|
177
|
+
port: asked,
|
|
178
|
+
open: !has("--no-open"),
|
|
179
|
+
version,
|
|
180
|
+
});
|
|
181
|
+
if (chose !== "terminal") process.exit(chose === "background" ? 0 : 1);
|
|
182
|
+
}
|
|
183
|
+
// The question waits as long as the person does, and a start takes a minute: a server another
|
|
184
|
+
// terminal started on this folder meanwhile is the one to use, not a second beside it
|
|
185
|
+
leaveToRunning();
|
|
128
186
|
const port = String(await freePort(asked, home));
|
|
129
187
|
const url = `http://localhost:${port}`;
|
|
130
188
|
holdFolder(home, url, version);
|
|
189
|
+
// launchd writes the background's output to a log that nothing else trims
|
|
190
|
+
if (process.env.THURSDAY_BACKGROUND) keepLogShort(home);
|
|
131
191
|
/** Where config.ts DB_PATH puts the database under the home. */
|
|
132
192
|
const database = join(home, "local.db");
|
|
133
193
|
|
|
@@ -173,6 +233,15 @@ function start() {
|
|
|
173
233
|
THURSDAY_URL: url,
|
|
174
234
|
// Where a bot's shell finds playwright-cli (workspace.ts TOOL_PATH)
|
|
175
235
|
THURSDAY_TOOL_PATH: toolPath().join(":"),
|
|
236
|
+
// How it was started and what the person types to run it, for Settings to say where it
|
|
237
|
+
// runs and how to stop or keep it (features/settings/running.ts)
|
|
238
|
+
THURSDAY_RUNS: process.env.THURSDAY_BACKGROUND
|
|
239
|
+
? "background"
|
|
240
|
+
: process.stdin.isTTY
|
|
241
|
+
? "terminal"
|
|
242
|
+
: "elsewhere",
|
|
243
|
+
THURSDAY_COMMAND: thursdayCommand(),
|
|
244
|
+
THURSDAY_START: commandFor("start", home),
|
|
176
245
|
PORT: port,
|
|
177
246
|
// This machine only. A voice agent with a shell is not a thing to expose.
|
|
178
247
|
// Never inherited: Docker exports HOSTNAME as the container and some
|
package/bin/tools.mjs
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// imports: this runs from the published `bin`, on a machine that has neither a
|
|
3
3
|
// build nor a TypeScript loader.
|
|
4
4
|
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
5
6
|
import { existsSync } from "node:fs";
|
|
6
7
|
import { createRequire } from "node:module";
|
|
8
|
+
import { homedir } from "node:os";
|
|
7
9
|
import { dirname, join, resolve, sep } from "node:path";
|
|
8
10
|
|
|
9
11
|
const require = createRequire(import.meta.url);
|
|
@@ -11,22 +13,74 @@ const require = createRequire(import.meta.url);
|
|
|
11
13
|
/** The checkout, or the installed package. */
|
|
12
14
|
export const ROOT = resolve(import.meta.dirname, "..");
|
|
13
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Where the copy that runs in the background is installed (background.mjs). Beside the
|
|
18
|
+
* default data folder, so everything the app keeps on the computer is under one folder.
|
|
19
|
+
*/
|
|
20
|
+
export const PROGRAM = join(homedir(), ".thursday", "app");
|
|
21
|
+
|
|
22
|
+
/** The one copy with the dev script beside it; the package ships no `scripts`. */
|
|
23
|
+
export const isCheckout = (root) =>
|
|
24
|
+
existsSync(join(root, "scripts", "dev.mts"));
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The user's files when no `--home` is given: database, workspace, installed skills. An
|
|
28
|
+
* installed package keeps them in the home folder, never inside the package — an upgrade
|
|
29
|
+
* replaces that. A checkout keeps them in the checkout, which is where `pnpm dev` already
|
|
30
|
+
* writes them (config.ts DATA_DIR): a build started here opens the data it was developed
|
|
31
|
+
* against, not a second, empty one beside it.
|
|
32
|
+
*/
|
|
33
|
+
export const DEFAULT_HOME = isCheckout(ROOT)
|
|
34
|
+
? ROOT
|
|
35
|
+
: join(homedir(), ".thursday");
|
|
36
|
+
|
|
14
37
|
/**
|
|
15
38
|
* What this person types to run the app, for a line that tells them to run it again. Only a
|
|
16
39
|
* global install puts `thursday` on the PATH: said to someone who ran `npx`, it is a command
|
|
17
|
-
* they do not have. npx names itself in npm_lifecycle_event and unpacks into its `_npx` cache
|
|
18
|
-
*
|
|
40
|
+
* they do not have. npx names itself in npm_lifecycle_event and unpacks into its `_npx` cache,
|
|
41
|
+
* and the copy that runs in the background was put there from one.
|
|
19
42
|
*/
|
|
20
43
|
export function thursdayCommand() {
|
|
44
|
+
// Written into the background job by the command that started it, which knew
|
|
45
|
+
if (process.env.THURSDAY_COMMAND?.trim())
|
|
46
|
+
return process.env.THURSDAY_COMMAND.trim();
|
|
21
47
|
if (
|
|
22
48
|
process.env.npm_lifecycle_event === "npx" ||
|
|
23
|
-
ROOT.includes(`${sep}_npx${sep}`)
|
|
49
|
+
ROOT.includes(`${sep}_npx${sep}`) ||
|
|
50
|
+
ROOT.startsWith(`${PROGRAM}${sep}`)
|
|
24
51
|
)
|
|
25
52
|
return "npx thursday-agent";
|
|
26
|
-
if (
|
|
53
|
+
if (isCheckout(ROOT)) return "pnpm start";
|
|
27
54
|
return "thursday";
|
|
28
55
|
}
|
|
29
56
|
|
|
57
|
+
/**
|
|
58
|
+
* The line to type for `sub` — start, stop, status, or "" to run it in a terminal — on this
|
|
59
|
+
* data folder: `--home` is said when it is not the one the command finds by itself. Followed
|
|
60
|
+
* as printed without it, a line served another folder, an empty app or a checkout's own data.
|
|
61
|
+
*/
|
|
62
|
+
export function commandFor(sub, home, command = thursdayCommand()) {
|
|
63
|
+
const line = sub ? `${command} ${sub}` : command;
|
|
64
|
+
return home && resolve(home) !== DEFAULT_HOME
|
|
65
|
+
? `${line} --home ${shellWord(home)}`
|
|
66
|
+
: line;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A path a shell reads back as it is: quoted once it holds more than plain characters. */
|
|
70
|
+
const shellWord = (path) =>
|
|
71
|
+
/^[\w@%+=:,./-]+$/.test(path) ? path : `'${path.replaceAll("'", `'\\''`)}'`;
|
|
72
|
+
|
|
73
|
+
/** A browser that will not open is not a failure. */
|
|
74
|
+
export function openBrowser(url) {
|
|
75
|
+
const [command, args] =
|
|
76
|
+
process.platform === "darwin"
|
|
77
|
+
? ["open", [url]]
|
|
78
|
+
: process.platform === "win32"
|
|
79
|
+
? ["cmd", ["/c", "start", "", url]]
|
|
80
|
+
: ["xdg-open", [url]];
|
|
81
|
+
spawn(command, args, { stdio: "ignore" }).on("error", () => {});
|
|
82
|
+
}
|
|
83
|
+
|
|
30
84
|
/**
|
|
31
85
|
* The `playwright-cli` entry, resolved rather than guessed: pnpm keeps it under
|
|
32
86
|
* `.pnpm`, npm hoists it, npx puts it in a temp tree. Null when it is not
|
package/guide/calls.md
CHANGED
|
@@ -28,6 +28,14 @@ several steps — goes to a bot while the call carries on. She picks the bot and
|
|
|
28
28
|
While she is working, the line under her face says so. The microphone stays open: anything said
|
|
29
29
|
meanwhile is heard and answered once she is done, so there is no need to repeat it.
|
|
30
30
|
|
|
31
|
+
**Share screen**, on that line during a spoken call, shows her a screen, a window or a tab; the
|
|
32
|
+
browser asks which. A small copy of it stands at the top right while it is shared. Nothing of it
|
|
33
|
+
is sent while it is only shared: she looks when what they ask needs it — "what does this error
|
|
34
|
+
say?" — and then a picture of it as it is at that moment goes to the model behind her, nowhere
|
|
35
|
+
else. **Stop** on the line, the browser's own bar, or the end of the call stops sharing. When the
|
|
36
|
+
browser refuses — on a Mac, the browser needs Screen Recording in System Settings › Privacy &
|
|
37
|
+
Security to share a window or the whole screen — its reason shows, and nothing is shared.
|
|
38
|
+
|
|
31
39
|
## Ending it
|
|
32
40
|
|
|
33
41
|
Saying goodbye usually ends the call, but not always. Tapping her face ends it for certain, and so
|
package/guide/setup.md
CHANGED
|
@@ -36,14 +36,17 @@ Two easier ways for bots come next:
|
|
|
36
36
|
shows how much of the plan is used and when it resets. It does not cover a spoken call, which
|
|
37
37
|
OpenAI bills by the minute on a key.
|
|
38
38
|
- **Vercel AI Gateway**: one key for every model; its row shows what credit is left.
|
|
39
|
+
- **OpenRouter**: the same, one key for every model it carries, free ones among them; its row
|
|
40
|
+
shows what credit is left.
|
|
39
41
|
|
|
40
42
|
Under them, every other provider (Claude, Gemini, xAI and more, some behind **More**) is a mark to
|
|
41
43
|
tap and paste a key into, with a link to the page that makes one.
|
|
42
44
|
|
|
43
45
|
A search key (Exa) is optional. With it, calls and bots all search through Exa, which is cheap and
|
|
44
46
|
has free monthly credits. Without it, a call uses OpenAI's own search, and a bot uses its model's
|
|
45
|
-
own search: the GPT Subscription, OpenAI, Claude, Gemini and
|
|
46
|
-
any other provider has no search of its own, so it opens pages in its browser
|
|
47
|
+
own search: the GPT Subscription, OpenAI, Claude, Gemini, xAI and OpenRouter have one. A bot on
|
|
48
|
+
the Gateway or any other provider has no search of its own, so it opens pages in its browser
|
|
49
|
+
instead.
|
|
47
50
|
|
|
48
51
|
## Models
|
|
49
52
|
|
|
@@ -121,20 +124,29 @@ with it. Chrome and Edge can install it as its own window with its own icon. The
|
|
|
121
124
|
this once (**Install** or **Not now**), and **Install app** stays at the foot of the Settings list
|
|
122
125
|
until it is installed. In Safari on a Mac it is **File › Add to Dock**; Firefox cannot do it.
|
|
123
126
|
|
|
124
|
-
The window only shows what the server serves, and the server is started
|
|
125
|
-
thursday-agent`. On a Mac,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
The window only shows what the server serves, and the server is started with `npx
|
|
128
|
+
thursday-agent`. On a Mac, the first start in a terminal asks once whether to keep it running in
|
|
129
|
+
the background. Yes, and no terminal is needed: it starts again when they log in, and comes back
|
|
130
|
+
by itself if it stops. `npx thursday-agent start` does the same later, and moves the background to
|
|
131
|
+
the version it was run as; if that version does not come up, the one before is started again, and
|
|
132
|
+
when nothing can run in the background, it runs in that terminal instead. When the Node it was
|
|
133
|
+
started with is removed, by a version manager or an upgrade, it starts on another Node it finds and
|
|
134
|
+
says which in its log, which keeps to about 10 MB with the one before beside it.
|
|
135
|
+
`npx thursday-agent stop` stops it, and it no longer starts at login; `npx thursday-agent status`
|
|
136
|
+
says whether it runs, where, and where its log is. **Settings › Thursday › Running** shows the same
|
|
137
|
+
and the command to change it, to copy; the app never stops or moves itself. The copy that runs in
|
|
138
|
+
the background is kept in `~/.thursday/app`. On Linux and Windows it runs in a terminal; add it to
|
|
139
|
+
the programs that start at login.
|
|
129
140
|
|
|
130
141
|
The app uses the same address every time: port 4747 by default. If that port is taken one day, it
|
|
131
142
|
says so and uses the next free one for that run, and the browser shows different settings there.
|
|
132
|
-
`--port` with a number moves it for good (
|
|
143
|
+
`--port` with a number moves it for good (in the background, `start` with it). `--home` uses another
|
|
133
144
|
data folder, `--no-open` starts without opening a browser, and `--help` lists everything.
|
|
134
145
|
|
|
135
146
|
Starting it again while it already runs on the same data folder opens the running one in the
|
|
136
147
|
browser instead of starting a second, and says how to stop it. It needs Node 22.18 or newer.
|
|
137
|
-
Closing the terminal it runs in stops it like Ctrl+C: running jobs pause and wait for **Continue
|
|
148
|
+
Closing the terminal it runs in stops it like Ctrl+C: running jobs pause and wait for **Continue**;
|
|
149
|
+
in the background, closing the terminal changes nothing.
|
|
138
150
|
|
|
139
151
|
## Where the files are
|
|
140
152
|
|
|
@@ -142,15 +154,17 @@ Everything is on this computer, in one folder: `.thursday` in their home folder
|
|
|
142
154
|
`npx thursday-agent` or installed, or the folder it was started from otherwise; every start prints
|
|
143
155
|
it. It holds the database (calls, memory, bots, keys, her settings), the kept sign-ins, and the
|
|
144
156
|
workspace with finished work, each bot's folder and installed skills. Updating the app never touches
|
|
145
|
-
|
|
146
|
-
|
|
157
|
+
any of these. On a Mac that keeps it running in the background, `app` in it is the copy that runs
|
|
158
|
+
there, which `start` replaces with each version. Nothing is sent anywhere except to the model
|
|
159
|
+
providers and services they set up. The app listens only to this computer and has no account.
|
|
147
160
|
|
|
148
161
|
The bots' browser is the one thing outside it: a download of a few hundred megabytes in the
|
|
149
162
|
computer's cache folder.
|
|
150
163
|
|
|
151
164
|
To back up, copy that folder with the app stopped; moving to another computer is the same folder
|
|
152
|
-
put in the same place
|
|
153
|
-
|
|
165
|
+
put in the same place, and `app` need not come along: `start` there installs a copy for that
|
|
166
|
+
computer. If the app ever cannot open the database, the terminal asks whether to set it aside and
|
|
167
|
+
start fresh; the old file is kept beside the new one, with `.corrupt-` in its name.
|
|
154
168
|
|
|
155
169
|
## What it costs
|
|
156
170
|
|
package/package.json
CHANGED
|
@@ -61,7 +61,7 @@ Words on the page are yours, in the user's language: set `lang` and `labels` whe
|
|
|
61
61
|
- **A photo per stop** is one of three: `"wiki"`, the English Wikipedia title of the place
|
|
62
62
|
(`"pt:Mosteiro dos Jerónimos"` for another language's — a place outside the English-speaking
|
|
63
63
|
world often has an article, or a picture, only in its own language), whose lead picture comes
|
|
64
|
-
with
|
|
64
|
+
with who made it and, where its file says, its licence; `"photo"` as a page url, whose own share picture is taken through the browser; `"photo"` as a
|
|
65
65
|
file beside the JSON. A stop with none shows without one — the airport, the hotel check-in, a walk.
|
|
66
66
|
- **Every link is a full `http(s)` address** — `flights.link`, `stay.link`, a stop's `link`, a
|
|
67
67
|
source's `url`. Anything shorter stops the build by name before a single photo is fetched.
|
|
@@ -188,14 +188,19 @@ const plain = (html) =>
|
|
|
188
188
|
.replace(/\s+/g, " ")
|
|
189
189
|
.trim();
|
|
190
190
|
|
|
191
|
-
/**
|
|
191
|
+
/**
|
|
192
|
+
* A Wikipedia article's own lead picture, with who made it and, where its file says, its licence.
|
|
193
|
+
* `pilicense=any`: the lead picture the article shows, not only a freely licensed one — the
|
|
194
|
+
* default (`free`) returns none for an article led by a non-free image, and the stop then shows
|
|
195
|
+
* without its photo.
|
|
196
|
+
*/
|
|
192
197
|
async function fromWiki(title) {
|
|
193
198
|
const [wiki, name] = /^[a-z]{2,3}:/.test(title)
|
|
194
199
|
? [title.slice(0, title.indexOf(":")), title.slice(title.indexOf(":") + 1)]
|
|
195
200
|
: ["en", title];
|
|
196
201
|
const api = `https://${wiki}.wikipedia.org/w/api.php?format=json&action=query&redirects=1`;
|
|
197
202
|
const q = await getJson(
|
|
198
|
-
`${api}&prop=pageimages|info&inprop=url&piprop=thumbnail|name&pithumbsize=960&titles=${encodeURIComponent(name)}`,
|
|
203
|
+
`${api}&prop=pageimages|info&inprop=url&piprop=thumbnail|name&pithumbsize=960&pilicense=any&titles=${encodeURIComponent(name)}`,
|
|
199
204
|
);
|
|
200
205
|
const page = Object.values(q.query?.pages ?? {})[0];
|
|
201
206
|
if (!page || "missing" in page)
|
|
@@ -77,8 +77,7 @@ first is the cover, asking the question the book answers.
|
|
|
77
77
|
Choose each page's picture in this order:
|
|
78
78
|
|
|
79
79
|
- **A real thing whose look matters** — a place, an animal, a machine, a
|
|
80
|
-
person's work — is a real photo from the web
|
|
81
|
-
or from Wikimedia Commons, whose files allow reuse with credit:
|
|
80
|
+
person's work — is a real photo from the web, taken from the page you read:
|
|
82
81
|
|
|
83
82
|
```bash
|
|
84
83
|
node "$THURSDAY_SKILLS/browser/scripts/webimage.mjs" <page url> --out <the book's folder> [--all]
|
|
@@ -88,7 +87,8 @@ Choose each page's picture in this order:
|
|
|
88
87
|
through the session's browser, keeps only what came back as an image, and
|
|
89
88
|
prints each file with its size and a `Credit:` line. Every run writes `web-01.…`, so rename what you keep to the
|
|
90
89
|
page's own name before fetching the next one. Put the credit in the figure:
|
|
91
|
-
`<figcaption>Photo: <
|
|
90
|
+
`<figcaption>Photo: <a href="…">source</a></figcaption>`, with who made it and
|
|
91
|
+
its licence added when the page says them.
|
|
92
92
|
- **A structure, a flow, a relation** — parts of a whole, one thing asking
|
|
93
93
|
another, a before and after — is an inline `<svg viewBox="0 0 800 400">`
|
|
94
94
|
drawn by hand. Fill it with `var(--ink)`, `var(--paper)`, `var(--blue)`,
|