elanous 0.2.42 → 0.2.43
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/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{7a98bc80.fa935989e829f9c2.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{73d2eb0e.4966ad55293c801a.js → 0ad6802e.ae7afb63fdcb4491.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/114.2b90424d1a3ce84c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1151-5c2bb8f002ca2dd6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1200.6a37c202f9f17e9a.js +226 -0
- package/apps/pwa/out/_next/static/chunks/1261-a616d5728e02e624.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1313-19f737e0222c4444.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1357.3bbef3976c37f94a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1362-20adddfaf662b0fa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3507.97e1977bc4d5fb0a.js → 1406.a1dc2ab6f8449374.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1737-9491fc6ab29b9ec6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1803-4f91a8e7dcaf042c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1961.a81b12872c3e93a9.js +23 -0
- package/apps/pwa/out/_next/static/chunks/{53c73f84.373b6160adfa89a4.js → 1970cf59.2d4d8ce5d6c81853.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9211-330b6736a63d4cb3.js → 2073-ba274e00e4f9efb4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{7411.9b4b8b747dc7b802.js → 2144.25b292396712196d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/2268-53861f339e0b65a2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2312.0c8b61e22d3136d7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6632.0eac1c554f8f2ef3.js → 2573.387a707f6f9d720c.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/273.f156eee28f11af77.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2873.d2140e5a82546401.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1262.e804feb8fd1acb8c.js → 3072.01338851ca21a6f7.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3091.a5a4143dea33d197.js +90 -0
- package/apps/pwa/out/_next/static/chunks/{2456.b6de0e1c05f28843.js → 3095.dc44586a5f83b86d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3207.a756c95e9ec8c3c8.js → 3113.d7472bbc27d580c7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3228-9650b6447b6fa288.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3402.44b565b314f2263c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3557ac4a.c8931684475018ad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8505.fd803c6c33b54cc3.js → 360.ae9f9f4c33c395e8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
- package/apps/pwa/out/_next/static/chunks/{b450776b.3db34d8d965f82d3.js → 363bfab3.9623b9f89363541f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3694.e0099884345f0198.js +64 -0
- package/apps/pwa/out/_next/static/chunks/3744.54f87db52acfd1ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3903.3ef4656c67572764.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3935.16701e33f8982dc9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3955.6922286237f2ac2b.js +24 -0
- package/apps/pwa/out/_next/static/chunks/3969.272ee7f9fd6c62e5.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{8138.6c10b2a356d52fca.js → 4199.ce86b281fd0a60b7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4311-6dd3144002cc0c2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4426-2b230fad00c88930.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2690.0521c738b7749931.js → 4445.7990c76b3751a918.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4447-14c5161fa59166c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4856-b0b8075bba8c53f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4870-de370d65e73c0bb5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4885-2c989165c4b29fad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1945.7b54990d578c119b.js → 4894.fec2ca9e99caefa2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5093.8f04b7f8cb899a95.js +94 -0
- package/apps/pwa/out/_next/static/chunks/5122-2bb177cebf89e19a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5154.5f56dc3902e3d275.js +36 -0
- package/apps/pwa/out/_next/static/chunks/529.64ff7257180b2ac9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5394.5dabeb0c62293a28.js +93 -0
- package/apps/pwa/out/_next/static/chunks/5461.08bf2404ff38ec85.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5474-22e08a85583209b2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9427.96aa912ddb5801e0.js → 5564.9e72532188f57586.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/5567-265df39ed8fe9dcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5570-a94ae19811cb2046.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5574-b47c9ef2dceff1fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4043.6b91203436c9c86b.js → 5628.6ddb2d5ffba4ff4c.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/{1319.b9b815ae0f181e06.js → 5730.43d7ccc09988e646.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3482.a9ae9d2ad6a5bd97.js → 5789.2da35c258292e1e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5824.da9527b15a3221e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1487.2f67b79444062da6.js → 5930.8b4df3b46c32b05a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5963-c4d8469c52a0828b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6001.ec4049ceb3c43418.js +27 -0
- package/apps/pwa/out/_next/static/chunks/6120-471f03db1e299c0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6175-41479e643aca1878.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6291.a2de4f9787637075.js +104 -0
- package/apps/pwa/out/_next/static/chunks/6400-6699907c3537436a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6428.1f4327d6ae5fdf9a.js +287 -0
- package/apps/pwa/out/_next/static/chunks/644.02cb026fa44bcd0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6466-6c87d60d3dd174fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3347.f846266b5e5f3ede.js → 6540.c7bef57ad8f90a87.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6773.d4264665ab31bec0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6822.3c789f1a8443e774.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8262.ddc03e06b733f184.js → 6944.309f4e3ea54d1537.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7261-8ff69d3b2ee671fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7266.084c6bbc70035140.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7271.5c0100e7320aa856.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7429-bf5731358c8f2f68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7464.01f7a0ae1215fbe7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7479.0fcad5f37eb64f0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4770.769c9cd9c7034eba.js → 7483.427a2fe2049e388d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{1147-5196d19c222051b3.js → 7502-be74718178e13e56.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7530.0889722b19572065.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7645.5b2ee3ad45c55ea3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7788.7d1c79f1a8e18946.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7900.096f455c7c1efc53.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7910-6f139bcafd238b9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7966.f71c8958d1637548.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8673-bab689a55f7e13b9.js → 8062-7cd0bcc7f01455ba.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8073.f6cf2f2c71aafbd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8201.190b94088980f430.js +74 -0
- package/apps/pwa/out/_next/static/chunks/8205.282ca4bb62d54a0a.js +62 -0
- package/apps/pwa/out/_next/static/chunks/8313-dfa1021bb58a46d6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/837-81336ebaca8198a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8447.7963352ef5f71b76.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8574-868e8129525ef6d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8588.d1c6a2903727ce87.js +149 -0
- package/apps/pwa/out/_next/static/chunks/8637.90f92d5c8db4732c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/868.6e953be05bcf6dca.js +41 -0
- package/apps/pwa/out/_next/static/chunks/8706-e1fe0309343a2273.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8749-06384cdfc4520add.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9656-374232558fd528d0.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5440-4236de26c5ea5856.js → 8967-7dfebf710c9dec9d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1063.2fb8a9dc55c731f2.js → 8986.8e2e4efbfa655c59.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8997-3c564dbb3b58b055.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4320.583cbab64db6be02.js → 923.2034d10ae91e9c20.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1574.878c18ecc97b1bd4.js → 943.39ae5e82f4f1893f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9469.0500480de55fb205.js +32 -0
- package/apps/pwa/out/_next/static/chunks/9770.5f75bc6088b16109.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9810-2543267050e58b82.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9870.8419702475254745.js +8 -0
- package/apps/pwa/out/_next/static/chunks/9941-376d1b74d51b01a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9958.385434ab04241758.js +1 -0
- package/apps/pwa/out/_next/static/chunks/aa57532f.510551854ff239b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-deea1450b17cb8dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-70985b904f8650ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a2e15e33e56a4353.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-fc72ce2db12d6ca9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-be03e41f9436ebd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-35a35999382da3f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-3ff5b1e6ca88b848.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-a65101300a0ee5c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3aca5b6d67dba511.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-45b8ab0a71e61314.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-53046e282d4cda8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-17809e60e8354c17.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-fd2442d347bf5898.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-e9d720d6fc082e21.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-6b8b4267bab0a677.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-deea1450b17cb8dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-8bcf6233ac7c17af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-7cc25591cfc2126f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-053e871f35c9beba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-eff819f0c2d5e084.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-4d7e9d8db5274a87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2b2d8f5aa5f69ad4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-0b8f92c5062e68b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1bd9d0fdac2ced3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-0f291d3c8fd55a3a.js → page-9ee28f7df07428ea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-44b7a1ff468c6648.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-cbc6523711dc1b65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-fdad47899c2695be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-79a8b5fee4c20871.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-03e8ac9606aeaffb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-4cd55c55ec287e2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-db17b4305404161e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-30041d848350fd02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c540da022dbf86b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9399efc538da057f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ca2d09128c585ca4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-0e2635aecd343038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ef7f4399b6b7726e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-deea1450b17cb8dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-caf530535b875468.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-eaa20c1543a5fd8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c541eb1b75120f61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-ab5e213eda9479f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-0a815f34367b6db6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-e858ba0ed9393b68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1638ee9dd6e0582f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4cf5a399109391f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b4396321238798ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-cb72bfd21006781a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6135d0242afbc434.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a1dccf907eddb856.js +1 -0
- package/apps/pwa/out/_next/static/chunks/c7945435-b44d4dbe90ba0dcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3d0154af.5331fec737ffe8c3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{e8543907.5b040a5f22a0b0e5.js → d96660fb.cbc21a2a88539dbb.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{50061469.0326382241ef3b2d.js → ea514caa.05a24f78d9dffe5f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/fb7d20d5-6892502b6ee39ca6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-e8a911e19b1be41f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-7022f418fabba021.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-e5f15df755756a1e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-4525f91e36940c9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-140f0e519c085b0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-8f22ef63dcb865b1.js +1 -0
- package/apps/pwa/out/_next/static/css/d1f8bb401740a549.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/catalog/external-commands.yaml +5 -3
- package/catalog/meta/catalogVersion.yaml +2 -1
- package/catalog/signing/catalog-signing-public.pem +3 -0
- package/graphs/intake/intake-daily.yaml +16 -0
- package/graphs/intake/news-sources.yaml +1 -0
- package/graphs/intake/recipes.yaml +7 -0
- package/graphs/overlays/examples/research-runtime-empty-terminal.yaml +28 -0
- package/graphs/profiles/local.yaml +5 -0
- package/graphs/profiles/pod.yaml +4 -0
- package/package.json +6 -2
- package/plugins/demo-absorption-briefing/plugin.json +18 -0
- package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
- package/plugins/demo-browser-hand/plugin.json +13 -0
- package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
- package/plugins/demo-linear-secretary/plugin.json +15 -0
- package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
- package/plugins/demo-plugin-wizard/plugin.json +11 -0
- package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
- package/plugins/demo-research/plugin.json +16 -0
- package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
- package/plugins/demo-video-briefing/plugin.json +15 -0
- package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
- package/scripts/build-signed-catalog.ts +48 -0
- package/scripts/ci-typecheck-main-delta.sh +88 -0
- package/scripts/codex-fallback-live-probe.ts +1 -1
- package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
- package/scripts/demo/demo1104-stage.config.ts +21 -0
- package/scripts/demo/demo1104-stage.ts +316 -0
- package/scripts/goal-method-audit.ts +17 -1
- package/scripts/graph-units/land-enqueue.ts +90 -0
- package/scripts/hooks/codex-notify.sh +32 -0
- package/scripts/install.sh +10 -38
- package/scripts/landing-heal/land-plan.ts +57 -0
- package/scripts/release-loop/auto-approve-node.ts +1 -1
- package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
- package/scripts/release-loop/gate-method.ts +139 -0
- package/scripts/release-loop/gate-node.ts +180 -20
- package/scripts/release-loop/gate-traffic-mode.ts +151 -3
- package/scripts/release-loop/node-verdict.ts +38 -25
- package/scripts/release-loop/preflight.ts +362 -8
- package/scripts/release-loop/unattended-release.ts +20 -9
- package/scripts/rhythm/daily.ts +36 -4
- package/scripts/rhythm/linear-progress-sync.ts +298 -0
- package/scripts/video-pipeline.ts +9 -1
- package/scripts/warm-pool-provider-config.ts +29 -6
- package/src/acp/agent-manager.ts +1 -0
- package/src/acp/codex-app-server-agent.ts +33 -0
- package/src/acp/codex-app-server-client.ts +153 -16
- package/src/acp/core-turn-bridge.ts +17 -12
- package/src/acp/event-router.ts +20 -1
- package/src/acp/server.ts +6 -0
- package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
- package/src/agent-mission/claude-headless.ts +4 -1
- package/src/agent-mission/codex-exec.ts +105 -0
- package/src/agent-mission/driver.ts +192 -11
- package/src/agent-mission/grok-auth-status.ts +47 -0
- package/src/agent-mission/hand-hooks.ts +101 -0
- package/src/agent-mission/mission-cli.ts +56 -21
- package/src/agent-mission/mission-hand-reply.ts +118 -0
- package/src/agent-mission/mission-line.ts +180 -0
- package/src/agent-mission/mission-out.ts +256 -18
- package/src/agent-mission/tool-install.ts +122 -11
- package/src/agents/general-purpose.md +1 -1
- package/src/auto-research/research-turn.ts +95 -10
- package/src/autopilot/pr-manager.ts +31 -3
- package/src/boot/daemon-tools/self-implement.ts +3 -1
- package/src/boot/daemon-tools/web-search.ts +1 -2
- package/src/briefing/brief-items.ts +55 -11
- package/src/cli/agent-cli.ts +2 -1
- package/src/cli/catalog-cli.ts +31 -0
- package/src/cli/connector-cli.ts +16 -0
- package/src/cli/doctor-fix.ts +2 -2
- package/src/cli/intake-source-cli.ts +44 -8
- package/src/cli/msg-cli.ts +32 -3
- package/src/cli/pr-cli.ts +21 -1
- package/src/cli/pr-land-heavy-remote.ts +44 -6
- package/src/cli/pr-land-overlap-evidence.ts +13 -1
- package/src/cli/pr-land-pod-shadow-job.ts +143 -5
- package/src/cli/pr-land-pod-shadow.ts +9 -2
- package/src/cli/release-checklist-read-cli.ts +44 -16
- package/src/cli/release-cli.ts +23 -3
- package/src/cli/research-cli.ts +9 -0
- package/src/cli/setup-cli.ts +166 -6
- package/src/cli/setup-keys.ts +187 -0
- package/src/cli/task-plugin-wizard-host.ts +114 -0
- package/src/cli/tasks-cli.ts +54 -9
- package/src/cli/tui-test-cli.ts +186 -0
- package/src/config.ts +4 -2
- package/src/connectors/linear-daily-progress.ts +228 -0
- package/src/connectors/linear-projector.ts +34 -12
- package/src/connectors/linear.ts +151 -7
- package/src/core-turn/deep-turn-bloom.ts +67 -0
- package/src/core-turn/research-policy.ts +37 -0
- package/src/core-turn/run-core-turn.ts +320 -30
- package/src/core-turn/types.ts +2 -0
- package/src/dashboard/chat/acp-chat.ts +10 -0
- package/src/dashboard/classic-sidetab-mission-job.ts +103 -0
- package/src/dashboard/classic-sidetab-mission-pair.ts +81 -0
- package/src/dashboard/classic-sidetab-mission-trio.ts +219 -0
- package/src/dashboard/classic-sidetab-mission.ts +167 -5
- package/src/dashboard/index.ts +378 -13
- package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +8 -0
- package/src/dashboard/mission-cli-consumer.ts +20 -8
- package/src/dashboard/plugin-wizard-runtime.ts +50 -0
- package/src/dashboard/plugin-wizard-tool.ts +55 -0
- package/src/dashboard/sidetab-runtime.ts +1 -1
- package/src/dashboard/terminal-popup-runtime.ts +6 -3
- package/src/decisions/linear-progress-summary.ts +78 -0
- package/src/decisions/linear-progress-sync.ts +152 -0
- package/src/domains/outbound-alert.ts +49 -11
- package/src/domains/telegram-kind-route.ts +16 -9
- package/src/graph-runner/arg-allowance.ts +13 -0
- package/src/graph-runner/graph-run-api.ts +3 -1
- package/src/graph-runner/runner.ts +85 -17
- package/src/graph-wizard/mission-compose.ts +407 -12
- package/src/harness/dispatch-backpressure.ts +54 -1
- package/src/harness/dispatch-shadow-compare.ts +74 -0
- package/src/harness/harness-cli-command.ts +11 -1
- package/src/harness/skill-exec.ts +21 -9
- package/src/harness/skill-select.ts +1 -1
- package/src/hooks/error-report-cloud.ts +101 -0
- package/src/hooks/receiver.ts +29 -2
- package/src/index.ts +127 -10
- package/src/intake-plane/actions.ts +354 -0
- package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
- package/src/intake-plane/intake-sources.ts +78 -8
- package/src/intake-plane/items.ts +14 -4
- package/src/intake-plane/linear-mission-sync.ts +80 -0
- package/src/intake-plane/linear-secretary-runtime.ts +178 -0
- package/src/intake-plane/linear-wish.ts +227 -1
- package/src/life/life-cli.ts +168 -0
- package/src/life/life-kinds.ts +160 -0
- package/src/live-supply/budget-consumer.ts +78 -0
- package/src/live-supply/read.ts +3 -0
- package/src/live-supply/snapshot.ts +45 -0
- package/src/llm/provider-credentials.ts +8 -2
- package/src/llm.ts +2 -1
- package/src/maturity/feature-maturity.ts +3 -3
- package/src/msg/msg-sse-server.ts +3 -3
- package/src/msg/msg-store.ts +177 -19
- package/src/native-tool-catalog.ts +36 -2
- package/src/nexus/api/http-server.ts +37 -1
- package/src/nexus/api/mcp-public-allowlist.ts +2 -0
- package/src/nexus/index.ts +7 -2
- package/src/nexus/outbound/format.ts +9 -0
- package/src/nexus/outbound/router.ts +98 -13
- package/src/nexus/setup-status.ts +9 -0
- package/src/nexus/state/state.ts +3 -0
- package/src/oauth/codex-account-store.ts +20 -7
- package/src/oauth/codex-owner-mirror.ts +44 -0
- package/src/oauth/codex.ts +17 -2
- package/src/oauth/fallback-chain.ts +47 -17
- package/src/onboarding/first-run-doctor.ts +8 -1
- package/src/onboarding/first-run.ts +85 -26
- package/src/onboarding/key-setup.ts +103 -0
- package/src/onboarding/menu-answer.ts +13 -0
- package/src/onboarding/secret-prompt.ts +37 -0
- package/src/plugins/install/plugin-install.ts +59 -0
- package/src/pr-tool/census.ts +130 -0
- package/src/pty-shell/pty-control-ipc.ts +4 -1
- package/src/registry/catalog-server.ts +232 -0
- package/src/registry/loader.ts +45 -1
- package/src/registry/types.ts +1 -2
- package/src/research/axis-fanout.ts +43 -28
- package/src/self-dev/ask-launch-flow.ts +72 -1
- package/src/self-dev/dev-cli.ts +4 -1
- package/src/self-dev/dev-pipeline.ts +5 -0
- package/src/self-dev/draft-residue.ts +64 -5
- package/src/self-dev/graph-front-nodes.ts +2 -1
- package/src/self-dev/graph-journey-route.ts +76 -21
- package/src/self-dev/launch-preflight.ts +58 -0
- package/src/self-dev/orchestrate.ts +1 -1
- package/src/self-dev/shard-aggregate.ts +4 -0
- package/src/self-dev/shard-run.ts +36 -15
- package/src/self-implement/abandoned-classification.ts +12 -3
- package/src/self-implement/budget-gate.ts +7 -0
- package/src/self-implement/child-llm-preference.ts +10 -1
- package/src/self-implement/doctor-visit.ts +30 -8
- package/src/self-implement/elanous-tui-spawn.ts +3 -0
- package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
- package/src/self-implement/gate-artifacts.ts +2 -1
- package/src/self-implement/goal-author-cli.ts +4 -2
- package/src/self-implement/goal-author.ts +358 -4
- package/src/self-implement/graph-overlay-yaml.ts +30 -4
- package/src/self-implement/graph-overlay.ts +3 -1
- package/src/self-implement/graph-profile-yaml.ts +107 -0
- package/src/self-implement/graph-yaml.ts +26 -3
- package/src/self-implement/off-diff-evidence.ts +249 -5
- package/src/self-implement/orchestrator.ts +240 -15
- package/src/self-implement/run-chart.ts +6 -3
- package/src/self-implement/run-ledger.ts +51 -1
- package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
- package/src/self-implement/tdd-evidence-tags.ts +9 -0
- package/src/self-implement/train-gate-receipt.ts +166 -0
- package/src/self-implement/train-gate-remote.ts +62 -18
- package/src/session/chat.ts +4 -2
- package/src/session/session-fanout.ts +2 -0
- package/src/session/streaming/acp-stream-sink.ts +2 -1
- package/src/session/streaming/chunk-producer.ts +6 -0
- package/src/session/streaming/stream-compositor.ts +3 -2
- package/src/session-runtime/index.ts +37 -1
- package/src/session-runtime/retry-policy.ts +1 -1
- package/src/setup/llm-env-detect.ts +3 -0
- package/src/setup/service-key-catalog.ts +46 -0
- package/src/setup/service-keys.ts +241 -0
- package/src/sidetab-core/visible-agent-mission.ts +98 -22
- package/src/skills/tools/agent.ts +23 -4
- package/src/skills/tools/omni-search.ts +123 -25
- package/src/task-agent/parent-host.ts +10 -0
- package/src/task-agent/repair-outcomes.ts +65 -0
- package/src/task-agent/task-hand.ts +20 -7
- package/src/task-orchestrator/dispatcher.ts +14 -1
- package/src/task-orchestrator/linear-capture-events.ts +55 -0
- package/src/task-orchestrator/store.ts +16 -5
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +4 -0
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +92 -1
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +23 -11
- package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +35 -9
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +172 -6
- package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
- package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
- package/src/task-orchestrator/types.ts +14 -0
- package/src/telegram.ts +14 -16
- package/src/terminal/coding-agent.ts +14 -5
- package/src/terminal/session-registry.ts +1 -1
- package/src/tool-hints/gate.ts +1 -0
- package/src/tool-runtime/agent-runtime.ts +1 -0
- package/src/tool-runtime/browser-hand-runtime.ts +381 -0
- package/src/tool-runtime/browser-runtime.ts +2 -1
- package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
- package/src/tool-runtime/elanous-linear-secretary-runtime.ts +57 -0
- package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
- package/src/tool-runtime/index.ts +6 -0
- package/src/tool-runtime/types.ts +3 -0
- package/src/tui/entry.ts +24 -1
- package/src/tui/sidetab/attach.ts +140 -11
- package/src/tui/sidetab/herdr-portal.ts +225 -0
- package/src/user-config.ts +34 -9
- package/src/user-intent/types.ts +4 -3
- package/src/ux-sim/browser-hand.ts +165 -0
- package/src/ux-sim/draft-inventory-builder.ts +198 -0
- package/src/ux-sim/fake-browser-page.ts +81 -0
- package/src/ux-sim/fake-linear-device.ts +31 -0
- package/src/ux-sim/graph-engine-sim.ts +47 -0
- package/src/ux-sim/linear-secretary.ts +216 -0
- package/src/ux-sim/mock-scenario-catalog.json +75 -23
- package/src/ux-sim/mock-scenario-catalog.ts +120 -2
- package/src/ux-sim/onboarding-first-run-device.ts +31 -21
- package/src/ux-sim/scenario.ts +70 -26
- package/src/ux-sim/service-key-setup.ts +50 -0
- package/src/ux-sim/term-slash-device.ts +74 -0
- package/src/ux-sim/turn-throw-sim.ts +31 -0
- package/src/version/packed-revision.json +1 -1
- package/src/web-search/exa.ts +77 -0
- package/src/web-search/index.ts +30 -9
- package/src/web-search/provider.ts +4 -1
- package/src/web-search/x-intent.ts +5 -0
- package/apps/pwa/out/_next/static/chunks/0244e5b5.6fc7670f8223d82d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +0 -36
- package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1455-530ca16c7e71baff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +0 -32
- package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +0 -286
- package/apps/pwa/out/_next/static/chunks/2160.a097e7b138ae1c55.js +0 -23
- package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +0 -34
- package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +0 -1
- package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2974.595d1e29d040cb6a.js +0 -64
- package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +0 -93
- package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +0 -41
- package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +0 -24
- package/apps/pwa/out/_next/static/chunks/3741.9cf76acaa2ee5298.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +0 -77
- package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4276.336d76d858fcdf1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +0 -149
- package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +0 -27
- package/apps/pwa/out/_next/static/chunks/5431-72a1dbde59400691.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5885.0a3e52c8faccec98.js +0 -287
- package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6131.348b7d6bdcd267ce.js +0 -226
- package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +0 -90
- package/apps/pwa/out/_next/static/chunks/6377.bc7df239edbff244.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +0 -104
- package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +0 -94
- package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +0 -1
- package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +0 -8
- package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8546-6f03f8ea34dd61d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9249.976f1e69a9d80754.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9415.69e4a21c60c7d2db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9633.ce5bddc56784da72.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +0 -62
- package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9a852a62-6192a6ea9346ced3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-0e3d7b9421b79dac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-bf067887b3307423.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +0 -1
- package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
- /package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
|
@@ -29,13 +29,14 @@ import { codexPolicyAllowsCredits, codexPolicyAllowsFallback, resolveCodexQuotaP
|
|
|
29
29
|
import { emitDecision } from '../live/detail-switch.js';
|
|
30
30
|
import { debug } from '../debug/log.js';
|
|
31
31
|
import {
|
|
32
|
-
decideFallback, normalizeFallbackChain, grokQuotaFromUsageSnapshot,
|
|
32
|
+
decideFallback, fallbackChainForProvider, normalizeFallbackChain, grokQuotaFromUsageSnapshot,
|
|
33
33
|
type FallbackDecision, type FallbackInput, type FallbackStep, type RotationOutcome,
|
|
34
34
|
} from './fallback-chain.js';
|
|
35
35
|
import { collectClaudePtyMaturitySample, judgeClaudePtyMaturity, type ClaudePtyMaturity } from './claude-pty-maturity.js';
|
|
36
36
|
import type { UsageOutcomesDeps } from '../budget/usage-outcomes.js';
|
|
37
37
|
import { resolveGrokCredential } from '../grok/credential.js';
|
|
38
38
|
import { getOpenRouterApiKey } from '../config.js';
|
|
39
|
+
import { zaiCodingPlanAvailable } from '../llm/zai-coding-plan.js';
|
|
39
40
|
import { lookupOpenRouterModelSpec } from '../model-tier/llm-tier-map.js';
|
|
40
41
|
import { sendOutbound } from '../domains/outbound-alert.js';
|
|
41
42
|
|
|
@@ -55,7 +56,7 @@ export function _setCodexAccountOutboundSenderForTesting(sender: CodexAccountOut
|
|
|
55
56
|
/** ⛔⭐ 정적 import 로 읽는다 — 종전 `require()` 는 ESM 에서 «정의되지 않을 수 있고», 그러면
|
|
56
57
|
* fail-soft 가 삼켜 ***config false 가 영영 무시된다***(리뷰 should-fix: 노브가 no-op 이 된다).
|
|
57
58
|
* ⚠️ 순환 없음을 확인했다 — user-config 는 oauth 를 안 끌어온다. */
|
|
58
|
-
type RotationConfig = { llm?: { codexCreditReserve?: unknown; codexAccountRotation?: boolean; codexAccountAlerts?: boolean; codexAccountRotationThresholdPercent?: unknown; codexAccountRotationThresholdPercentByAccount?: Readonly<Record<string, unknown>>; codexCreditsAllowed?: boolean; codexResetAutoConsumePerDay?: number; codexQuotaPolicy?: unknown; fallbackChain?: unknown; openrouter?: { fallbackModel?: unknown } } };
|
|
59
|
+
type RotationConfig = { llm?: { provider?: string; model?: string; codexCreditReserve?: unknown; codexAccountRotation?: boolean; codexAccountAlerts?: boolean; codexAccountRotationThresholdPercent?: unknown; codexAccountRotationThresholdPercentByAccount?: Readonly<Record<string, unknown>>; codexCreditsAllowed?: boolean; codexResetAutoConsumePerDay?: number; codexQuotaPolicy?: unknown; fallbackChain?: unknown; openrouter?: { fallbackModel?: unknown } } };
|
|
59
60
|
|
|
60
61
|
function readUserConfig(): RotationConfig {
|
|
61
62
|
return getUserConfig();
|
|
@@ -312,7 +313,8 @@ function rotationCreditsGrant(candidates: readonly RotationCandidate[]): Rotatio
|
|
|
312
313
|
if (codexPolicyAllowsCredits(policy)) return { allowed: true, via: 'policy' };
|
|
313
314
|
if (!codexPolicyAllowsFallback(policy)) return { allowed: false, via: 'none' };
|
|
314
315
|
try {
|
|
315
|
-
const
|
|
316
|
+
const llm = configReader().llm;
|
|
317
|
+
const { chain } = normalizeFallbackChain(llm?.fallbackChain, llm?.provider);
|
|
316
318
|
if (!chain.includes('codex-credits')) return { allowed: false, via: 'none' };
|
|
317
319
|
const creditAccountCount = codexCreditAccountNames(candidates, codexCreditReserveFromConfig()).length;
|
|
318
320
|
const fallbackModel = configReader().llm?.openrouter?.fallbackModel;
|
|
@@ -1121,6 +1123,8 @@ export function resolveRunFallback(
|
|
|
1121
1123
|
readonly grokQuota?: 'usable' | 'exhausted' | 'unknown';
|
|
1122
1124
|
/** OpenRouter 키 «존재» seam(테스트 격리) — 안 주면 `getOpenRouterApiKey()` 로 잰다. 키 값은 기록하지 않는다. */
|
|
1123
1125
|
readonly openrouterAvailable?: boolean;
|
|
1126
|
+
/** Z.ai 키 «존재» seam(테스트 격리) — 안 주면 키 존재만 잰다. */
|
|
1127
|
+
readonly zaiAvailable?: boolean;
|
|
1124
1128
|
/** codex 크레딧 잔액 «확인» seam — 안 주면 회전 후보의 크레딧 신호(잔액 > 0 · 보유 ≠ false)로 잰다. */
|
|
1125
1129
|
readonly codexCreditsAvailable?: boolean;
|
|
1126
1130
|
/** ⛔ 런 원장 «읽기» seam — 체인에 `claude-pty` 가 있을 때만 쓴다. 안 주면 실제 런 원장을 읽는다. */
|
|
@@ -1150,11 +1154,18 @@ export function resolveRunFallback(
|
|
|
1150
1154
|
rotation = { reason: 'no-candidate' };
|
|
1151
1155
|
}
|
|
1152
1156
|
|
|
1153
|
-
const
|
|
1157
|
+
const llm = configReader().llm;
|
|
1158
|
+
const normalized = normalizeFallbackChain(llm?.fallbackChain, llm?.provider);
|
|
1154
1159
|
const { dropped, usedDefault } = normalized;
|
|
1155
1160
|
// 대표 정책 `within-quota` — codex 밖으로 폴백하지 않는다(회전만). 전부 차면 멈춘다.
|
|
1156
1161
|
const quotaPolicy = codexQuotaPolicyFromConfig();
|
|
1157
|
-
|
|
1162
|
+
// A non-Codex primary has no Codex quota to enforce. Only its implicit
|
|
1163
|
+
// provider default bypasses the Codex fallback policy; an explicit chain
|
|
1164
|
+
// continues to obey the existing within-quota contract.
|
|
1165
|
+
const nonCodexProviderDefault = usedDefault
|
|
1166
|
+
&& (llm?.provider === 'glm' || llm?.provider === 'zai' || llm?.provider === 'openrouter')
|
|
1167
|
+
&& fallbackChainForProvider(llm?.provider) !== undefined;
|
|
1168
|
+
const chain = codexPolicyAllowsFallback(quotaPolicy) || nonCodexProviderDefault
|
|
1158
1169
|
? normalized.chain
|
|
1159
1170
|
: normalized.chain.filter((step) => step === 'codex-rotate');
|
|
1160
1171
|
// ⛔ grok 가용성은 «호출자가 확정»해서 줄 수 있다(테스트 격리). 안 주면 여기서 잰다.
|
|
@@ -1164,7 +1175,8 @@ export function resolveRunFallback(
|
|
|
1164
1175
|
// ⛔ 「지금 쓸 수 있나」는 «자격과 다른 축»이다. 안 주면 'unknown' — 그리고 unknown 은 «통과»다.
|
|
1165
1176
|
// ⇒ 「모르고 갔다」와 「알고 갔다」가 관측에서 갈린다(아래 grokQuota).
|
|
1166
1177
|
const grokQuota = deps.grokQuota ?? readCachedGrokQuota();
|
|
1167
|
-
const fallbackModel =
|
|
1178
|
+
const fallbackModel = llm?.openrouter?.fallbackModel
|
|
1179
|
+
?? (llm?.provider === 'openrouter' ? llm.model : undefined);
|
|
1168
1180
|
// SUBSCRIPTION-EXHAUST-REROUTE — 크레딧 예비분에 닿은 «넘김»은 OpenRouter 가 먼저다(대표 OP 10-11: grok 이 아니다).
|
|
1169
1181
|
// 운영 체인 `['codex-rotate','grok']` 에는 openrouter 칸이 없다 ⇒ 이 경로에만 codex 바로 뒤에 openrouter 를 끼운다
|
|
1170
1182
|
// (나머지 칸은 그 뒤 · 키가 없으면 종전 체인으로). 모델은 `llm.openrouter.fallbackModel`, 없으면 «중» 기본 glm-5.3.
|
|
@@ -1179,6 +1191,7 @@ export function resolveRunFallback(
|
|
|
1179
1191
|
: reserveReroute ? CREDIT_RESERVE_OPENROUTER_MODEL : undefined;
|
|
1180
1192
|
const openrouterAvailable = effectiveChain.includes('openrouter')
|
|
1181
1193
|
&& (deps.openrouterAvailable ?? Boolean(getOpenRouterApiKey()?.trim()));
|
|
1194
|
+
const zaiAvailable = effectiveChain.includes('zai') && (deps.zaiAvailable ?? zaiCodingPlanAvailable());
|
|
1182
1195
|
// CODEX-CREDITS-STEP — 체인에 그 칸이 있을 때만 잰다(없으면 판정이 안 읽는다). 잔액을 «모르면» 없다고 본다(돈 · fail-closed).
|
|
1183
1196
|
// ⛔ 사람이 계정을 «명시»했으면 그 계정의 잔액만 본다 — 다른 계정 잔액으로 칸을 열고 명시 계정으로 쏘면 fail-closed 가 깨진다.
|
|
1184
1197
|
const explicitAccount = snapshot.reason === 'explicit';
|
|
@@ -1191,7 +1204,7 @@ export function resolveRunFallback(
|
|
|
1191
1204
|
// ⛔ 없으면 `undefined` 이고 판정은 종전 그대로다(수집 0회 · 판정식 무변경).
|
|
1192
1205
|
const claudePtyMaturity = claudePtyMaturityForChain(effectiveChain, deps.claudePtyLedger);
|
|
1193
1206
|
const fallbackBase = {
|
|
1194
|
-
rotation, chain: effectiveChain, grokAvailable, grokQuota, openrouterFallbackModel, openrouterAvailable, codexCreditsAvailable,
|
|
1207
|
+
rotation, chain: effectiveChain, grokAvailable, grokQuota, openrouterFallbackModel, openrouterAvailable, zaiAvailable, codexCreditsAvailable,
|
|
1195
1208
|
...(claudePtyMaturity ? { claudePtyMaturity } : {}),
|
|
1196
1209
|
};
|
|
1197
1210
|
const fallbackInput: FallbackInput = deps.currentCredentialRateLimited === true && deps.currentStep
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { hostname } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { elanousStateRoot } from '../autopilot/state-paths.js';
|
|
4
|
+
import { getUserConfig } from '../user-config.js';
|
|
5
|
+
import { loadTokens, type ProviderAuthState } from './store.js';
|
|
6
|
+
|
|
7
|
+
export const CODEX_OWNER_MIRROR_RELATIVE_PATH = join('remote-parent-credentials', 'cli-mirror', 'auth.json');
|
|
8
|
+
export const CODEX_OWNER_MIRROR_REQUIRED = 'Codex 주인 미러가 없거나 만료됐다 — 주인 호스트에서 `eln codex mirror push <host>` 를 실행해야 한다';
|
|
9
|
+
|
|
10
|
+
export function codexOwnerMirrorAuthPath(): string {
|
|
11
|
+
return join(elanousStateRoot(), CODEX_OWNER_MIRROR_RELATIVE_PATH);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function normalizedHost(value: string): string {
|
|
15
|
+
return value.trim().replace(/\.local$/i, '').toLowerCase();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** The HQ-configured machine identity is the stable short name used by the lease. */
|
|
19
|
+
export function isCodexTokenOwnerHost(config = getUserConfig(), machine = hostname()): boolean {
|
|
20
|
+
const owner = normalizedHost(config.llm.codexTokenOwnerHost || 'mbp');
|
|
21
|
+
const local = normalizedHost(config.hq?.hostName || machine);
|
|
22
|
+
return local === owner;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Read only a fresh, access-only HQ snapshot. This helper never performs OAuth refresh. */
|
|
26
|
+
export function readCodexOwnerAccessMirror(
|
|
27
|
+
storeKey: string,
|
|
28
|
+
opts: { path?: string; now?: number } = {},
|
|
29
|
+
): ProviderAuthState {
|
|
30
|
+
const path = opts.path ?? codexOwnerMirrorAuthPath();
|
|
31
|
+
const now = opts.now ?? Date.now();
|
|
32
|
+
let state: ProviderAuthState | null = null;
|
|
33
|
+
try { state = loadTokens(storeKey, path); } catch { /* fail closed below */ }
|
|
34
|
+
const tokenFields = state?.tokens as (ProviderAuthState['tokens'] & { refresh_token?: unknown }) | undefined;
|
|
35
|
+
const expiresAt = state?.tokens.expiresAt;
|
|
36
|
+
if (!state || state.authMode !== 'chatgpt' || !state.tokens.accessToken
|
|
37
|
+
|| tokenFields?.refreshToken !== '' || tokenFields?.refresh_token !== ''
|
|
38
|
+
|| typeof expiresAt !== 'number'
|
|
39
|
+
|| !Number.isFinite(expiresAt) || expiresAt <= now + 120_000) {
|
|
40
|
+
throw new Error(CODEX_OWNER_MIRROR_REQUIRED);
|
|
41
|
+
}
|
|
42
|
+
return state;
|
|
43
|
+
}
|
|
44
|
+
|
package/src/oauth/codex.ts
CHANGED
|
@@ -29,7 +29,8 @@ import { join } from 'node:path';
|
|
|
29
29
|
import { DEFAULT_CODEX_ACCOUNT, codexStoreKey, isValidAccountName, resolveCodexAccount, effectiveCodexHome, type CodexAccountResolution } from './codex-account.js';
|
|
30
30
|
import { importCodexAccountFromHome, resolveCodexAccountForRun } from './codex-account-store.js';
|
|
31
31
|
import { decodeJWTPayload } from './jwt.js';
|
|
32
|
-
import { authStorePath } from './store.js';
|
|
32
|
+
import { authStorePath, isUnderTestRunner } from './store.js';
|
|
33
|
+
import { codexOwnerMirrorAuthPath, isCodexTokenOwnerHost, readCodexOwnerAccessMirror } from './codex-owner-mirror.js';
|
|
33
34
|
import { platform, release, arch } from 'node:os';
|
|
34
35
|
import {
|
|
35
36
|
saveTokens, loadTokens, expiresAtFromSeconds,
|
|
@@ -428,8 +429,22 @@ function remainingSeconds(state: ProviderAuthState | null): number | null {
|
|
|
428
429
|
}
|
|
429
430
|
|
|
430
431
|
export async function loadFreshCodexAuthState(
|
|
431
|
-
opts: { fetchImpl?: typeof fetch; mirrorCodex?: boolean } = {},
|
|
432
|
+
opts: { fetchImpl?: typeof fetch; mirrorCodex?: boolean; ownerMirrorPath?: string } = {},
|
|
432
433
|
): Promise<ProviderAuthState | null> {
|
|
434
|
+
let tokenOwnerHost = process.env.ELANOUS_REMOTE_CODEX_ACCESS_ONLY !== '1' && isUnderTestRunner();
|
|
435
|
+
if (!tokenOwnerHost && process.env.ELANOUS_REMOTE_CODEX_ACCESS_ONLY !== '1' && isCodexTokenOwnerHost()) {
|
|
436
|
+
const { hqFenceDecision } = await import('../hq/hq.js');
|
|
437
|
+
tokenOwnerHost = hqFenceDecision('ledger-cli').run;
|
|
438
|
+
}
|
|
439
|
+
if (!tokenOwnerHost) {
|
|
440
|
+
// A non-owner host reads only the HQ-pushed access snapshot. It never
|
|
441
|
+
// reconciles ~/.codex or reaches the refresh endpoint with local credentials.
|
|
442
|
+
const mirrorPath = opts.ownerMirrorPath ?? codexOwnerMirrorAuthPath();
|
|
443
|
+
const account = resolveCodexAccountForRun(process.env, { storePath: mirrorPath });
|
|
444
|
+
const state = readCodexOwnerAccessMirror(account.storeKey, { path: mirrorPath });
|
|
445
|
+
observeCodexAuth('fresh', { storeKey: account.storeKey, remainingSeconds: remainingSeconds(state), refreshed: false, source: 'owner-cli-mirror' });
|
|
446
|
+
return state;
|
|
447
|
+
}
|
|
433
448
|
// ⭐ 어느 «계정»의 토큰인가 — 기본 계정이면 종전과 동일한 키(`openai-codex`)다.
|
|
434
449
|
// ⛔ 이름 계정이면 그 계정의 스토어 키와 «그 계정의 홈» 미러를 쓴다(A 가 B 를 덮지 않게).
|
|
435
450
|
// ⭐⭐ 그리고 «리밋에 걸렸으면 다른 계정으로 넘긴다»(S4 · 대표 결정).
|
|
@@ -44,6 +44,22 @@ export type FallbackStep = (typeof FALLBACK_STEPS)[number];
|
|
|
44
44
|
* «머문다». 즉 기본에 두는 비용은 0 이고 얻는 것은 「죽지 않음」이다. */
|
|
45
45
|
export const DEFAULT_FALLBACK_CHAIN: readonly FallbackStep[] = ['codex-rotate', 'grok'];
|
|
46
46
|
|
|
47
|
+
/** Build a one-provider default when the user has explicitly selected a provider.
|
|
48
|
+
*
|
|
49
|
+
* Keep this mapping here so chat retry, account rotation, child defaults and launch
|
|
50
|
+
* budgeting do not each invent their own provider priority. `auto` keeps the
|
|
51
|
+
* historical default chain; explicit provider selection must never add Codex/Grok.
|
|
52
|
+
*/
|
|
53
|
+
export function fallbackChainForProvider(provider: unknown): readonly FallbackStep[] | undefined {
|
|
54
|
+
if (typeof provider !== 'string') return undefined;
|
|
55
|
+
switch (provider.trim().toLowerCase()) {
|
|
56
|
+
case 'glm':
|
|
57
|
+
case 'zai': return ['zai'];
|
|
58
|
+
case 'openrouter': return ['openrouter'];
|
|
59
|
+
default: return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
47
63
|
export function isFallbackStep(value: unknown): value is FallbackStep {
|
|
48
64
|
return typeof value === 'string' && (FALLBACK_STEPS as readonly string[]).includes(value);
|
|
49
65
|
}
|
|
@@ -54,9 +70,11 @@ export function isFallbackStep(value: unknown): value is FallbackStep {
|
|
|
54
70
|
* ⛔ 비었거나 전부 무효면 기본 체인으로 — 「설정이 있다」와 「설정이 유효하다」는 다르다. */
|
|
55
71
|
export function normalizeFallbackChain(
|
|
56
72
|
value: unknown,
|
|
73
|
+
configuredProvider?: unknown,
|
|
57
74
|
): { chain: readonly FallbackStep[]; dropped: readonly string[]; usedDefault: boolean } {
|
|
75
|
+
const configuredDefault = fallbackChainForProvider(configuredProvider);
|
|
58
76
|
if (!Array.isArray(value)) {
|
|
59
|
-
return { chain: DEFAULT_FALLBACK_CHAIN, dropped: [], usedDefault: true };
|
|
77
|
+
return { chain: configuredDefault ?? DEFAULT_FALLBACK_CHAIN, dropped: [], usedDefault: true };
|
|
60
78
|
}
|
|
61
79
|
const chain: FallbackStep[] = [];
|
|
62
80
|
const dropped: string[] = [];
|
|
@@ -68,7 +86,7 @@ export function normalizeFallbackChain(
|
|
|
68
86
|
}
|
|
69
87
|
}
|
|
70
88
|
if (chain.length === 0) {
|
|
71
|
-
return { chain: DEFAULT_FALLBACK_CHAIN, dropped, usedDefault: true };
|
|
89
|
+
return { chain: configuredDefault ?? DEFAULT_FALLBACK_CHAIN, dropped, usedDefault: true };
|
|
72
90
|
}
|
|
73
91
|
return { chain, dropped, usedDefault: false };
|
|
74
92
|
}
|
|
@@ -83,7 +101,7 @@ export type FallbackDecision =
|
|
|
83
101
|
/** codex 계정을 갈아탄다(종전 동작). */
|
|
84
102
|
| { readonly action: 'codex-rotate'; readonly to: RotationCandidate }
|
|
85
103
|
/** 백엔드를 통째로 바꾼다. */
|
|
86
|
-
| { readonly action: 'switch-backend'; readonly backend: 'grok' | 'claude' }
|
|
104
|
+
| { readonly action: 'switch-backend'; readonly backend: 'grok' | 'claude' | 'zai' }
|
|
87
105
|
/** 명시한 유료 OpenRouter 모델로 전환한다. 호출부가 모델을 바꾸지 못하면 실행하지 않는다. */
|
|
88
106
|
| { readonly action: 'switch-backend'; readonly backend: 'openrouter'; readonly model: string }
|
|
89
107
|
/** codex 로 «돌아와» 선불 크레딧으로 계속한다 — 체인의 `codex-credits` 칸(마지막 수단 · 유료).
|
|
@@ -116,6 +134,7 @@ export type StayReason =
|
|
|
116
134
|
| 'grok-exhausted'
|
|
117
135
|
/** 유료 OpenRouter 모델 또는 키가 없다. */
|
|
118
136
|
| 'openrouter-unavailable'
|
|
137
|
+
| 'zai-unavailable'
|
|
119
138
|
/** claude PTY 의 최근 표본이 성숙 관문을 통과하지 못했거나 읽히지 않는다. */
|
|
120
139
|
| 'claude-pty-immature'
|
|
121
140
|
/** 체인에 `codex-credits` 가 있는데 크레딧 잔액이 «확인된» codex 계정이 없다(모름 포함 — 돈이라 fail-closed). */
|
|
@@ -137,6 +156,8 @@ export type FallbackInput = {
|
|
|
137
156
|
readonly openrouterFallbackModel?: string;
|
|
138
157
|
/** OpenRouter 키 존재 여부(키 값 자체는 판정·관측에 넣지 않는다). */
|
|
139
158
|
readonly openrouterAvailable?: boolean;
|
|
159
|
+
/** Direct Z.ai coding-plan credential is available (key presence only). */
|
|
160
|
+
readonly zaiAvailable?: boolean;
|
|
140
161
|
/**
|
|
141
162
|
* grok 이 «지금 쓸 수 있나» — ⛔ 자격(`grokAvailable`)과 «다른 축»이다.
|
|
142
163
|
* 'usable' 쓸 수 있다(잔량 있음 · 무제한 · 임계 미만)
|
|
@@ -183,13 +204,13 @@ export function decideFallback(input: FallbackInput): FallbackDecision {
|
|
|
183
204
|
const {
|
|
184
205
|
rotation, chain, currentStep, currentCredentialRateLimited = false,
|
|
185
206
|
grokAvailable, grokQuota = 'unknown', claudePtyMaturity, stayOnResetCreditAvailable = false,
|
|
186
|
-
openrouterFallbackModel, openrouterAvailable = false, codexCreditsAvailable = false,
|
|
207
|
+
openrouterFallbackModel, openrouterAvailable = false, zaiAvailable = false, codexCreditsAvailable = false,
|
|
187
208
|
} = input;
|
|
188
|
-
const
|
|
209
|
+
const providerExtras = { openrouterModel: openrouterFallbackModel, openrouterAvailable, zaiAvailable, codexCreditsAvailable };
|
|
189
210
|
|
|
190
211
|
if (currentCredentialRateLimited) {
|
|
191
212
|
if (currentStep === undefined) return { action: 'stay', why: 'chain-exhausted' };
|
|
192
|
-
return stepAfter(chain, currentStep, grokAvailable, grokQuota, claudePtyMaturity,
|
|
213
|
+
return stepAfter(chain, currentStep, grokAvailable, grokQuota, claudePtyMaturity, providerExtras, 'chain-exhausted');
|
|
193
214
|
}
|
|
194
215
|
if (rotation.reason === 'explicit') return { action: 'stay', why: 'explicit' };
|
|
195
216
|
if (rotation.reason === 'not-reached' || (rotation.reason === 'credit-pace' && !('to' in rotation))) {
|
|
@@ -203,13 +224,13 @@ export function decideFallback(input: FallbackInput): FallbackDecision {
|
|
|
203
224
|
// 회전이 답을 냈는데 체인이 codex-rotate 를 «빼» 놨다면 그 뜻을 존중하고
|
|
204
225
|
// 다음 칸으로 간다(회전을 원치 않는 구성).
|
|
205
226
|
if (chain.includes('codex-rotate')) return { action: 'codex-rotate', to: rotation.to };
|
|
206
|
-
return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity,
|
|
227
|
+
return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity, providerExtras, 'chain-exhausted');
|
|
207
228
|
}
|
|
208
229
|
|
|
209
230
|
// no-candidate | disabled | reset-credit-available(기본) — codex 축이 끝났다. 다음 칸을 본다.
|
|
210
231
|
// ⛔ 다음 칸이 «없을 때»의 이름만 고른다. 진행(stepAfterCodex)은 그대로다.
|
|
211
232
|
const fallbackWhy = stayReasonWhenCodexAxisEnds(rotation.reason === 'credit-pace' ? 'no-candidate' : rotation.reason);
|
|
212
|
-
return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity,
|
|
233
|
+
return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity, providerExtras, fallbackWhy);
|
|
213
234
|
}
|
|
214
235
|
|
|
215
236
|
/** codex 축이 끝났는데 체인 다음 칸도 없을 때 머무는 이유.
|
|
@@ -223,18 +244,23 @@ export function stayReasonWhenCodexAxisEnds(
|
|
|
223
244
|
return 'chain-exhausted';
|
|
224
245
|
}
|
|
225
246
|
|
|
226
|
-
/**
|
|
227
|
-
type StepExtras = {
|
|
247
|
+
/** Per-provider evidence consumed by backend steps. */
|
|
248
|
+
type StepExtras = {
|
|
249
|
+
readonly openrouterModel?: string;
|
|
250
|
+
readonly openrouterAvailable?: boolean;
|
|
251
|
+
readonly zaiAvailable?: boolean;
|
|
252
|
+
readonly codexCreditsAvailable?: boolean;
|
|
253
|
+
};
|
|
228
254
|
|
|
229
255
|
function stepAfterCodex(
|
|
230
256
|
chain: readonly FallbackStep[],
|
|
231
257
|
grokAvailable: boolean,
|
|
232
258
|
grokQuota: 'usable' | 'exhausted' | 'unknown',
|
|
233
259
|
claudePtyMaturity: ClaudePtyMaturity | undefined,
|
|
234
|
-
|
|
260
|
+
providerExtras: StepExtras,
|
|
235
261
|
whyIfNone: StayReason,
|
|
236
262
|
): FallbackDecision {
|
|
237
|
-
return stepAfter(chain, 'codex-rotate', grokAvailable, grokQuota, claudePtyMaturity,
|
|
263
|
+
return stepAfter(chain, 'codex-rotate', grokAvailable, grokQuota, claudePtyMaturity, providerExtras, whyIfNone);
|
|
238
264
|
}
|
|
239
265
|
|
|
240
266
|
function stepAfter(
|
|
@@ -243,7 +269,7 @@ function stepAfter(
|
|
|
243
269
|
grokAvailable: boolean,
|
|
244
270
|
grokQuota: 'usable' | 'exhausted' | 'unknown',
|
|
245
271
|
claudePtyMaturity: ClaudePtyMaturity | undefined,
|
|
246
|
-
|
|
272
|
+
providerExtras: StepExtras,
|
|
247
273
|
whyIfNone: StayReason,
|
|
248
274
|
): FallbackDecision {
|
|
249
275
|
const idx = currentStep === undefined ? -1 : chain.indexOf(currentStep);
|
|
@@ -255,12 +281,16 @@ function stepAfter(
|
|
|
255
281
|
for (const step of rest) {
|
|
256
282
|
if (step === 'codex-credits') {
|
|
257
283
|
// ⛔ 크레딧은 돈이다 — 잔액이 «확인된» 계정이 없으면 건너뛴다(「모른다」는 통과가 «아니다»).
|
|
258
|
-
if (
|
|
284
|
+
if (providerExtras.codexCreditsAvailable !== true) { skip(step, 'codex-credits-unavailable'); continue; }
|
|
259
285
|
return { action: 'codex-credits', skipped };
|
|
260
286
|
}
|
|
287
|
+
if (step === 'zai') {
|
|
288
|
+
if (!providerExtras.zaiAvailable) { skip(step, 'zai-unavailable'); continue; }
|
|
289
|
+
return { action: 'switch-backend', backend: 'zai' };
|
|
290
|
+
}
|
|
261
291
|
if (step === 'openrouter') {
|
|
262
|
-
const model =
|
|
263
|
-
if (!
|
|
292
|
+
const model = providerExtras.openrouterModel?.trim();
|
|
293
|
+
if (!providerExtras.openrouterAvailable || !model || !/^openrouter\/[^/\s]+\/[^\s]+$/.test(model)) {
|
|
264
294
|
skip(step, 'openrouter-unavailable');
|
|
265
295
|
continue;
|
|
266
296
|
}
|
|
@@ -290,7 +320,7 @@ export function describeFallback(decision: FallbackDecision): string {
|
|
|
290
320
|
case 'switch-backend':
|
|
291
321
|
return decision.backend === 'openrouter'
|
|
292
322
|
? `백엔드 전환 → openrouter (${decision.model} · API 과금)`
|
|
293
|
-
: `백엔드 전환 → ${decision.backend} (구독)`;
|
|
323
|
+
: decision.backend === 'zai' ? '백엔드 전환 → Z.ai GLM' : `백엔드 전환 → ${decision.backend} (구독)`;
|
|
294
324
|
case 'codex-credits':
|
|
295
325
|
return `codex 크레딧으로 계속 (마지막 칸 · 선불 크레딧 과금${decision.skipped.length ? ` · 건너뜀 ${decision.skipped.map((s) => `${s.step}:${s.why}`).join(', ')}` : ''})`;
|
|
296
326
|
case 'stay':
|
|
@@ -7,6 +7,13 @@ const AUTOMATIC = new Set<DoctorFixItem['id']>(['private-files', 'key-cache-perm
|
|
|
7
7
|
const DEFERRED = new Set<DoctorFixItem['id']>(['install-path', 'bun-tmpdir']);
|
|
8
8
|
const LATER_LINE = '나중에: elanous doctor --fix (셸 시작 파일 수정)';
|
|
9
9
|
|
|
10
|
+
export function safeDoctorReason(reason: string | undefined): string {
|
|
11
|
+
if (!reason) return '원인 불명';
|
|
12
|
+
return /(?:api[_-]?key|secret|token)\s*(?:=|:)?\s*\S+/i.test(reason)
|
|
13
|
+
? '민감 정보가 포함된 오류'
|
|
14
|
+
: reason;
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
export interface FirstRunDoctorResult {
|
|
11
18
|
fixed: string[];
|
|
12
19
|
skipped: string[];
|
|
@@ -20,7 +27,7 @@ export function runFirstRunDoctor(deps: DoctorFixDeps): FirstRunDoctorResult {
|
|
|
20
27
|
const result: FirstRunDoctorResult = { fixed: [], skipped: [], failed: [], later: [], lines: [] };
|
|
21
28
|
const record = (id: string, outcome: 'fixed' | 'skipped' | 'failed', reason?: string) => {
|
|
22
29
|
result[outcome].push(id);
|
|
23
|
-
if (outcome === 'failed') result.lines.push(`doctor: ${id} 수리 실패 — ${reason
|
|
30
|
+
if (outcome === 'failed') result.lines.push(`doctor: ${id} 수리 실패 — ${safeDoctorReason(reason)}`);
|
|
24
31
|
try { debug.log('doctor.first-run', outcome, { id }); } catch { /* 관측 실패가 첫 실행을 막지 않는다. */ }
|
|
25
32
|
};
|
|
26
33
|
|
|
@@ -4,6 +4,12 @@ import { debug } from '../debug/log.js';
|
|
|
4
4
|
import { detectLocale, type Locale } from '../expression/locale.js';
|
|
5
5
|
import { unattendedNextStepLine } from './entry-hints.js';
|
|
6
6
|
import { resolveProviderCredential } from '../llm/provider-credentials.js';
|
|
7
|
+
import { zaiCodingPlanAvailable } from '../llm/zai-coding-plan.js';
|
|
8
|
+
import { collectServiceKeys, printKeySetupReport } from './key-setup.js';
|
|
9
|
+
import { getSecretAsync, setSecretAsync } from '../nexus/config/secrets/index.js';
|
|
10
|
+
import { probeProvider } from '../llm/provider-probe.js';
|
|
11
|
+
import { createSecretPrompt } from './secret-prompt.js';
|
|
12
|
+
import { parseMenuAnswer as parseNumericMenuAnswer } from './menu-answer.js';
|
|
7
13
|
import {
|
|
8
14
|
getUserConfig, saveUserConfig, userConfigPath,
|
|
9
15
|
type LLMProviderName, type UserConfig,
|
|
@@ -11,44 +17,45 @@ import {
|
|
|
11
17
|
|
|
12
18
|
export interface FirstRunDeps {
|
|
13
19
|
config?: UserConfig;
|
|
20
|
+
env?: NodeJS.ProcessEnv;
|
|
14
21
|
path?: string;
|
|
15
22
|
detectProviders?: () => Promise<DetectedProvider[]>;
|
|
16
23
|
isTTY?: boolean;
|
|
17
24
|
/** Locale for user-facing wording; defaults to the shared ambient decision (detectLocale). */
|
|
18
25
|
locale?: Locale;
|
|
19
26
|
chooseProvider?: (detected: readonly LLMProviderName[]) => Promise<LLMProviderName | null>;
|
|
27
|
+
promptSecret?: (message: string) => Promise<string | undefined>;
|
|
28
|
+
getSecretAsync?: typeof getSecretAsync;
|
|
29
|
+
setSecretAsync?: typeof setSecretAsync;
|
|
30
|
+
probeKey?: typeof probeProvider;
|
|
31
|
+
setupWhenNoProvider?: (config: UserConfig) => Promise<FirstRunProviderSetupResult>;
|
|
20
32
|
print?: (message: string) => void;
|
|
21
33
|
saveConfig?: (config: UserConfig, path: string) => void;
|
|
22
34
|
}
|
|
23
35
|
|
|
24
|
-
|
|
25
|
-
const CHOICE_LABEL: Partial<Record<LLMProviderName, string>> = { 'openai-codex': 'Codex', grok: 'Grok', anthropic: 'Claude' };
|
|
26
|
-
const SUBSCRIPTION_PRIORITY = ['openai-codex', 'grok', 'anthropic', 'gemini', 'openai', 'openrouter'] as const;
|
|
36
|
+
export type FirstRunProviderSetupResult = LLMProviderName | null | { kind: 'needs-llm' };
|
|
27
37
|
|
|
28
|
-
|
|
38
|
+
const CHOICE_BASE: readonly LLMProviderName[] = ['openai-codex', 'grok', 'anthropic', 'openrouter', 'glm'];
|
|
39
|
+
const CHOICE_LABEL: Partial<Record<LLMProviderName, string>> = { 'openai-codex': 'Codex', grok: 'Grok', anthropic: 'Claude', openrouter: 'OpenRouter', glm: 'GLM' };
|
|
40
|
+
const SUBSCRIPTION_PRIORITY = ['openai-codex', 'grok', 'anthropic', 'gemini', 'openai', 'glm', 'openrouter'] as const;
|
|
41
|
+
|
|
42
|
+
/** Menu order: detected usable providers first, then the remaining supported choices. */
|
|
29
43
|
export function orderProviderChoices(detected: readonly LLMProviderName[] = []): LLMProviderName[] {
|
|
30
44
|
return [...detected, ...CHOICE_BASE.filter((name) => !detected.includes(name))];
|
|
31
45
|
}
|
|
32
46
|
|
|
33
|
-
export type MenuAnswer =
|
|
34
|
-
| { kind: 'chosen'; provider: LLMProviderName }
|
|
35
|
-
| { kind: 'cancel' }
|
|
36
|
-
| { kind: 'miss' };
|
|
47
|
+
export type MenuAnswer = import('./menu-answer.js').MenuAnswer<LLMProviderName>;
|
|
37
48
|
|
|
38
49
|
// FIRST10-FIX: 첫 화면의 오타 한 번이 first-run 전체를 취소하던 마찰 — 빈 입력(취소 의사)과 달리
|
|
39
50
|
// 선택지를 가리키지 못하는 입력(범위 밖·전각·비정수)은 취소가 아니라 다시 묻는다.
|
|
40
51
|
// 메뉴 답으로 인정하는 건 반각 십진 자릿수 문자열뿐이다 — Number() 는 '1e0'·'0x1'·'+1' 같은
|
|
41
52
|
// 수식 표기를 정수로 강제 변환해 선택지로 샌다(0.2.35 재측정).
|
|
42
53
|
export function parseMenuAnswer(answer: string, choices: readonly LLMProviderName[]): MenuAnswer {
|
|
43
|
-
|
|
44
|
-
if (trimmed === '') return { kind: 'cancel' };
|
|
45
|
-
if (!/^[0-9]+$/.test(trimmed)) return { kind: 'miss' };
|
|
46
|
-
const provider = choices[Number(trimmed) - 1];
|
|
47
|
-
return provider !== undefined ? { kind: 'chosen', provider } : { kind: 'miss' };
|
|
54
|
+
return parseNumericMenuAnswer(answer, choices);
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
/**
|
|
51
|
-
* The
|
|
58
|
+
* The choice line of the first-run menu.
|
|
52
59
|
* Single source of the wording: the prompt below renders it, and the ux-sim
|
|
53
60
|
* first-run device asserts against it, so a wording change cannot drift apart.
|
|
54
61
|
*/
|
|
@@ -56,6 +63,8 @@ export function formatProviderMenu(choices: readonly LLMProviderName[]): string
|
|
|
56
63
|
return choices.map((name, i) => `${i + 1} ${CHOICE_LABEL[name] ?? name}`).join(', ');
|
|
57
64
|
}
|
|
58
65
|
|
|
66
|
+
export const FIRST_RUN_PROVIDER_MENU_PROMPT = 'Choose LLM';
|
|
67
|
+
|
|
59
68
|
export async function promptProviderMenu(
|
|
60
69
|
ask: (prompt: string) => Promise<string>,
|
|
61
70
|
detected: readonly LLMProviderName[] = [],
|
|
@@ -63,7 +72,7 @@ export async function promptProviderMenu(
|
|
|
63
72
|
const choices = orderProviderChoices(detected);
|
|
64
73
|
const menu = formatProviderMenu(choices);
|
|
65
74
|
for (;;) {
|
|
66
|
-
const parsed = parseMenuAnswer(await ask(
|
|
75
|
+
const parsed = parseMenuAnswer(await ask(`${FIRST_RUN_PROVIDER_MENU_PROMPT} (${menu}; Enter to cancel): `), choices);
|
|
67
76
|
if (parsed.kind === 'chosen') return parsed.provider;
|
|
68
77
|
if (parsed.kind === 'cancel') return null;
|
|
69
78
|
}
|
|
@@ -84,6 +93,8 @@ const FIRST_RUN_TEXT = {
|
|
|
84
93
|
detectedPrefix: '감지: ',
|
|
85
94
|
subscription: ' 구독',
|
|
86
95
|
needsLlm: 'eln setup llm 으로 고르세요',
|
|
96
|
+
keyStoredNotReady: '키를 저장하고 검증했지만 첫 실행에서 사용할 provider 연결은 아직 완료되지 않았습니다.',
|
|
97
|
+
keySetupFailed: '키 설정을 완료하지 못했습니다. 비밀 값을 표시하지 않고 중단했습니다.',
|
|
87
98
|
claudeNoPath: 'claude-code 구독은 구독으로 쓸 수 있는 경로가 없어 자동 선택하지 않음',
|
|
88
99
|
multipleDetected: '둘 이상 감지되어 고르세요',
|
|
89
100
|
},
|
|
@@ -91,6 +102,8 @@ const FIRST_RUN_TEXT = {
|
|
|
91
102
|
detectedPrefix: 'detected: ',
|
|
92
103
|
subscription: ' subscription',
|
|
93
104
|
needsLlm: 'pick a provider via eln setup llm',
|
|
105
|
+
keyStoredNotReady: 'The key was saved and verified, but first-run provider setup is not complete yet.',
|
|
106
|
+
keySetupFailed: 'Key setup could not be completed. It stopped without displaying secret values.',
|
|
94
107
|
claudeNoPath: 'claude-code subscription has no usable path in elanous; not auto-selecting',
|
|
95
108
|
multipleDetected: 'more than one detected; pick one',
|
|
96
109
|
},
|
|
@@ -105,7 +118,19 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
|
|
|
105
118
|
const text = FIRST_RUN_TEXT[(deps.locale ?? detectLocale()) === 'en' ? 'en' : 'ko'];
|
|
106
119
|
const detectionLabel = (provider: string) =>
|
|
107
120
|
`${provider === 'openai-codex' ? 'codex' : provider}${text.subscription}`;
|
|
121
|
+
// An incomplete onboarding marker does not mean the user's LLM is unconfigured.
|
|
122
|
+
// Keep an already usable provider, key and model rather than replacing it with a detected subscription.
|
|
123
|
+
const existing = cfg.llm.provider !== 'auto'
|
|
124
|
+
? resolveProviderCredential({ provider: cfg.llm.provider, rotation: cfg.llm.rotation,
|
|
125
|
+
baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey, env: deps.env })
|
|
126
|
+
: undefined;
|
|
127
|
+
const configured = existing && existing.source !== 'none'
|
|
128
|
+
? cfg.llm.provider
|
|
129
|
+
// Z.ai's coding-plan credential is stored in its dedicated cache/env, not llm.apiKey.
|
|
130
|
+
: cfg.llm.provider === 'glm' && zaiCodingPlanAvailable() ? 'glm' : undefined;
|
|
108
131
|
let detected: DetectedProvider[] = [];
|
|
132
|
+
// This read-only scan is unconditional, even with an incomplete existing config;
|
|
133
|
+
// provider availability must not depend on the setup marker/config being absent.
|
|
109
134
|
try { detected = await (deps.detectProviders ?? detectProviders)(); }
|
|
110
135
|
catch { /* Detection is advisory; a TTY can still choose. */ }
|
|
111
136
|
const subscriptions = detected.filter((d) => d.available && (d.auth === 'oauth' || d.auth === 'agent-cli'));
|
|
@@ -113,14 +138,6 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
|
|
|
113
138
|
const observe = (event: 'detected' | 'chosen' | 'ready' | 'needs-llm', inputs: number) =>
|
|
114
139
|
debug.log('onboarding.first-run', event, { providers, inputs });
|
|
115
140
|
observe('detected', 0);
|
|
116
|
-
// An incomplete onboarding marker does not mean the user's LLM is unconfigured.
|
|
117
|
-
// Keep an already usable provider, key and model rather than replacing them with a detected subscription.
|
|
118
|
-
const existing = cfg.llm.provider !== 'auto'
|
|
119
|
-
? resolveProviderCredential({ provider: cfg.llm.provider, rotation: cfg.llm.rotation,
|
|
120
|
-
baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey })
|
|
121
|
-
: undefined;
|
|
122
|
-
const configured = existing && existing.source !== 'none'
|
|
123
|
-
? cfg.llm.provider : undefined;
|
|
124
141
|
// claude-code is detected but has no subscription path in elanous: mapping it to the 'anthropic'
|
|
125
142
|
// API-key provider would save a provider whose first call fails for a subscription-only user.
|
|
126
143
|
const usable = SUBSCRIPTION_PRIORITY.filter((name) => providers.includes(name));
|
|
@@ -134,6 +151,7 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
|
|
|
134
151
|
let provider: LLMProviderName | null | undefined = configured ?? (usable.length === 1 ? usable[0] : undefined);
|
|
135
152
|
if (!configured && provider) print(detectionLine(provider));
|
|
136
153
|
let inputs = 0;
|
|
154
|
+
let providerSetUpInPlace = false;
|
|
137
155
|
if (!provider) {
|
|
138
156
|
if (providers.length > 0) {
|
|
139
157
|
print(detectionLine(usable.length === 0
|
|
@@ -144,23 +162,64 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
|
|
|
144
162
|
// FIRST-CHAT-NONTTY — bare `elanous` with no TTY gets the same one-line next step as the other entrances.
|
|
145
163
|
return needsLlm(0, [unattendedNextStepLine()]);
|
|
146
164
|
}
|
|
165
|
+
if (deps.setupWhenNoProvider && usable.length === 0) {
|
|
166
|
+
inputs = 1;
|
|
167
|
+
const setupResult = await deps.setupWhenNoProvider(cfg);
|
|
168
|
+
if (typeof setupResult === 'object' && setupResult !== null && setupResult.kind === 'needs-llm') {
|
|
169
|
+
return needsLlm(inputs);
|
|
170
|
+
}
|
|
171
|
+
provider = typeof setupResult === 'string' ? setupResult : null;
|
|
172
|
+
if (!provider) {
|
|
173
|
+
print('LLM 없이 첫 화면을 엽니다. LLM 기능은 사용할 수 없습니다. 다시 설정: `elanous setup keys` 또는 `elanous login openai-codex`.');
|
|
174
|
+
(deps.saveConfig ?? saveUserConfig)({ ...cfg, onboarding: { ...cfg.onboarding, ready: true } }, path);
|
|
175
|
+
observe('ready', inputs);
|
|
176
|
+
return { outcome: 'ready', inputs };
|
|
177
|
+
}
|
|
178
|
+
providerSetUpInPlace = true;
|
|
179
|
+
observe('chosen', inputs);
|
|
180
|
+
} else {
|
|
147
181
|
inputs = 1;
|
|
148
182
|
provider = await (deps.chooseProvider ?? chooseProvider)(usable);
|
|
149
183
|
if (!provider) return { outcome: 'cancelled', inputs };
|
|
150
184
|
observe('chosen', inputs);
|
|
185
|
+
}
|
|
151
186
|
}
|
|
152
187
|
const credential = inputs === 1 || provider !== cfg.llm.provider
|
|
153
188
|
? resolveProviderCredential({
|
|
154
189
|
provider, rotation: cfg.llm.rotation,
|
|
155
190
|
baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey,
|
|
191
|
+
env: deps.env,
|
|
156
192
|
})
|
|
157
193
|
: undefined;
|
|
158
|
-
if (inputs === 1 && credential?.source === 'none'
|
|
194
|
+
if (inputs === 1 && credential?.source === 'none'
|
|
195
|
+
&& !(providerSetUpInPlace && provider === 'openai-codex')) {
|
|
196
|
+
if ((deps.isTTY ?? process.stdin.isTTY) !== true) return needsLlm(inputs);
|
|
197
|
+
try {
|
|
198
|
+
const results = await collectServiceKeys({
|
|
199
|
+
config: cfg,
|
|
200
|
+
promptSecret: deps.promptSecret ?? createSecretPrompt(),
|
|
201
|
+
print,
|
|
202
|
+
getSecret: deps.getSecretAsync,
|
|
203
|
+
setSecret: deps.setSecretAsync,
|
|
204
|
+
probe: deps.probeKey,
|
|
205
|
+
providers: [provider],
|
|
206
|
+
});
|
|
207
|
+
printKeySetupReport(results, print);
|
|
208
|
+
if (results.length === 0 || results.some((result) => result.status !== 'success')) return needsLlm(inputs);
|
|
209
|
+
return needsLlm(inputs, [text.keyStoredNotReady]);
|
|
210
|
+
} catch {
|
|
211
|
+
return needsLlm(inputs, [text.keySetupFailed]);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
159
214
|
(deps.saveConfig ?? saveUserConfig)({
|
|
160
215
|
...cfg,
|
|
161
216
|
llm: { ...cfg.llm, provider,
|
|
162
|
-
...(provider !== cfg.llm.provider ? {
|
|
163
|
-
|
|
217
|
+
...(provider !== cfg.llm.provider ? {
|
|
218
|
+
apiKey: credential?.source === 'rotation' ? credential.apiKey : undefined,
|
|
219
|
+
baseUrl: credential?.baseUrl,
|
|
220
|
+
model: undefined,
|
|
221
|
+
} : {}),
|
|
222
|
+
...(credential?.source === 'rotation' && credential.apiKey ? { apiKey: credential.apiKey } : {}),
|
|
164
223
|
...(credential?.baseUrl ? { baseUrl: credential.baseUrl } : {}) },
|
|
165
224
|
onboarding: { ...cfg.onboarding, ready: true },
|
|
166
225
|
}, path);
|