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
|
@@ -76,6 +76,26 @@ function evidenceJson(stdout: string): Record<string, unknown> | null {
|
|
|
76
76
|
return null;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
// E4 reads only the exact event near the evidence timestamp; absent timestamps fail closed.
|
|
80
|
+
const E4_LOG_WINDOW_MS = 30 * 60_000;
|
|
81
|
+
const EVIDENCE_ISO_TIMESTAMP = /\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})\b/gu;
|
|
82
|
+
|
|
83
|
+
function evidenceTimestampNearIdentity(evidence: string, identity: string): number | null {
|
|
84
|
+
const identityAt = evidence.indexOf(identity);
|
|
85
|
+
if (identityAt < 0) return null;
|
|
86
|
+
const lineStart = evidence.lastIndexOf('\n', identityAt) + 1;
|
|
87
|
+
const lineEnd = evidence.indexOf('\n', identityAt);
|
|
88
|
+
const identityLine = evidence.slice(lineStart, lineEnd < 0 ? undefined : lineEnd);
|
|
89
|
+
let nearest: { distance: number; timestamp: number } | null = null;
|
|
90
|
+
for (const match of identityLine.matchAll(EVIDENCE_ISO_TIMESTAMP)) {
|
|
91
|
+
const timestamp = Date.parse(match[0]);
|
|
92
|
+
if (!Number.isFinite(timestamp)) continue;
|
|
93
|
+
const distance = Math.abs((match.index ?? 0) - (identityAt - lineStart));
|
|
94
|
+
if (!nearest || distance < nearest.distance) nearest = { distance, timestamp };
|
|
95
|
+
}
|
|
96
|
+
return nearest?.timestamp ?? null;
|
|
97
|
+
}
|
|
98
|
+
|
|
79
99
|
export function collectChecklistEvidenceStages(item: ReturnType<typeof listChecklist>['items'][number], run: ChecklistEvidenceCommandRunner = evidenceCommand): ChecklistEvidenceStage[] {
|
|
80
100
|
const measuredAt = new Date().toISOString();
|
|
81
101
|
const evidence = item.evidence ?? '';
|
|
@@ -135,22 +155,30 @@ export function collectChecklistEvidenceStages(item: ReturnType<typeof listCheck
|
|
|
135
155
|
const verificationCommand = /(?:완료 경계 증거 명령|증거 명령|verification command)\s*[:=]\s*([^\r\n]+)/iu.exec(`${item.title}\n${evidence}`)?.[1]?.trim() ?? null;
|
|
136
156
|
const e4: ChecklistEvidenceStage = { id: 'E4', state: 'missing', source: null, measuredAt, verificationCommand, reason: '근거에 runId·missionId·taskId 중 하나와 event·원문 검증 명령이 모두 필요하다' };
|
|
137
157
|
if (runId && event && verificationCommand) {
|
|
138
|
-
const
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
} catch { return
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
const identityAt = evidenceTimestampNearIdentity(evidence, runId);
|
|
159
|
+
if (identityAt === null) {
|
|
160
|
+
e4.state = 'unmeasurable';
|
|
161
|
+
e4.reason = `근거의 ${identityField}=${runId} 주변에 시간대가 명시된 ISO 시각이 없어 로그 조회 창을 만들 수 없다`;
|
|
162
|
+
} else {
|
|
163
|
+
const since = new Date(identityAt - E4_LOG_WINDOW_MS).toISOString();
|
|
164
|
+
const until = new Date(identityAt + E4_LOG_WINDOW_MS).toISOString();
|
|
165
|
+
const logs = run('eln', ['logs', '--event', event, '--since', since, '--until', until, '--all', '--include-test', '--limit', '1000', '--json'], 30_000);
|
|
166
|
+
if (logs.status !== 0) { e4.state = 'unmeasurable'; e4.reason = `runId 로그 조회 실패${logs.error ? `: ${logs.error}` : ''}`; }
|
|
167
|
+
else {
|
|
168
|
+
const rows = logs.stdout.split(/\r?\n/u).flatMap((line) => { try { return [JSON.parse(line) as Record<string, unknown>]; } catch { return []; } });
|
|
169
|
+
const truncated = rows.length >= 1000 || rows.some((row) => row._meta && typeof row._meta === 'object' && (row._meta as { limitReached?: unknown }).limitReached === true);
|
|
170
|
+
const observed = rows.some((row) => {
|
|
171
|
+
if (row.event !== event || typeof row.data !== 'string') return false;
|
|
172
|
+
try {
|
|
173
|
+
const data = JSON.parse(row.data) as { runId?: unknown; missionId?: unknown; taskId?: unknown };
|
|
174
|
+
return data[identityField] === runId;
|
|
175
|
+
} catch { return false; }
|
|
176
|
+
});
|
|
177
|
+
e4.source = `eln logs --event ${event} --since ${since} --until ${until} --all --include-test --limit 1000 --json (${identityField}=${runId})`;
|
|
178
|
+
if (observed) { e4.state = 'observed'; e4.reason = `같은 ${identityField}의 ${event} 실물 이벤트를 찾았다`; }
|
|
179
|
+
else if (truncated) { e4.state = 'unmeasurable'; e4.reason = '로그 결과가 잘려 사건 부재를 판정할 수 없다'; }
|
|
180
|
+
else { e4.reason = `같은 ${identityField}의 ${event} 이벤트가 없다`; }
|
|
181
|
+
}
|
|
154
182
|
}
|
|
155
183
|
}
|
|
156
184
|
|
package/src/cli/release-cli.ts
CHANGED
|
@@ -52,7 +52,7 @@ import type { PrereleaseKind } from '../../scripts/release-loop/release-version.
|
|
|
52
52
|
import { releaseReadiness } from '../../scripts/release-loop/release-readiness.js';
|
|
53
53
|
import { runReleaseIfReady } from './release-run-if-ready.js';
|
|
54
54
|
import { ReleaseRunClaimConflict, findActiveReleaseRun, readActiveForceReleaseRun, isPidAlive, readReleaseRunLock, withDirectReleaseRunLock, withForceReleaseRunMarker } from './release-single-flight.js';
|
|
55
|
-
import { formatPreflight, releasePreflight } from '../../scripts/release-loop/preflight.js';
|
|
55
|
+
import { formatCountdown, formatPreflight, releasePreflight, runReleaseCountdown } from '../../scripts/release-loop/preflight.js';
|
|
56
56
|
import { defaultReleaseGraphRunsRoot, formatPublishProposal, measurePublishWindow, proposePublishAt, publishWindowWarning } from '../../scripts/release-loop/publish-window.js';
|
|
57
57
|
import { autoStartScheduledRelease, type AutoStartDeferral } from '../release-loop/auto-start.js';
|
|
58
58
|
import { runRehearsalTick, type RehearsalDeps } from '../release-loop/rehearsal.js';
|
|
@@ -62,6 +62,7 @@ import { formatLightRc, runLightRc, type LightRcDeps } from '../release-loop/lig
|
|
|
62
62
|
import { applyWatchList, formatGateHistory, gateHistory, ghMergedPrs } from '../../scripts/release-loop/gate-history.js';
|
|
63
63
|
import { registerRfcCommands } from './rfc-cli.js';
|
|
64
64
|
import { checklistCodenames, checklistVersion, isReleaseVersion, readChecklistContext, registerChecklistReadCommands, type ChecklistEvidenceReader } from './release-checklist-read-cli.js';
|
|
65
|
+
import { syncLinearProgress } from '../decisions/linear-progress-sync.js';
|
|
65
66
|
|
|
66
67
|
export { isReleaseVersion } from './release-checklist-read-cli.js';
|
|
67
68
|
|
|
@@ -814,6 +815,16 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
814
815
|
console.log(`칸 ${rows.length} · 🟢 ${byStatus.green} · 🟡 ${byStatus.yellow} · 🔴 ${byStatus.red} · ✅ ${byStatus.done}`);
|
|
815
816
|
});
|
|
816
817
|
registerChecklistReadCommands(checklist, checklistEvidenceReader);
|
|
818
|
+
withContext(checklist.command('progress-sync').description('Linear 일일 진행 요약 계획 · --live 에서만 댓글 발송'))
|
|
819
|
+
.option('--live', '요약을 Linear 에 댓글로 발송(판별 뒤에만 사용)')
|
|
820
|
+
.action(async (opts: { live?: boolean }, cmd: Command) => {
|
|
821
|
+
const { version, json } = context(cmd);
|
|
822
|
+
if (!version) throw new CliUserError('조회할 판을 지정하라', '--version <v>');
|
|
823
|
+
const result = await syncLinearProgress({ version, live: opts.live === true });
|
|
824
|
+
if (json) { await writeStdoutJson(`${JSON.stringify(result)}\n`); return; }
|
|
825
|
+
console.log(`Linear 진행 요약 ${result.day} · 계획 ${result.planned} · 발송 ${result.posted} · 중복 건너뜀 ${result.skipped} · 실패 ${result.failed}`);
|
|
826
|
+
for (const row of result.plan) console.log(`· ${row.issue} ${row.action}: ${row.body.split('\n').slice(0, 4).join(' / ')}`);
|
|
827
|
+
});
|
|
817
828
|
withContext(checklist.command('landed-but-yellow').description('병합 PR 이 있지만 노랑·빨강인 칸(기본 읽기 전용)'))
|
|
818
829
|
.option('--owner <owner>', '자리 또는 하위 자리로 거르기')
|
|
819
830
|
.option('--open', '미발행 일정 판 중 칸이 있는 판 전부')
|
|
@@ -1261,12 +1272,21 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
|
|
|
1261
1272
|
.option('--json', '결과 한 줄 JSON(stdout) · 사람 줄은 stderr')
|
|
1262
1273
|
.action(async (o: { version: string; cutCommit?: string; mainCut?: boolean; prerelease?: string; dryRun?: boolean; ifReady?: boolean; publishAt?: string; forceFreeze?: boolean; forceNew?: boolean; gateExecutor?: string; gateHost?: string; json?: boolean }) => { await runAction(o); });
|
|
1263
1274
|
release.command('preflight')
|
|
1264
|
-
.description('컷 전 사전 점검(읽기 전용) —
|
|
1275
|
+
.description('컷 전 사전 점검(기본 읽기 전용) — --countdown 은 단계 판정 모델만 표시하고 컷을 실행하지 않는다. --allow-side-effects 를 명시해야 실패 우편·원장을 기록한다.')
|
|
1265
1276
|
.requiredOption('--version <v>', '점검할 판(x.y.z)')
|
|
1266
1277
|
.option('--publish-at <iso>', '계획 발행 시각(기본: 컷 뒤 첫 07·18시 KST)')
|
|
1278
|
+
.option('--countdown', '발사 카운트다운 — T−120 노트·export·게이트 모의 → T−60 컷 트리 고정⊕node-b 자리 → T−30 gate 모드 → T0 컷 · 기본 dry-run')
|
|
1279
|
+
.option('--allow-side-effects', '카운트다운 실패 때 담당 자리 우편·부적합 보고 원장 기록 허용(명시적 opt-in)')
|
|
1267
1280
|
.option('--json', '결과 한 줄 JSON(stdout)')
|
|
1268
|
-
.action(async (o: { version: string; publishAt?: string; json?: boolean }) => {
|
|
1281
|
+
.action(async (o: { version: string; publishAt?: string; countdown?: boolean; allowSideEffects?: boolean; json?: boolean }) => {
|
|
1269
1282
|
try {
|
|
1283
|
+
if (o.countdown) {
|
|
1284
|
+
const countdown = await runReleaseCountdown(o.version, { publishAt: o.publishAt, releaseRunDeps, allowSideEffects: o.allowSideEffects });
|
|
1285
|
+
if (o.json) await writeStdoutJson(`${JSON.stringify(countdown)}\n`);
|
|
1286
|
+
else for (const line of formatCountdown(countdown)) console.log(line);
|
|
1287
|
+
if (countdown.verdict === 'block') process.exitCode = 1;
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1270
1290
|
const result = await releasePreflight(o.version, { publishAt: o.publishAt, releaseRunDeps });
|
|
1271
1291
|
if (o.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
1272
1292
|
else for (const line of formatPreflight(result)) console.log(line);
|
package/src/cli/research-cli.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface ResearchCliDeps {
|
|
|
9
9
|
readonly availableEngines?: () => string[];
|
|
10
10
|
readonly maxDetailOn?: (runId?: string) => boolean;
|
|
11
11
|
readonly log?: typeof debug.log;
|
|
12
|
+
readonly registerLogSink?: (surface: string) => Promise<unknown>;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export function registerResearchCommand(program: Command, deps: ResearchCliDeps = {}): void {
|
|
@@ -31,6 +32,14 @@ export function registerResearchCommand(program: Command, deps: ResearchCliDeps
|
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
// 독립 CLI 프로세스는 데몬의 StoreSink 를 상속하지 않는다. Sink 등록이 없으면
|
|
36
|
+
// debug.log 이벤트가 파일 trail 에만 남아 `eln logs` 에서 관측되지 않는다.
|
|
37
|
+
try {
|
|
38
|
+
const register = deps.registerLogSink
|
|
39
|
+
?? (async (surface: string) => (await import('../domains/standalone-log-sink.js')).registerStandaloneLogSink(surface));
|
|
40
|
+
await register('research');
|
|
41
|
+
} catch { /* fail-open: logging must not prevent research */ }
|
|
42
|
+
|
|
34
43
|
const log = deps.log ?? ((category: string, event: string, data?: unknown) => debug.log(category, event, data));
|
|
35
44
|
const maxDetailOn = deps.maxDetailOn ?? isLiveDetailOn;
|
|
36
45
|
const runId = process.env.ELANOUS_RUN_ID?.trim() || undefined;
|
package/src/cli/setup-cli.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
1
|
+
import { accessSync, constants, existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
3
|
+
import { delimiter, join } from 'node:path';
|
|
4
4
|
import { createHash } from 'node:crypto';
|
|
5
5
|
import { addSource, listSources } from '../intake-plane/intake-sources.js';
|
|
6
6
|
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
@@ -11,6 +11,18 @@ import { recommendedSetup } from './setup-recommend.js';
|
|
|
11
11
|
import { detectSkillCliAuth, type CliAuthStatus } from '../onboarding/cli-auth-status.js';
|
|
12
12
|
import { debug } from '../debug/log.js';
|
|
13
13
|
import { getUserConfig, saveUserConfig, userConfigPath, type UserConfig } from '../user-config.js';
|
|
14
|
+
import { collectServiceKeys, printKeySetupReport } from '../onboarding/key-setup.js';
|
|
15
|
+
import { getSecretAsync, setSecretAsync } from '../nexus/config/secrets/index.js';
|
|
16
|
+
import { probeProvider } from '../llm/provider-probe.js';
|
|
17
|
+
import { createSecretPrompt } from '../onboarding/secret-prompt.js';
|
|
18
|
+
import { realIO } from '../onboarding.js';
|
|
19
|
+
import { parseServiceKeyEnv, readMaskedServiceEnvPaste } from '../setup/service-keys.js';
|
|
20
|
+
import { importServiceKeys, renderServiceKeyStatus, runSetupKeys } from './setup-keys.js';
|
|
21
|
+
import { SERVICE_KEY_CATALOG, type ServiceKeyCatalogEntry } from '../setup/llm-env-detect.js';
|
|
22
|
+
import { serviceKeyStatus } from '../setup/service-keys.js';
|
|
23
|
+
import { detectProviders } from '../llm/provider-detect.js';
|
|
24
|
+
import { DEFAULT_PLUGIN_GROUP, defaultPluginStatuses } from '../plugins/install/plugin-install.js';
|
|
25
|
+
import type { DefaultPluginStatus } from '../plugins/install/plugin-install.js';
|
|
14
26
|
|
|
15
27
|
const ELANOUS_LOGIN_COMMAND = 'elanous login openai-codex';
|
|
16
28
|
const PROVIDER_COMMAND = 'elanous config set llm.provider openai-codex';
|
|
@@ -38,11 +50,18 @@ export interface SetupCliDeps extends DoctorOptions {
|
|
|
38
50
|
planClaudePluginSetup?: typeof planClaudePluginSetup;
|
|
39
51
|
applyClaudePluginSetup?: typeof applyClaudePluginSetup;
|
|
40
52
|
prompt?: (message: string) => Promise<string | undefined>;
|
|
53
|
+
promptSecret?: (message: string) => Promise<string | undefined>;
|
|
54
|
+
getSecretAsync?: typeof getSecretAsync;
|
|
55
|
+
setSecretAsync?: typeof setSecretAsync;
|
|
56
|
+
probeKey?: typeof probeProvider;
|
|
41
57
|
isStdinTty?: () => boolean;
|
|
42
58
|
out?: { log: (value: string) => void; error?: (value: string) => void };
|
|
43
59
|
setExitCode?: (code: number) => void;
|
|
44
60
|
/** 런타임이 이 config 로 «실제로» 고르는 provider(`decideProviderForConfig().provider`). 시험 seam. */
|
|
45
61
|
resolveRuntimeProvider?: (config: UserConfig) => string | undefined;
|
|
62
|
+
detectProviders?: typeof detectProviders;
|
|
63
|
+
getServiceKeyStatus?: typeof serviceKeyStatus;
|
|
64
|
+
isCommandAvailable?: (command: string) => boolean;
|
|
46
65
|
}
|
|
47
66
|
|
|
48
67
|
/** ⛔ 2026-09-23 — provider 단계는 «문자열 비교»가 아니라 ***런타임의 최종 결정***으로 잰다.
|
|
@@ -118,6 +137,10 @@ function missingRequiredCommands(doctor: DoctorReport): boolean {
|
|
|
118
137
|
return doctor.externalCommands.some((command) => command.status === 'missing' && command.tier === 'required');
|
|
119
138
|
}
|
|
120
139
|
|
|
140
|
+
function missingGitCapability(doctor: DoctorReport): boolean {
|
|
141
|
+
return doctor.externalCommands.some((command) => command.name === 'git' && command.status !== 'found');
|
|
142
|
+
}
|
|
143
|
+
|
|
121
144
|
function displayCommand(command: string[]): string {
|
|
122
145
|
return command.map((arg) => /^[A-Za-z0-9_@%+=:,./-]+$/.test(arg)
|
|
123
146
|
? arg
|
|
@@ -128,7 +151,7 @@ export function formatSetupReport(doctor: DoctorReport, steps: SetupStep[], nonI
|
|
|
128
151
|
const elanousLogin = steps[0]!.complete;
|
|
129
152
|
const provider = steps[1]!.complete;
|
|
130
153
|
const codexLogin = steps[2]!.complete;
|
|
131
|
-
const externalReady = doctor.ok && !missingRequiredCommands(doctor);
|
|
154
|
+
const externalReady = doctor.ok && !missingRequiredCommands(doctor) && !missingGitCapability(doctor);
|
|
132
155
|
const capabilities = [
|
|
133
156
|
{ name: 'OpenAI Codex-backed elanous sessions', ready: elanousLogin && provider },
|
|
134
157
|
{ name: 'Codex app-server integration', ready: codexLogin && externalReady },
|
|
@@ -215,13 +238,82 @@ function formatDefaultBundleProposal(): string[] {
|
|
|
215
238
|
];
|
|
216
239
|
}
|
|
217
240
|
|
|
241
|
+
/** Check the default plugin group's required/optional connector declarations against the runtime catalog. */
|
|
242
|
+
export function validateDefaultPluginServiceKeys(
|
|
243
|
+
group: readonly { id: string; requiredServiceKeys: readonly string[]; optionalServiceKeys: readonly string[] }[] = DEFAULT_PLUGIN_GROUP,
|
|
244
|
+
catalog: readonly Pick<ServiceKeyCatalogEntry, 'id' | 'kind'>[] = SERVICE_KEY_CATALOG,
|
|
245
|
+
): string[] {
|
|
246
|
+
const errors: string[] = [];
|
|
247
|
+
const catalogIds = new Set<string>();
|
|
248
|
+
for (const item of catalog) {
|
|
249
|
+
if (catalogIds.has(item.id)) errors.push(`중복 서비스 카탈로그 id: ${item.id}`);
|
|
250
|
+
catalogIds.add(item.id);
|
|
251
|
+
}
|
|
252
|
+
for (const plugin of group) {
|
|
253
|
+
const required = new Set<string>();
|
|
254
|
+
const optional = new Set<string>();
|
|
255
|
+
for (const id of plugin.requiredServiceKeys) {
|
|
256
|
+
if (required.has(id)) errors.push(`${plugin.id}: 필수 키 중복 ${id}`);
|
|
257
|
+
required.add(id);
|
|
258
|
+
}
|
|
259
|
+
for (const id of plugin.optionalServiceKeys) {
|
|
260
|
+
if (optional.has(id)) errors.push(`${plugin.id}: 선택 키 중복 ${id}`);
|
|
261
|
+
optional.add(id);
|
|
262
|
+
if (required.has(id)) errors.push(`${plugin.id}: required/optional 중복 ${id}`);
|
|
263
|
+
}
|
|
264
|
+
for (const id of [...required, ...optional]) {
|
|
265
|
+
const item = catalog.find(candidate => candidate.id === id);
|
|
266
|
+
if (!item) errors.push(`${plugin.id}: 서비스 카탈로그에 없는 키 ${id}`);
|
|
267
|
+
else if (item.kind !== 'api-key') errors.push(`${plugin.id}: API 키가 아닌 서비스 참조 ${id} (${item.kind})`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return errors;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function commandAvailable(command: string): boolean {
|
|
274
|
+
const path = process.env.PATH ?? '';
|
|
275
|
+
return path.split(delimiter).some(directory => {
|
|
276
|
+
try { accessSync(join(directory, command), constants.X_OK); return true; } catch { return false; }
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function formatDefaultPluginStatuses(statuses: readonly DefaultPluginStatus[]): string[] {
|
|
281
|
+
return [
|
|
282
|
+
'Setup: 기본 플러그인 묶음 상태 (실제 키·선행 조건)',
|
|
283
|
+
...statuses.map(plugin => {
|
|
284
|
+
const missing = [
|
|
285
|
+
...(plugin.missingRequiredKeys.length ? [`필수 키 ${plugin.missingRequiredKeys.join(', ')}`] : []),
|
|
286
|
+
...(plugin.missingPrerequisites.length ? [`선행 조건 ${plugin.missingPrerequisites.join(', ')}`] : []),
|
|
287
|
+
];
|
|
288
|
+
const optional = plugin.optionalKeysMissing.length
|
|
289
|
+
? ` · 선택 키 미설정 ${plugin.optionalKeysMissing.join(', ')}` : '';
|
|
290
|
+
return `${plugin.status === 'ready' ? '✓' : '○'} ${plugin.label}: ${plugin.status}${missing.length ? ` · ${missing.join(' · ')}` : ''}${optional}`;
|
|
291
|
+
}),
|
|
292
|
+
];
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async function readDefaultPluginStatuses(deps: SetupCliDeps): Promise<DefaultPluginStatus[]> {
|
|
296
|
+
const catalogErrors = validateDefaultPluginServiceKeys();
|
|
297
|
+
if (catalogErrors.length) throw new Error(`기본 플러그인 서비스 카탈로그 오류: ${catalogErrors.join('; ')}`);
|
|
298
|
+
const keys = (deps.getServiceKeyStatus ?? serviceKeyStatus)()
|
|
299
|
+
.filter(item => item.configured).map(item => item.id);
|
|
300
|
+
const providers = await (deps.detectProviders ?? detectProviders)();
|
|
301
|
+
const prerequisites = new Set<string>();
|
|
302
|
+
if (providers.some(provider => provider.available && provider.auth !== 'agent-cli')) prerequisites.add('llm-provider');
|
|
303
|
+
if ((deps.isCommandAvailable ?? commandAvailable)('aside')) prerequisites.add('aside');
|
|
304
|
+
if ((deps.isCommandAvailable ?? commandAvailable)('claude')) prerequisites.add('claude-cli');
|
|
305
|
+
if ((deps.isCommandAvailable ?? commandAvailable)('gh')) prerequisites.add('github-cli');
|
|
306
|
+
return defaultPluginStatuses({ readyServiceKeyIds: keys, satisfiedPrerequisites: [...prerequisites] });
|
|
307
|
+
}
|
|
308
|
+
|
|
218
309
|
export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}): void {
|
|
219
310
|
const out = deps.out ?? { log: (value: string) => console.log(value), error: (value: string) => console.error(value) };
|
|
220
311
|
const setExitCode = deps.setExitCode ?? ((code: number) => { process.exitCode = code; });
|
|
221
312
|
const doctorRunner = deps.runDoctor ?? runDoctor;
|
|
222
313
|
const isFirstRunSetup = (): boolean => deps.firstRunTopics ?? (!deps.getUserConfig && !existsSync(userConfigPath()));
|
|
223
|
-
const showDefaultBundleProposal = (): void => {
|
|
314
|
+
const showDefaultBundleProposal = async (): Promise<void> => {
|
|
224
315
|
for (const line of formatDefaultBundleProposal()) out.log(line);
|
|
316
|
+
for (const line of formatDefaultPluginStatuses(await readDefaultPluginStatuses(deps))) out.log(line);
|
|
225
317
|
};
|
|
226
318
|
const showCliSkills = (apply: boolean) => {
|
|
227
319
|
out.log('Setup: CLI skills (public GitHub repository reads remain available without login)');
|
|
@@ -233,6 +325,8 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
|
|
|
233
325
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
234
326
|
try { return await rl.question(message); } finally { rl.close(); }
|
|
235
327
|
});
|
|
328
|
+
// API keys must never fall back to the ordinary (echoing) setup prompt.
|
|
329
|
+
const askSecret = deps.promptSecret ?? createSecretPrompt();
|
|
236
330
|
|
|
237
331
|
const setup = program.command('setup')
|
|
238
332
|
.description('Check OpenAI Codex setup and guide each missing credential step')
|
|
@@ -243,7 +337,7 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
|
|
|
243
337
|
if (opts.nonInteractive) {
|
|
244
338
|
out.log(formatSetupReport(doctor, setupSteps(deps), true));
|
|
245
339
|
showCliSkills(false);
|
|
246
|
-
if (isFirstRunSetup()) showDefaultBundleProposal();
|
|
340
|
+
if (isFirstRunSetup()) await showDefaultBundleProposal();
|
|
247
341
|
for (const line of recommendedSetup((deps.getUserConfig ?? getUserConfig)())) out.log(line);
|
|
248
342
|
setExitCode(0);
|
|
249
343
|
return;
|
|
@@ -268,7 +362,7 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
|
|
|
268
362
|
}
|
|
269
363
|
out.log(formatSetupReport(doctor, steps, false));
|
|
270
364
|
showCliSkills(false);
|
|
271
|
-
if (isFirstRun) showDefaultBundleProposal();
|
|
365
|
+
if (isFirstRun) await showDefaultBundleProposal();
|
|
272
366
|
for (const line of recommendedSetup((deps.getUserConfig ?? getUserConfig)())) out.log(line);
|
|
273
367
|
let configured = (deps.getUserConfig ?? getUserConfig)();
|
|
274
368
|
if (!configured.starter?.topics && configured.watch?.enabled !== false
|
|
@@ -314,6 +408,31 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
|
|
|
314
408
|
setExitCode(0);
|
|
315
409
|
});
|
|
316
410
|
|
|
411
|
+
setup.command('service-keys')
|
|
412
|
+
.description('Import and verify service API keys without rendering their values')
|
|
413
|
+
.action(async () => {
|
|
414
|
+
if (!isStdinTty()) {
|
|
415
|
+
(out.error ?? out.log)('키 설정은 stdin TTY가 있는 자리에서만 실행할 수 있다.');
|
|
416
|
+
setExitCode(1);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
try {
|
|
420
|
+
const results = await collectServiceKeys({
|
|
421
|
+
config: (deps.getUserConfig ?? getUserConfig)(),
|
|
422
|
+
promptSecret: askSecret,
|
|
423
|
+
print: out.log,
|
|
424
|
+
getSecret: deps.getSecretAsync,
|
|
425
|
+
setSecret: deps.setSecretAsync,
|
|
426
|
+
probe: deps.probeKey,
|
|
427
|
+
});
|
|
428
|
+
printKeySetupReport(results, out.log);
|
|
429
|
+
setExitCode(results.some((result) => result.status === 'failed') ? 1 : 0);
|
|
430
|
+
} catch {
|
|
431
|
+
(out.error ?? out.log)('키 설정을 완료하지 못했습니다. 민감한 오류 내용은 숨겼습니다.');
|
|
432
|
+
setExitCode(1);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
|
|
317
436
|
setup.command('claude-code')
|
|
318
437
|
.description('Plan or install the elanous Claude Code plugin')
|
|
319
438
|
.option('--apply', 'Install missing steps and verify the MCP connection')
|
|
@@ -365,4 +484,45 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
|
|
|
365
484
|
setExitCode(1);
|
|
366
485
|
}
|
|
367
486
|
});
|
|
487
|
+
|
|
488
|
+
setup.command('keys')
|
|
489
|
+
.description('Set up service credentials without printing secret values')
|
|
490
|
+
.option('--status', 'Show credential presence only')
|
|
491
|
+
.option('--import-env-file <path>', 'Import catalogued keys from a dotenv file')
|
|
492
|
+
.option('--paste-env', 'Paste a dotenv block into a hidden terminal prompt')
|
|
493
|
+
.option('--all', 'Include optional service keys during interactive setup; --status always shows all services')
|
|
494
|
+
.action(async (opts: { status?: boolean; importEnvFile?: string; pasteEnv?: boolean; all?: boolean }) => {
|
|
495
|
+
const keyConfig = (deps.getUserConfig ?? getUserConfig)();
|
|
496
|
+
const keyOptions = { config: keyConfig, includeOptional: opts.all === true };
|
|
497
|
+
try {
|
|
498
|
+
if (opts.status) {
|
|
499
|
+
if (opts.all) throw new Error('--status already shows the full catalog; omit --all');
|
|
500
|
+
for (const line of renderServiceKeyStatus()) out.log(line);
|
|
501
|
+
for (const line of formatDefaultPluginStatuses(await readDefaultPluginStatuses(deps))) out.log(line);
|
|
502
|
+
setExitCode(0);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
let text: string | undefined;
|
|
506
|
+
if (opts.importEnvFile) text = readFileSync(opts.importEnvFile, 'utf8');
|
|
507
|
+
else if (opts.pasteEnv) {
|
|
508
|
+
if (!isStdinTty()) throw new Error('hidden paste import requires a terminal');
|
|
509
|
+
text = await readMaskedServiceEnvPaste();
|
|
510
|
+
}
|
|
511
|
+
if (text !== undefined) {
|
|
512
|
+
const parsed = parseServiceKeyEnv(text);
|
|
513
|
+
const result = await importServiceKeys(parsed, { print: (line) => out.log(line) }, keyOptions);
|
|
514
|
+
setExitCode(result.rejected.length ? 1 : 0);
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
if (!isStdinTty()) throw new Error('secret input requires a terminal; use --import-env-file for a protected dotenv file');
|
|
518
|
+
const io = realIO();
|
|
519
|
+
try { await runSetupKeys(io, keyOptions); }
|
|
520
|
+
finally { io.close(); }
|
|
521
|
+
setExitCode(0);
|
|
522
|
+
} catch (error) {
|
|
523
|
+
const message = error instanceof Error ? error.message : 'setup keys failed';
|
|
524
|
+
(out.error ?? out.log)(message.replace(/\r?\n/g, ' '));
|
|
525
|
+
setExitCode(1);
|
|
526
|
+
}
|
|
527
|
+
});
|
|
368
528
|
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { SERVICE_KEY_CATALOG } from '../setup/llm-env-detect.js';
|
|
2
|
+
import { serviceKeyStatus, storeServiceKeys, verifyServiceKey, type ParsedServiceKeyEnv } from '../setup/service-keys.js';
|
|
3
|
+
import { detectProviders } from '../llm/provider-detect.js';
|
|
4
|
+
import { loginWithCodex } from '../oauth/codex.js';
|
|
5
|
+
import type { FirstRunProviderSetupResult } from '../onboarding/first-run.js';
|
|
6
|
+
import { MODEL_ROLES, resolveRoleLlm, type LLMProviderName, type UserConfig } from '../user-config.js';
|
|
7
|
+
import { parseMenuAnswer } from '../onboarding/menu-answer.js';
|
|
8
|
+
|
|
9
|
+
export interface SetupKeysIO {
|
|
10
|
+
ask(prompt: string): Promise<string>;
|
|
11
|
+
askSecret?(prompt: string): Promise<string>;
|
|
12
|
+
print(message: string): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface SetupKeysOptions {
|
|
16
|
+
config: UserConfig;
|
|
17
|
+
env?: NodeJS.ProcessEnv;
|
|
18
|
+
cacheDir?: string;
|
|
19
|
+
includeOptional?: boolean;
|
|
20
|
+
/** Existing OAuth fetch injection used by deterministic login simulation. */
|
|
21
|
+
loginWithCodex?: typeof loginWithCodex;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function providerForService(id: string): string | undefined {
|
|
25
|
+
switch (id) {
|
|
26
|
+
case 'openai-api': return 'openai';
|
|
27
|
+
case 'anthropic-api': return 'anthropic';
|
|
28
|
+
case 'gemini-api': return 'gemini';
|
|
29
|
+
case 'openrouter': return 'openrouter';
|
|
30
|
+
case 'xai': return 'grok';
|
|
31
|
+
case 'opengateway': return 'opengateway';
|
|
32
|
+
default: return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function providerBaseUrl(config: UserConfig, serviceId: string): string | undefined {
|
|
37
|
+
const provider = providerForService(serviceId);
|
|
38
|
+
if (!provider) return undefined;
|
|
39
|
+
return config.llm.rotation?.find(item => item.provider === provider)?.baseUrl;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function renderProviderProposal(config: UserConfig, providers: Awaited<ReturnType<typeof detectProviders>>): string[] {
|
|
43
|
+
const available = providers.filter(provider => provider.available).sort((a, b) => a.rank - b.rank);
|
|
44
|
+
const ordered = [...new Set(available.map(provider => provider.provider))];
|
|
45
|
+
const defaultProvider = ordered.includes(config.llm.provider) ? config.llm.provider : ordered[0];
|
|
46
|
+
const fallback = config.llm.fallbackChain ?? [];
|
|
47
|
+
const suggestion = defaultProvider ? [defaultProvider, ...ordered.filter(name => name !== defaultProvider)] : [];
|
|
48
|
+
return [
|
|
49
|
+
`LLM 감지: ${available.length ? available.map(provider => `${provider.provider}(${provider.auth})`).join(' · ') : '사용 가능한 인증 없음'}`,
|
|
50
|
+
`기본 제안: ${defaultProvider ?? '설정 후 선택'} · 현재 기본: ${config.llm.provider}`,
|
|
51
|
+
`폴백 제안: ${suggestion.length ? suggestion.join(' → ') : '현재 설정 유지'} · 현재 llm.fallbackChain: ${fallback.length ? fallback.join(' → ') : '미설정'}`,
|
|
52
|
+
`역할별 현재 해석: ${MODEL_ROLES.map(role => {
|
|
53
|
+
try {
|
|
54
|
+
const resolved = resolveRoleLlm(role, { config });
|
|
55
|
+
return `${role}=${resolved.provider}/${resolved.model}`;
|
|
56
|
+
} catch {
|
|
57
|
+
return `${role}=미설정`;
|
|
58
|
+
}
|
|
59
|
+
}).join(' · ')}`,
|
|
60
|
+
'위 내용은 제안만 표시하며 roleLlm·llm.fallbackChain을 변경하지 않습니다.',
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function renderServiceKeyStatus(options: { env?: NodeJS.ProcessEnv; cacheDir?: string } = {}): string[] {
|
|
65
|
+
const status = serviceKeyStatus(options);
|
|
66
|
+
return SERVICE_KEY_CATALOG.map(item => {
|
|
67
|
+
const row = status.find(candidate => candidate.id === item.id);
|
|
68
|
+
if (!row) return `${item.label}: 상태 확인 불가`;
|
|
69
|
+
if (item.kind === 'api-key') return `${item.label}: ${row.configured ? '키 있음' : '키 필요'} (${item.envNames.join(', ')})`;
|
|
70
|
+
return `${item.label}: ${item.kind === 'subscription' || item.kind === 'oauth' || item.kind === 'cli' ? '로그인/설치 상태는 별도 감지' : '로컬 도구 확인 필요'}`;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function importServiceKeys(values: ParsedServiceKeyEnv, io: Pick<SetupKeysIO, 'print'>, options: SetupKeysOptions): Promise<{ stored: string[]; rejected: string[]; unverified: string[] }> {
|
|
75
|
+
const accepted = new Map<string, string>();
|
|
76
|
+
const rejected: string[] = [];
|
|
77
|
+
const unverified: string[] = [];
|
|
78
|
+
const env = options.env ?? process.env;
|
|
79
|
+
for (const [name, value] of values) {
|
|
80
|
+
const item = SERVICE_KEY_CATALOG.find(candidate => candidate.kind === 'api-key' && candidate.envNames.includes(name));
|
|
81
|
+
if (!item) { rejected.push(name); continue; }
|
|
82
|
+
if (env[name]?.trim() === value) io.print(`${name}: 환경에서 이미 제공됨 · 캐시에도 저장합니다 · 값 출력 0`);
|
|
83
|
+
const verification = await verifyServiceKey(item.id, value, {
|
|
84
|
+
env,
|
|
85
|
+
cacheDir: options.cacheDir,
|
|
86
|
+
baseUrl: providerBaseUrl(options.config, item.id),
|
|
87
|
+
});
|
|
88
|
+
if (verification.result === 'verified') accepted.set(name, value);
|
|
89
|
+
else if (verification.result === 'unsupported') {
|
|
90
|
+
accepted.set(name, value);
|
|
91
|
+
unverified.push(name);
|
|
92
|
+
io.print(`${item.label}: 최소 확인을 지원하지 않아 검증 없이 저장합니다 · 값 출력 0`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
rejected.push(name);
|
|
96
|
+
io.print(`${item.label}: 검증 ${verification.result}${verification.httpStatus ? ` (HTTP ${verification.httpStatus})` : ''} · 저장 안 함`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const saved = accepted.size ? storeServiceKeys(accepted, { env, cacheDir: options.cacheDir }) : { stored: [] };
|
|
100
|
+
if (saved.stored.length) io.print(`저장 완료: ${saved.stored.join(', ')} · 값 출력 0`);
|
|
101
|
+
return { stored: saved.stored, rejected: rejected.sort(), unverified: unverified.sort() };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function runSetupKeys(io: SetupKeysIO, options: SetupKeysOptions): Promise<{ stored: string[]; skipped: string[] }> {
|
|
105
|
+
const providers = await detectProviders({ env: options.env });
|
|
106
|
+
for (const line of renderProviderProposal(options.config, providers)) io.print(line);
|
|
107
|
+
const { listCodexAccountsInStore } = await import('../oauth/codex-account-store.js');
|
|
108
|
+
const codexAccounts = listCodexAccountsInStore().map(account => account.name);
|
|
109
|
+
io.print(`Codex 계정: ${codexAccounts.length ? codexAccounts.join(', ') : '없음'} · 추가: 별도 CODEX_HOME에서 codex login 후 elanous provider codex account import <이름> --home <홈>`);
|
|
110
|
+
const statuses = serviceKeyStatus({ env: options.env, cacheDir: options.cacheDir });
|
|
111
|
+
const entries = SERVICE_KEY_CATALOG.filter(item => item.kind === 'api-key' && (item.demoRequired || options.includeOptional));
|
|
112
|
+
const stored: string[] = [];
|
|
113
|
+
const skipped: string[] = [];
|
|
114
|
+
for (const item of entries) {
|
|
115
|
+
const status = statuses.find(candidate => candidate.id === item.id);
|
|
116
|
+
if (!status) { io.print(`${item.label}: 상태 확인 불가 · 건너뜀`); skipped.push(item.id); continue; }
|
|
117
|
+
if (status.configured) { io.print(`${item.label}: 이미 설정됨`); continue; }
|
|
118
|
+
const envName = item.envNames[0];
|
|
119
|
+
if (!envName) continue;
|
|
120
|
+
io.print(`${item.label} · ${item.setupUrl} · ${item.demoRequired ? '데모 필요' : '선택'}`);
|
|
121
|
+
if (!io.askSecret) {
|
|
122
|
+
io.print(`${item.label}: 이 입력 화면은 비밀 입력을 지원하지 않습니다 · eln setup keys --paste-env 사용`);
|
|
123
|
+
skipped.push(item.id);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const value = (await io.askSecret(`${envName} (Enter=건너뜀): `)).trim();
|
|
127
|
+
if (!value) { skipped.push(item.id); continue; }
|
|
128
|
+
const result = await importServiceKeys(new Map([[envName, value]]), io, options);
|
|
129
|
+
if (result.stored.includes(envName)) stored.push(envName);
|
|
130
|
+
else skipped.push(item.id);
|
|
131
|
+
}
|
|
132
|
+
for (const line of renderServiceKeyStatus({ env: options.env, cacheDir: options.cacheDir })) io.print(line);
|
|
133
|
+
return { stored, skipped };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export const FIRST_RUN_PROVIDER_SETUP_MENU_HEADING = '처음 실행 LLM 설정';
|
|
137
|
+
export const FIRST_RUN_PROVIDER_SETUP_MENU_CHOICES = '1 Codex 구독 로그인 · 2 API 키 입력 · Enter 건너뛰기';
|
|
138
|
+
export const FIRST_RUN_PROVIDER_SETUP_MENU_MAX_MISSES = 3;
|
|
139
|
+
|
|
140
|
+
/** First-run entry: offer the existing Codex device login or the same verified-key flow as `setup keys`. */
|
|
141
|
+
export async function runFirstRunProviderSetup(io: SetupKeysIO, options: SetupKeysOptions): Promise<FirstRunProviderSetupResult> {
|
|
142
|
+
const choices = ['codex-login', 'api-key'] as const;
|
|
143
|
+
let misses = 0;
|
|
144
|
+
let choice: typeof choices[number];
|
|
145
|
+
for (;;) {
|
|
146
|
+
io.print(FIRST_RUN_PROVIDER_SETUP_MENU_HEADING);
|
|
147
|
+
io.print(FIRST_RUN_PROVIDER_SETUP_MENU_CHOICES);
|
|
148
|
+
const parsed = parseMenuAnswer(await io.ask('선택: '), choices);
|
|
149
|
+
if (parsed.kind === 'cancel') return null;
|
|
150
|
+
if (parsed.kind === 'miss') {
|
|
151
|
+
misses += 1;
|
|
152
|
+
if (misses >= FIRST_RUN_PROVIDER_SETUP_MENU_MAX_MISSES) return { kind: 'needs-llm' };
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
choice = parsed.provider;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (choice === 'codex-login') {
|
|
160
|
+
try {
|
|
161
|
+
await (options.loginWithCodex ?? loginWithCodex)({ onProgress: (event) => {
|
|
162
|
+
if (event.type === 'user_code') io.print(`Codex 로그인: ${event.loginUrl} · 코드 ${event.userCode}`);
|
|
163
|
+
else if (event.type === 'polling') io.print('Codex 로그인을 기다리는 중…');
|
|
164
|
+
else if (event.type === 'exchanging') io.print('Codex 로그인을 확인하는 중…');
|
|
165
|
+
} });
|
|
166
|
+
io.print('Codex 로그인 완료');
|
|
167
|
+
return 'openai-codex';
|
|
168
|
+
} catch {
|
|
169
|
+
io.print('Codex 로그인을 완료하지 못했습니다. 다시 시도하거나 Enter로 건너뛰세요.');
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Keep the exact environment object through storage and rediscovery: storeServiceKeys
|
|
174
|
+
// writes accepted values into it as well as the protected cache, so a newly entered
|
|
175
|
+
// key is immediately visible to detectProviders and resolveProviderCredential.
|
|
176
|
+
const env = options.env ?? process.env;
|
|
177
|
+
await runSetupKeys(io, { ...options, env });
|
|
178
|
+
// runSetupKeys handles an absent askSecret capability per item (skip + safe guidance);
|
|
179
|
+
// it does not throw or turn the first-run entry into a crash.
|
|
180
|
+
const providers = (await detectProviders({ env }))
|
|
181
|
+
.filter(provider => provider.available && provider.auth === 'apikey');
|
|
182
|
+
const available = [...new Set(providers.map(provider => provider.provider as LLMProviderName))];
|
|
183
|
+
if (!available.length) return null;
|
|
184
|
+
io.print(`기본 공급자 선택: ${available.map((provider, index) => `${index + 1} ${provider}`).join(' · ')}`);
|
|
185
|
+
const answer = (await io.ask('기본 공급자 번호 (Enter=건너뜀): ')).trim();
|
|
186
|
+
return available[Number(answer) - 1] ?? null;
|
|
187
|
+
}
|