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
|
@@ -6,8 +6,14 @@ import type { Command } from 'commander';
|
|
|
6
6
|
import { debug, redactSecretText } from '../debug/log.js';
|
|
7
7
|
import type { AsyncLockHandle } from '../storage/file-lock.js';
|
|
8
8
|
import { stateDirSourceForChild } from '../agent/identity-env.js';
|
|
9
|
+
import { createMissionLineStore, MissionLineHttpError, postMissionLineEvent, type MissionLineType } from './mission-line.js';
|
|
10
|
+
import type { LinearMissionLink } from '../intake-plane/linear-mission-sync.js';
|
|
9
11
|
|
|
10
12
|
const MISSION_CONTEXT_ENV = 'ELANOUS_MISSION_CONTEXT';
|
|
13
|
+
const HAND_CHILD_ENV_KEYS = [
|
|
14
|
+
'ELANOUS_MISSION_ID', 'ELANOUS_ATTEMPT_ID', 'ELANOUS_HAND_TOKEN', 'ELANOUS_HAND_ATTEMPT_ID',
|
|
15
|
+
'ELANOUS_HAND_FINAL_LINE_ID', 'ELANOUS_HAND_AGENT', 'ELANOUS_HAND_RUN_ID', 'ELANOUS_HAND_PTY_ID',
|
|
16
|
+
] as const;
|
|
11
17
|
|
|
12
18
|
interface MissionContext { missionId: string; storeRoot: string }
|
|
13
19
|
|
|
@@ -21,17 +27,27 @@ function missionContextForEnv(env: NodeJS.ProcessEnv, missionId: string): Missio
|
|
|
21
27
|
} catch { return undefined; }
|
|
22
28
|
}
|
|
23
29
|
|
|
24
|
-
function missionChildEnv(root: string, missionId: string, base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
|
|
30
|
+
export function missionChildEnv(root: string, missionId: string, base: NodeJS.ProcessEnv = process.env, line?: { token: string; attemptId: string; finalLineId: string; agent: 'codex' | 'claude'; nexusUrl?: string; runId?: string; ptyId?: string }): NodeJS.ProcessEnv {
|
|
25
31
|
const storeRoot = resolve(root);
|
|
32
|
+
const childBase = { ...base };
|
|
33
|
+
for (const key of HAND_CHILD_ENV_KEYS) delete childBase[key];
|
|
26
34
|
return {
|
|
27
|
-
...
|
|
35
|
+
...childBase,
|
|
28
36
|
ELANOUS_STATE_DIR: storeRoot,
|
|
29
37
|
ELANOUS_STATE_DIR_SOURCE: stateDirSourceForChild(storeRoot, base),
|
|
38
|
+
...(line ? { ELANOUS_MISSION_ID: missionId, ELANOUS_ATTEMPT_ID: line.attemptId,
|
|
39
|
+
ELANOUS_HAND_TOKEN: line.token, ELANOUS_HAND_ATTEMPT_ID: line.attemptId,
|
|
40
|
+
ELANOUS_HAND_FINAL_LINE_ID: line.finalLineId, ELANOUS_HAND_AGENT: line.agent,
|
|
41
|
+
...(line.runId ? { ELANOUS_HAND_RUN_ID: line.runId, ELANOUS_RUN_ID: line.runId } : {}),
|
|
42
|
+
...(line.ptyId ? { ELANOUS_HAND_PTY_ID: line.ptyId } : {}), ...(line.nexusUrl ? { ELANOUS_NEXUS_URL: line.nexusUrl } : {}) } : {}),
|
|
30
43
|
[MISSION_CONTEXT_ENV]: JSON.stringify({ missionId, storeRoot }),
|
|
31
44
|
};
|
|
32
45
|
}
|
|
33
46
|
|
|
34
47
|
export type MissionOutStatus = 'running' | 'completed' | 'cancelled' | 'failed' | 'timeout';
|
|
48
|
+
export class MissionReplyStateError extends Error {
|
|
49
|
+
constructor(readonly status: 404 | 409, message: string) { super(message); this.name = 'MissionReplyStateError'; }
|
|
50
|
+
}
|
|
35
51
|
export interface MissionReplyEvent {
|
|
36
52
|
type: 'mission.reply';
|
|
37
53
|
missionId: string;
|
|
@@ -45,6 +61,18 @@ export interface MissionReplyEvent {
|
|
|
45
61
|
scope?: string;
|
|
46
62
|
stop?: boolean;
|
|
47
63
|
priority?: string;
|
|
64
|
+
lineId?: string;
|
|
65
|
+
attemptId?: string;
|
|
66
|
+
runId?: string;
|
|
67
|
+
ptyId?: string;
|
|
68
|
+
replyTo?: number;
|
|
69
|
+
agent?: 'codex' | 'claude';
|
|
70
|
+
lineType?: 'progress' | 'final' | 'ask' | 'answer' | 'correct';
|
|
71
|
+
source?: string;
|
|
72
|
+
state?: string;
|
|
73
|
+
who?: string;
|
|
74
|
+
what?: string;
|
|
75
|
+
graphEvents?: Array<{ seq: number; ts: string; type: 'node-added'; node: string; kind: 'hand'; decider: 'mission-line'; reason: string; who: string; what: string; missionId: string }>;
|
|
48
76
|
}
|
|
49
77
|
export interface MissionReplyMessageFields {
|
|
50
78
|
kind?: string;
|
|
@@ -53,6 +81,17 @@ export interface MissionReplyMessageFields {
|
|
|
53
81
|
scope?: string;
|
|
54
82
|
stop?: boolean;
|
|
55
83
|
priority?: string;
|
|
84
|
+
lineId?: string;
|
|
85
|
+
attemptId?: string;
|
|
86
|
+
runId?: string;
|
|
87
|
+
ptyId?: string;
|
|
88
|
+
replyTo?: number;
|
|
89
|
+
agent?: 'codex' | 'claude';
|
|
90
|
+
lineType?: 'progress' | 'final' | 'ask' | 'answer' | 'correct';
|
|
91
|
+
source?: string;
|
|
92
|
+
state?: string;
|
|
93
|
+
who?: string;
|
|
94
|
+
what?: string;
|
|
56
95
|
}
|
|
57
96
|
export interface MissionOutRecord {
|
|
58
97
|
missionId: string;
|
|
@@ -70,6 +109,8 @@ export interface MissionOutRecord {
|
|
|
70
109
|
pendingFinalReply?: string;
|
|
71
110
|
workerPid?: number;
|
|
72
111
|
agentPid?: number;
|
|
112
|
+
/** Server-validated DEMO child issue; never populated from a reply payload. */
|
|
113
|
+
linearLink?: LinearMissionLink;
|
|
73
114
|
}
|
|
74
115
|
export interface MissionOutStoreDeps {
|
|
75
116
|
now?: () => Date;
|
|
@@ -151,12 +192,22 @@ function validateReplyMessageFields(fields: MissionReplyMessageFields): MissionR
|
|
|
151
192
|
const value = fields[key];
|
|
152
193
|
if (value !== undefined && (typeof value !== 'string' || !value.trim())) throw new Error(`reply ${key} 는 비어 있지 않은 문자열이어야 합니다`);
|
|
153
194
|
}
|
|
195
|
+
for (const key of ['attemptId', 'runId', 'ptyId', 'source', 'state', 'who', 'what', 'lineId'] as const) {
|
|
196
|
+
const value = fields[key];
|
|
197
|
+
if (value !== undefined && (typeof value !== 'string' || !value.trim())) throw new Error(`reply ${key} 는 비어 있지 않은 문자열이어야 합니다`);
|
|
198
|
+
}
|
|
199
|
+
if (fields.replyTo !== undefined && (!Number.isInteger(fields.replyTo) || fields.replyTo < 1)) throw new Error('reply replyTo 는 양의 정수여야 합니다');
|
|
200
|
+
if (fields.lineId !== undefined && !/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i.test(fields.lineId)) {
|
|
201
|
+
throw new Error('reply lineId 는 UUID 형식이어야 합니다');
|
|
202
|
+
}
|
|
203
|
+
if (fields.agent !== undefined && fields.agent !== 'codex' && fields.agent !== 'claude') throw new Error('reply agent 값이 올바르지 않습니다');
|
|
204
|
+
if (fields.lineType !== undefined && !['progress', 'final', 'ask', 'answer', 'correct'].includes(fields.lineType)) throw new Error('reply lineType 값이 올바르지 않습니다');
|
|
154
205
|
if (fields.stop !== undefined && typeof fields.stop !== 'boolean') throw new Error('reply stop 은 boolean 이어야 합니다');
|
|
155
206
|
if (fields.kind === 'correct' && (!fields.scope || fields.stop === undefined || !fields.priority)) {
|
|
156
207
|
throw new Error('reply kind=correct 에는 scope, stop, priority 가 필요합니다');
|
|
157
208
|
}
|
|
158
209
|
// ask / answer / correct are reserved names. Unknown names remain accepted
|
|
159
|
-
// as extension kinds
|
|
210
|
+
// as extension kinds.
|
|
160
211
|
return fields;
|
|
161
212
|
}
|
|
162
213
|
|
|
@@ -166,6 +217,19 @@ function atomicJson(path: string, value: unknown): void {
|
|
|
166
217
|
renameSync(temp, path);
|
|
167
218
|
}
|
|
168
219
|
|
|
220
|
+
export async function waitForMissionAnswer(store: ReturnType<typeof createMissionOutStore>, missionId: string, ask: Pick<MissionReplyEvent, 'sequence' | 'deadline'>, defaults: string, deps: { now?: () => number; sleep?: (ms: number) => Promise<void> } = {}): Promise<{ text: string; usedDefault: boolean }> {
|
|
221
|
+
const now = deps.now ?? Date.now;
|
|
222
|
+
const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolveDelay) => setTimeout(resolveDelay, ms)));
|
|
223
|
+
const parsedDeadline = ask.deadline ? Date.parse(ask.deadline) : Number.NaN;
|
|
224
|
+
const deadline = Number.isFinite(parsedDeadline) ? parsedDeadline : now() + 2 * 60_000;
|
|
225
|
+
while (now() < deadline) {
|
|
226
|
+
const answer = store.replies(missionId).find((event) => event.kind === 'answer' && event.replyTo === ask.sequence);
|
|
227
|
+
if (answer) return { text: answer.text, usedDefault: false };
|
|
228
|
+
await sleep(Math.min(250, Math.max(1, deadline - now())));
|
|
229
|
+
}
|
|
230
|
+
return { text: defaults, usedDefault: true };
|
|
231
|
+
}
|
|
232
|
+
|
|
169
233
|
export function createMissionOutStore(root: string, deps: MissionOutStoreDeps = {}) {
|
|
170
234
|
const now = deps.now ?? (() => new Date());
|
|
171
235
|
const withLock = async <T>(missionId: string, action: (lock: AsyncLockHandle) => T): Promise<T> => {
|
|
@@ -196,7 +260,7 @@ export function createMissionOutStore(root: string, deps: MissionOutStoreDeps =
|
|
|
196
260
|
} catch { return []; }
|
|
197
261
|
};
|
|
198
262
|
return {
|
|
199
|
-
create(input: { missionId?: string; agent: 'codex' | 'claude'; prompt: string; cwd: string; outputPath: string; targetOutputPath: string }): MissionOutRecord {
|
|
263
|
+
create(input: { missionId?: string; agent: 'codex' | 'claude'; prompt: string; cwd: string; outputPath: string; targetOutputPath: string; linearLink?: LinearMissionLink }): MissionOutRecord {
|
|
200
264
|
const dir = join(root, 'agent-missions');
|
|
201
265
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
202
266
|
const createdAt = now().toISOString();
|
|
@@ -218,13 +282,27 @@ export function createMissionOutStore(root: string, deps: MissionOutStoreDeps =
|
|
|
218
282
|
if (!text.trim()) throw new Error('reply 본문이 비었습니다');
|
|
219
283
|
const messageFields = validateReplyMessageFields(fields);
|
|
220
284
|
return withLock(missionId, (lock) => {
|
|
285
|
+
const priorLine = messageFields.lineId
|
|
286
|
+
? replies(missionId).find((event) => event.lineId === messageFields.lineId)
|
|
287
|
+
: undefined;
|
|
288
|
+
if (priorLine) return priorLine;
|
|
221
289
|
const current = read(missionId);
|
|
222
|
-
if (!current) throw new
|
|
223
|
-
if (current.status !== 'running') throw new
|
|
224
|
-
if (current.doneReceived || replies(missionId).some((event) => event.done)) throw new
|
|
290
|
+
if (!current) throw new MissionReplyStateError(404, `미션을 찾을 수 없습니다: ${missionId}`);
|
|
291
|
+
if (current.status !== 'running') throw new MissionReplyStateError(409, `미션이 실행 중이 아닙니다: ${current.status}`);
|
|
292
|
+
if (current.doneReceived || replies(missionId).some((event) => event.done)) throw new MissionReplyStateError(409, '최종 답변이 이미 제출됐습니다');
|
|
293
|
+
if (messageFields.kind === 'ask' && replies(missionId).filter((event) => event.kind === 'ask').length >= 3) {
|
|
294
|
+
throw new MissionReplyStateError(409, '미션당 ask 는 최대 3회입니다; 남은 정보로 진행하거나 다시 작성하세요');
|
|
295
|
+
}
|
|
296
|
+
const askDeadline = messageFields.kind === 'ask'
|
|
297
|
+
? (messageFields.deadline ?? new Date(now().getTime() + 2 * 60_000).toISOString())
|
|
298
|
+
: undefined;
|
|
225
299
|
const event: MissionReplyEvent = {
|
|
226
300
|
type: 'mission.reply', missionId, sequence: replies(missionId).length + 1,
|
|
227
301
|
text, done, createdAt: now().toISOString(), ...messageFields,
|
|
302
|
+
...(askDeadline ? { deadline: askDeadline } : {}),
|
|
303
|
+
...(replies(missionId).length === 0 && messageFields.who && messageFields.what ? {
|
|
304
|
+
graphEvents: [{ seq: 1, ts: now().toISOString(), type: 'node-added', node: `hand-${missionId}`, kind: 'hand', decider: 'mission-line', reason: 'hand mission line opened', who: messageFields.who, what: messageFields.what, missionId }],
|
|
305
|
+
} : {}),
|
|
228
306
|
};
|
|
229
307
|
if (!lock.stillHeld()) throw new Error('미션 상태 잠금을 잃어 reply 기록을 중단했습니다');
|
|
230
308
|
appendFileSync(replyPath(root, missionId), `${JSON.stringify(event)}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
@@ -339,7 +417,34 @@ export async function runMissionOutWorker(root: string, missionId: string, runAg
|
|
|
339
417
|
if (!existsSync(record.outputPath) || statSync(record.outputPath).size === 0) throw new Error('결과 파일이 없어 미션을 실패 처리했습니다');
|
|
340
418
|
const latest = store.read(missionId);
|
|
341
419
|
if (!latest || latest.status !== 'running') return;
|
|
342
|
-
if (!latest.doneReceived)
|
|
420
|
+
if (!latest.doneReceived) {
|
|
421
|
+
const finalText = readFileSync(record.outputPath, 'utf8');
|
|
422
|
+
const lineToken = process.env.ELANOUS_HAND_TOKEN?.trim();
|
|
423
|
+
const lineAttemptId = process.env.ELANOUS_HAND_ATTEMPT_ID?.trim();
|
|
424
|
+
const lineId = process.env.ELANOUS_HAND_FINAL_LINE_ID?.trim() || randomUUID();
|
|
425
|
+
const persistedFinal = lineAttemptId
|
|
426
|
+
? store.replies(missionId).find((event) => event.done && event.attemptId === lineAttemptId)
|
|
427
|
+
: undefined;
|
|
428
|
+
if (persistedFinal) {
|
|
429
|
+
// NEXUS may have durably appended the final row but lost its HTTP
|
|
430
|
+
// response. Reuse that row; never append a second terminal event.
|
|
431
|
+
} else if (lineToken && lineAttemptId) {
|
|
432
|
+
try {
|
|
433
|
+
await postMissionLineEvent({ lineId, missionId, attemptId: lineAttemptId, agent: record.agent, type: 'final', source: 'mission-worker', text: finalText, state: 'completed' });
|
|
434
|
+
} catch (error) {
|
|
435
|
+
if (error instanceof MissionLineHttpError && error.status < 500) throw error;
|
|
436
|
+
// The local mission ledger is the durability boundary. NEXUS is an
|
|
437
|
+
// observation/transport edge; an unavailable daemon must not turn a
|
|
438
|
+
// valid output file into a lost final reply.
|
|
439
|
+
debug.log('agent-mission', 'line-ingress-fallback', { missionId, error: redactSecretText(String(error)) });
|
|
440
|
+
const racedFinal = store.replies(missionId).find((event) => event.lineId === lineId);
|
|
441
|
+
if (!racedFinal) await store.reply(missionId, finalText, true, {
|
|
442
|
+
lineId, attemptId: lineAttemptId, agent: record.agent, lineType: 'final', source: 'mission-worker', state: 'completed',
|
|
443
|
+
...(store.replies(missionId).length === 0 ? { who: record.agent === 'claude' ? 'Claude' : 'Codex', what: record.prompt.replace(/\s+/g, ' ').trim().slice(0, 180) || 'hand mission' } : {}),
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
} else await store.reply(missionId, finalText, true);
|
|
447
|
+
}
|
|
343
448
|
await store.complete(missionId);
|
|
344
449
|
} catch (e) {
|
|
345
450
|
const latest = store.read(missionId);
|
|
@@ -353,6 +458,11 @@ export async function runMissionOutWorker(root: string, missionId: string, runAg
|
|
|
353
458
|
debug.log('agent-mission', 'terminal-write-failed', { missionId, error: redactSecretText(String(stateError)) }, { level: 'error' });
|
|
354
459
|
}
|
|
355
460
|
}
|
|
461
|
+
} finally {
|
|
462
|
+
// The attempt credential belongs to this worker job, including failure and
|
|
463
|
+
// cancellation paths. Revocation is idempotent when a final line already
|
|
464
|
+
// closed the token at the NEXUS ingress.
|
|
465
|
+
createMissionLineStore(root).revoke(missionId);
|
|
356
466
|
}
|
|
357
467
|
}
|
|
358
468
|
|
|
@@ -402,7 +512,7 @@ const missionUsage = {
|
|
|
402
512
|
command: 'eln mission',
|
|
403
513
|
commands: {
|
|
404
514
|
run: {
|
|
405
|
-
args: [], flags: ['--agent codex|claude', '--prompt <text>|--prompt-file <path>', '--out <path>', '--dry-run', '--output-format json'],
|
|
515
|
+
args: [], flags: ['--agent codex|claude', '--prompt <text>|--prompt-file <path>', '--out <path>', '--linear-issue-id <id>', '--dry-run', '--output-format json'],
|
|
406
516
|
responseSchema: { type: 'object', required: ['id', 'missionId', 'status'], properties: { id: { type: 'string', format: 'uuid' }, missionId: { type: 'string', format: 'uuid' }, status: { const: 'running' }, artifacts: { type: 'array', items: { type: 'string' } } } },
|
|
407
517
|
},
|
|
408
518
|
status: {
|
|
@@ -410,7 +520,7 @@ const missionUsage = {
|
|
|
410
520
|
responseSchema: { type: 'object', required: ['id', 'missionId', 'status', 'artifacts', 'replies'], properties: { id: { type: 'string', format: 'uuid' }, missionId: { type: 'string', format: 'uuid' }, status: { enum: ['running', 'done', 'cancelled', 'failed', 'timeout'] }, body: { type: 'string' }, artifacts: { type: 'array', items: { type: 'string' } }, replies: { type: 'array', items: { $ref: '#/events/mission.reply' } }, result: { type: 'string' }, lockStale: { type: 'boolean' }, error: { type: 'string' } } },
|
|
411
521
|
},
|
|
412
522
|
reply: {
|
|
413
|
-
args: ['[missionId]', '[text|stdin]'], flags: ['--mission <missionId>', '--done', '--kind <kind>', '--defaults <text>', '--deadline <value>', '--scope <text>', '--[no-]stop', '--priority <value>'],
|
|
523
|
+
args: ['[missionId]', '[text|stdin]'], flags: ['--mission <missionId>', '--done', '--kind <kind>', '--defaults <text>', '--deadline <value>', '--reply-to <sequence>', '--scope <text>', '--[no-]stop', '--priority <value>'],
|
|
414
524
|
responseSchema: { type: 'object', required: ['missionId', 'accepted', 'sequence', 'done'], properties: { missionId: { type: 'string', format: 'uuid' }, accepted: { const: true }, sequence: { type: 'integer', minimum: 1 }, done: { type: 'boolean' } } },
|
|
415
525
|
},
|
|
416
526
|
cancel: {
|
|
@@ -418,12 +528,14 @@ const missionUsage = {
|
|
|
418
528
|
responseSchema: { type: 'object', required: ['missionId', 'status', 'cancelled'], properties: { missionId: { type: 'string', format: 'uuid' }, status: { enum: ['running', 'completed', 'cancelled', 'failed'] }, cancelled: { type: 'boolean' } } },
|
|
419
529
|
},
|
|
420
530
|
},
|
|
421
|
-
events: { 'mission.reply': { type: 'object', required: ['type', 'missionId', 'sequence', 'text', 'done', 'createdAt'], properties: { type: { const: 'mission.reply' }, missionId: { type: 'string', format: 'uuid' }, sequence: { type: 'integer' }, text: { type: 'string' }, done: { type: 'boolean' }, createdAt: { type: 'string', format: 'date-time' }, kind: { type: 'string', description: 'Reserved kinds: ask, answer, correct.
|
|
531
|
+
events: { 'mission.reply': { type: 'object', required: ['type', 'missionId', 'sequence', 'text', 'done', 'createdAt'], properties: { type: { const: 'mission.reply' }, missionId: { type: 'string', format: 'uuid' }, sequence: { type: 'integer' }, replyTo: { type: 'integer', minimum: 1 }, runId: { type: 'string' }, ptyId: { type: 'string' }, text: { type: 'string' }, done: { type: 'boolean' }, createdAt: { type: 'string', format: 'date-time' }, kind: { type: 'string', description: 'Reserved kinds: ask, answer, correct.' }, defaults: { type: 'string' }, deadline: { type: 'string' }, scope: { type: 'string' }, stop: { type: 'boolean' }, priority: { type: 'string' } } } },
|
|
422
532
|
replyContract: 'Use `eln --config-dir <storeRoot> mission reply --mission <missionId> <text> [--kind ask|answer|correct]` for replies and `eln --config-dir <storeRoot> mission reply --mission <missionId> --done <text>` for the final answer.',
|
|
423
533
|
agentInstructionBlock: [
|
|
424
534
|
'You can send durable progress and final answers to Elanous with `eln mission reply`.',
|
|
425
535
|
'Use `eln --config-dir <storeRoot> mission reply --mission <missionId> "<message>"` for progress/questions.',
|
|
426
|
-
'
|
|
536
|
+
'Ask for a decision with `--kind ask --defaults <fallback>`; include question and options in the text. An unanswered ask defaults after two minutes. Ask at most three times, then continue with available information or rewrite the task.',
|
|
537
|
+
'Example: `eln --config-dir <storeRoot> mission reply --mission <missionId> --kind ask --defaults main "Which base should I use? Options: main or release/2.4."` blocks until HandReply or the deadline.',
|
|
538
|
+
'For a correction, include --scope, --stop, and --priority; corrections require a bound child run and PTY.',
|
|
427
539
|
'Finish with `eln --config-dir <storeRoot> mission reply --mission <missionId> --done "<final answer>"`.',
|
|
428
540
|
'Use `eln --config-dir <storeRoot> mission status <missionId>` to inspect the interaction; do not return output file paths.',
|
|
429
541
|
].join('\n'),
|
|
@@ -436,6 +548,8 @@ export function registerMissionOutCommand(program: Command, deps: {
|
|
|
436
548
|
write?: (text: string) => void;
|
|
437
549
|
error?: (text: string) => void;
|
|
438
550
|
startWorker?: (root: string, missionId: string) => number;
|
|
551
|
+
/** Test seam; production resolves the registered current NEXUS endpoint. */
|
|
552
|
+
resolveNexusUrl?: () => string | null;
|
|
439
553
|
} = {}): Command {
|
|
440
554
|
const write = deps.write ?? ((text) => process.stdout.write(text));
|
|
441
555
|
const error = deps.error ?? ((text) => process.stderr.write(text));
|
|
@@ -452,6 +566,26 @@ export function registerMissionOutCommand(program: Command, deps: {
|
|
|
452
566
|
const missionContext = missionContextForEnv(process.env, missionId);
|
|
453
567
|
return missionContext ? observingStoreAt(missionContext.storeRoot) : storeAt(true);
|
|
454
568
|
};
|
|
569
|
+
const syncAcceptedLinearReply = async (store: ReturnType<typeof createMissionOutStore>, missionId: string, event: MissionReplyEvent): Promise<void> => {
|
|
570
|
+
try {
|
|
571
|
+
const linkedMission = store.read(missionId);
|
|
572
|
+
if (!linkedMission?.linearLink) return;
|
|
573
|
+
const latestLine = (): { lineType: string; sequence: number } | undefined => store.replies(missionId)
|
|
574
|
+
.filter(reply => reply.lineType === 'progress' || reply.lineType === 'final')
|
|
575
|
+
.sort((a, b) => b.sequence - a.sequence)
|
|
576
|
+
.map(reply => ({ lineType: reply.lineType!, sequence: reply.sequence }))[0];
|
|
577
|
+
const missionContext = missionContextForEnv(process.env, missionId);
|
|
578
|
+
const lockRoot = missionContext?.storeRoot ?? await root();
|
|
579
|
+
const { syncLinearMissionProgress } = await import('../intake-plane/linear-mission-sync.js');
|
|
580
|
+
await syncLinearMissionProgress({
|
|
581
|
+
link: linkedMission.linearLink, lineType: event.lineType, sequence: event.sequence, latestLine: latestLine(),
|
|
582
|
+
}, { lockRoot, getLatestLine: async () => latestLine() });
|
|
583
|
+
} catch (error) {
|
|
584
|
+
debug.log('agent-mission', 'linear-progress-sync-setup-failed', {
|
|
585
|
+
missionId, error: redactSecretText(String(error)),
|
|
586
|
+
}, { level: 'warn' });
|
|
587
|
+
}
|
|
588
|
+
};
|
|
455
589
|
const out = (opts: { json?: boolean; outputFormat?: string }, value: unknown): void => {
|
|
456
590
|
write(opts.json || opts.outputFormat === 'json' ? `${JSON.stringify(value)}\n` : `${JSON.stringify(value, null, 2)}\n`);
|
|
457
591
|
};
|
|
@@ -466,10 +600,11 @@ export function registerMissionOutCommand(program: Command, deps: {
|
|
|
466
600
|
.option('--prompt <text>', 'Mission prompt')
|
|
467
601
|
.option('--prompt-file <path>', 'Read the prompt from a UTF-8 file')
|
|
468
602
|
.option('--out <path>', 'Internal result file required for fail-closed completion')
|
|
603
|
+
.option('--linear-issue-id <id>', 'Bind this mission to a verified DEMO subtask')
|
|
469
604
|
.option('--dry-run', 'Resolve and print request without creating a job')
|
|
470
605
|
.option('--json', 'Emit JSON')
|
|
471
606
|
.option('--output-format <format>', 'text or json', 'text')
|
|
472
|
-
.action(async (opts: { agent?: string; prompt?: string; promptFile?: string; out?: string; dryRun?: boolean; json?: boolean; outputFormat?: string; usage?: boolean }, command: Command) => {
|
|
607
|
+
.action(async (opts: { agent?: string; prompt?: string; promptFile?: string; out?: string; linearIssueId?: string; dryRun?: boolean; json?: boolean; outputFormat?: string; usage?: boolean }, command: Command) => {
|
|
473
608
|
if (opts.usage || command.optsWithGlobals().usage) { out({ json: true }, missionUsage.commands.run); return; }
|
|
474
609
|
if (!opts.agent) { error('--agent 는 필수입니다\n'); process.exitCode = 2; return; }
|
|
475
610
|
if (!opts.out) { error('--out 은 필수입니다\n'); process.exitCode = 2; return; }
|
|
@@ -485,9 +620,29 @@ export function registerMissionOutCommand(program: Command, deps: {
|
|
|
485
620
|
const store = await storeAt();
|
|
486
621
|
let record: MissionOutRecord | undefined;
|
|
487
622
|
try {
|
|
623
|
+
const linearLink = opts.linearIssueId
|
|
624
|
+
? await (await import('../intake-plane/linear-mission-sync.js')).resolveDemoLinearMissionLink(opts.linearIssueId)
|
|
625
|
+
: undefined;
|
|
488
626
|
const missionId = randomUUID();
|
|
489
627
|
const outputPath = `${targetOutputPath}.eln-mission-${missionId}.tmp`;
|
|
490
|
-
record = store.create({ missionId, agent: opts.agent as 'codex' | 'claude', prompt, cwd: process.cwd(), outputPath, targetOutputPath });
|
|
628
|
+
record = store.create({ missionId, agent: opts.agent as 'codex' | 'claude', prompt, cwd: process.cwd(), outputPath, targetOutputPath, ...(linearLink ? { linearLink } : {}) });
|
|
629
|
+
// Injected state roots are test fixtures: avoid discovering a global
|
|
630
|
+
// daemon whose state belongs to another instance. Production callers
|
|
631
|
+
// use effectiveInstanceRoot and resolve their registered NEXUS here.
|
|
632
|
+
const candidateNexusUrl = process.env.ELANOUS_NEXUS_URL?.trim() || deps.resolveNexusUrl?.()
|
|
633
|
+
|| (deps.stateRoot ? null : (await import('../nexus/daemon-endpoint.js')).resolveDaemonEndpoint()?.baseUrl);
|
|
634
|
+
let nexusUrl: string | null = null;
|
|
635
|
+
if (candidateNexusUrl) {
|
|
636
|
+
try {
|
|
637
|
+
const parsed = new URL(candidateNexusUrl);
|
|
638
|
+
if (parsed.protocol === 'http:' || parsed.protocol === 'https:') nexusUrl = parsed.origin;
|
|
639
|
+
} catch { /* invalid NEXUS configuration cannot receive a mission token */ }
|
|
640
|
+
}
|
|
641
|
+
const handLine = nexusUrl ? createMissionLineStore(await root()).issue({
|
|
642
|
+
missionId, attemptId: randomUUID(), agent: record.agent,
|
|
643
|
+
who: record.agent === 'claude' ? 'Claude' : 'Codex',
|
|
644
|
+
what: prompt.replace(/\s+/g, ' ').trim().slice(0, 180) || 'hand mission',
|
|
645
|
+
}) : undefined;
|
|
491
646
|
const { mkdirSync } = await import('node:fs');
|
|
492
647
|
mkdirSync(dirname(targetOutputPath), { recursive: true });
|
|
493
648
|
let workerPid: number;
|
|
@@ -498,7 +653,7 @@ export function registerMissionOutCommand(program: Command, deps: {
|
|
|
498
653
|
if (!entry) throw new Error('CLI 엔트리 경로를 확인할 수 없습니다');
|
|
499
654
|
const stateRoot = await root();
|
|
500
655
|
const child = spawn(process.execPath, [entry, 'mission', '__worker', record.missionId], {
|
|
501
|
-
cwd: record.cwd, detached: true, stdio: 'ignore', env: missionChildEnv(stateRoot, record.missionId),
|
|
656
|
+
cwd: record.cwd, detached: true, stdio: 'ignore', env: missionChildEnv(stateRoot, record.missionId, process.env, handLine && nexusUrl ? { ...handLine, agent: record.agent, nexusUrl } : undefined),
|
|
502
657
|
});
|
|
503
658
|
if (!child.pid) throw new Error('미션 워커 PID 생성 실패');
|
|
504
659
|
child.unref();
|
|
@@ -553,8 +708,9 @@ export function registerMissionOutCommand(program: Command, deps: {
|
|
|
553
708
|
.option('--scope <text>', 'Correction scope')
|
|
554
709
|
.option('--[no-]stop', 'Correction stop request')
|
|
555
710
|
.option('--priority <value>', 'Correction priority')
|
|
711
|
+
.option('--reply-to <sequence>', 'Ask sequence being answered/corrected')
|
|
556
712
|
.option('--json', 'Emit JSON').option('--output-format <format>', 'text or json', 'text')
|
|
557
|
-
.action(async (rawArgs: string[], opts: { mission?: string; done?: boolean; kind?: string; defaults?: string; deadline?: string; scope?: string; stop?: boolean; priority?: string; json?: boolean; outputFormat?: string; usage?: boolean }, command: Command) => {
|
|
713
|
+
.action(async (rawArgs: string[], opts: { mission?: string; done?: boolean; kind?: string; defaults?: string; deadline?: string; scope?: string; stop?: boolean; priority?: string; replyTo?: string; json?: boolean; outputFormat?: string; usage?: boolean }, command: Command) => {
|
|
558
714
|
if (opts.usage || command.optsWithGlobals().usage) { out({ json: true }, missionUsage.commands.reply); return; }
|
|
559
715
|
const args = [...rawArgs];
|
|
560
716
|
const missionId = opts.mission?.trim() || args.shift();
|
|
@@ -562,7 +718,85 @@ export function registerMissionOutCommand(program: Command, deps: {
|
|
|
562
718
|
let text = args.join(' ');
|
|
563
719
|
if (!text.trim()) text = await (deps.readStdin ?? (async () => (await import('../cli/piped-stdin.js')).readPipedStdin()))();
|
|
564
720
|
try {
|
|
565
|
-
|
|
721
|
+
if (opts.kind === 'ask' && !opts.defaults?.trim()) throw new Error('reply kind=ask 에는 --defaults 가 필요합니다');
|
|
722
|
+
const lineToken = process.env.ELANOUS_HAND_TOKEN?.trim();
|
|
723
|
+
const lineAttemptId = process.env.ELANOUS_HAND_ATTEMPT_ID?.trim();
|
|
724
|
+
const lineAgent = process.env.ELANOUS_HAND_AGENT === 'claude' ? 'claude' : process.env.ELANOUS_HAND_AGENT === 'codex' ? 'codex' : undefined;
|
|
725
|
+
if (lineToken && lineAttemptId && lineAgent) {
|
|
726
|
+
const replyTo = opts.replyTo === undefined ? undefined : Number(opts.replyTo);
|
|
727
|
+
if (opts.replyTo !== undefined && (!Number.isInteger(replyTo) || (replyTo ?? 0) < 1)) throw new Error('--reply-to 는 양의 정수여야 합니다');
|
|
728
|
+
if (opts.kind === 'correct' && (!opts.scope || opts.stop === undefined || !opts.priority)) {
|
|
729
|
+
throw new Error('reply kind=correct 에는 scope, stop, priority 가 필요합니다');
|
|
730
|
+
}
|
|
731
|
+
const lineId = randomUUID();
|
|
732
|
+
const lineType: NonNullable<MissionReplyMessageFields['lineType']> = opts.done
|
|
733
|
+
? 'final'
|
|
734
|
+
: opts.kind === 'ask' || opts.kind === 'answer' || opts.kind === 'correct' ? opts.kind : 'progress';
|
|
735
|
+
const fields: MissionReplyMessageFields & { lineId: string; attemptId: string; agent: 'codex' | 'claude'; lineType: MissionLineType; source: string } = {
|
|
736
|
+
lineId,
|
|
737
|
+
attemptId: lineAttemptId, agent: lineAgent,
|
|
738
|
+
...(process.env.ELANOUS_HAND_RUN_ID ? { runId: process.env.ELANOUS_HAND_RUN_ID } : {}),
|
|
739
|
+
...(process.env.ELANOUS_HAND_PTY_ID ? { ptyId: process.env.ELANOUS_HAND_PTY_ID } : {}),
|
|
740
|
+
...(replyTo ? { replyTo } : {}),
|
|
741
|
+
lineType,
|
|
742
|
+
source: 'mission-reply', ...(opts.done ? { state: 'completed' } : {}),
|
|
743
|
+
...(opts.kind !== undefined ? { kind: opts.kind } : {}),
|
|
744
|
+
...(opts.defaults !== undefined ? { defaults: opts.defaults } : {}),
|
|
745
|
+
...(opts.deadline !== undefined ? { deadline: opts.deadline } : {}),
|
|
746
|
+
...(opts.scope !== undefined ? { scope: opts.scope } : {}),
|
|
747
|
+
...(opts.stop !== undefined ? { stop: opts.stop } : {}),
|
|
748
|
+
...(opts.priority !== undefined ? { priority: opts.priority } : {}),
|
|
749
|
+
};
|
|
750
|
+
let event: MissionReplyEvent;
|
|
751
|
+
try {
|
|
752
|
+
const lineEvent = await postMissionLineEvent({
|
|
753
|
+
lineId, missionId, attemptId: lineAttemptId, agent: lineAgent,
|
|
754
|
+
...(process.env.ELANOUS_HAND_RUN_ID ? { runId: process.env.ELANOUS_HAND_RUN_ID } : {}),
|
|
755
|
+
...(process.env.ELANOUS_HAND_PTY_ID ? { ptyId: process.env.ELANOUS_HAND_PTY_ID } : {}),
|
|
756
|
+
...(replyTo ? { replyTo } : {}),
|
|
757
|
+
type: lineType, source: 'mission-reply', text, ...(opts.done ? { state: 'completed' } : {}),
|
|
758
|
+
...(opts.kind !== undefined ? { kind: opts.kind } : {}),
|
|
759
|
+
...(opts.defaults !== undefined ? { defaults: opts.defaults } : {}),
|
|
760
|
+
...(opts.deadline !== undefined ? { deadline: opts.deadline } : {}),
|
|
761
|
+
...(opts.scope !== undefined ? { scope: opts.scope } : {}),
|
|
762
|
+
...(opts.stop !== undefined ? { stop: opts.stop } : {}),
|
|
763
|
+
...(opts.priority !== undefined ? { priority: opts.priority } : {}),
|
|
764
|
+
});
|
|
765
|
+
event = {
|
|
766
|
+
type: 'mission.reply', missionId, sequence: lineEvent.sequence,
|
|
767
|
+
text: lineEvent.text, done: lineEvent.done, createdAt: lineEvent.createdAt,
|
|
768
|
+
...fields,
|
|
769
|
+
...(lineEvent.deadline ? { deadline: lineEvent.deadline } : {}),
|
|
770
|
+
};
|
|
771
|
+
} catch (error) {
|
|
772
|
+
if (error instanceof MissionLineHttpError && error.status < 500) throw error;
|
|
773
|
+
debug.log('agent-mission', 'line-ingress-fallback', { missionId, error: redactSecretText(String(error)) });
|
|
774
|
+
const replyStore = await replyStoreAt(missionId);
|
|
775
|
+
const persistedLine = replyStore.replies(missionId).find((reply) => reply.lineId === lineId);
|
|
776
|
+
if (persistedLine) event = persistedLine;
|
|
777
|
+
else {
|
|
778
|
+
const existingReplies = replyStore.replies(missionId);
|
|
779
|
+
const mission = replyStore.read(missionId);
|
|
780
|
+
event = await replyStore.reply(missionId, text, opts.done ?? false, {
|
|
781
|
+
...fields,
|
|
782
|
+
...(existingReplies.length === 0 && mission ? {
|
|
783
|
+
who: lineAgent === 'claude' ? 'Claude' : 'Codex',
|
|
784
|
+
what: mission.prompt.replace(/\s+/g, ' ').trim().slice(0, 180) || 'hand mission',
|
|
785
|
+
} : {}),
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
const linkedStore = await replyStoreAt(missionId);
|
|
790
|
+
await syncAcceptedLinearReply(linkedStore, missionId, event);
|
|
791
|
+
if (opts.kind === 'ask') {
|
|
792
|
+
const answerStore = await replyStoreAt(missionId);
|
|
793
|
+
const answer = await waitForMissionAnswer(answerStore, missionId, event, opts.defaults!);
|
|
794
|
+
out(opts, { missionId, accepted: true, sequence: event.sequence, done: event.done, answer: answer.text, usedDefault: answer.usedDefault });
|
|
795
|
+
} else out(opts, { missionId, accepted: true, sequence: event.sequence, done: event.done });
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
const replyStore = await replyStoreAt(missionId);
|
|
799
|
+
const event = await replyStore.reply(missionId, text, opts.done ?? false, {
|
|
566
800
|
...(opts.kind !== undefined ? { kind: opts.kind } : {}),
|
|
567
801
|
...(opts.defaults !== undefined ? { defaults: opts.defaults } : {}),
|
|
568
802
|
...(opts.deadline !== undefined ? { deadline: opts.deadline } : {}),
|
|
@@ -570,7 +804,11 @@ export function registerMissionOutCommand(program: Command, deps: {
|
|
|
570
804
|
...(opts.stop !== undefined ? { stop: opts.stop } : {}),
|
|
571
805
|
...(opts.priority !== undefined ? { priority: opts.priority } : {}),
|
|
572
806
|
});
|
|
573
|
-
|
|
807
|
+
await syncAcceptedLinearReply(replyStore, missionId, event);
|
|
808
|
+
if (opts.kind === 'ask') {
|
|
809
|
+
const answer = await waitForMissionAnswer(replyStore, missionId, event, opts.defaults!);
|
|
810
|
+
out(opts, { missionId, accepted: true, sequence: event.sequence, done: event.done, answer: answer.text, usedDefault: answer.usedDefault });
|
|
811
|
+
} else out(opts, { missionId, accepted: true, sequence: event.sequence, done: event.done });
|
|
574
812
|
} catch (e) { error(`${String(e)}\n`); process.exitCode = 1; }
|
|
575
813
|
});
|
|
576
814
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process';
|
|
1
|
+
import { spawn, spawnSync, type ChildProcess } from 'node:child_process';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import { existsSync, mkdtempSync, rmSync } from 'node:fs';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
@@ -33,20 +33,131 @@ export type AgentCliDetection = {
|
|
|
33
33
|
agent: AgentCli;
|
|
34
34
|
/** null means the executable/version probe could not establish installation state. */
|
|
35
35
|
installed: boolean | null;
|
|
36
|
+
/** Sanitized semantic version only; raw CLI output is never exposed. */
|
|
37
|
+
version?: string;
|
|
36
38
|
executable: 'present' | 'missing' | 'unknown';
|
|
37
39
|
login: 'ready' | 'needed' | 'api-key' | 'unknown';
|
|
38
40
|
message: string;
|
|
39
41
|
};
|
|
40
42
|
|
|
43
|
+
/** The supported, non-privileged installer for each visible coding CLI. */
|
|
44
|
+
export const AGENT_CLI_INSTALLERS: Record<AgentCli, { command: string; args: string[]; display: string }> = {
|
|
45
|
+
codex: { command: 'npm', args: ['install', '-g', '@openai/codex@latest'], display: 'npm install -g @openai/codex@latest' },
|
|
46
|
+
claude: { command: 'npm', args: ['install', '-g', '@anthropic-ai/claude-code'], display: 'npm install -g @anthropic-ai/claude-code' },
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type AgentCliPreparation = {
|
|
50
|
+
ready: boolean;
|
|
51
|
+
detection: AgentCliDetection;
|
|
52
|
+
installation: 'not-needed' | 'declined' | 'installed' | 'failed';
|
|
53
|
+
message: string;
|
|
54
|
+
};
|
|
55
|
+
|
|
41
56
|
type AgentCliRunner = (command: string, args: string[], options: {
|
|
42
57
|
encoding: 'utf8'; timeout: number; env: Record<string, string>;
|
|
43
58
|
}) => ReturnType<typeof spawnSync>;
|
|
44
59
|
|
|
45
|
-
|
|
60
|
+
export interface AgentCliPreparationDeps {
|
|
61
|
+
env?: Record<string, string | undefined>;
|
|
62
|
+
detect?: (agent: AgentCli, options: { env: Record<string, string | undefined>; runCli?: AgentCliRunner }) => AgentCliDetection;
|
|
63
|
+
runCli?: AgentCliRunner;
|
|
64
|
+
/** Must be an explicit user confirmation; no installer runs when it is absent or declines. */
|
|
65
|
+
confirmInstall?: (prompt: string) => boolean | Promise<boolean>;
|
|
66
|
+
/** Injection seam for tests. Production runs npm only after confirmInstall returns true. */
|
|
67
|
+
install?: (command: string, args: string[], options: { env: Record<string, string>; timeoutMs: number }) => { status: number | null; error?: { code?: string } | null } | Promise<{ status: number | null; error?: { code?: string } | null }>;
|
|
68
|
+
onStatus?: (line: string) => void;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function runAgentCliInstaller(command: string, args: string[], options: { env: Record<string, string>; timeoutMs: number }): Promise<{ status: number | null; error?: { code?: string } | null }> {
|
|
72
|
+
return new Promise((resolve) => {
|
|
73
|
+
const spawnInstaller = spawn as unknown as (file: string, args: string[], options: { env: Record<string, string>; stdio: 'ignore'; windowsHide: true }) => ChildProcess;
|
|
74
|
+
const child = spawnInstaller(command, args, { env: options.env, stdio: 'ignore', windowsHide: true });
|
|
75
|
+
let settled = false;
|
|
76
|
+
let timedOut = false;
|
|
77
|
+
let forceKill: ReturnType<typeof setTimeout> | undefined;
|
|
78
|
+
const timeout = setTimeout(() => {
|
|
79
|
+
timedOut = true;
|
|
80
|
+
child.kill('SIGTERM');
|
|
81
|
+
forceKill = setTimeout(() => child.kill('SIGKILL'), 2_000);
|
|
82
|
+
}, options.timeoutMs);
|
|
83
|
+
const finish = (result: { status: number | null; error?: { code?: string } | null }): void => {
|
|
84
|
+
if (settled) return;
|
|
85
|
+
settled = true;
|
|
86
|
+
clearTimeout(timeout);
|
|
87
|
+
if (forceKill) clearTimeout(forceKill);
|
|
88
|
+
resolve(result);
|
|
89
|
+
};
|
|
90
|
+
child.once('error', (error: Error & { code?: string }) => finish({ status: null, error }));
|
|
91
|
+
child.once('close', (status: number | null) => finish(timedOut
|
|
92
|
+
? { status: null, error: { code: 'ETIMEDOUT' } }
|
|
93
|
+
: { status }));
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function agentCliNotReadyMessage(detection: AgentCliDetection): string {
|
|
98
|
+
if (detection.installed === false) return `${detection.agent}: 설치되지 않음`;
|
|
99
|
+
if (detection.installed === null) return `${detection.agent}: 설치 상태 확인 불가`;
|
|
100
|
+
if (detection.login === 'api-key') return `${detection.agent}: API 키 인증은 감지했지만 구독 로그인이 필요합니다. ${detection.agent} login을 실행해 주세요`;
|
|
101
|
+
if (detection.login === 'needed') return `${detection.agent}: 로그인이 필요합니다. ${detection.agent} login을 실행해 주세요`;
|
|
102
|
+
return `${detection.agent}: 로그인 상태를 확인할 수 없습니다`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Detect first, ask once before an official install, then re-detect before the caller launches. */
|
|
106
|
+
export async function prepareAgentCli(
|
|
107
|
+
agent: AgentCli,
|
|
108
|
+
deps: AgentCliPreparationDeps = {},
|
|
109
|
+
): Promise<AgentCliPreparation> {
|
|
110
|
+
const env = deps.env ?? process.env;
|
|
111
|
+
const detect = deps.detect ?? detectAgentCli;
|
|
112
|
+
const detectOptions = { env, ...(deps.runCli ? { runCli: deps.runCli } : {}) };
|
|
113
|
+
const installer = AGENT_CLI_INSTALLERS[agent];
|
|
114
|
+
let detection = detect(agent, detectOptions);
|
|
115
|
+
deps.onStatus?.(detection.message);
|
|
116
|
+
if (detection.installed === true && detection.login === 'ready') {
|
|
117
|
+
return { ready: true, detection, installation: 'not-needed', message: detection.message };
|
|
118
|
+
}
|
|
119
|
+
if (detection.installed !== false) {
|
|
120
|
+
return { ready: false, detection, installation: 'not-needed', message: agentCliNotReadyMessage(detection) };
|
|
121
|
+
}
|
|
122
|
+
if (!deps.confirmInstall || !await deps.confirmInstall(`설치할까요? ${installer.display}`)) {
|
|
123
|
+
return { ready: false, detection, installation: 'declined', message: `${agent}: 설치를 건너뛰었습니다` };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const install = deps.install ?? runAgentCliInstaller;
|
|
127
|
+
let result: { status: number | null; error?: { code?: string } | null };
|
|
128
|
+
try {
|
|
129
|
+
const backend = agent === 'codex' ? codexBackend : claudeBackend;
|
|
130
|
+
result = await install(installer.command, [...installer.args], {
|
|
131
|
+
env: resolveBackendSpawn(backend, env).env,
|
|
132
|
+
timeoutMs: 300_000,
|
|
133
|
+
});
|
|
134
|
+
} catch {
|
|
135
|
+
return { ready: false, detection, installation: 'failed', message: `${agent}: 설치 명령을 실행하지 못했습니다` };
|
|
136
|
+
}
|
|
137
|
+
if (result.status !== 0) {
|
|
138
|
+
const detail = result.error?.code === 'ENOENT' ? 'npm을 찾을 수 없습니다' : '설치 명령이 성공하지 않았습니다';
|
|
139
|
+
return { ready: false, detection, installation: 'failed', message: `${agent}: ${detail}` };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
detection = detect(agent, detectOptions);
|
|
143
|
+
deps.onStatus?.(detection.message);
|
|
144
|
+
if (detection.installed !== true) {
|
|
145
|
+
return { ready: false, detection, installation: 'failed', message: `${agent}: 설치 뒤 버전 확인에 실패했습니다` };
|
|
146
|
+
}
|
|
147
|
+
if (detection.login !== 'ready') {
|
|
148
|
+
return { ready: false, detection, installation: 'installed', message: agentCliNotReadyMessage(detection) };
|
|
149
|
+
}
|
|
150
|
+
return { ready: true, detection, installation: 'installed', message: detection.message };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function agentVersion(agent: AgentCli, raw: string): { version?: string } | undefined {
|
|
46
154
|
const prefix = agent === 'claude' ? /^(?:Claude(?: Code)?\s+)?v?/i : /^(?:Codex(?:-CLI)?\s+)?v?/i;
|
|
47
155
|
const versioned = raw.replace(prefix, '');
|
|
48
|
-
// Probe output is untrusted: validate
|
|
49
|
-
|
|
156
|
+
// Probe output is untrusted: validate the semver shape but expose only a bounded numeric core.
|
|
157
|
+
const match = /^(\d+\.\d+\.\d+)(?:[-+][A-Za-z0-9.-]{1,40})?(?: \(Claude Code\))?$/i.exec(versioned);
|
|
158
|
+
if (!match) return undefined;
|
|
159
|
+
const parts = match[1]!.split('.');
|
|
160
|
+
return parts.every((part) => part.length <= 6) ? { version: match[1]! } : undefined;
|
|
50
161
|
}
|
|
51
162
|
|
|
52
163
|
function agentExecutableExists(command: string, env: Record<string, string>): boolean {
|
|
@@ -79,8 +190,8 @@ export function detectAgentCli(
|
|
|
79
190
|
return { agent, installed: present ? null : false, executable: present ? 'unknown' : 'missing', login: 'unknown', message: present ? `${agent}: 실행 파일을 실행할 수 없어 상태 확인 불가` : `${agent}: 설치되지 않음` };
|
|
80
191
|
}
|
|
81
192
|
const rawVersion = `${versionResult.stdout ?? ''}\n${versionResult.stderr ?? ''}`.trim().split(/\r?\n/, 1)[0] ?? '';
|
|
82
|
-
const
|
|
83
|
-
if (!
|
|
193
|
+
const verifiedVersion = versionResult.status === 0 ? agentVersion(agent, rawVersion) : undefined;
|
|
194
|
+
if (!verifiedVersion) {
|
|
84
195
|
const executable = versionResult.status === null || versionResult.error ? 'unknown' : 'present';
|
|
85
196
|
return {
|
|
86
197
|
agent, installed: null, executable, login: 'unknown',
|
|
@@ -103,13 +214,13 @@ export function detectAgentCli(
|
|
|
103
214
|
} catch { /* Keep authentication unknown when the probe itself fails. */ }
|
|
104
215
|
}
|
|
105
216
|
const message = login === 'ready'
|
|
106
|
-
? `${agent}:
|
|
217
|
+
? `${agent}: 설치됨${verifiedVersion.version ? ` v${verifiedVersion.version}` : ''} · 로그인 확인됨`
|
|
107
218
|
: login === 'api-key'
|
|
108
|
-
? `${agent}: API 키 로그인됨 (구독 로그인 아님)`
|
|
219
|
+
? `${agent}: 설치됨${verifiedVersion.version ? ` v${verifiedVersion.version}` : ''} · API 키 로그인됨 (구독 로그인 아님)`
|
|
109
220
|
: login === 'needed'
|
|
110
|
-
? `${agent}:
|
|
111
|
-
: `${agent}:
|
|
112
|
-
return { agent, installed: true, executable: 'present', login, message };
|
|
221
|
+
? `${agent}: 설치됨${verifiedVersion.version ? ` v${verifiedVersion.version}` : ''} · 로그인 필요`
|
|
222
|
+
: `${agent}: 설치됨${verifiedVersion.version ? ` v${verifiedVersion.version}` : ''} · 로그인 상태 확인 불가`;
|
|
223
|
+
return { agent, installed: true, ...(verifiedVersion.version ? { version: verifiedVersion.version } : {}), executable: 'present', login, message };
|
|
113
224
|
}
|
|
114
225
|
|
|
115
226
|
function defaultExec(cmd: string[], opts: { stdin?: string; timeoutMs: number }): ExecResult {
|
|
@@ -8,7 +8,7 @@ You are a sub-agent spawned by a parent task. The parent has delegated a focused
|
|
|
8
8
|
|
|
9
9
|
## What you have
|
|
10
10
|
- A task description (the `prompt` argument the parent sent)
|
|
11
|
-
-
|
|
11
|
+
- Use the exact tool catalog supplied to this child. Standard CLI defaults are Bash, Read, Edit, Grep, and WebFetch; the TUI may provide a wider policy-filtered catalog.
|
|
12
12
|
- Your own context window — what you read here does not pollute the parent's
|
|
13
13
|
|
|
14
14
|
## What you owe back
|