elanous 0.2.41 → 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/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{2fe2c302.41b517f88d6fe502.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{385e4574.e9886ab32759eda3.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/{6874.d5cf7eb8edb2cabe.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/{5744.b9415e18ad623100.js → 1961.a81b12872c3e93a9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1970cf59.2d4d8ce5d6c81853.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2073-ba274e00e4f9efb4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5471.1e611302ed3a7c53.js → 2144.25b292396712196d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{3230-49298c3b73ef2268.js → 2268-53861f339e0b65a2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9834.63ab2bbc3153172e.js → 2312.0c8b61e22d3136d7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1800.f7ff51dc4978a958.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/{9048.212083de42d25be3.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/3095.dc44586a5f83b86d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2263.e09b6edea33bad2d.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/{addc2b32.8c4ff8f0aefe987d.js → 3557ac4a.c8931684475018ad.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/360.ae9f9f4c33c395e8.js +79 -0
- package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
- package/apps/pwa/out/_next/static/chunks/{a0a01613.6d1cca322238d7fe.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/4199.ce86b281fd0a60b7.js +1 -0
- 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/{530.d26346e18089640a.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/4894.fec2ca9e99caefa2.js +1 -0
- 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/{1219.7e17964e0e7cd8e5.js → 5564.9e72532188f57586.js} +3 -3
- 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/5628.6ddb2d5ffba4ff4c.js +309 -0
- package/apps/pwa/out/_next/static/chunks/5730.43d7ccc09988e646.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1178.1aa9cad0e7695427.js → 5789.2da35c258292e1e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4133.2056bb4d78f621af.js → 5824.da9527b15a3221e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4527.a69f2894d1bc9f4a.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/{9507.7026657a2f47eb64.js → 6540.c7bef57ad8f90a87.js} +16 -16
- 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/{5574.f35accf4f132b29d.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/7483.427a2fe2049e388d.js +148 -0
- package/apps/pwa/out/_next/static/chunks/7502-be74718178e13e56.js +1 -0
- 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/{5947-135e26537d80a6b9.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/{2743.5d3f76948be32b34.js → 868.6e953be05bcf6dca.js} +2 -2
- 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/{5964-7e21164a8f2cf0ce.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8967-7dfebf710c9dec9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5159.115f1c2ca471386c.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/923.2034d10ae91e9c20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
- package/apps/pwa/out/_next/static/chunks/943.39ae5e82f4f1893f.js +1 -0
- 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/{b2271e54.c1de3347976e90b0.js → aa57532f.510551854ff239b1.js} +1 -1
- 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-9ee28f7df07428ea.js +1 -0
- 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-40f9e19149024298.js → page-79a8b5fee4c20871.js} +1 -1
- 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-a142dfb0331a05f5.js → page-ca2d09128c585ca4.js} +1 -1
- 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/{53aeb4ee-51c92f8d683f5220.js → c7945435-b44d4dbe90ba0dcb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2fdf2931.b431eee4fb468bc3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{c0c1a699.0ba79f97005965d4.js → d96660fb.cbc21a2a88539dbb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/ea514caa.05a24f78d9dffe5f.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{83184dcd-0ee6247ff41eb3f2.js → fb7d20d5-6892502b6ee39ca6.js} +1 -1
- 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/{b9d8151e48998417.css → 62c858ad53854f47.css} +1 -1
- 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 +24 -25
- 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 +23 -23
- 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 +24 -25
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +24 -25
- 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/docs/goal-context/04-mock-scenarios.md +13 -0
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/heal/heal-loop.yaml +1 -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/overlays/stop-heal-ladder.yaml +113 -0
- package/graphs/profiles/local.yaml +5 -0
- package/graphs/profiles/pod.yaml +4 -0
- package/graphs/units/verbs/recipes.yaml +11 -11
- package/graphs/work/research-report.yaml +10 -2
- 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/heal/run-role.ts +99 -5
- package/scripts/hooks/codex-notify.sh +32 -0
- package/scripts/install.sh +10 -38
- package/scripts/land-global-checks.ts +6 -1
- package/scripts/landing-heal/land-plan.ts +57 -0
- package/scripts/lib/decompose-ab.ts +1 -0
- package/scripts/lib/fixtures/tui-regress/help-insufficient-commands.txt +15 -0
- package/scripts/lib/fixtures/tui-regress/help-live.txt +42 -0
- package/scripts/lib/fixtures/tui-regress/help-missing-keys.txt +21 -0
- package/scripts/lib/fixtures/tui-regress/help-original.txt +51 -0
- package/scripts/lib/fixtures/tui-regress/help-shifted-input.txt +26 -0
- package/scripts/lib/tui-regress-checks.ts +33 -13
- 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-baseline-receipt.ts +47 -9
- package/scripts/release-loop/gate-image-pin.ts +81 -0
- package/scripts/release-loop/gate-method.ts +139 -0
- package/scripts/release-loop/gate-node-sim.ts +207 -0
- package/scripts/release-loop/gate-node.ts +463 -64
- package/scripts/release-loop/gate-pod-image-sticky-plan.ts +99 -0
- package/scripts/release-loop/gate-radius-live.ts +97 -13
- package/scripts/release-loop/gate-shard-dispatch.ts +43 -0
- package/scripts/release-loop/gate-traffic-mode.ts +151 -3
- package/scripts/release-loop/gate-train-receipts.ts +122 -0
- package/scripts/release-loop/node-verdict.ts +38 -25
- package/scripts/release-loop/preflight.ts +362 -8
- package/scripts/release-loop/resume-release.ts +83 -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/ux-sim.ts +18 -1
- package/scripts/video-pipeline.ts +9 -1
- package/scripts/warm-pool-provider-config.ts +286 -0
- package/skills/omni-crawl/SKILL.md +5 -2
- package/skills/omni-crawl/scripts/main.ts +84 -23
- 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 +27 -9
- package/src/acp/event-router.ts +20 -1
- package/src/acp/server.ts +6 -0
- package/src/agent/registry.ts +2 -0
- package/src/agent/task-notification.ts +25 -5
- package/src/agent/types.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 +63 -4
- 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 +833 -0
- package/src/agent-mission/tool-install.ts +200 -3
- package/src/agent-substrate/context-strategy.ts +4 -4
- package/src/agent-substrate/self-review-cli.ts +178 -13
- package/src/agents/general-purpose.md +1 -1
- package/src/auto-research/research-turn.ts +211 -53
- package/src/autopilot/pr-manager.ts +69 -10
- package/src/autopilot/pty-control-loop.ts +2 -0
- 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/capture/tui-self-report.ts +22 -6
- package/src/chat/index.ts +1 -1
- 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/fixtures/review-loop-breaker/opwaiver-32646-1694ccc7a170.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-32853-bd8f73595c83.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-33097-1cc85900413c.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-33106-972f31e4a3ca.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-33113-3ab51f05968f.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/pr-33097-1cc85900413c.json +1 -0
- 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 +75 -5
- package/src/cli/pr-land-overlap-evidence.ts +113 -2
- package/src/cli/pr-land-pod-shadow-job.ts +202 -4
- package/src/cli/pr-land-pod-shadow.ts +9 -2
- package/src/cli/release-checklist-read-cli.ts +57 -19
- package/src/cli/release-cli.ts +23 -3
- package/src/cli/research-cli.ts +13 -5
- 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 +61 -9
- package/src/cli/tui-test-cli.ts +186 -0
- package/src/compact/auto.ts +8 -1
- 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/control-plane/ledger.ts +52 -2
- package/src/control-plane/server.ts +16 -2
- 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 +606 -95
- package/src/core-turn/run-goal-loop.ts +18 -0
- package/src/core-turn/types.ts +4 -0
- package/src/dashboard/chat/acp-chat.ts +10 -0
- package/src/dashboard/classic-sidetab-mission-job.ts +161 -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 +347 -0
- package/src/dashboard/index.ts +517 -18
- package/src/dashboard/input/agent-wake.ts +23 -1
- package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +17 -0
- package/src/dashboard/mission-cli-consumer.ts +165 -0
- package/src/dashboard/plugin-wizard-runtime.ts +50 -0
- package/src/dashboard/plugin-wizard-tool.ts +55 -0
- package/src/dashboard/seat-boot-preamble.ts +171 -1
- package/src/dashboard/side-basic-runtime.ts +54 -1
- package/src/dashboard/sidetab-runtime.ts +90 -1
- package/src/dashboard/skill-catalog-preamble.ts +101 -0
- package/src/dashboard/skill-detection-runtime.ts +55 -15
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +15 -0
- package/src/dashboard/terminal-popup-runtime.ts +6 -3
- package/src/dashboard/turn-preamble.ts +53 -15
- package/src/dashboard/turn-prompt-runtime.ts +4 -2
- 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-cli.ts +23 -7
- package/src/graph-runner/graph-run-api.ts +3 -1
- package/src/graph-runner/graph-tick.ts +10 -2
- package/src/graph-runner/runner.ts +86 -18
- package/src/graph-wizard/mission-compose.ts +407 -12
- package/src/grok/agent-search.ts +14 -4
- package/src/grok/credential.ts +28 -11
- 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/harness-pod-dispatch.ts +81 -15
- package/src/harness/harness-stop.ts +155 -11
- 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 +159 -13
- package/src/instance/spawn-elanous.ts +6 -4
- 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 +168 -9
- package/src/loops/orchestrator/coordinator-shadow.ts +226 -0
- package/src/loops/orchestrator/tick.ts +13 -0
- package/src/maturity/feature-maturity.ts +4 -4
- package/src/msg/msg-sse-server.ts +3 -3
- package/src/msg/msg-store.ts +177 -19
- package/src/native-tool-catalog.ts +38 -4
- package/src/nexus/api/harness-traversal.ts +11 -0
- 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 +133 -2
- package/src/pty-shell/pty-control-ipc.ts +4 -1
- package/src/pty-shell/tui-run-state.ts +188 -2
- package/src/registry/catalog-server.ts +232 -0
- package/src/registry/loader.ts +45 -1
- package/src/registry/types.ts +1 -2
- package/src/release-loop/checklist-target-path-hint.ts +13 -0
- package/src/release-loop/checklist.ts +9 -1
- package/src/repl/index.ts +43 -2
- package/src/research/axis-fanout.ts +136 -16
- package/src/research/bloom-exemplars.ts +3 -1
- package/src/research/gap-followup.ts +13 -1
- package/src/research/plugin-discovery.ts +36 -14
- package/src/research-bridge/invoke.ts +22 -5
- package/src/research-bridge/types.ts +2 -0
- package/src/self-dev/ask-launch-flow.ts +72 -1
- package/src/self-dev/decompose.ts +119 -5
- 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-text.ts +5 -6
- package/src/self-dev/launch-preflight.ts +58 -0
- package/src/self-dev/orchestrate.ts +13 -3
- package/src/self-dev/review-provider-fallback.ts +9 -2
- package/src/self-dev/run-supervisor.ts +42 -4
- package/src/self-dev/run-types.ts +4 -0
- 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 +118 -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 +684 -7
- package/src/self-implement/graph-overlay-yaml.ts +37 -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/headless-elanous-driver.ts +31 -2
- package/src/self-implement/heal-intake.ts +112 -4
- package/src/self-implement/heal-triage.ts +20 -0
- package/src/self-implement/host-regate.ts +27 -4
- package/src/self-implement/merge-train.ts +5 -0
- package/src/self-implement/off-diff-evidence.ts +249 -5
- package/src/self-implement/orchestrator.ts +365 -25
- package/src/self-implement/regate-detail.ts +38 -1
- package/src/self-implement/rework-child-provider.ts +25 -0
- package/src/self-implement/run-chart.ts +122 -0
- package/src/self-implement/run-ledger.ts +162 -11
- package/src/self-implement/run-stop.ts +188 -4
- package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
- package/src/self-implement/stop-autoheal.ts +13 -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 +40 -4
- 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 +135 -5
- package/src/session-runtime/retry-policy.ts +1 -1
- package/src/session-runtime/tier-flip.ts +3 -3
- 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/model.ts +19 -5
- package/src/sidetab-core/visible-agent-mission.ts +262 -0
- package/src/skills/name-match.ts +20 -0
- package/src/skills/tools/agent.ts +53 -6
- package/src/skills/tools/omni-search.ts +173 -13
- package/src/task-agent/parent-host.ts +10 -0
- package/src/task-agent/pod-distributor-entry.ts +3 -0
- package/src/task-agent/repair-outcomes.ts +65 -0
- package/src/task-agent/task-hand.ts +47 -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-distributor.ts +48 -0
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +92 -1
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +38 -1
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
- package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +33 -6
- package/src/task-orchestrator/surfaces/pod-source-bundle.ts +45 -9
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +178 -16
- package/src/task-orchestrator/surfaces/pod-source-spec.ts +3 -3
- package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +237 -41
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +80 -3
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +337 -51
- 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/tokens.ts +35 -2
- package/src/tool-hints/gate.ts +1 -0
- package/src/tool-runtime/agent-runtime.ts +2 -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/elanous-skills-list-runtime.ts +5 -1
- package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
- package/src/tool-runtime/index.ts +6 -0
- package/src/tool-runtime/skill-exec-runtime.ts +33 -13
- package/src/tool-runtime/types.ts +4 -0
- package/src/tui/entry.ts +38 -5
- package/src/tui/sidetab/attach.ts +177 -1
- package/src/tui/sidetab/herdr-portal.ts +225 -0
- package/src/tui-client/local-chat-turn.ts +26 -13
- package/src/tui.ts +22 -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-kubectl.ts +37 -3
- package/src/ux-sim/fake-linear-device.ts +31 -0
- package/src/ux-sim/fault-pool-cap.ts +11 -6
- 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 +93 -0
- package/src/ux-sim/mock-scenario-catalog.ts +274 -0
- package/src/ux-sim/onboarding-first-run-device.ts +31 -21
- package/src/ux-sim/scenario.ts +185 -48
- 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/voice/voice-tts-singleton.ts +18 -3
- package/src/web-search/exa.ts +77 -0
- package/src/web-search/grok.ts +5 -9
- 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/1115.434ae2ecb0ad986d.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +0 -36
- package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +0 -90
- package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1765.679b29625c8e88d4.js +0 -77
- package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +0 -1
- package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +0 -32
- package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +0 -79
- package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +0 -148
- package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +0 -226
- package/apps/pwa/out/_next/static/chunks/4667.97e31aa38c95c475.js +0 -309
- package/apps/pwa/out/_next/static/chunks/4702.4a4adc1f16d7c93b.js +0 -64
- package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +0 -94
- package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +0 -8
- package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +0 -24
- package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +0 -286
- package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +0 -62
- package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +0 -122
- package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7191.fdc955f7d96064a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8050-9b364bdef8f71927.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +0 -104
- package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +0 -93
- package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +0 -34
- package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-14949db884bfa672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +0 -1
- package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
- package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +0 -1
- /package/apps/pwa/out/_next/static/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
package/src/compact/auto.ts
CHANGED
|
@@ -31,8 +31,15 @@ export function shouldAutoCompact(
|
|
|
31
31
|
messages: MessageLike[],
|
|
32
32
|
modelId: string | undefined,
|
|
33
33
|
config: ChatAutoCompactConfig,
|
|
34
|
+
observedInputTokens?: number,
|
|
34
35
|
): AutoCompactDecision {
|
|
35
|
-
const
|
|
36
|
+
const hasObservedInputTokens = typeof observedInputTokens === 'number'
|
|
37
|
+
&& Number.isFinite(observedInputTokens)
|
|
38
|
+
&& observedInputTokens >= 0;
|
|
39
|
+
const estimatedTokens = estimateMessagesTokens(messages);
|
|
40
|
+
// Provider usage captures model/tokenizer overhead; current history also
|
|
41
|
+
// includes tool output appended since that provider response.
|
|
42
|
+
const usedTokens = hasObservedInputTokens ? Math.max(observedInputTokens, estimatedTokens) : estimatedTokens;
|
|
36
43
|
const windowTokens = resolveModelContextWindow(modelId) ?? inferContextWindow(modelId);
|
|
37
44
|
const configuredBudget = config.workingBudgetTokens;
|
|
38
45
|
const budgetTokens = typeof configuredBudget === 'number'
|
package/src/config.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { listSshHosts } from './ssh/ssh-hosts.js';
|
|
|
7
7
|
import { isInstalledPackagePath } from './instance/installed-package.js';
|
|
8
8
|
import { defaultObsidianVault } from './obsidian/default-vault.js';
|
|
9
9
|
import { OPENGATEWAY_DEFAULT_MODEL } from './llm/opengateway-models.js';
|
|
10
|
+
import { SERVICE_KEY_CATALOG } from './setup/service-key-catalog.js';
|
|
10
11
|
|
|
11
12
|
// ── User config ──
|
|
12
13
|
export const REMOTE_HOME = homedir();
|
|
@@ -191,10 +192,11 @@ export function refreshKeyFromCache(envName: string): boolean {
|
|
|
191
192
|
* (음성 STT/TTS 등) plist 에서 키만 빼면 조용히 죽는다 ⇒ 부팅 한 곳에서 캐시를 env 에 싣는다(규약 = 캐시 우선 · ⓐⓑ 동일).
|
|
192
193
|
* 자식 프로세스도 이 env 를 물려받는다. 반환 = 캐시로 채운 이름(값은 절대 안 싣는다).
|
|
193
194
|
*/
|
|
194
|
-
export const DAEMON_KEY_ENV_NAMES = [
|
|
195
|
+
export const DAEMON_KEY_ENV_NAMES = [...new Set([
|
|
195
196
|
'ANTHROPIC_API_KEY', 'GEMINI_API_KEY', 'OPENAI_API_KEY', 'XAI_API_KEY', 'OPENROUTER_API_KEY', 'OPENGATEWAY_API_KEY',
|
|
196
197
|
'ELANOUS_OPENAI_RELAY_SHARED_SECRET',
|
|
197
|
-
|
|
198
|
+
...SERVICE_KEY_CATALOG.flatMap(item => item.envNames),
|
|
199
|
+
])];
|
|
198
200
|
|
|
199
201
|
export function hydrateEnvFromKeyCache(names: readonly string[] = DAEMON_KEY_ENV_NAMES, env: NodeJS.ProcessEnv = process.env): string[] {
|
|
200
202
|
const filled: string[] = [];
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { closeSync, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { elanousStateRoot } from '../autopilot/state-paths.js';
|
|
5
|
+
import { getSecretAsync } from '../nexus/config/secrets/index.js';
|
|
6
|
+
import { debug } from '../debug/log.js';
|
|
7
|
+
import { listChecklist, checklistHistory, checklistDevVersion, type Checklist, type ChecklistHistory } from '../release-loop/checklist.js';
|
|
8
|
+
import { DecisionLedger, type DecisionEntry } from '../decisions/decision-ledger.js';
|
|
9
|
+
import { commentLinearIssue } from './linear.js';
|
|
10
|
+
|
|
11
|
+
const ISSUE_REF = /\bELA-\d+\b/g;
|
|
12
|
+
const BODY_MARKER = '<!-- elanous-daily-progress:';
|
|
13
|
+
const WAIT = new Int32Array(new SharedArrayBuffer(4));
|
|
14
|
+
|
|
15
|
+
export interface LinearDailyProgressSummary {
|
|
16
|
+
identifier: string;
|
|
17
|
+
day: string;
|
|
18
|
+
body: string;
|
|
19
|
+
contentHash: string;
|
|
20
|
+
}
|
|
21
|
+
export interface LinearDailyProgressResult {
|
|
22
|
+
posted: number;
|
|
23
|
+
skipped: number;
|
|
24
|
+
failed: number;
|
|
25
|
+
dryRun: boolean;
|
|
26
|
+
plan: Array<{ identifier: string; day: string; contentHash: string; body: string; status: 'dry-run' | 'posted' | 'duplicate' | 'failed' }>;
|
|
27
|
+
}
|
|
28
|
+
export interface LinearDailyProgressDeps {
|
|
29
|
+
version?: string;
|
|
30
|
+
checklist?: Checklist;
|
|
31
|
+
history?: (id: string) => ChecklistHistory[];
|
|
32
|
+
decisions?: DecisionEntry[];
|
|
33
|
+
now?: Date;
|
|
34
|
+
apiKey?: string;
|
|
35
|
+
getSecret?: (id: string) => Promise<string | undefined>;
|
|
36
|
+
fetch?: typeof fetch;
|
|
37
|
+
stateDir?: string;
|
|
38
|
+
dryRun?: boolean;
|
|
39
|
+
log?: typeof debug.log;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function refsIn(...values: unknown[]): string[] {
|
|
43
|
+
const found = new Set<string>();
|
|
44
|
+
for (const value of values) {
|
|
45
|
+
const text = typeof value === 'string' ? value : value == null ? '' : JSON.stringify(value);
|
|
46
|
+
for (const match of text.matchAll(ISSUE_REF)) found.add(match[0]);
|
|
47
|
+
}
|
|
48
|
+
return [...found];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function cleanTitle(value: string): string {
|
|
52
|
+
return value.replace(/[\r\n\t]+/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 180);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function prLinks(value: unknown): string[] {
|
|
56
|
+
if (typeof value !== 'string') return [];
|
|
57
|
+
return [...new Set(value.match(/https:\/\/github\.com\/[^\s)]+\/pull\/\d+|\bPR\s*#\d+\b/gi) ?? [])];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Build public-safe daily summaries from checklist and decision ledgers. Bodies contain titles, states and links only. */
|
|
61
|
+
export function buildLinearDailyProgressSummaries({ checklist, history = checklistHistory, decisions, now = new Date() }: {
|
|
62
|
+
checklist?: Checklist; history?: (id: string) => ChecklistHistory[]; decisions: DecisionEntry[]; now?: Date;
|
|
63
|
+
}): LinearDailyProgressSummary[] {
|
|
64
|
+
if (!checklist) throw new Error('checklist snapshot is required');
|
|
65
|
+
if (!Number.isFinite(now.getTime())) throw new Error('valid summary date is required');
|
|
66
|
+
const day = now.toISOString().slice(0, 10);
|
|
67
|
+
const start = Date.parse(`${day}T00:00:00.000Z`);
|
|
68
|
+
const end = start + 86_400_000;
|
|
69
|
+
const issueIds = new Set<string>();
|
|
70
|
+
const itemRefs = new Map<string, Set<string>>();
|
|
71
|
+
const changed = new Map<string, ChecklistHistory[]>();
|
|
72
|
+
for (const item of checklist.items) {
|
|
73
|
+
const events = history(item.id);
|
|
74
|
+
const refs = new Set(refsIn(item.id, item.title, item.evidence, item.refs, ...events.flatMap(event => [event.from, event.to])));
|
|
75
|
+
itemRefs.set(item.id, refs);
|
|
76
|
+
refs.forEach(id => issueIds.add(id));
|
|
77
|
+
const today = events.filter(event => {
|
|
78
|
+
const at = Date.parse(event.at);
|
|
79
|
+
return Number.isFinite(at) && at >= start && at < end && ['status', 'evidence', 'title', 'move'].includes(event.field);
|
|
80
|
+
});
|
|
81
|
+
if (today.length) changed.set(item.id, today);
|
|
82
|
+
}
|
|
83
|
+
const decisionRefs = new Map<string, string[]>();
|
|
84
|
+
for (const decision of decisions) {
|
|
85
|
+
const refs = refsIn(decision.refs);
|
|
86
|
+
decisionRefs.set(decision.id, refs);
|
|
87
|
+
refs.forEach(id => issueIds.add(id));
|
|
88
|
+
}
|
|
89
|
+
const summaries: LinearDailyProgressSummary[] = [];
|
|
90
|
+
for (const identifier of [...issueIds].sort()) {
|
|
91
|
+
const lines = [`elanous 진행 요약 · ${day}`];
|
|
92
|
+
const changes: string[] = [];
|
|
93
|
+
for (const item of checklist.items) {
|
|
94
|
+
if (!itemRefs.get(item.id)?.has(identifier)) continue;
|
|
95
|
+
const events = changed.get(item.id) ?? [];
|
|
96
|
+
if (!events.length) continue;
|
|
97
|
+
const status = events.filter(event => event.field === 'status').at(-1);
|
|
98
|
+
const value = status ? `${String(status.from ?? '미상')} → ${String(status.to ?? '미상')}`
|
|
99
|
+
: events.some(event => event.field === 'evidence') ? '근거 갱신'
|
|
100
|
+
: events.some(event => event.field === 'title') ? '제목 변경' : '칸 이동';
|
|
101
|
+
changes.push(`- 칸 ${item.id}: ${cleanTitle(item.title)} · ${value}`);
|
|
102
|
+
const landedToday = events.some(event => event.field === 'status' && (event.to === 'green' || event.to === 'done'));
|
|
103
|
+
for (const event of events.filter(event => event.field === 'evidence' && landedToday)) {
|
|
104
|
+
for (const link of prLinks(event.to)) changes.push(` 착지 PR: ${link}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
lines.push('칸 변화');
|
|
108
|
+
lines.push(...(changes.length ? [...new Set(changes)] : ['- 오늘 기록된 칸 변화 없음']));
|
|
109
|
+
const issueDecisions = decisions.filter(decision => decisionRefs.get(decision.id)?.includes(identifier) &&
|
|
110
|
+
(decision.history.some(event => event.at && Date.parse(event.at) >= start && Date.parse(event.at) < end) ||
|
|
111
|
+
(decision.decidedAt && Date.parse(decision.decidedAt) >= start && Date.parse(decision.decidedAt) < end)));
|
|
112
|
+
lines.push('결정');
|
|
113
|
+
lines.push(...(issueDecisions.length ? issueDecisions.map(decision => `- ${cleanTitle(decision.title)} · ${decision.status}`) : ['- 오늘 기록된 결정 없음']));
|
|
114
|
+
const next = checklist.items.filter(item => item.status !== 'green' && item.status !== 'done' && itemRefs.get(item.id)?.has(identifier));
|
|
115
|
+
lines.push('다음 할 일');
|
|
116
|
+
lines.push(...(next.length ? next.slice(0, 8).map(item => `- ${item.id}: ${cleanTitle(item.title)}`) : ['- 연결된 미완료 칸 없음']));
|
|
117
|
+
const content = lines.join('\n');
|
|
118
|
+
const contentHash = createHash('sha256').update(content).digest('hex');
|
|
119
|
+
summaries.push({ identifier, day, body: `${content}\n\n${BODY_MARKER}${day} -->`, contentHash });
|
|
120
|
+
}
|
|
121
|
+
return summaries;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function findIssueAndDuplicate({ apiKey, identifier, day, body, fetch: fetchFn }: { apiKey: string; identifier: string; day: string; body: string; fetch: typeof fetch }): Promise<{ issueId: string; duplicate: boolean }> {
|
|
125
|
+
// Linear's GraphQL quickstart explicitly queries issue(id: "BLA-123"): https://linear.app/developers/graphql
|
|
126
|
+
const query = `query DailyProgressIssue($identifier: String!, $after: String) {
|
|
127
|
+
issue(id: $identifier) { id comments(first: 100, after: $after) { nodes { body } pageInfo { hasNextPage endCursor } } }
|
|
128
|
+
}`;
|
|
129
|
+
let after: string | null = null;
|
|
130
|
+
const cursors = new Set<string>();
|
|
131
|
+
let issueId: string | undefined;
|
|
132
|
+
let duplicate = false;
|
|
133
|
+
do {
|
|
134
|
+
let response: Response;
|
|
135
|
+
try {
|
|
136
|
+
response = await fetchFn('https://api.linear.app/graphql', { method: 'POST', headers: { Authorization: apiKey, 'Content-Type': 'application/json' },
|
|
137
|
+
body: JSON.stringify({ query, variables: { identifier, after } }) });
|
|
138
|
+
} catch { throw new Error('linear-request-failed'); }
|
|
139
|
+
if (!response.ok) throw new Error(`linear-http-${response.status}`);
|
|
140
|
+
let result: { data?: { issue?: { id?: string; comments?: { nodes?: Array<{ body?: string }>; pageInfo?: { hasNextPage?: boolean; endCursor?: string | null } } | null } }; errors?: unknown[] };
|
|
141
|
+
try { result = await response.json() as typeof result; } catch { throw new Error('linear-invalid-json'); }
|
|
142
|
+
if (result.errors?.length || !result.data?.issue?.id) throw new Error('linear-issue-not-found-or-query-failed');
|
|
143
|
+
issueId = result.data.issue.id;
|
|
144
|
+
const comments = result.data.issue.comments;
|
|
145
|
+
if (comments?.nodes?.some(comment => comment.body?.includes(`${BODY_MARKER}${day} -->`))) duplicate = true;
|
|
146
|
+
const page = comments?.pageInfo;
|
|
147
|
+
if (page?.hasNextPage && (!page.endCursor || cursors.has(page.endCursor))) throw new Error('linear-comment-pagination-invalid');
|
|
148
|
+
after = page?.hasNextPage ? page.endCursor! : null;
|
|
149
|
+
if (after) cursors.add(after);
|
|
150
|
+
} while (after && !duplicate);
|
|
151
|
+
return { issueId, duplicate };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function withDailyLock<T>(stateDir: string, fn: () => Promise<T>): Promise<T> {
|
|
155
|
+
const path = join(stateDir, 'linear-daily-progress', 'send.lock');
|
|
156
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
157
|
+
const deadline = Date.now() + 30_000;
|
|
158
|
+
let fd: number | undefined;
|
|
159
|
+
for (;;) {
|
|
160
|
+
try {
|
|
161
|
+
fd = openSync(path, 'wx', 0o600);
|
|
162
|
+
try { writeSync(fd, `${process.pid}`); }
|
|
163
|
+
catch (error) { closeSync(fd); fd = undefined; unlinkSync(path); throw error; }
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
|
|
168
|
+
try {
|
|
169
|
+
const pid = Number(readFileSync(path, 'utf8'));
|
|
170
|
+
if (Number.isSafeInteger(pid) && pid > 0 && Date.now() - statSync(path).mtimeMs > 30_000) {
|
|
171
|
+
try { process.kill(pid, 0); } catch (inner) { if ((inner as NodeJS.ErrnoException).code === 'ESRCH') { unlinkSync(path); continue; } }
|
|
172
|
+
}
|
|
173
|
+
} catch (inner) { if ((inner as NodeJS.ErrnoException).code === 'ENOENT') continue; }
|
|
174
|
+
if (Date.now() >= deadline) throw new Error('linear daily progress lock timeout');
|
|
175
|
+
Atomics.wait(WAIT, 0, 0, 25);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return fn().finally(() => {
|
|
179
|
+
if (fd === undefined) return;
|
|
180
|
+
try { closeSync(fd); }
|
|
181
|
+
finally {
|
|
182
|
+
try { unlinkSync(path); }
|
|
183
|
+
catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** Dry-run by default at the CLI; live delivery checks Linear first so a retry after a crash cannot duplicate a comment. */
|
|
189
|
+
export async function syncLinearDailyProgress(deps: LinearDailyProgressDeps = {}): Promise<LinearDailyProgressResult> {
|
|
190
|
+
const checklist = deps.checklist ?? listChecklist(deps.version ?? checklistDevVersion());
|
|
191
|
+
const decisions = deps.decisions ?? new DecisionLedger({ stateDir: deps.stateDir }).list({ status: 'all' });
|
|
192
|
+
const summaries = buildLinearDailyProgressSummaries({ checklist, history: deps.history ?? checklistHistory, decisions, now: deps.now });
|
|
193
|
+
const result: LinearDailyProgressResult = { posted: 0, skipped: 0, failed: 0, dryRun: deps.dryRun !== false, plan: [] };
|
|
194
|
+
if (!summaries.length) return result;
|
|
195
|
+
const log = deps.log ?? debug.log.bind(debug);
|
|
196
|
+
const stateDir = deps.stateDir ?? elanousStateRoot();
|
|
197
|
+
if (result.dryRun) {
|
|
198
|
+
result.plan = summaries.map(({ identifier, day, contentHash, body }) => ({ identifier, day, contentHash, body, status: 'dry-run' }));
|
|
199
|
+
return result;
|
|
200
|
+
}
|
|
201
|
+
const apiKey = deps.apiKey ?? await (deps.getSecret ?? getSecretAsync)('connector.linear.apiKey');
|
|
202
|
+
if (!apiKey) throw new Error('connector.linear.apiKey missing');
|
|
203
|
+
return withDailyLock(stateDir, async () => {
|
|
204
|
+
for (const summary of summaries) {
|
|
205
|
+
const fields = { traceId: randomUUID(), identifier: summary.identifier, day: summary.day, contentHash: summary.contentHash };
|
|
206
|
+
try {
|
|
207
|
+
const issue = await findIssueAndDuplicate({ apiKey, identifier: summary.identifier, day: summary.day, body: summary.body, fetch: deps.fetch ?? fetch });
|
|
208
|
+
if (issue.duplicate) {
|
|
209
|
+
result.skipped++;
|
|
210
|
+
result.plan.push({ identifier: summary.identifier, day: summary.day, contentHash: summary.contentHash, body: summary.body, status: 'duplicate' });
|
|
211
|
+
log('connector.linear.daily-progress', 'skipped', { ...fields, reason: 'duplicate-content' });
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
await commentLinearIssue({ apiKey, issueId: issue.issueId, body: summary.body, fetch: deps.fetch ?? fetch });
|
|
215
|
+
result.posted++;
|
|
216
|
+
result.plan.push({ identifier: summary.identifier, day: summary.day, contentHash: summary.contentHash, body: summary.body, status: 'posted' });
|
|
217
|
+
log('connector.linear.daily-progress', 'posted', fields);
|
|
218
|
+
} catch (error) {
|
|
219
|
+
result.failed++;
|
|
220
|
+
result.plan.push({ identifier: summary.identifier, day: summary.day, contentHash: summary.contentHash, body: summary.body, status: 'failed' });
|
|
221
|
+
const reason = error instanceof Error && /^linear-(?:request-failed|http-\d{3}|invalid-json|issue-not-found-or-query-failed|comment-pagination-invalid)$/.test(error.message)
|
|
222
|
+
? error.message : 'linear-operation-failed';
|
|
223
|
+
log('connector.linear.daily-progress', 'failed', { ...fields, reason });
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
});
|
|
228
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import type { Task, TaskExecution, TaskStatus } from '../task-orchestrator/types.js';
|
|
3
3
|
import { EventLedger } from './event-ledger.js';
|
|
4
|
+
import { parseLinearSecretaryManifest, readApprovedLinearCapture, updateLinearSecretaryProgress } from '../intake-plane/linear-wish.js';
|
|
4
5
|
|
|
5
6
|
const LINEAR_GRAPHQL_URL = 'https://api.linear.app/graphql';
|
|
6
7
|
const STATE_NAMES: Partial<Record<TaskStatus, string>> = {
|
|
@@ -10,7 +11,7 @@ const STATE_NAMES: Partial<Record<TaskStatus, string>> = {
|
|
|
10
11
|
failed: 'Todo',
|
|
11
12
|
};
|
|
12
13
|
|
|
13
|
-
type ProjectableTask = Pick<Task, 'id' | 'status' | 'generatedBy' | 'lastExecutionId' | 'notes'>;
|
|
14
|
+
type ProjectableTask = Pick<Task, 'id' | 'status' | 'generatedBy' | 'lastExecutionId' | 'notes'> & Pick<Partial<Task>, 'description' | 'title'>;
|
|
14
15
|
|
|
15
16
|
export interface LinearProjectionOptions {
|
|
16
17
|
task: ProjectableTask;
|
|
@@ -19,7 +20,7 @@ export interface LinearProjectionOptions {
|
|
|
19
20
|
ledger?: EventLedger;
|
|
20
21
|
/** Linear user ID for the elanous agent, when configured. */
|
|
21
22
|
assigneeId?: string;
|
|
22
|
-
execution?: Pick<TaskExecution, 'output' | 'error'>;
|
|
23
|
+
execution?: Pick<TaskExecution, 'output' | 'error' | 'runId' | 'captureArtifacts'>;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
async function graphql<T>(apiKey: string, fetchFn: typeof fetch, query: string, variables: Record<string, unknown>): Promise<T> {
|
|
@@ -34,25 +35,46 @@ async function graphql<T>(apiKey: string, fetchFn: typeof fetch, query: string,
|
|
|
34
35
|
return result.data;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
function projectionComment(task: ProjectableTask
|
|
38
|
+
function projectionComment(task: ProjectableTask): string | null {
|
|
38
39
|
switch (task.status) {
|
|
39
40
|
case 'running': return `elanous 실행 시작 (task: ${task.id}${task.lastExecutionId ? `, execution: ${task.lastExecutionId}` : ''}).`;
|
|
40
|
-
case 'review': return `elanous 실행 결과가 사람 확인을 기다립니다 (task: ${task.id})
|
|
41
|
-
case 'done': return `elanous 실행 완료 (task: ${task.id})
|
|
42
|
-
case 'failed': {
|
|
43
|
-
const reason = execution?.error?.message ?? task.notes.at(-1);
|
|
44
|
-
return `elanous 실행 실패 (task: ${task.id}).${reason ? `\n\n${reason.slice(0, 2000)}` : ''}`;
|
|
45
|
-
}
|
|
41
|
+
case 'review': return `elanous 실행 결과가 사람 확인을 기다립니다 (task: ${task.id}).`;
|
|
42
|
+
case 'done': return `elanous 실행 완료 (task: ${task.id}).`;
|
|
43
|
+
case 'failed': return `elanous 실행 실패 (task: ${task.id}).`;
|
|
46
44
|
default: return null;
|
|
47
45
|
}
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
/** Project only Linear-origin task transitions. Every successful write is recorded for inbound echo filtering. */
|
|
51
49
|
export async function projectLinearTask({ task, apiKey, fetch: fetchFn = fetch, ledger, assigneeId, execution }: LinearProjectionOptions): Promise<boolean> {
|
|
52
|
-
if (task.generatedBy?.kind !== 'external' || task.generatedBy.provider !== 'linear' || !task.generatedBy.ref
|
|
53
|
-
if (!apiKey) throw new Error('Linear API key is required for projection');
|
|
50
|
+
if (task.generatedBy?.kind !== 'external' || task.generatedBy.provider !== 'linear' || !task.generatedBy.ref) return false;
|
|
54
51
|
const issueId = task.generatedBy.ref;
|
|
55
52
|
const events = ledger ?? new EventLedger();
|
|
53
|
+
const secretary = parseLinearSecretaryManifest(task.description ?? '', issueId);
|
|
54
|
+
if (secretary) {
|
|
55
|
+
if (task.status !== 'running' && task.status !== 'review' && task.status !== 'done' && task.status !== 'failed') return false;
|
|
56
|
+
if (!apiKey) throw new Error('Linear API key is required for projection');
|
|
57
|
+
const state = task.status === 'running' ? 'started' : task.status === 'done' ? 'completed' : 'comment';
|
|
58
|
+
const captureCandidate = execution?.captureArtifacts?.find(capture =>
|
|
59
|
+
capture.runId === execution.runId && capture.runId.trim().length > 0 &&
|
|
60
|
+
capture.linearIssueId === secretary.parentIssueId && capture.externalShare === true && capture.sensitivity === 'public');
|
|
61
|
+
let captureArtifact: typeof captureCandidate;
|
|
62
|
+
if (captureCandidate) {
|
|
63
|
+
try { readApprovedLinearCapture(captureCandidate); captureArtifact = captureCandidate; }
|
|
64
|
+
catch { /* Invalid, stale, or unavailable captures fail closed; progress still syncs without a URL. */ }
|
|
65
|
+
}
|
|
66
|
+
await updateLinearSecretaryProgress({ apiKey, parentIssueId: secretary.parentIssueId, taskIssueId: issueId,
|
|
67
|
+
taskTitle: secretary.tasks.find(item => item.issueId === issueId)!.title, tasks: secretary.tasks, state,
|
|
68
|
+
summary: task.status === 'running' ? '하위 작업을 시작했습니다.'
|
|
69
|
+
: task.status === 'done' ? '하위 작업을 완료했습니다.'
|
|
70
|
+
: task.status === 'failed' ? '하위 작업이 실패했습니다.' : '하위 작업 진행 상태를 갱신했습니다.',
|
|
71
|
+
workaround: task.status === 'failed' ? 'Linear 상태는 In Progress로 유지하고 실패 내용을 기록했습니다.' : undefined,
|
|
72
|
+
captureArtifact,
|
|
73
|
+
ledger: events, fetch: fetchFn });
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
if (!STATE_NAMES[task.status]) return false;
|
|
77
|
+
if (!apiKey) throw new Error('Linear API key is required for projection');
|
|
56
78
|
const { issue, viewer } = await graphql<{
|
|
57
79
|
issue?: { team?: { states?: { nodes?: Array<{ id: string; name: string }> } } };
|
|
58
80
|
viewer?: { id?: string };
|
|
@@ -72,7 +94,7 @@ export async function projectLinearTask({ task, apiKey, fetch: fetchFn = fetch,
|
|
|
72
94
|
events.record('linear', `outgoing:state:${issueId}:${update.issueUpdate.issue.updatedAt}:${stateHash}`,
|
|
73
95
|
{ ref: issueId, occurredAt: update.issueUpdate.issue.updatedAt });
|
|
74
96
|
|
|
75
|
-
const comment = projectionComment(task
|
|
97
|
+
const comment = projectionComment(task);
|
|
76
98
|
if (comment) {
|
|
77
99
|
const created = await graphql<{ commentCreate?: { success?: boolean; comment?: { id?: string; updatedAt?: string; issue?: { updatedAt?: string } } } }>(apiKey, fetchFn,
|
|
78
100
|
'mutation ProjectorComment($input: CommentCreateInput!) { commentCreate(input: $input) { success comment { id updatedAt issue { updatedAt } } } }',
|
package/src/connectors/linear.ts
CHANGED
|
@@ -180,6 +180,12 @@ export async function resolveLinearProjectId({ apiKey, project, fetch: fetchFn =
|
|
|
180
180
|
return projectId;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
export async function resolveLinearViewerId({ apiKey, fetch: fetchFn = fetch }: LinearRequestOptions): Promise<string> {
|
|
184
|
+
const data = await linearRequest<{ viewer?: { id?: string } }>({ apiKey, fetch: fetchFn }, 'query LinearSecretaryViewer { viewer { id } }', {});
|
|
185
|
+
if (!data.viewer?.id) throw new Error('Linear viewer id could not be resolved');
|
|
186
|
+
return data.viewer.id;
|
|
187
|
+
}
|
|
188
|
+
|
|
183
189
|
/** Read-only project lookup. A name is resolved uniquely before querying its issues. */
|
|
184
190
|
export async function fetchLinearProjectIssues({ apiKey, project, includeDone = false, fetch: fetchFn = fetch }: {
|
|
185
191
|
apiKey: string; project: string; includeDone?: boolean; fetch?: typeof fetch;
|
|
@@ -234,17 +240,47 @@ export async function findLinearDecisionIssue({ apiKey, projectId, decisionId, f
|
|
|
234
240
|
return match;
|
|
235
241
|
}
|
|
236
242
|
|
|
237
|
-
/** Create in
|
|
238
|
-
export async function createLinearIssue({ apiKey, projectId, title, description, dueDate, fetch: fetchFn = fetch }: LinearRequestOptions & {
|
|
239
|
-
projectId
|
|
243
|
+
/** Create in a project or directly in an explicitly selected team. */
|
|
244
|
+
export async function createLinearIssue({ apiKey, projectId, teamKey, title, description, dueDate, parentId, assigneeId, stateType, fetch: fetchFn = fetch }: LinearRequestOptions & {
|
|
245
|
+
projectId?: string; teamKey?: string; title: string; description: string; dueDate?: string; parentId?: string; assigneeId?: string;
|
|
246
|
+
stateType?: 'started' | 'unstarted' | 'completed' | 'canceled';
|
|
240
247
|
}): Promise<string> {
|
|
241
|
-
|
|
242
|
-
|
|
248
|
+
if (!apiKey.trim() || (!projectId?.trim() && !teamKey?.trim())) throw new Error('Linear project or team and API key are required');
|
|
249
|
+
if (!projectId?.trim()) return createLinearTeamIssue({ apiKey, teamKey: teamKey!.trim(), title, description, dueDate, parentId, assigneeId, stateType, fetch: fetchFn });
|
|
250
|
+
type Team = { id: string; states?: { nodes?: Array<{ id: string; type: string }> } };
|
|
251
|
+
const data = await linearRequest<{ project?: { teams?: { nodes?: Team[] } } }>({ apiKey, fetch: fetchFn },
|
|
252
|
+
'query DecisionProjectTeam($id: String!) { project(id: $id) { teams { nodes { id states { nodes { id type } } } } } }', { id: projectId });
|
|
243
253
|
const teams = data.project?.teams?.nodes;
|
|
244
254
|
if (!teams?.[0]?.id) throw new Error('Linear project has no team');
|
|
255
|
+
const stateId = stateType ? teams[0].states?.nodes?.find(state => state.type === stateType)?.id : undefined;
|
|
256
|
+
if (stateType && !stateId) throw new Error(`Linear team workflow state not found: ${stateType}`);
|
|
245
257
|
const created = await linearRequest<{ issueCreate?: { success?: boolean; issue?: { id?: string } } }>({ apiKey, fetch: fetchFn },
|
|
246
258
|
'mutation DecisionIssueCreate($input: IssueCreateInput!) { issueCreate(input: $input) { success issue { id } } }',
|
|
247
|
-
{ input: {
|
|
259
|
+
{ input: {
|
|
260
|
+
teamId: teams[0].id, projectId, title, description,
|
|
261
|
+
...(dueDate ? { dueDate } : {}), ...(parentId ? { parentId } : {}), ...(assigneeId ? { assigneeId } : {}), ...(stateId ? { stateId } : {}),
|
|
262
|
+
} });
|
|
263
|
+
const id = created.issueCreate?.issue?.id;
|
|
264
|
+
if (!created.issueCreate?.success || !id) throw new Error('Linear issueCreate did not return an issue id');
|
|
265
|
+
return id;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** Create an issue directly in a team, without requiring a project. */
|
|
269
|
+
export async function createLinearTeamIssue({ apiKey, teamKey, title, description, dueDate, parentId, assigneeId, stateType, fetch: fetchFn = fetch }: LinearRequestOptions & {
|
|
270
|
+
teamKey: string; title: string; description?: string; dueDate?: string; parentId?: string; assigneeId?: string;
|
|
271
|
+
stateType?: 'started' | 'unstarted' | 'completed' | 'canceled';
|
|
272
|
+
}): Promise<string> {
|
|
273
|
+
if (!apiKey.trim() || !teamKey.trim() || !title.trim()) throw new Error('Linear team, title and API key are required');
|
|
274
|
+
const data = await linearRequest<{ teams?: { nodes?: Array<{ id?: string; states?: { nodes?: Array<{ id: string; type: string }> } }> } }>({ apiKey, fetch: fetchFn },
|
|
275
|
+
'query LinearTeamByKey($key: String!) { teams(filter: { key: { eq: $key } }) { nodes { id states { nodes { id type } } } } }', { key: teamKey.trim() });
|
|
276
|
+
const teams = data.teams?.nodes ?? [];
|
|
277
|
+
if (teams.length !== 1 || !teams[0]?.id) throw new Error(teams.length ? 'Linear team key is ambiguous' : 'Linear team key was not found');
|
|
278
|
+
const stateId = stateType ? teams[0].states?.nodes?.find(state => state.type === stateType)?.id : undefined;
|
|
279
|
+
if (stateType && !stateId) throw new Error(`Linear team workflow state not found: ${stateType}`);
|
|
280
|
+
const created = await linearRequest<{ issueCreate?: { success?: boolean; issue?: { id?: string } } }>({ apiKey, fetch: fetchFn },
|
|
281
|
+
'mutation LinearTeamIssueCreate($input: IssueCreateInput!) { issueCreate(input: $input) { success issue { id } } }',
|
|
282
|
+
{ input: { teamId: teams[0].id, title: title.trim(), ...(description?.trim() ? { description: description.trim() } : {}),
|
|
283
|
+
...(dueDate ? { dueDate } : {}), ...(parentId ? { parentId } : {}), ...(assigneeId ? { assigneeId } : {}), ...(stateId ? { stateId } : {}) } });
|
|
248
284
|
const id = created.issueCreate?.issue?.id;
|
|
249
285
|
if (!created.issueCreate?.success || !id) throw new Error('Linear issueCreate did not return an issue id');
|
|
250
286
|
return id;
|
|
@@ -257,8 +293,74 @@ export async function commentLinearIssue({ apiKey, issueId, body, fetch: fetchFn
|
|
|
257
293
|
if (!data.commentCreate?.success || !data.commentCreate.comment?.id) throw new Error('Linear commentCreate failed');
|
|
258
294
|
}
|
|
259
295
|
|
|
296
|
+
export async function createLinearAttachment({ apiKey, issueId, title, url, subtitle, fetch: fetchFn = fetch }: LinearRequestOptions & {
|
|
297
|
+
issueId: string; title: string; url: string; subtitle?: string;
|
|
298
|
+
}): Promise<string> {
|
|
299
|
+
const parsed = new URL(url);
|
|
300
|
+
if (parsed.protocol !== 'https:') throw new Error('Linear attachment URL must use HTTPS');
|
|
301
|
+
const data = await linearRequest<{ attachmentCreate?: { success?: boolean; attachment?: { id?: string } } }>({ apiKey, fetch: fetchFn },
|
|
302
|
+
'mutation LinearAttachmentCreate($input: AttachmentCreateInput!) { attachmentCreate(input: $input) { success attachment { id } } }',
|
|
303
|
+
{ input: { issueId, title, url: parsed.toString(), ...(subtitle ? { subtitle } : {}) } });
|
|
304
|
+
const id = data.attachmentCreate?.attachment?.id;
|
|
305
|
+
if (!data.attachmentCreate?.success || !id) throw new Error('Linear attachmentCreate did not return an attachment id');
|
|
306
|
+
return id;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** Request a signed Linear upload URL and stream a generated artifact from the server. */
|
|
310
|
+
export async function uploadLinearFile({ apiKey, filename, contentType, body, fetch: fetchFn = fetch }: LinearRequestOptions & {
|
|
311
|
+
filename: string; contentType: string; body: Buffer;
|
|
312
|
+
}): Promise<string> {
|
|
313
|
+
const data = await linearRequest<{ fileUpload?: { success?: boolean; uploadFile?: {
|
|
314
|
+
uploadUrl?: string; assetUrl?: string; headers?: Array<{ key: string; value: string }>;
|
|
315
|
+
} } }>({ apiKey, fetch: fetchFn },
|
|
316
|
+
`mutation LinearFileUpload($contentType: String!, $filename: String!, $size: Int!) {
|
|
317
|
+
fileUpload(contentType: $contentType, filename: $filename, size: $size) {
|
|
318
|
+
success uploadFile { uploadUrl assetUrl headers { key value } }
|
|
319
|
+
}
|
|
320
|
+
}`,
|
|
321
|
+
{ contentType, filename, size: body.byteLength });
|
|
322
|
+
const upload = data.fileUpload?.uploadFile;
|
|
323
|
+
if (!data.fileUpload?.success || !upload?.uploadUrl || !upload.assetUrl || !Array.isArray(upload.headers)) {
|
|
324
|
+
throw new Error('Linear fileUpload did not return an upload URL');
|
|
325
|
+
}
|
|
326
|
+
const uploadUrl = new URL(upload.uploadUrl);
|
|
327
|
+
const assetUrl = new URL(upload.assetUrl);
|
|
328
|
+
if (uploadUrl.protocol !== 'https:' || assetUrl.protocol !== 'https:') throw new Error('Linear file upload URLs must use HTTPS');
|
|
329
|
+
const headers = new Headers({ 'Content-Type': contentType, 'Cache-Control': 'public, max-age=31536000' });
|
|
330
|
+
for (const header of upload.headers) {
|
|
331
|
+
if (!header || typeof header.key !== 'string' || typeof header.value !== 'string') throw new Error('Linear fileUpload returned invalid headers');
|
|
332
|
+
headers.set(header.key, header.value);
|
|
333
|
+
}
|
|
334
|
+
let response: Response;
|
|
335
|
+
try {
|
|
336
|
+
const uploadBody = new Uint8Array(body.byteLength);
|
|
337
|
+
uploadBody.set(body);
|
|
338
|
+
response = await fetchFn(uploadUrl, { method: 'PUT', headers, body: uploadBody, redirect: 'error' });
|
|
339
|
+
} catch {
|
|
340
|
+
throw new Error('Linear file upload PUT failed');
|
|
341
|
+
}
|
|
342
|
+
if (!response.ok) throw new Error(`Linear file upload PUT HTTP ${response.status}`);
|
|
343
|
+
return assetUrl.toString();
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export async function updateLinearIssueDescription({ apiKey, issueId, description, fetch: fetchFn = fetch }: LinearRequestOptions & {
|
|
347
|
+
issueId: string; description: string;
|
|
348
|
+
}): Promise<void> {
|
|
349
|
+
const data = await linearRequest<{ issueUpdate?: { success?: boolean } }>({ apiKey, fetch: fetchFn },
|
|
350
|
+
'mutation LinearIssueDescriptionUpdate($id: String!, $input: IssueUpdateInput!) { issueUpdate(id: $id, input: $input) { success } }',
|
|
351
|
+
{ id: issueId, input: { description } });
|
|
352
|
+
if (!data.issueUpdate?.success) throw new Error('Linear issue description update failed');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export async function fetchLinearIssueDescription({ apiKey, issueId, fetch: fetchFn = fetch }: LinearRequestOptions & { issueId: string }): Promise<string> {
|
|
356
|
+
const data = await linearRequest<{ issue?: { description?: string | null } }>({ apiKey, fetch: fetchFn },
|
|
357
|
+
'query LinearIssueDescription($id: String!) { issue(id: $id) { description } }', { id: issueId });
|
|
358
|
+
if (typeof data.issue?.description !== 'string') throw new Error('Linear issue description is missing');
|
|
359
|
+
return data.issue.description;
|
|
360
|
+
}
|
|
361
|
+
|
|
260
362
|
export async function moveLinearIssueToStateType({ apiKey, issueId, type, fetch: fetchFn = fetch }: LinearRequestOptions & {
|
|
261
|
-
issueId: string; type: 'completed' | 'canceled';
|
|
363
|
+
issueId: string; type: 'unstarted' | 'started' | 'completed' | 'canceled';
|
|
262
364
|
}): Promise<void> {
|
|
263
365
|
const data = await linearRequest<{ issue?: { team?: { states?: { nodes?: Array<{ id: string; type: string }> } } } }>({ apiKey, fetch: fetchFn },
|
|
264
366
|
'query DecisionIssueStates($id: String!) { issue(id: $id) { team { states { nodes { id type } } } } }', { id: issueId });
|
|
@@ -270,6 +372,48 @@ export async function moveLinearIssueToStateType({ apiKey, issueId, type, fetch:
|
|
|
270
372
|
if (!updated.issueUpdate?.success) throw new Error('Linear issueUpdate failed');
|
|
271
373
|
}
|
|
272
374
|
|
|
375
|
+
/** Check the issue's current workflow state and transition in one fresh read/write operation. */
|
|
376
|
+
export async function transitionLinearIssueStateType({ apiKey, issueId, type, fromTypes, fetch: fetchFn = fetch }: LinearRequestOptions & {
|
|
377
|
+
issueId: string; type: 'unstarted' | 'started' | 'completed' | 'canceled'; fromTypes?: readonly string[];
|
|
378
|
+
}): Promise<boolean> {
|
|
379
|
+
const data = await linearRequest<{ issue?: { state?: { type?: string } | null; team?: { states?: { nodes?: Array<{ id: string; type: string }> } } } }>({ apiKey, fetch: fetchFn },
|
|
380
|
+
'query LinearIssueTransitionGuard($id: String!) { issue(id: $id) { state { type } team { states { nodes { id type } } } } }', { id: issueId });
|
|
381
|
+
const currentType = data.issue?.state?.type;
|
|
382
|
+
if (!currentType || currentType === 'completed' || currentType === 'canceled' || (fromTypes && !fromTypes.includes(currentType))) return false;
|
|
383
|
+
const state = data.issue?.team?.states?.nodes?.find(node => node.type === type);
|
|
384
|
+
if (!state?.id) throw new Error(`Linear team workflow state not found: ${type}`);
|
|
385
|
+
const updated = await linearRequest<{ issueUpdate?: { success?: boolean } }>({ apiKey, fetch: fetchFn },
|
|
386
|
+
'mutation LinearIssueTransition($id: String!, $input: IssueUpdateInput!) { issueUpdate(id: $id, input: $input) { success } }',
|
|
387
|
+
{ id: issueId, input: { stateId: state.id } });
|
|
388
|
+
if (!updated.issueUpdate?.success) throw new Error('Linear issueUpdate failed');
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export async function fetchLinearIssueStateType({ apiKey, issueId, fetch: fetchFn = fetch }: LinearRequestOptions & { issueId: string }): Promise<string> {
|
|
393
|
+
const data = await linearRequest<{ issue?: { state?: { type?: string } | null } }>({ apiKey, fetch: fetchFn },
|
|
394
|
+
'query LinearIssueStatus($id: String!) { issue(id: $id) { state { type } } }', { id: issueId });
|
|
395
|
+
const type = data.issue?.state?.type;
|
|
396
|
+
if (!type) throw new Error('Linear issue state type is missing');
|
|
397
|
+
return type;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/** Read the immutable identity needed to bind a demo mission to a real child issue. */
|
|
401
|
+
export async function fetchLinearMissionIssueIdentity({ apiKey, issueId, fetch: fetchFn = fetch }: LinearRequestOptions & { issueId: string }): Promise<{ id: string; teamKey: string; parentId: string | null }> {
|
|
402
|
+
const data = await linearRequest<{ issue?: { id?: string; team?: { key?: string } | null; parent?: { id?: string } | null } }>({ apiKey, fetch: fetchFn },
|
|
403
|
+
'query LinearMissionIssueIdentity($id: String!) { issue(id: $id) { id team { key } parent { id } } }', { id: issueId });
|
|
404
|
+
const issue = data.issue;
|
|
405
|
+
if (!issue?.id || !issue.team?.key) throw new Error('Linear issue identity is incomplete');
|
|
406
|
+
return { id: issue.id, teamKey: issue.team.key, parentId: issue.parent?.id ?? null };
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export async function fetchLinearIssueUpdatedAt({ apiKey, issueId, fetch: fetchFn = fetch }: LinearRequestOptions & { issueId: string }): Promise<string> {
|
|
410
|
+
const data = await linearRequest<{ issue?: { updatedAt?: string } }>({ apiKey, fetch: fetchFn },
|
|
411
|
+
'query LinearIssueUpdatedAt($id: String!) { issue(id: $id) { updatedAt } }', { id: issueId });
|
|
412
|
+
const updatedAt = data.issue?.updatedAt;
|
|
413
|
+
if (!updatedAt || !Number.isFinite(Date.parse(updatedAt))) throw new Error('Linear issue updatedAt is missing');
|
|
414
|
+
return updatedAt;
|
|
415
|
+
}
|
|
416
|
+
|
|
273
417
|
export function toTaskRequest(event: ExternalTaskEvent): {
|
|
274
418
|
title: string; description: string; priority: 'high' | 'medium' | 'low';
|
|
275
419
|
external: { provider: 'linear'; ref: string; url?: string; team?: string };
|