elanous 0.2.29 → 0.2.32
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/{cIpv5nU9AycwYWZI9H589 → IVKr3AlRUVLKsw2fh7eXF}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{058a98ba.7eb28d5e6dc03565.js → 0bb0ff36.b8d418980951e5ba.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +287 -0
- package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +62 -0
- package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6013-2f769370d8b4c2c6.js → 1335-6731f392c35216eb.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8332.6f0f49df772e163b.js → 1654.32de4b324981a188.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{8795.32573a185af18c7b.js → 1913.7cc6fb6055b1ed3f.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{419.736c0d6f426249a7.js → 2001.6c7e0fd02190886c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6767.1fcfc9b8be83975f.js → 2213.2ccbada92c33ea0f.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4759.1f76713aefb87db5.js → 2871.0bca6137343b3f76.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6776.06ff1e3b464cc607.js → 2898.fd781bc7cf01a7b7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1782-59db1b5aa06df38a.js → 2940-619bfd8ef337c611.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{8471.8d2a8c74f09c36ff.js → 2985.39ccdecd36848b12.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +115 -0
- package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +64 -0
- package/apps/pwa/out/_next/static/chunks/{bc324b7c.02a09dd93f6a399b.js → 3267c0e6.d34854e7b3984a6e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3278.2e5d15b53a4091c8.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{7725-4f83d5541fbdb81b.js → 3541-ce3a5424ed5ad7f1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +34 -0
- package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{46bd8bea.2f4b4099172fcdb7.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1142.65d002789ab3af7d.js → 4174.92ed04922709ac9e.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +36 -0
- package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +286 -0
- package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +77 -0
- package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +226 -0
- package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +79 -0
- package/apps/pwa/out/_next/static/chunks/5173-233188df2f42c626.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +148 -0
- package/apps/pwa/out/_next/static/chunks/5307.60f2209e809bd627.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3396-97b97928c49190c9.js → 5458-16cd7a2b51b74c8c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3403.7199205e65124486.js → 5525.86debf231e181813.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9143.ff14585db1d275ff.js → 5543.a438b8ab5a13ea47.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +74 -0
- package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +94 -0
- package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8398.73a19b39715eda04.js → 6092.a7f99e68b188ca66.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5591.a35e7a217734a8b9.js → 6157.0c9af021de4fb31b.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7375.050ea0d72968e49f.js → 6433.fc573af22bbc9ab7.js} +17 -17
- package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +90 -0
- package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +32 -0
- package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +104 -0
- package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +24 -0
- package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +93 -0
- package/apps/pwa/out/_next/static/chunks/69-0a2c8209c6d4a158.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1852.7f7b53991fcb99ef.js → 7502.ccd5b8065545edd0.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
- package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6534.1ab00f370db7b105.js → 7862.30a8d6482bb238eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{285adb1a.5654e605dddf86d2.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
- package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
- package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1516.dfaceff3fd2d0e0d.js → 9138.b6e80031afb1d973.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9907.49be0fcadaf214b5.js → 9221.7d22eaf353a2d4e7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8767-2f6a634f5abeaa01.js → 9279-d28c5b7754d010ae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3160-95c96f4d2a21dd26.js → 9398-6aed28f0a96d0d6f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{328bb3ab-6628a1114fe3fb3b.js → 997ce8a5-2ad501927003b41b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6853.cc5174a9dee59593.js → 9989.3694300e5f000b14.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a27b1e5a0d1b308f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-32866485913d6a04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/{page-29900ed0011b2c83.js → page-c219f2ed171131be.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-04d00ae9b0890349.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{425cfc4d.fb91158e3971c39f.js → b313b242.cb1265eea908db61.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +122 -0
- package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
- package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
- package/apps/pwa/out/_next/static/css/b5d88eba78a3d7bf.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 +26 -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/bin/elanous.mjs +7 -3
- package/graphs/context/nightly-condense.yaml +1 -0
- package/graphs/implement-loop.yaml +5 -0
- package/graphs/intake/intake-daily.yaml +8 -1
- package/graphs/intake/recipes.yaml +5 -0
- package/graphs/lecture/lecture-note.yaml +2 -2
- package/graphs/ops/harness-gc.yaml +1 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +9 -5
- package/graphs/units/recipes.yaml +3 -0
- package/graphs/units/release-gate-recheck.yaml +15 -0
- package/package.json +2 -1
- package/scripts/check-native-tool-wiring.ts +3 -2
- package/scripts/ci-android-unit-tests.ts +16 -0
- package/scripts/ci-typecheck-changed.ts +63 -10
- package/scripts/coord-channel-watch.sh +22 -16
- package/scripts/coord-role-pack.ts +81 -2
- package/scripts/cron-run.ts +96 -3
- package/scripts/detect-test-interference.ts +38 -5
- package/scripts/gate-pr-cache.ts +65 -0
- package/scripts/gh-surface/capture.ts +126 -0
- package/scripts/gh-surface/gh +40 -0
- package/scripts/import-graph-scc.ts +38 -0
- package/scripts/install.ps1 +19 -0
- package/scripts/intake-social.ts +181 -0
- package/scripts/lecture-note/node.ts +71 -4
- package/scripts/lib/android-toolchain.ts +32 -0
- package/scripts/lib/deterministic-env.ts +62 -0
- package/scripts/lib/gate-test-env.ts +19 -0
- package/scripts/measure-goal-grounding-corpus.ts +2 -1
- package/scripts/measure-si-task-cpu.ts +143 -0
- package/scripts/ratchets/test-interference-patterns.allowlist.txt +255 -0
- package/scripts/ratchets/test-interference-patterns.ts +367 -0
- package/scripts/release-loop/cut-branch.ts +4 -3
- package/scripts/release-loop/export-check-node.ts +0 -1
- package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
- package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
- package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
- package/scripts/release-loop/gate-closure.ts +12 -8
- package/scripts/release-loop/gate-diff.ts +1 -1
- package/scripts/release-loop/gate-host-mirror.ts +66 -0
- package/scripts/release-loop/gate-node.ts +523 -75
- package/scripts/release-loop/gate-partial.ts +106 -9
- package/scripts/release-loop/gate-pr-cache.ts +66 -0
- package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
- package/scripts/release-loop/gate-r2-verdict.ts +189 -0
- package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
- package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
- package/scripts/release-loop/import-graph-scc-run.ts +54 -0
- package/scripts/release-loop/import-graph-scc.ts +215 -0
- package/scripts/release-loop/node-verdict.ts +2 -0
- package/scripts/release-loop/prepare-node.ts +102 -4
- package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
- package/scripts/release-loop/resume-release.ts +33 -4
- package/scripts/release-loop/resume.ts +13 -5
- package/scripts/release-loop/spawn-lane.ts +2 -19
- package/scripts/release-loop/tui-sim-node.ts +3 -2
- package/scripts/release-loop/unattended-release.ts +16 -0
- package/scripts/test-deterministic.ts +5 -61
- package/scripts/train-reach-grouping.ts +48 -0
- package/scripts/tsc-incremental-cache.ts +86 -0
- package/scripts/tsc-incremental-diagnostics.ts +76 -0
- package/scripts/tsc-main-safety-net.ts +2 -2
- package/src/acp/client.ts +4 -1
- package/src/acp/core-turn-bridge.ts +65 -8
- package/src/acp/elanous-extensions.ts +3 -0
- package/src/acp/server.ts +3 -0
- package/src/acp/tool-trace.ts +186 -11
- package/src/ad-pipeline/run.ts +4 -2
- package/src/agent/runner.ts +169 -3
- package/src/agent/self-ambient-cache.ts +156 -0
- package/src/agent/self-ambient.ts +8 -1
- package/src/agent/subagent-callable.ts +3 -2
- package/src/agent/task-notification.ts +5 -0
- package/src/agent-mission/review-loop.ts +6 -3
- package/src/agent-substrate/acp-implementer.ts +14 -2
- package/src/agent-substrate/pr-reviewer.ts +14 -0
- package/src/agent-substrate/self-review-cli.ts +30 -4
- package/src/ask-user-question/tool.ts +22 -0
- package/src/autopilot/build/llm-conflict-merge.ts +56 -10
- package/src/autopilot/pr-manager.ts +80 -7
- package/src/briefing/brief-items.ts +24 -22
- package/src/capture/frame-state-detect.ts +39 -0
- package/src/capture/tui-self-report.ts +149 -6
- package/src/chat/chat-cli.ts +10 -2
- package/src/chat/index.ts +138 -26
- package/src/chat/input-control-key.ts +5 -3
- package/src/chat/pickers/modal-runtime.ts +6 -0
- package/src/chat/pickers/modals.ts +8 -2
- package/src/chat/tool-interrupt-behavior.ts +38 -0
- package/src/chat/tool-render/dispatch.ts +5 -1
- package/src/chat/turn-typeahead.ts +75 -20
- package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
- package/src/cli/agent-cli.ts +41 -13
- package/src/cli/ask-bare.ts +1 -0
- package/src/cli/config-audit.ts +123 -0
- package/src/cli/decisions-cli.ts +80 -6
- package/src/cli/import-cli.ts +12 -0
- package/src/cli/log-event-names.ts +17 -0
- package/src/cli/mcp-login.ts +21 -5
- package/src/cli/msg-cli.ts +89 -0
- package/src/cli/pod-cli.ts +14 -3
- package/src/cli/pr-cli.ts +273 -81
- package/src/cli/pr-land-base-read.ts +34 -0
- package/src/cli/pr-land-heavy-remote.ts +82 -26
- package/src/cli/pr-land-overlap-evidence.ts +109 -11
- package/src/cli/pr-land-pod-shadow-job.ts +106 -0
- package/src/cli/pr-land-pod-shadow.ts +16 -3
- package/src/cli/pr-land-refusal.ts +20 -5
- package/src/cli/pr-land-virtual-rebase.ts +108 -0
- package/src/cli/pty-takeover-cli.ts +88 -14
- package/src/cli/release-cli.ts +80 -14
- package/src/cli/seat-cli.ts +138 -3
- package/src/cli/self-update.ts +5 -2
- package/src/cli/sim-cli.ts +18 -0
- package/src/cli/tasks-cli.ts +97 -19
- package/src/context-bus/context-first.ts +13 -0
- package/src/context-bus/context-now.ts +13 -2
- package/src/context-bus/ops-events.ts +79 -0
- package/src/control-plane/lease-holder.ts +12 -8
- package/src/control-plane/ledger.ts +163 -4
- package/src/control-plane/server.ts +91 -11
- package/src/core-turn/run-core-turn.ts +2 -0
- package/src/core-turn/run-goal-loop.ts +243 -3
- package/src/core-turn/seat-turn-cap.ts +79 -0
- package/src/core-turn/short-question.ts +38 -6
- package/src/core-turn/types.ts +6 -0
- package/src/dashboard/acp-active-model.ts +42 -1
- package/src/dashboard/acp-boot.ts +3 -0
- package/src/dashboard/background-jobs-status.ts +66 -0
- package/src/dashboard/index.ts +339 -657
- package/src/dashboard/input/agent-wake.ts +242 -0
- package/src/dashboard/input/chat-main-entry-runtime.ts +6 -1
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +4 -1
- package/src/dashboard/input/chat-main-session.ts +8 -1
- package/src/dashboard/input/chat-main-turn.ts +12 -3
- package/src/dashboard/input/compact-prepass-recovery.ts +33 -0
- package/src/dashboard/input/external-input-host.ts +49 -9
- package/src/dashboard/input/internal-turn.ts +261 -0
- package/src/dashboard/input/mouse-wiring.ts +108 -11
- package/src/dashboard/input/seat-autowake.ts +318 -0
- package/src/dashboard/input/turn-steer-bridge.ts +70 -0
- package/src/dashboard/log-click-runtime.ts +118 -2
- package/src/dashboard/loop-scheduler.ts +72 -0
- package/src/dashboard/seat-boot-preamble.ts +18 -0
- package/src/dashboard/skill-runtime.ts +2 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +126 -1181
- package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
- package/src/dashboard/slash-runtime/index.ts +13 -0
- package/src/dashboard/turn-busy-teardown.ts +50 -0
- package/src/dashboard/turn-preamble.ts +116 -40
- package/src/dashboard/turn-session-layers.ts +4 -2
- package/src/dashboard/turn-start-segments.ts +222 -0
- package/src/decisions/decision-ledger.ts +45 -4
- package/src/discord-self-message.ts +4 -4
- package/src/display/prompt-row-owner.ts +146 -0
- package/src/display/resize-listener.ts +33 -2
- package/src/domains/release-tool.ts +18 -1
- package/src/field-note/transcribe.ts +17 -0
- package/src/fold-stack.ts +4 -2
- package/src/git-fs/index.ts +263 -36
- package/src/github/remote-call.ts +81 -0
- package/src/goals/registry.ts +46 -6
- package/src/goals/types.ts +7 -1
- package/src/graph-runner/runner.ts +1 -0
- package/src/grok/credential.ts +26 -0
- package/src/harness/gate-reserve.ts +87 -0
- package/src/harness/harness-clean.ts +2 -1
- package/src/harness/harness-cli-command.ts +52 -5
- package/src/harness/harness-gc.ts +2 -1
- package/src/harness/harness-incidents.ts +70 -20
- package/src/harness/harness-pod-dispatch.ts +87 -10
- package/src/harness/harness-queue.ts +68 -4
- package/src/harness/harness-stop.ts +4 -3
- package/src/harness/harness-substrate-default.ts +78 -7
- package/src/harness/harness-worktree-auto.ts +2 -1
- package/src/harness/harness-worktrees.ts +3 -2
- package/src/hooks/dispatch.ts +2 -1
- package/src/index.ts +156 -27
- package/src/input/external-input-queue.ts +64 -7
- package/src/intake-plane/slash.ts +14 -3
- package/src/keybindings.ts +4 -1
- package/src/llm/route-decision.ts +36 -0
- package/src/llm/tool-loop-steered-rejection.ts +41 -0
- package/src/llm-request-shape.ts +209 -0
- package/src/llm.ts +301 -283
- package/src/loops/consensus.ts +348 -0
- package/src/loops/msg-wake.ts +206 -4
- package/src/loops/observe.ts +19 -3
- package/src/loops/orchestrator/tick.ts +88 -12
- package/src/loops/orchestrator/traffic.ts +64 -1
- package/src/loops/registry.ts +30 -0
- package/src/market/signed-index.ts +14 -0
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/mcp/mcp-oauth.ts +54 -5
- package/src/models/prompts.ts +28 -0
- package/src/msg/msg-sse-client.ts +223 -0
- package/src/msg/msg-store.ts +86 -2
- package/src/mss/logging/log-store.ts +225 -1
- package/src/mss/logging/render-categories.ts +5 -0
- package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
- package/src/nexus/api/http-server.ts +54 -15
- package/src/nexus/api/loop-resources.ts +19 -3
- package/src/nexus/api/ops-api.ts +11 -0
- package/src/nexus/daemon-thin-inventory.md +37 -0
- package/src/nexus/index.ts +70 -0
- package/src/nexus/state/state.ts +1 -0
- package/src/oauth/store.ts +32 -7
- package/src/onboarding/first-run.ts +28 -3
- package/src/ops/overview-cache.ts +16 -4
- package/src/ops/overview.ts +59 -2
- package/src/ops/resources.ts +82 -0
- package/src/plugins/maker/connector-maker.ts +41 -0
- package/src/plugins/maker/skill-maker.ts +42 -0
- package/src/pr-tool/census.ts +303 -0
- package/src/pr-tool/inflight-registry.ts +143 -0
- package/src/prompt-library/chat-conciseness.ts +13 -0
- package/src/prompt-library/universal-preamble.ts +10 -5
- package/src/pty-shell/pty-manifest.ts +12 -3
- package/src/pty-shell/tui-run-state.ts +34 -3
- package/src/release-loop/gate-host-reservation.ts +97 -0
- package/src/release-loop/landing-freeze.ts +5 -0
- package/src/release-loop/light-rc.ts +5 -2
- package/src/release-loop/placement.ts +92 -1
- package/src/release-loop/rehearsal-shard-plan.ts +149 -0
- package/src/release-loop/rehearsal.ts +73 -17
- package/src/repl/index.ts +20 -2
- package/src/seat-loop/seat-knowhow.ts +282 -0
- package/src/seat-loop/seat-loop.ts +41 -2
- package/src/seat-loop/traffic-signal.ts +5 -1
- package/src/self-dev/ask-launch-flow.ts +37 -3
- package/src/self-dev/decompose-compose-graph.ts +28 -27
- package/src/self-dev/decompose-proposal.ts +53 -38
- package/src/self-dev/decompose.ts +17 -0
- package/src/self-dev/dev-pipeline.ts +31 -2
- package/src/self-dev/draft-residue.ts +267 -33
- package/src/self-dev/draft-sweep.ts +59 -4
- package/src/self-dev/external-call-zero.ts +77 -0
- package/src/self-dev/launch-preflight-text.ts +6 -0
- package/src/self-dev/launch-preflight.ts +25 -3
- package/src/self-dev/local-supervisor-judge.ts +185 -0
- package/src/self-dev/run-supervisor.ts +229 -19
- package/src/self-dev/run-types.ts +20 -0
- package/src/self-dev/shard-aggregate.ts +13 -2
- package/src/self-dev/shard-plan.ts +56 -1
- package/src/self-dev/shard-run.ts +207 -12
- package/src/self-dev/spawn-lane-files.ts +19 -0
- package/src/self-implement/app-api-budget.ts +51 -11
- package/src/self-implement/config-gate.ts +2 -1
- package/src/self-implement/elanous-tui-spawn.ts +14 -0
- package/src/self-implement/expose-gate.ts +2 -1
- package/src/self-implement/follow-up-placement.ts +79 -0
- package/src/self-implement/gate-artifacts.ts +416 -0
- package/src/self-implement/gate-baseline.ts +96 -5
- package/src/self-implement/gate-cli.ts +207 -17
- package/src/self-implement/gate-remote.ts +136 -26
- package/src/self-implement/gate-scenario.ts +85 -0
- package/src/self-implement/goal-author.ts +160 -8
- package/src/self-implement/graph-authority.ts +38 -6
- package/src/self-implement/graph-overlay-condition.ts +92 -1
- package/src/self-implement/heal-triage.ts +79 -0
- package/src/self-implement/host-regate.ts +97 -7
- package/src/self-implement/orchestrator.ts +115 -134
- package/src/self-implement/pr-title.ts +123 -0
- package/src/self-implement/run-checkpoint.ts +235 -0
- package/src/self-implement/run-ledger.ts +162 -15
- package/src/self-implement/run-stop.ts +4 -3
- package/src/self-implement/run-ttl.ts +28 -4
- package/src/self-implement/seams.ts +2 -0
- package/src/self-implement/shadow-stage.ts +7 -6
- package/src/self-implement/stop-autoheal.ts +2 -1
- package/src/self-implement/train-gate-remote.ts +37 -8
- package/src/self-implement/train-reach-grouping.ts +157 -0
- package/src/self-implement/train-scenario-layers.ts +133 -0
- package/src/self-implement/uncommitted-work.ts +2 -0
- package/src/session/pending-input.ts +19 -0
- package/src/session/session-start.ts +224 -0
- package/src/session-runtime/index.ts +22 -267
- package/src/session-runtime/parallel-dispatch.ts +22 -5
- package/src/shell-runner/background-surface.ts +15 -5
- package/src/skills/tools/agent.ts +39 -6
- package/src/skills/tools/dev-harness.ts +6 -4
- package/src/skills/tools/list-dir.ts +11 -0
- package/src/skills/tools/schedule-wakeup.ts +408 -0
- package/src/skills/tools/shell.ts +246 -4
- package/src/status/bar.ts +26 -0
- package/src/steward/digest-delivery.ts +118 -0
- package/src/steward/hold-hygiene.ts +120 -0
- package/src/steward/resync-tick.ts +114 -23
- package/src/steward/ta-repair-event-collect.ts +158 -0
- package/src/steward/triage.ts +10 -0
- package/src/surface/shell-runner-boot.ts +5 -2
- package/src/task-agent/card-evidence.ts +25 -1
- package/src/task-agent/green-sweep.ts +8 -3
- package/src/task-agent/judge.ts +76 -0
- package/src/task-agent/land-queue.ts +79 -0
- package/src/task-agent/live-moves.ts +30 -9
- package/src/task-agent/postland-card.ts +5 -0
- package/src/task-agent/prelaunch-already-done.ts +98 -0
- package/src/task-agent/real-launch-guard.ts +37 -0
- package/src/task-agent/rejudge-on-head.ts +89 -12
- package/src/task-agent/remote-rejudge-bind.ts +28 -8
- package/src/task-agent/repair-cycle.ts +45 -7
- package/src/task-agent/repair-worker.ts +7 -0
- package/src/task-agent/run-identity.ts +200 -0
- package/src/task-agent/shadow.ts +50 -3
- package/src/task-agent/task-hand.ts +182 -5
- package/src/task-agent/train-landing.ts +77 -0
- package/src/task-agent/work-order.ts +104 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +151 -37
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
- package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
- package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
- package/src/task-orchestrator/surfaces/pod-install-slots.ts +121 -9
- package/src/task-orchestrator/surfaces/pod-lease.ts +118 -6
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
- package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +27 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +3 -1
- package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
- package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +67 -0
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
- package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
- package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +525 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runner.ts +90 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +362 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +138 -19
- package/src/telegram.ts +2 -4
- package/src/tui/chat/execution-badge.ts +5 -1
- package/src/tui/input/pickers.ts +732 -0
- package/src/tui/input-lag-probe.ts +230 -0
- package/src/tui/slash/mission.ts +492 -0
- package/src/tui/slash/term.ts +877 -0
- package/src/tui-client/dashboard-session.ts +9 -0
- package/src/tui.ts +52 -0
- package/src/user-config/gemini-server-tools.ts +9 -0
- package/src/user-config.ts +53 -16
- package/src/util/spawn-sync-output.ts +7 -0
- package/src/ux-sim/fake-bin.ts +154 -0
- package/src/ux-sim/fake-clock.ts +36 -0
- package/src/ux-sim/headless-tui.ts +72 -0
- package/src/ux-sim/in-process-cli.ts +2 -1
- package/src/ux-sim/scenario.ts +255 -0
- package/src/ux-sim/temp-git-remote.ts +82 -0
- package/src/version/packed-revision.json +1 -1
- package/src/video-pipeline/recipes/vlog.ts +25 -7
- package/apps/pwa/out/_next/static/chunks/1015-9cba22a5a4554797.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +0 -8
- package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +0 -34
- package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +0 -286
- package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +0 -24
- package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +0 -36
- package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +0 -64
- package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +0 -115
- package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +0 -1
- package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +0 -90
- package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +0 -94
- package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +0 -62
- package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +0 -27
- package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +0 -104
- package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +0 -93
- package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +0 -2
- package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +0 -148
- package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +0 -149
- package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +0 -79
- package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +0 -287
- package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +0 -77
- package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +0 -74
- package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +0 -226
- package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +0 -32
- package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +0 -1
- package/apps/pwa/out/_next/static/chunks/a435ad95.577add051b4facb2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-a5635eba0d73b84e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-8aaa6dedc4c10dfb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-33bf667a5fb297bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9f92737b8766009a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +0 -1
- package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +0 -122
- package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +0 -1
- package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +0 -1
- /package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → IVKr3AlRUVLKsw2fh7eXF}/_ssgManifest.js +0 -0
package/src/llm.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
import { debug, redactSecrets, redactSecretText } from './debug/log.js';
|
|
27
27
|
import { llmUsageCostFields } from './budget/llm-cost.js';
|
|
28
28
|
import { accumulateByokUsage } from './llm/openrouter-byok-cost.js';
|
|
29
|
+
import { ACTION_PHASE_OPS_TOOLS, isSteeredShellRejection, REPAIR_PHASE_READ_ONLY_OPS_TOOLS } from './llm/tool-loop-steered-rejection.js';
|
|
29
30
|
import { ToolCallTiming } from './chat/tool-call-timing.js';
|
|
30
31
|
import {
|
|
31
32
|
dispatchWithParallelSafety,
|
|
@@ -47,7 +48,8 @@ import {
|
|
|
47
48
|
type ProviderFallbackAttempt,
|
|
48
49
|
type ProviderFallbackTerminalVerdict,
|
|
49
50
|
} from './session-runtime/retry-policy.js';
|
|
50
|
-
import { fetchApiWithRetry, OverloadFailoverError, type FetchApiWithRetryOpts } from './session-runtime/retry-api.js';
|
|
51
|
+
import { ApiHttpError, fetchApiWithRetry, OverloadFailoverError, type FetchApiWithRetryOpts } from './session-runtime/retry-api.js';
|
|
52
|
+
import { isShapeRelevantRejection, summarizeCodexRequestShape } from './llm-request-shape.js';
|
|
51
53
|
import { BedrockProvider, isBedrockCompatibleModel, makeBedrockProvider } from './llm/bedrock-provider.js';
|
|
52
54
|
import { OPEN_WEIGHT_TOOL_DISCIPLINE } from './llm/open-weight-discipline.js';
|
|
53
55
|
import { makeZaiCodingPlanProvider, zaiCodingPlanAvailable } from './llm/zai-coding-plan.js';
|
|
@@ -60,8 +62,6 @@ import { undoTurnRuntime } from './tool-runtime/undo-turn-runtime.js';
|
|
|
60
62
|
import { listSnapshots } from './undo-turn/index.js';
|
|
61
63
|
// Zero-dep spec module (no tool-runtime registry) — safe for this hot path.
|
|
62
64
|
import { takeHydratedTools } from './skills/tools/tool-search-spec.js';
|
|
63
|
-
import { dispatchAskUserQuestion } from './ask-user-question/index.js';
|
|
64
|
-
import type { AskUserQuestionResult } from './ask-user-question/index.js';
|
|
65
65
|
import { isPlanModeActive } from './plan-mode/session.js';
|
|
66
66
|
import { mintTurnUri } from './mss/uri/builder.js';
|
|
67
67
|
import type { TurnUri } from './mss/uri/brand.js';
|
|
@@ -397,6 +397,18 @@ export interface LLMOpts {
|
|
|
397
397
|
* e.g. driving a headless coding-agent terminal (SpawnCodingAgentHeadless
|
|
398
398
|
* + PtyShell Snapshot/Send loop). Absent ⇒ no extension (default). */
|
|
399
399
|
budgetGrant?: { tools: readonly string[]; perCall: number; ceiling: number };
|
|
400
|
+
/** TUI-GOAL-LOOP-FRICTION(#46·#63) — «종결 신호» 도구 이름(예: goal loop 의 `update_goal`).
|
|
401
|
+
* ① 도구 예산·탐색 예산·후속 단계의 거부를 받지 않는다 — 완료 신호를 «TOOL CALL REJECTED» 로
|
|
402
|
+
* 막으면 모델이 둘째 답 ⊕ 사과를 쓴다(#46).
|
|
403
|
+
* ② 한 턴의 호출이 «종결 신호뿐»이고 그 턴(또는 이전 도구 라운드)에 답 텍스트가 있으면, 신호를
|
|
404
|
+
* 디스패치한 뒤 다음 모델 턴을 열지 않고 그 답으로 끝낸다 — 빈 턴 반복 → `[NO FINAL SYNTHESIS]`(#63) 차단.
|
|
405
|
+
* ③ 종결 신호를 받은 뒤의 빈 턴 포기에도 이미 쓴 답이 있으면 `[NO FINAL SYNTHESIS]` 를 붙이지 않는다.
|
|
406
|
+
* 비우면(기본) 종전 동작 그대로. */
|
|
407
|
+
terminalToolNames?: readonly string[];
|
|
408
|
+
/** TUI-H1-GOALLOOP-EMPTY-TAIL — 호출자가 이 스트림 «앞»에 사람에게 답을 이미 보였다(예: goal loop 의 앞 iteration).
|
|
409
|
+
* 그러면 종결 신호 뒤 빈 턴은 이 스트림에 쓴 답이 없어도 재촉·`[NO FINAL SYNTHESIS]` 없이 빈 답으로 끝낸다.
|
|
410
|
+
* 비우면(기본) 종전대로 — 답이 «어디에도» 없을 때의 경고는 그대로 보인다. */
|
|
411
|
+
terminalPriorAnswerVisible?: boolean;
|
|
400
412
|
/** Prompt-caching toggle. Honored by Anthropic (attaches
|
|
401
413
|
* cache_control markers on system + tools + 2nd-to-last history
|
|
402
414
|
* message) and OpenAI (passes stream_options.include_usage so
|
|
@@ -416,12 +428,9 @@ export interface LLMOpts {
|
|
|
416
428
|
* every tool-loop turn gets a stable checkpoint identity without
|
|
417
429
|
* forcing existing callers to thread the brand through. */
|
|
418
430
|
turnUri?: TurnUri;
|
|
419
|
-
/** Chat session id
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
* `elanous/ask/*` envelope instead of the raw `[ASK USER]` text
|
|
423
|
-
* fallback. Absent for CLI / startup-script callers without a chat
|
|
424
|
-
* session context. */
|
|
431
|
+
/** Chat session id (context compaction · provider sticky routing).
|
|
432
|
+
* Absent for CLI / startup-script callers without a chat session
|
|
433
|
+
* context. */
|
|
425
434
|
sessionId?: string;
|
|
426
435
|
/** Server-side built-in tools the provider should advertise to the
|
|
427
436
|
* model alongside the caller-supplied `tools`. Each provider has
|
|
@@ -2186,6 +2195,31 @@ export async function* streamCodexResponsesEvents(
|
|
|
2186
2195
|
// applies the same tool/SSE conventions
|
|
2187
2196
|
const promptCache = extra.promptCache !== false;
|
|
2188
2197
|
const cacheKey = promptCache ? computePromptCacheKey(body.model, body.instructions) : undefined;
|
|
2198
|
+
// TUI-OBS-400-SHAPE(#69) — 전송 객체·문자열을 한 번 만들어 둔다: 4xx 거절 때 «실제로 보낸 것» 의 모양을 잰다.
|
|
2199
|
+
const wireBody: Record<string, unknown> = {
|
|
2200
|
+
...body,
|
|
2201
|
+
stream: true,
|
|
2202
|
+
// store=true wave: when caller opts in, the backend persists the
|
|
2203
|
+
// response and the next request can thread `previous_response_id`
|
|
2204
|
+
// to send only the delta input items. Default still false so any
|
|
2205
|
+
// caller that doesn't opt in (tests building bodies directly)
|
|
2206
|
+
// sees the legacy wire shape.
|
|
2207
|
+
store: body.store === true,
|
|
2208
|
+
...(body.tool_choice ? { tool_choice: body.tool_choice } : {}),
|
|
2209
|
+
...(body.previousResponseId ? { previous_response_id: body.previousResponseId } : {}),
|
|
2210
|
+
...(cacheKey ? { prompt_cache_key: cacheKey } : {}),
|
|
2211
|
+
// Reasoning opt-in (gpt-5 family). When the caller sets
|
|
2212
|
+
// body.reasoning we mirror it onto the wire AND append the
|
|
2213
|
+
// include directive that lets multi-turn requests thread the
|
|
2214
|
+
// model's encrypted reasoning context. Omit both when absent
|
|
2215
|
+
// so non-reasoning models / opt-out users see the legacy
|
|
2216
|
+
// wire shape unchanged.
|
|
2217
|
+
...(body.reasoning ? {
|
|
2218
|
+
reasoning: body.reasoning,
|
|
2219
|
+
include: ['reasoning.encrypted_content'],
|
|
2220
|
+
} : {}),
|
|
2221
|
+
};
|
|
2222
|
+
const wireJson = JSON.stringify(wireBody);
|
|
2189
2223
|
const response = await fetchApiWithRetry(
|
|
2190
2224
|
url,
|
|
2191
2225
|
{
|
|
@@ -2203,33 +2237,14 @@ export async function* streamCodexResponsesEvents(
|
|
|
2203
2237
|
// Codex". See getCodexUserAgent (oauth/codex.ts).
|
|
2204
2238
|
'User-Agent': getCodexUserAgent(),
|
|
2205
2239
|
},
|
|
2206
|
-
body:
|
|
2207
|
-
...body,
|
|
2208
|
-
stream: true,
|
|
2209
|
-
// store=true wave: when caller opts in, the backend persists the
|
|
2210
|
-
// response and the next request can thread `previous_response_id`
|
|
2211
|
-
// to send only the delta input items. Default still false so any
|
|
2212
|
-
// caller that doesn't opt in (tests building bodies directly)
|
|
2213
|
-
// sees the legacy wire shape.
|
|
2214
|
-
store: body.store === true,
|
|
2215
|
-
...(body.tool_choice ? { tool_choice: body.tool_choice } : {}),
|
|
2216
|
-
...(body.previousResponseId ? { previous_response_id: body.previousResponseId } : {}),
|
|
2217
|
-
...(cacheKey ? { prompt_cache_key: cacheKey } : {}),
|
|
2218
|
-
// Reasoning opt-in (gpt-5 family). When the caller sets
|
|
2219
|
-
// body.reasoning we mirror it onto the wire AND append the
|
|
2220
|
-
// include directive that lets multi-turn requests thread the
|
|
2221
|
-
// model's encrypted reasoning context. Omit both when absent
|
|
2222
|
-
// so non-reasoning models / opt-out users see the legacy
|
|
2223
|
-
// wire shape unchanged.
|
|
2224
|
-
...(body.reasoning ? {
|
|
2225
|
-
reasoning: body.reasoning,
|
|
2226
|
-
include: ['reasoning.encrypted_content'],
|
|
2227
|
-
} : {}),
|
|
2228
|
-
}),
|
|
2240
|
+
body: wireJson,
|
|
2229
2241
|
signal,
|
|
2230
2242
|
},
|
|
2231
2243
|
retryOptsFor('codex', 'Codex API', extra.remainingFallbacks),
|
|
2232
|
-
)
|
|
2244
|
+
).catch((err: unknown) => {
|
|
2245
|
+
observeCodexRequestRejection(err, wireBody, wireJson);
|
|
2246
|
+
throw err;
|
|
2247
|
+
});
|
|
2233
2248
|
debug.log('llm.response.status', `codex ${response.status}`, {
|
|
2234
2249
|
url, status: response.status, elapsedMs: Date.now() - startedAt,
|
|
2235
2250
|
});
|
|
@@ -2367,6 +2382,19 @@ export async function* streamCodexResponsesEvents(
|
|
|
2367
2382
|
}
|
|
2368
2383
|
}
|
|
2369
2384
|
|
|
2385
|
+
/** TUI-OBS-400-SHAPE(#69) — Codex 가 요청을 4xx(401·403·429 제외)로 거절하면 보낸 요청의 «모양» 만 남긴다.
|
|
2386
|
+
* Codex 400 은 `{"detail":"Bad Request"}` 뿐이라 크기·메시지 수·도구 짝 깨짐을 여기서 잰다.
|
|
2387
|
+
* ⛔ 본문·프롬프트·도구 인자/출력·키는 싣지 않는다(수·바이트·종류·call_id 해시 앞 8자만).
|
|
2388
|
+
* 관측 실패는 오류 계약을 바꾸지 않는다 — 호출부는 원래 오류를 그대로 던진다. */
|
|
2389
|
+
function observeCodexRequestRejection(err: unknown, wireBody: Record<string, unknown>, wireJson: string): void {
|
|
2390
|
+
if (!(err instanceof ApiHttpError) || !isShapeRelevantRejection(err.status)) return;
|
|
2391
|
+
try {
|
|
2392
|
+
debug.log('llm.codex', 'request-rejected-shape', summarizeCodexRequestShape(wireBody, wireJson, err.status, err.bodyText));
|
|
2393
|
+
} catch {
|
|
2394
|
+
// Observability must not interfere with the provider error contract.
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2370
2398
|
function toolNames(raw: unknown): string[] | undefined {
|
|
2371
2399
|
if (!Array.isArray(raw)) return undefined;
|
|
2372
2400
|
return raw.map(item => {
|
|
@@ -4989,6 +5017,14 @@ export interface StreamWithToolsHandlers {
|
|
|
4989
5017
|
* before the `onText('', enriched)` re-emit so presentation hosts can
|
|
4990
5018
|
* keep the user answer to `answer` and send `supplement` to logs. */
|
|
4991
5019
|
onFinalAnswerSupplement?(info: { answer: string; supplement: string; finalText: string }): void;
|
|
5020
|
+
/** 검증 보충 — final-answer supplement attachment point. Called after the
|
|
5021
|
+
* final answer is settled (and after any finalization-snapshot enrichment)
|
|
5022
|
+
* so callers can append verification-recency / loop-closure wording after
|
|
5023
|
+
* the final answer. Return a non-empty string to append it to the final
|
|
5024
|
+
* answer output (it will be joined after `finalText` and the combined
|
|
5025
|
+
* supplement surfaces via `onFinalAnswerSupplement`); return
|
|
5026
|
+
* undefined/null/empty to keep the prior behavior unchanged. */
|
|
5027
|
+
onAppendFinalAnswerSupplement?(req: FinalAnswerSupplementAttachmentRequest): string | null | undefined;
|
|
4992
5028
|
/** Optional: notify when a tool_call is about to fire (for log line,
|
|
4993
5029
|
* HUD segment, etc). */
|
|
4994
5030
|
onToolCall?(call: { id: string; name: string; args: Record<string, unknown> }): void;
|
|
@@ -5774,10 +5810,13 @@ const TOOL_LOOP_PHASE_DIRECTIVES: Record<ToolLoopFollowupPhase, (autoNarrowedRea
|
|
|
5774
5810
|
'repair-action': () =>
|
|
5775
5811
|
'REPAIR ACTION REQUIRED — execution has already failed or a debugging repair step is armed. '
|
|
5776
5812
|
+ 'Stop gathering more files and move to Edit/Write/RunShell/Bash or a narrow code-intel followup (Read/Lsp/AstGrep/Grep content/count), '
|
|
5813
|
+
+ 'ops ledger/delegate tools (MsgList/MsgPost/MsgAck/Checklist*/AgentOutput) still run, '
|
|
5777
5814
|
+ 'or answer in plain text if no code change is needed (e.g. a read-only investigation whose finding is the deliverable).',
|
|
5778
5815
|
'verify-action': () =>
|
|
5779
5816
|
'VERIFY ACTION REQUIRED — edits already happened. '
|
|
5780
|
-
+ 'Stop gathering more files and move to RunShell/Bash/Agent or a narrow verification followup (Read/Lsp/Grep content/count),
|
|
5817
|
+
+ 'Stop gathering more files and move to RunShell/Bash/Agent or a narrow verification followup (Read/Lsp/Grep content/count), '
|
|
5818
|
+
+ 'ops ledger/delegate tools (MsgList/MsgPost/MsgAck/Checklist*/AgentOutput) still run, '
|
|
5819
|
+
+ 'or answer in plain text if verification is not needed.',
|
|
5781
5820
|
};
|
|
5782
5821
|
|
|
5783
5822
|
const TOOL_LOOP_PHASE_REJECTION_EVENTS: Record<ToolLoopFollowupPhase, string> = {
|
|
@@ -5844,44 +5883,15 @@ function buildAutoUndoRepairNotice(result: { output?: string; restoredId?: strin
|
|
|
5844
5883
|
].filter(Boolean).join('\n');
|
|
5845
5884
|
}
|
|
5846
5885
|
|
|
5847
|
-
//
|
|
5848
|
-
// reachable (no resolver, no sessionId, dispatch error). The marker
|
|
5849
|
-
// `[ASK USER]` is preserved so `isUserInterventionRequired` downstream
|
|
5850
|
-
// still skips force-synthesis — that gate predates the bridge route and
|
|
5851
|
-
// other surfaces (TUI) still rely on the marker as a hard-stop signal.
|
|
5852
|
-
function buildAutoUndoAskUserNotice(reason: DoomLoopReason, detail?: string | null): string {
|
|
5853
|
-
const why = reason === 'plan-mode'
|
|
5854
|
-
? 'Auto-undo was skipped because plan mode is active.'
|
|
5855
|
-
: reason === 'no-undo-available'
|
|
5856
|
-
? 'Auto-undo was skipped because no undo snapshot is available.'
|
|
5857
|
-
: reason === 'undo-failed'
|
|
5858
|
-
? 'Auto-undo was attempted but the undo runtime failed.'
|
|
5859
|
-
: 'Retry policy did not authorize auto-undo for this failure.';
|
|
5860
|
-
return [
|
|
5861
|
-
'[ASK USER] The same tool call kept failing — stopping to avoid wasting more turns.',
|
|
5862
|
-
why,
|
|
5863
|
-
detail ? `Detail: ${detail}` : '',
|
|
5864
|
-
'Reply with how to proceed (retry, change approach, or stop).',
|
|
5865
|
-
].filter(Boolean).join(' ');
|
|
5866
|
-
}
|
|
5867
|
-
|
|
5868
|
-
// ── Doom-loop → AskUserQuestion routing ─────────────────────────
|
|
5886
|
+
// ── Doom-loop self-heal ─────────────────────────────────────────
|
|
5869
5887
|
//
|
|
5870
|
-
// When the tool-loop trips the doom-loop gate (same tool error 3x)
|
|
5871
|
-
//
|
|
5872
|
-
//
|
|
5873
|
-
//
|
|
5874
|
-
//
|
|
5875
|
-
//
|
|
5876
|
-
//
|
|
5877
|
-
//
|
|
5878
|
-
// Falls back to the legacy `[ASK USER]` chat text when:
|
|
5879
|
-
// - no `sessionId` plumbed (CLI / startup script callers),
|
|
5880
|
-
// - no resolver wired (TUI-only or dispatch error), or
|
|
5881
|
-
// - the bridge throws (peer disconnected, surface mismatch).
|
|
5882
|
-
//
|
|
5883
|
-
// The fallback marker `[ASK USER]` is preserved so the downstream
|
|
5884
|
-
// `isUserInterventionRequired` gate continues to skip force-synthesis.
|
|
5888
|
+
// When the tool-loop trips the doom-loop gate (same tool error 3x) and
|
|
5889
|
+
// auto-undo cannot run, the loop heals itself instead of asking the user
|
|
5890
|
+
// (대표 10-17 — doom-loop is not a user-facing notice: in 40 h of runs it
|
|
5891
|
+
// tripped 3 times and the AskUser prompt was answered 0 times, each one
|
|
5892
|
+
// sitting 5 min until timeout). First trip → a «change approach» note for
|
|
5893
|
+
// the model and the turn continues; a second trip in the same turn → the
|
|
5894
|
+
// turn ends with a plain stop text (no question to the user).
|
|
5885
5895
|
|
|
5886
5896
|
export type DoomLoopReason = 'plan-mode' | 'no-undo-available' | 'undo-failed' | 'policy';
|
|
5887
5897
|
|
|
@@ -5971,174 +5981,35 @@ function stringifyDoomFailureDetail(value: unknown): string {
|
|
|
5971
5981
|
}
|
|
5972
5982
|
|
|
5973
5983
|
export type DoomLoopRouteOutcome =
|
|
5974
|
-
| { kind: 'retry'; interventionClass: DoomLoopInterventionClass }
|
|
5975
5984
|
| { kind: 'guidance'; userMessage: string; interventionClass: DoomLoopInterventionClass }
|
|
5976
|
-
| { kind: 'stop'; hardStopText: string; interventionClass: DoomLoopInterventionClass }
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5985
|
+
| { kind: 'stop'; hardStopText: string; interventionClass: DoomLoopInterventionClass };
|
|
5986
|
+
|
|
5987
|
+
/** Visible text when the turn ends on a second doom trip. Deliberately not a
|
|
5988
|
+
* question and without the `[ASK USER]` marker — nobody is asked. */
|
|
5989
|
+
export const DOOM_LOOP_SELF_HEAL_STOP_TEXT =
|
|
5990
|
+
'같은 도구 호출이 방법을 바꾼 뒤에도 계속 실패해 이번 턴을 여기서 마칩니다.';
|
|
5991
|
+
|
|
5992
|
+
export interface DoomLoopSelfHealInput {
|
|
5993
|
+
/** 1 = first trip in this turn, 2+ = tripped again after the guidance. */
|
|
5994
|
+
attempt: number;
|
|
5995
|
+
tool?: string;
|
|
5996
|
+
fingerprint: string;
|
|
5982
5997
|
interventionClass?: DoomLoopInterventionClass | null;
|
|
5983
|
-
detail?: string | null;
|
|
5984
|
-
doomWindow: string[];
|
|
5985
|
-
sessionId?: string;
|
|
5986
|
-
signal?: AbortSignal;
|
|
5987
|
-
/** Override the AskUser gate timeout (ms). Defaults to
|
|
5988
|
-
* DOOM_ASK_TIMEOUT_MS. Primarily a test seam. */
|
|
5989
|
-
timeoutMs?: number;
|
|
5990
|
-
}
|
|
5991
|
-
|
|
5992
|
-
export function buildDoomLoopAskRequest(opts: DoomLoopRouteOpts): Record<string, unknown> {
|
|
5993
|
-
const interventionClass = normalizeDoomLoopInterventionClass(opts.interventionClass);
|
|
5994
|
-
const why = opts.reason === 'plan-mode'
|
|
5995
|
-
? 'plan mode is active so auto-undo was skipped'
|
|
5996
|
-
: opts.reason === 'undo-failed'
|
|
5997
|
-
? `auto-undo was attempted but failed (${opts.detail ?? 'no detail'})`
|
|
5998
|
-
: `auto-undo was not authorized by the retry policy (${opts.detail ?? 'no detail'})`;
|
|
5999
|
-
const lastFingerprint = opts.doomWindow[opts.doomWindow.length - 1] ?? 'unknown';
|
|
6000
|
-
return {
|
|
6001
|
-
interventionClass,
|
|
6002
|
-
questions: [
|
|
6003
|
-
{
|
|
6004
|
-
id: 'doom_loop_next_step',
|
|
6005
|
-
header: 'Loop blocked',
|
|
6006
|
-
question:
|
|
6007
|
-
'The same tool call kept failing after 3 attempts — '
|
|
6008
|
-
+ `${why}. How should I proceed?\n\nLast failure: ${lastFingerprint}`,
|
|
6009
|
-
options: [
|
|
6010
|
-
{
|
|
6011
|
-
label: 'Retry once more',
|
|
6012
|
-
description: 'Reset the retry tracker and let me try the same approach one more time.',
|
|
6013
|
-
},
|
|
6014
|
-
{
|
|
6015
|
-
label: 'Different approach',
|
|
6016
|
-
description: 'Type guidance in Other and I will follow it on the next turn.',
|
|
6017
|
-
},
|
|
6018
|
-
{
|
|
6019
|
-
label: 'Stop here',
|
|
6020
|
-
description: 'Halt this run. I will summarize what was tried and what was blocked.',
|
|
6021
|
-
},
|
|
6022
|
-
],
|
|
6023
|
-
includeOther: true,
|
|
6024
|
-
},
|
|
6025
|
-
],
|
|
6026
|
-
};
|
|
6027
5998
|
}
|
|
6028
5999
|
|
|
6029
|
-
export function
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
): DoomLoopRouteOutcome {
|
|
6033
|
-
if (result.cancelled === true) {
|
|
6034
|
-
return {
|
|
6035
|
-
kind: 'stop',
|
|
6036
|
-
interventionClass,
|
|
6037
|
-
hardStopText:
|
|
6038
|
-
'[ASK USER] The same tool call kept failing and you cancelled the prompt — stopping this run.',
|
|
6039
|
-
};
|
|
6040
|
-
}
|
|
6041
|
-
const answer = result.answers?.['doom_loop_next_step'];
|
|
6042
|
-
const picked = Array.isArray(answer) ? (answer[0] ?? '') : (answer ?? '');
|
|
6043
|
-
const otherText = result.otherText?.['doom_loop_next_step']?.trim();
|
|
6044
|
-
|
|
6045
|
-
if (picked.startsWith('Retry')) {
|
|
6046
|
-
return { kind: 'retry', interventionClass };
|
|
6047
|
-
}
|
|
6048
|
-
if (picked.startsWith('Different') || picked === 'Other') {
|
|
6049
|
-
const guidance = otherText && otherText.length > 0
|
|
6050
|
-
? otherText
|
|
6051
|
-
: 'Please try a different approach to the same goal — the previous tool call kept failing.';
|
|
6052
|
-
return { kind: 'guidance', userMessage: guidance, interventionClass };
|
|
6053
|
-
}
|
|
6054
|
-
if (picked.startsWith('Stop')) {
|
|
6000
|
+
export function decideDoomLoopSelfHeal(input: DoomLoopSelfHealInput): DoomLoopRouteOutcome {
|
|
6001
|
+
const interventionClass = normalizeDoomLoopInterventionClass(input.interventionClass);
|
|
6002
|
+
if (input.attempt <= 1) {
|
|
6055
6003
|
return {
|
|
6056
|
-
kind: '
|
|
6004
|
+
kind: 'guidance',
|
|
6057
6005
|
interventionClass,
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
kind: 'stop',
|
|
6063
|
-
interventionClass,
|
|
6064
|
-
hardStopText:
|
|
6065
|
-
'[ASK USER] The same tool call kept failing and the response was unrecognized — stopping this run.',
|
|
6066
|
-
};
|
|
6067
|
-
}
|
|
6068
|
-
|
|
6069
|
-
// Doom-loop AskUser gate timeout — the doom-loop HITL prompt awaits an
|
|
6070
|
-
// operator answer with NO timeout of its own (TUI modal `await modal.promise`
|
|
6071
|
-
// and the ACP bridge `Promise.race([pushAskRequest, cancellation])` both lack
|
|
6072
|
-
// a timer). In an autonomous drive there is no operator to answer, so the
|
|
6073
|
-
// dispatch region freezes indefinitely — between tool-loop turns, invisible to
|
|
6074
|
-
// the stream idle-watchdog (armed only inside the stream loop) and to the
|
|
6075
|
-
// goal-loop (which awaits the hung iteration). This was the 16-minute freeze in
|
|
6076
|
-
// RESEARCH-autonomous-runaway-discipline-2026-07-19 (R2). Bound the wait: after
|
|
6077
|
-
// this budget, fall back to the same auto-undo notice used when no session /
|
|
6078
|
-
// no cap-able peer is present. Generous enough that a present operator answers
|
|
6079
|
-
// first; short enough that an absent one doesn't stall the run for long.
|
|
6080
|
-
const DOOM_ASK_TIMEOUT_MS = 5 * 60_000;
|
|
6081
|
-
|
|
6082
|
-
export async function routeDoomLoopToAskUser(opts: DoomLoopRouteOpts): Promise<DoomLoopRouteOutcome> {
|
|
6083
|
-
const interventionClass = normalizeDoomLoopInterventionClass(opts.interventionClass);
|
|
6084
|
-
if (!opts.sessionId) {
|
|
6085
|
-
return {
|
|
6086
|
-
kind: 'fallback',
|
|
6087
|
-
interventionClass,
|
|
6088
|
-
hardStopText: buildAutoUndoAskUserNotice(opts.reason, opts.detail),
|
|
6089
|
-
};
|
|
6090
|
-
}
|
|
6091
|
-
try {
|
|
6092
|
-
const dispatchCtx: { sessionId: string; signal?: AbortSignal } = { sessionId: opts.sessionId };
|
|
6093
|
-
if (opts.signal) dispatchCtx.signal = opts.signal;
|
|
6094
|
-
const timeoutMs = opts.timeoutMs ?? DOOM_ASK_TIMEOUT_MS;
|
|
6095
|
-
const TIMED_OUT = Symbol('doom-ask-timeout');
|
|
6096
|
-
let askTimer: ReturnType<typeof setTimeout> | undefined;
|
|
6097
|
-
const raced = await Promise.race([
|
|
6098
|
-
dispatchAskUserQuestion(buildDoomLoopAskRequest(opts), dispatchCtx),
|
|
6099
|
-
new Promise<typeof TIMED_OUT>((res) => {
|
|
6100
|
-
askTimer = setTimeout(() => res(TIMED_OUT), timeoutMs);
|
|
6101
|
-
}),
|
|
6102
|
-
]);
|
|
6103
|
-
if (askTimer) clearTimeout(askTimer);
|
|
6104
|
-
if (raced === TIMED_OUT) {
|
|
6105
|
-
debug.log('llm.tool-loop.retry', 'doom-loop-ask-timeout', {
|
|
6106
|
-
reason: opts.reason,
|
|
6107
|
-
interventionClass,
|
|
6108
|
-
timeoutMs,
|
|
6109
|
-
}, { level: 'warn' });
|
|
6110
|
-
return {
|
|
6111
|
-
kind: 'fallback',
|
|
6112
|
-
interventionClass,
|
|
6113
|
-
hardStopText: buildAutoUndoAskUserNotice(opts.reason, opts.detail),
|
|
6114
|
-
};
|
|
6115
|
-
}
|
|
6116
|
-
const r = raced;
|
|
6117
|
-
if (!r.result) {
|
|
6118
|
-
debug.log('llm.tool-loop.retry', 'doom-loop-ask-route-failed', {
|
|
6119
|
-
error: r.output,
|
|
6120
|
-
reason: opts.reason,
|
|
6121
|
-
interventionClass,
|
|
6122
|
-
}, { level: 'error' });
|
|
6123
|
-
return {
|
|
6124
|
-
kind: 'fallback',
|
|
6125
|
-
interventionClass,
|
|
6126
|
-
hardStopText: buildAutoUndoAskUserNotice(opts.reason, opts.detail),
|
|
6127
|
-
};
|
|
6128
|
-
}
|
|
6129
|
-
return interpretDoomLoopAskResult(r.result, interventionClass);
|
|
6130
|
-
} catch (err) {
|
|
6131
|
-
debug.log('llm.tool-loop.retry', 'doom-loop-ask-route-failed', {
|
|
6132
|
-
error: err instanceof Error ? err.message : String(err),
|
|
6133
|
-
reason: opts.reason,
|
|
6134
|
-
interventionClass,
|
|
6135
|
-
}, { level: 'error' });
|
|
6136
|
-
return {
|
|
6137
|
-
kind: 'fallback',
|
|
6138
|
-
interventionClass,
|
|
6139
|
-
hardStopText: buildAutoUndoAskUserNotice(opts.reason, opts.detail),
|
|
6006
|
+
userMessage:
|
|
6007
|
+
`The same ${input.tool ?? 'tool'} call failed 3 times in a row (last failure: ${input.fingerprint}). `
|
|
6008
|
+
+ 'Do not call it again with the same arguments. Change approach — a different tool or different '
|
|
6009
|
+
+ 'arguments, or first verify the precondition that keeps failing — or state plainly what is blocked.',
|
|
6140
6010
|
};
|
|
6141
6011
|
}
|
|
6012
|
+
return { kind: 'stop', interventionClass, hardStopText: DOOM_LOOP_SELF_HEAL_STOP_TEXT };
|
|
6142
6013
|
}
|
|
6143
6014
|
|
|
6144
6015
|
interface AutoNarrowedInspection {
|
|
@@ -7819,6 +7690,7 @@ const EXPLORATORY_TOOLS = new Set([
|
|
|
7819
7690
|
]);
|
|
7820
7691
|
|
|
7821
7692
|
const INSPECT_ACTION_TOOLS = new Set([
|
|
7693
|
+
...ACTION_PHASE_OPS_TOOLS,
|
|
7822
7694
|
'Edit',
|
|
7823
7695
|
'Write',
|
|
7824
7696
|
'Bash',
|
|
@@ -7833,6 +7705,7 @@ const INSPECT_ACTION_TOOLS = new Set([
|
|
|
7833
7705
|
]);
|
|
7834
7706
|
|
|
7835
7707
|
const VERIFY_ACTION_TOOLS = new Set([
|
|
7708
|
+
...ACTION_PHASE_OPS_TOOLS,
|
|
7836
7709
|
'Edit',
|
|
7837
7710
|
'Write',
|
|
7838
7711
|
'RunShell',
|
|
@@ -7848,6 +7721,7 @@ const VERIFY_ACTION_TOOLS = new Set([
|
|
|
7848
7721
|
]);
|
|
7849
7722
|
|
|
7850
7723
|
const EXECUTION_ACTION_TOOLS = new Set([
|
|
7724
|
+
...ACTION_PHASE_OPS_TOOLS,
|
|
7851
7725
|
'RunShell',
|
|
7852
7726
|
'Bash',
|
|
7853
7727
|
'Agent',
|
|
@@ -7861,6 +7735,8 @@ const EXECUTION_ACTION_TOOLS = new Set([
|
|
|
7861
7735
|
]);
|
|
7862
7736
|
|
|
7863
7737
|
const REPAIR_ACTION_TOOLS = new Set([
|
|
7738
|
+
...REPAIR_PHASE_READ_ONLY_OPS_TOOLS,
|
|
7739
|
+
...ACTION_PHASE_OPS_TOOLS,
|
|
7864
7740
|
'Edit',
|
|
7865
7741
|
'Write',
|
|
7866
7742
|
'RunShell',
|
|
@@ -8147,9 +8023,10 @@ export function billingRouteForProvider(provider: string | undefined, model: str
|
|
|
8147
8023
|
// local 은 호출이 «일어났다면» 언제나 local 이다 — 주소가 env 가 아니라 config rotation 에 있어도(자격 판정은 env 만 본다).
|
|
8148
8024
|
if (name === 'local') return 'local';
|
|
8149
8025
|
try {
|
|
8026
|
+
// A recorded rotation decision is the authoritative route for that Codex call;
|
|
8027
|
+
// auth-kind inference alone can otherwise relabel credit spend as subscription/API.
|
|
8028
|
+
if (name === 'openai-codex' && codexCreditSpendReason()) return 'credit';
|
|
8150
8029
|
const auth = authKindForProvider(name, model);
|
|
8151
|
-
// CREDIT-BILLING-LABEL(10-14) — codex 회전이 크레딧 소진을 정한 호출은 구독이 아니라 크레딧이다.
|
|
8152
|
-
if (auth === 'oauth' && name === 'openai-codex' && codexCreditSpendReason()) return 'credit';
|
|
8153
8030
|
return auth === 'oauth' ? 'subscription' : auth === 'local' ? 'local' : auth === 'apikey' ? 'api' : 'unknown';
|
|
8154
8031
|
} catch {
|
|
8155
8032
|
return 'unknown';
|
|
@@ -8179,6 +8056,41 @@ export function logAgentTurnUsage(model: string, usage: LLMUsage, providerNameOr
|
|
|
8179
8056
|
} catch { /* usage observation must not change the turn */ }
|
|
8180
8057
|
}
|
|
8181
8058
|
|
|
8059
|
+
/** 검증 보충 — final-answer supplement attachment point.
|
|
8060
|
+
* Request passed to `StreamWithToolsHandlers.onAppendFinalAnswerSupplement`
|
|
8061
|
+
* after the final answer is settled: `answer` is the visible answer text and
|
|
8062
|
+
* `finalText` is the current final answer output (including any
|
|
8063
|
+
* finalization-snapshot enrichment from the onFinalAnswerSupplement
|
|
8064
|
+
* foundation). */
|
|
8065
|
+
export interface FinalAnswerSupplementAttachmentRequest {
|
|
8066
|
+
answer: string;
|
|
8067
|
+
finalText: string;
|
|
8068
|
+
}
|
|
8069
|
+
|
|
8070
|
+
/** Callback type for the attachment point. Return a non-empty string to have
|
|
8071
|
+
* it appended after the final answer; undefined/null/empty keeps the final
|
|
8072
|
+
* answer output unchanged. */
|
|
8073
|
+
export type FinalAnswerSupplementAttachment = (
|
|
8074
|
+
req: FinalAnswerSupplementAttachmentRequest,
|
|
8075
|
+
) => string | null | undefined;
|
|
8076
|
+
|
|
8077
|
+
/** Final-answer supplement attachment point: call the optional
|
|
8078
|
+
* `onAppendFinalAnswerSupplement` handler and return the final answer text
|
|
8079
|
+
* with its supplement appended (or the original text when the handler is
|
|
8080
|
+
* absent or yields nothing). No numeric thresholds are applied. */
|
|
8081
|
+
export function attachFinalAnswerSupplement(
|
|
8082
|
+
handlers: { onAppendFinalAnswerSupplement?: FinalAnswerSupplementAttachment },
|
|
8083
|
+
req: FinalAnswerSupplementAttachmentRequest,
|
|
8084
|
+
): string {
|
|
8085
|
+
const provider = handlers.onAppendFinalAnswerSupplement;
|
|
8086
|
+
if (!provider) return req.finalText;
|
|
8087
|
+
const supplement = provider(req);
|
|
8088
|
+
if (typeof supplement !== 'string' || supplement.trim().length === 0) return req.finalText;
|
|
8089
|
+
const base = req.finalText;
|
|
8090
|
+
if (base.length === 0 || base.endsWith('\n')) return base + supplement.trim();
|
|
8091
|
+
return base + '\n\n' + supplement.trim();
|
|
8092
|
+
}
|
|
8093
|
+
|
|
8182
8094
|
export async function streamLLMWithTools(
|
|
8183
8095
|
messages: LLMMessage[],
|
|
8184
8096
|
handlers: StreamWithToolsHandlers,
|
|
@@ -8194,10 +8106,14 @@ export async function streamLLMWithTools(
|
|
|
8194
8106
|
let blockedProviders: ProviderFallbackAttempt[] = [];
|
|
8195
8107
|
const effectiveModel = activeModel;
|
|
8196
8108
|
const modelFamily = getModelFamily(effectiveModel);
|
|
8109
|
+
// TUI-GPT6-GUARD-PARITY — codex «모델 행동» 가드 켬 여부(단일 원천 = models/prompts.ts
|
|
8110
|
+
// usesCodexBehaviorGuards). gpt-6 세대도 true. 넓힌 자리·안 넓힌 자리는 그 함수 주석이 정본.
|
|
8111
|
+
const codexBehaviorGuards = usesCodexBehaviorGuards(effectiveModel);
|
|
8197
8112
|
debug.log('llm.router', 'streamLLMWithTools', {
|
|
8198
8113
|
provider: provider.name,
|
|
8199
8114
|
model: effectiveModel,
|
|
8200
8115
|
modelFamily,
|
|
8116
|
+
codexBehaviorGuards,
|
|
8201
8117
|
messageCount: messages.length,
|
|
8202
8118
|
messageRoles: summarizeRoles(messages),
|
|
8203
8119
|
tools: opts.tools?.map(t => t.name),
|
|
@@ -8373,6 +8289,12 @@ export async function streamLLMWithTools(
|
|
|
8373
8289
|
};
|
|
8374
8290
|
let fullText = '';
|
|
8375
8291
|
let sawToolRound = false;
|
|
8292
|
+
// TUI-GOAL-LOOP-FRICTION — 종결 신호 도구(LLMOpts.terminalToolNames). 비면 아래 분기는 전부 꺼진다.
|
|
8293
|
+
const terminalToolNames: ReadonlySet<string> = new Set(opts.terminalToolNames ?? []);
|
|
8294
|
+
/** 이 스트림에서 종결 신호를 한 번이라도 디스패치했나. */
|
|
8295
|
+
let terminalSignalDispatched = false;
|
|
8296
|
+
/** 도구 라운드에 실린 마지막 «비지 않은» 답 텍스트(종결 신호 턴 마감·빈 턴 포기에서 쓴다). */
|
|
8297
|
+
let lastToolRoundText = '';
|
|
8376
8298
|
const agentBatchTickIntervalMs = opts.agentBatchTickIntervalMs ?? BATCH_TICK_INTERVAL_MS;
|
|
8377
8299
|
|
|
8378
8300
|
// Empty-turn guard: smaller models (gpt-5.4-mini, haiku) sometimes
|
|
@@ -8436,6 +8358,8 @@ export async function streamLLMWithTools(
|
|
|
8436
8358
|
// instructing the model to reuse prior tool_results or write its
|
|
8437
8359
|
// final answer. Codex-family-only: Claude path is unaffected.
|
|
8438
8360
|
const seenToolCallSignatures = new Map<string, number>();
|
|
8361
|
+
// TUI-INITIATIVE-S ② — 같은 도구·같은 인자가 «같은 오류»로 끝난 횟수(성공하면 지운다). 아래 L-2 차단을 gpt 계열·비탐색 도구로 넓힌다.
|
|
8362
|
+
const erroredToolCallSignatures = new Map<string, { error: string; count: number }>();
|
|
8439
8363
|
// W3-A + extension (2026-05-03) — Broad-spot dedup map. MUST live
|
|
8440
8364
|
// outside the turn loop so the counter persists across turns. (Bug
|
|
8441
8365
|
// 2026-05-03 PM: original placement inside turn loop reset the map
|
|
@@ -8490,6 +8414,8 @@ export async function streamLLMWithTools(
|
|
|
8490
8414
|
// broken dispatch forever. Window=3 mirrors opencode's
|
|
8491
8415
|
// session/processor.ts DOOM_LOOP_THRESHOLD.
|
|
8492
8416
|
const toolErrorDoomTracker = new DoomLoopTracker(3);
|
|
8417
|
+
// Doom-loop self-heal attempts in this turn (guidance first, then stop).
|
|
8418
|
+
let doomSelfHealAttempts = 0;
|
|
8493
8419
|
// A (RESEARCH-autonomous-runaway-discipline-2026-07-19 R1) — the error tracker
|
|
8494
8420
|
// above only fires on *failing* calls; identical *successful* calls (the model
|
|
8495
8421
|
// re-reading / re-grepping the same file over and over — the grep-thrash that
|
|
@@ -8993,19 +8919,37 @@ export async function streamLLMWithTools(
|
|
|
8993
8919
|
verificationLoopState,
|
|
8994
8920
|
finalization,
|
|
8995
8921
|
);
|
|
8996
|
-
|
|
8922
|
+
// 검증 보충 — final-answer supplement attachment point: let the caller
|
|
8923
|
+
// append verification-recency / loop-closure wording after the final
|
|
8924
|
+
// answer (on top of the onFinalAnswerSupplement foundation from PR #27520).
|
|
8925
|
+
const attachedText = attachFinalAnswerSupplement(handlers, { answer: visibleText.trim(), finalText });
|
|
8926
|
+
if (attachedText !== visibleText) {
|
|
8997
8927
|
const answer = visibleText.trim();
|
|
8998
|
-
handlers.onFinalAnswerSupplement?.({ answer, supplement:
|
|
8928
|
+
handlers.onFinalAnswerSupplement?.({ answer, supplement: attachedText.slice(answer.length).trim(), finalText: attachedText });
|
|
8999
8929
|
}
|
|
9000
|
-
if (
|
|
9001
|
-
emitTurnComplete(
|
|
9002
|
-
return
|
|
8930
|
+
if (attachedText !== fullText) handlers.onText('', attachedText);
|
|
8931
|
+
emitTurnComplete(attachedText);
|
|
8932
|
+
return attachedText;
|
|
9003
8933
|
}
|
|
9004
8934
|
|
|
9005
8935
|
// No tool calls + empty text = model stalled. Re-prompt up to
|
|
9006
8936
|
// MAX_EMPTY_RETRIES times. Beyond that, return an explicit
|
|
9007
8937
|
// no-synthesis notice instead of silently ending the turn empty.
|
|
9008
8938
|
if (pendingCalls.length === 0 && turnText.length === 0) {
|
|
8939
|
+
// TUI-GOAL-LOOP-FRICTION(#63) — 종결 신호(update_goal)를 이미 받았고 답도 이미 썼다 = 할 말이 없는 게 맞다.
|
|
8940
|
+
// 빈 턴을 «정체»로 보고 재촉·`[NO FINAL SYNTHESIS]` 를 붙이지 않고 그 답으로 끝낸다.
|
|
8941
|
+
// TUI-H1-GOALLOOP-EMPTY-TAIL — 답이 이 스트림 «앞»에 이미 보였어도 같다(opts.terminalPriorAnswerVisible —
|
|
8942
|
+
// 예: Bash → «끝» → 재주입 → update_goal 만 → 빈 턴). 이 스트림에 답이 없으면 빈 문자열로 끝내고 화면은
|
|
8943
|
+
// 건드리지 않는다(onText 생략 · emitTurnComplete 는 빈 답을 이력에 안 싣는다). 마감은 호출자(goal loop) 몫.
|
|
8944
|
+
if (terminalSignalDispatched && (lastToolRoundText.trim().length > 0 || opts.terminalPriorAnswerVisible === true)) {
|
|
8945
|
+
const answer = lastToolRoundText.trim().length > 0 ? lastToolRoundText : '';
|
|
8946
|
+
debug.log('goal.loop', 'empty-turn-after-terminal-signal', {
|
|
8947
|
+
turn, emptyRetries, answerChars: answer.length,
|
|
8948
|
+
}, { level: 'info' });
|
|
8949
|
+
if (answer.length > 0 && answer !== fullText) handlers.onText('', answer);
|
|
8950
|
+
emitTurnComplete(answer);
|
|
8951
|
+
return answer;
|
|
8952
|
+
}
|
|
9009
8953
|
if (emptyRetries >= MAX_EMPTY_RETRIES) {
|
|
9010
8954
|
const notice = buildNoFinalSynthesisNotice('empty-turn');
|
|
9011
8955
|
const visibleText = finalizeVisibleAssistantText(
|
|
@@ -9041,6 +8985,11 @@ export async function streamLLMWithTools(
|
|
|
9041
8985
|
clearVisibleAssistantTextForToolRound(handlers, sawToolRound);
|
|
9042
8986
|
}
|
|
9043
8987
|
sawToolRound = true;
|
|
8988
|
+
if (turnText.trim().length > 0) lastToolRoundText = turnText;
|
|
8989
|
+
// TUI-GOAL-LOOP-FRICTION(#46) — 이 턴의 호출이 «종결 신호뿐»이면 예산·후속 단계 거부를 걸지 않는다.
|
|
8990
|
+
const terminalOnlyTurn = terminalToolNames.size > 0
|
|
8991
|
+
&& pendingCalls.length > 0
|
|
8992
|
+
&& pendingCalls.every((call) => terminalToolNames.has(call.name));
|
|
9044
8993
|
const wasExploratoryTurn = isExploratoryTurn(pendingCalls);
|
|
9045
8994
|
const prevExploratoryStreak = exploratoryTurnStreak;
|
|
9046
8995
|
exploratoryTurnStreak = wasExploratoryTurn ? exploratoryTurnStreak + 1 : 0;
|
|
@@ -9097,40 +9046,47 @@ export async function streamLLMWithTools(
|
|
|
9097
9046
|
// maxTurns hard-stops it, producing 0 chars of output. Hard
|
|
9098
9047
|
// rejection forces the synthesis that soft pressure couldn't.
|
|
9099
9048
|
const inSynthesisPhase =
|
|
9100
|
-
|
|
9049
|
+
!terminalOnlyTurn
|
|
9050
|
+
&& maxTurns >= BUDGET_WARNING_MIN_TURNS
|
|
9101
9051
|
&& turn >= maxTurns - FINAL_SYNTHESIS_TURNS;
|
|
9102
9052
|
const codexInspectionStillProgressing =
|
|
9103
9053
|
modelFamily === 'codex'
|
|
9104
9054
|
&& autoNarrowedReadCount > 0
|
|
9105
9055
|
&& autoNarrowedReadCount < inspectBudgetThreshold;
|
|
9106
9056
|
const inExplorationSynthesisPhase =
|
|
9107
|
-
|
|
9057
|
+
!terminalOnlyTurn
|
|
9058
|
+
&& exploratoryTurnStreak >= explorationThresholdForTurn
|
|
9108
9059
|
&& isExploratoryTurn(pendingCalls)
|
|
9109
9060
|
&& !codexInspectionStillProgressing;
|
|
9110
9061
|
const inInspectSynthesisPhase =
|
|
9111
|
-
|
|
9062
|
+
!terminalOnlyTurn
|
|
9063
|
+
&& inspectSynthesisArmed
|
|
9112
9064
|
&& inspectFollowupMode === 'synthesis'
|
|
9113
9065
|
&& pendingCalls.length > 0;
|
|
9114
9066
|
const inInspectActionPhase =
|
|
9115
|
-
|
|
9067
|
+
!terminalOnlyTurn
|
|
9068
|
+
&& inspectSynthesisArmed
|
|
9116
9069
|
&& inspectFollowupMode === 'action'
|
|
9117
9070
|
&& !verifyActionArmed
|
|
9118
9071
|
&& pendingCalls.length > 0
|
|
9119
9072
|
&& !isInspectActionTurn(pendingCalls);
|
|
9120
9073
|
const inInspectExecutionPhase =
|
|
9121
|
-
|
|
9074
|
+
!terminalOnlyTurn
|
|
9075
|
+
&& inspectSynthesisArmed
|
|
9122
9076
|
&& inspectFollowupMode === 'execution'
|
|
9123
9077
|
&& !repairActionArmed
|
|
9124
9078
|
&& !verifyActionArmed
|
|
9125
9079
|
&& pendingCalls.length > 0
|
|
9126
9080
|
&& !isExecutionActionTurn(pendingCalls);
|
|
9127
9081
|
const inRepairActionPhase =
|
|
9128
|
-
|
|
9082
|
+
!terminalOnlyTurn
|
|
9083
|
+
&& repairActionArmed
|
|
9129
9084
|
&& !verifyActionArmed
|
|
9130
9085
|
&& pendingCalls.length > 0
|
|
9131
9086
|
&& !isRepairActionTurn(pendingCalls);
|
|
9132
9087
|
const inVerifyActionPhase =
|
|
9133
|
-
|
|
9088
|
+
!terminalOnlyTurn
|
|
9089
|
+
&& verifyActionArmed
|
|
9134
9090
|
&& pendingCalls.length > 0
|
|
9135
9091
|
&& !isVerifyActionTurn(pendingCalls);
|
|
9136
9092
|
const inInspectFollowupPhase =
|
|
@@ -9180,11 +9136,18 @@ export async function streamLLMWithTools(
|
|
|
9180
9136
|
let callsToDispatch = pendingCalls;
|
|
9181
9137
|
let appendedToolResultNotice: string | null = null;
|
|
9182
9138
|
let phaseRejectionMessage: string | null = null;
|
|
9183
|
-
|
|
9139
|
+
// TUI-GOAL-LOOP-FRICTION(#46) — 섞인 턴에서도 종결 신호는 거부 대상에서 뺀다(다른 호출만 거부).
|
|
9140
|
+
const phaseRejectedCalls = getToolLoopPhaseRejectedCalls(inspectFollowupPhase, pendingCalls)
|
|
9141
|
+
.filter((call) => !terminalToolNames.has(call.name));
|
|
9184
9142
|
const phaseRejectedCallIds = new Set(phaseRejectedCalls.map((call) => call.id));
|
|
9185
9143
|
const rejectsWholeBatch = inSynthesisPhase || inExplorationSynthesisPhase || inInspectSynthesisPhase;
|
|
9144
|
+
/** 통째 거부 턴에 섞인 종결 신호 — 거부 스텁 대신 수신 확인을 준다. */
|
|
9145
|
+
const isTerminalCall = (call: { name: string }): boolean => terminalToolNames.has(call.name);
|
|
9146
|
+
const terminalAck = (call: { name: string }): string => JSON.stringify({
|
|
9147
|
+
ok: true, terminalSignal: call.name, note: 'terminal signal recorded; other tool calls in this turn did not run',
|
|
9148
|
+
});
|
|
9186
9149
|
if (rejectsWholeBatch || phaseRejectedCalls.length > 0) {
|
|
9187
|
-
const rejectedCalls = rejectsWholeBatch ? pendingCalls : phaseRejectedCalls;
|
|
9150
|
+
const rejectedCalls = rejectsWholeBatch ? pendingCalls.filter((call) => !isTerminalCall(call)) : phaseRejectedCalls;
|
|
9188
9151
|
const executedCalls = rejectsWholeBatch ? [] : pendingCalls.filter((call) => !phaseRejectedCallIds.has(call.id));
|
|
9189
9152
|
const rejectionMsg =
|
|
9190
9153
|
inspectFollowupPhase
|
|
@@ -9207,8 +9170,17 @@ export async function streamLLMWithTools(
|
|
|
9207
9170
|
phaseRejectionMessage = rejectionMsg;
|
|
9208
9171
|
if (rejectsWholeBatch) {
|
|
9209
9172
|
callsToDispatch = [];
|
|
9210
|
-
|
|
9211
|
-
|
|
9173
|
+
// 공급자 순서를 지키려고 pendingCalls 순서대로 채운다 — 종결 신호만 수신 확인, 나머지는 거부 스텁.
|
|
9174
|
+
for (const call of pendingCalls) {
|
|
9175
|
+
if (isTerminalCall(call)) {
|
|
9176
|
+
terminalSignalDispatched = true;
|
|
9177
|
+
resultBlocks.push({ type: 'tool_result', tool_use_id: call.id, content: terminalAck(call) });
|
|
9178
|
+
debug.log('goal.loop', 'terminal-signal-exempt-from-budget', {
|
|
9179
|
+
turn, maxTurns, tool: call.name, rejectedTools: rejectedCalls.map((c) => c.name),
|
|
9180
|
+
}, { level: 'info' });
|
|
9181
|
+
} else {
|
|
9182
|
+
resultBlocks.push({ type: 'tool_result', tool_use_id: call.id, content: rejectionMsg });
|
|
9183
|
+
}
|
|
9212
9184
|
}
|
|
9213
9185
|
}
|
|
9214
9186
|
// P2 (2026-05-03) — Three predicates as before, but each now consults
|
|
@@ -9459,7 +9431,9 @@ export async function streamLLMWithTools(
|
|
|
9459
9431
|
for (const call of pendingCalls) {
|
|
9460
9432
|
handlers.onToolCall?.(call);
|
|
9461
9433
|
toolCallHistory.push({ name: call.name, args: call.args });
|
|
9462
|
-
handlers.onToolResult?.({
|
|
9434
|
+
handlers.onToolResult?.({
|
|
9435
|
+
id: call.id, name: call.name, result: isTerminalCall(call) ? terminalAck(call) : phaseRejectionMessage!,
|
|
9436
|
+
});
|
|
9463
9437
|
}
|
|
9464
9438
|
}
|
|
9465
9439
|
if (!rejectsWholeBatch && hardStopText === null) {
|
|
@@ -9503,6 +9477,14 @@ export async function streamLLMWithTools(
|
|
|
9503
9477
|
result: unknown,
|
|
9504
9478
|
): void => {
|
|
9505
9479
|
if (call.name !== 'RunShell' && call.name !== 'Bash') return;
|
|
9480
|
+
if (isSteeredShellRejection(result)) {
|
|
9481
|
+
debug.log('llm.router', 'tool-loop.steered-rejection-not-failure', {
|
|
9482
|
+
turn,
|
|
9483
|
+
tool: call.name,
|
|
9484
|
+
approvalKey: (result as { approvalKey: string }).approvalKey,
|
|
9485
|
+
});
|
|
9486
|
+
return;
|
|
9487
|
+
}
|
|
9506
9488
|
const verificationAttempt = verifyActionArmed;
|
|
9507
9489
|
const executionCommand = summarizeExecutionCommand(call.name, call.args);
|
|
9508
9490
|
const executionSummary = summarizeExecutionResult(result);
|
|
@@ -9954,7 +9936,14 @@ export async function streamLLMWithTools(
|
|
|
9954
9936
|
// naturally rotates files (verified 2026-04-25T06:56
|
|
9955
9937
|
// reproduction: docs/CAPABILITIES → PLAN → HANDOFF → ROADMAP
|
|
9956
9938
|
// → src/code-edit/{index,apply,safety}.ts across 5 turns).
|
|
9957
|
-
|
|
9939
|
+
// TUI-INITIATIVE-S ② — 같은 호출이 같은 오류로 DEDUP_THRESHOLD 번 끝났으면 계열·도구 무관(openai-codex·gpt 계열)하게 같은 RE-CALL 차단을 건다.
|
|
9940
|
+
const repeatedError = (modelFamily === 'codex' || modelFamily === 'gpt' || activeProvider.name === 'openai-codex')
|
|
9941
|
+
? erroredToolCallSignatures.get(signatureOf(call)) : undefined;
|
|
9942
|
+
if (repeatedError && repeatedError.count >= DEDUP_THRESHOLD) {
|
|
9943
|
+
debug.log('llm.router', 'tool-loop.dedup-blocked', { turn, tool: call.name, signature: signatureOf(call), priorCount: repeatedError.count, threshold: DEDUP_THRESHOLD, reason: 'repeated-error' });
|
|
9944
|
+
return { result: `${buildDedupStub(call, repeatedError.count)} Every one of those calls failed with the same error: ${repeatedError.error.slice(0, 200)}`, isError: false, phaseRejected: false };
|
|
9945
|
+
}
|
|
9946
|
+
if (codexBehaviorGuards && EXPLORATORY_TOOLS.has(call.name)) {
|
|
9958
9947
|
// W4-anchor — Anchor file Grep blocking. AGENTS.md / CLAUDE.md
|
|
9959
9948
|
// are already in the system prompt; greppling them is pure
|
|
9960
9949
|
// token waste and trains codex to ignore the in-prompt copy.
|
|
@@ -10259,6 +10248,13 @@ export async function streamLLMWithTools(
|
|
|
10259
10248
|
// 스펙을 프로바이더에 선언하지 않는다는 의도가 우회되지 않게.
|
|
10260
10249
|
const resultSignalsError = !!result && typeof result === 'object'
|
|
10261
10250
|
&& typeof (result as { error?: unknown }).error === 'string';
|
|
10251
|
+
{
|
|
10252
|
+
const errSig = signatureOf(call);
|
|
10253
|
+
const errText = resultSignalsError ? (result as { error: string }).error : isError ? String(result) : null;
|
|
10254
|
+
const prevErr = erroredToolCallSignatures.get(errSig);
|
|
10255
|
+
if (errText === null) erroredToolCallSignatures.delete(errSig);
|
|
10256
|
+
else erroredToolCallSignatures.set(errSig, { error: errText, count: prevErr?.error === errText ? prevErr.count + 1 : 1 });
|
|
10257
|
+
}
|
|
10262
10258
|
if (!isError && !resultSignalsError) {
|
|
10263
10259
|
for (const spec of hydrated) {
|
|
10264
10260
|
if (activeToolNames.has(spec.name)) continue;
|
|
@@ -10286,7 +10282,7 @@ export async function streamLLMWithTools(
|
|
|
10286
10282
|
// W4-A — Track Read dispatches (only successful ones; error
|
|
10287
10283
|
// results don't count as "the file is in your context"). The
|
|
10288
10284
|
// post-Read broad-search guard above reads this counter.
|
|
10289
|
-
if (call.name === 'Read' && !isError &&
|
|
10285
|
+
if (call.name === 'Read' && !isError && codexBehaviorGuards) {
|
|
10290
10286
|
dispatchedReadCount++;
|
|
10291
10287
|
}
|
|
10292
10288
|
return { result, isError, phaseRejected: false };
|
|
@@ -10479,12 +10475,25 @@ export async function streamLLMWithTools(
|
|
|
10479
10475
|
};
|
|
10480
10476
|
const partition = phaseRejectedCalls.length > 0
|
|
10481
10477
|
? { parallelActivated: false, safeCount: 0, unsafeCount: callsToDispatch.length }
|
|
10482
|
-
: await dispatchWithParallelSafety(callsToDispatch, dispatchWithPostProc);
|
|
10478
|
+
: await dispatchWithParallelSafety(callsToDispatch, dispatchWithPostProc, opts.signal);
|
|
10483
10479
|
if (phaseRejectedCalls.length > 0) {
|
|
10484
10480
|
for (let index = 0; index < callsToDispatch.length; index++) {
|
|
10481
|
+
if (opts.signal?.aborted) continue;
|
|
10485
10482
|
await dispatchWithPostProc(callsToDispatch[index]!, index);
|
|
10486
10483
|
}
|
|
10487
10484
|
}
|
|
10485
|
+
// ⭐ TUI-ESC-ABORT-TOOLS — 중단(Esc)으로 «시작하지 않은» 호출은 «중단됨» 결과로 채운다
|
|
10486
|
+
// (tool_call/tool_result 짝 유지). `phaseRejected: true` 로 둬 doom·반복 추적에서 뺀다.
|
|
10487
|
+
// 다음 바퀴 머리의 `opts.signal?.aborted` 가 루프를 멈춘다.
|
|
10488
|
+
if (opts.signal?.aborted) {
|
|
10489
|
+
let skipped = 0;
|
|
10490
|
+
for (let index = 0; index < callsToDispatch.length; index++) {
|
|
10491
|
+
if (dispatchedResults[index]) continue;
|
|
10492
|
+
dispatchedResults[index] = { result: 'Tool call not started: the turn was aborted by the user (Esc).', isError: true, phaseRejected: true };
|
|
10493
|
+
skipped++;
|
|
10494
|
+
}
|
|
10495
|
+
if (skipped > 0) debug.log('llm.tools.aborted', 'batch-remaining-skipped', { turn, skipped });
|
|
10496
|
+
}
|
|
10488
10497
|
if (debug.enabled && partition.parallelActivated) {
|
|
10489
10498
|
debug.log('llm.tool-loop.parallel', 'safe-batch-dispatch', {
|
|
10490
10499
|
safeCount: partition.safeCount,
|
|
@@ -10554,41 +10563,36 @@ export async function streamLLMWithTools(
|
|
|
10554
10563
|
debug.log('llm.tool-loop.retry', 'doom-loop-detected', {
|
|
10555
10564
|
turn, tool: doomToolName, window: doomWindow,
|
|
10556
10565
|
}, { level: 'warn' });
|
|
10557
|
-
const
|
|
10566
|
+
const applySelfHeal = (reason: DoomLoopReason, detail: string | null) => {
|
|
10558
10567
|
const interventionClass = classifyDoomLoopIntervention({
|
|
10559
10568
|
detail: [detail, doomFailureDetail].filter(Boolean).join('\n'), doomWindow,
|
|
10560
10569
|
});
|
|
10561
|
-
|
|
10562
|
-
|
|
10563
|
-
|
|
10564
|
-
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
|
|
10568
|
-
|
|
10569
|
-
|
|
10570
|
-
|
|
10571
|
-
|
|
10572
|
-
|
|
10573
|
-
|
|
10574
|
-
}
|
|
10570
|
+
doomSelfHealAttempts += 1;
|
|
10571
|
+
const fingerprint = doomWindow[doomWindow.length - 1] ?? 'unknown';
|
|
10572
|
+
const outcome = decideDoomLoopSelfHeal({
|
|
10573
|
+
attempt: doomSelfHealAttempts, tool: doomToolName, fingerprint, interventionClass,
|
|
10574
|
+
});
|
|
10575
|
+
debug.log('llm.tool-loop.retry', 'doom-loop-self-heal', {
|
|
10576
|
+
turn,
|
|
10577
|
+
tool: doomToolName,
|
|
10578
|
+
attempt: doomSelfHealAttempts,
|
|
10579
|
+
action: outcome.kind,
|
|
10580
|
+
fingerprint,
|
|
10581
|
+
reason,
|
|
10582
|
+
interventionClass: outcome.interventionClass,
|
|
10583
|
+
}, { level: 'warn' });
|
|
10584
|
+
if (outcome.kind === 'guidance') {
|
|
10575
10585
|
toolErrorDoomTracker.reset();
|
|
10576
10586
|
postToolResultUserNote = outcome.userMessage;
|
|
10577
|
-
debug.log('llm.tool-loop.retry', 'doom-loop-ask-guidance', {
|
|
10578
|
-
turn, reason, interventionClass: outcome.interventionClass,
|
|
10579
|
-
});
|
|
10580
10587
|
} else {
|
|
10581
10588
|
hardStopText = outcome.hardStopText;
|
|
10582
|
-
debug.log('llm.tool-loop.retry', outcome.kind === 'fallback' ? 'doom-loop-ask-fallback' : 'doom-loop-ask-stop', {
|
|
10583
|
-
turn, reason, interventionClass: outcome.interventionClass, window: doomWindow,
|
|
10584
|
-
});
|
|
10585
10589
|
}
|
|
10586
10590
|
};
|
|
10587
10591
|
if (retryDecision.action === 'auto-undo') {
|
|
10588
10592
|
if (isPlanModeActive()) {
|
|
10589
|
-
|
|
10593
|
+
applySelfHeal('plan-mode', retryDecision.reason);
|
|
10590
10594
|
} else if (listSnapshots().length === 0) {
|
|
10591
|
-
|
|
10595
|
+
applySelfHeal('no-undo-available', 'UndoTurn: no snapshots available');
|
|
10592
10596
|
} else {
|
|
10593
10597
|
try {
|
|
10594
10598
|
const undoResult = await undoTurnRuntime.run({}, { surface: 'tui' });
|
|
@@ -10602,11 +10606,11 @@ export async function streamLLMWithTools(
|
|
|
10602
10606
|
window: doomWindow,
|
|
10603
10607
|
});
|
|
10604
10608
|
} catch (err) {
|
|
10605
|
-
|
|
10609
|
+
applySelfHeal('undo-failed', err instanceof Error ? err.message : String(err));
|
|
10606
10610
|
}
|
|
10607
10611
|
}
|
|
10608
10612
|
} else {
|
|
10609
|
-
|
|
10613
|
+
applySelfHeal('policy', retryDecision.reason);
|
|
10610
10614
|
}
|
|
10611
10615
|
}
|
|
10612
10616
|
if (executionDoomDetectedThisTurn && !hardStopText) {
|
|
@@ -10806,10 +10810,24 @@ export async function streamLLMWithTools(
|
|
|
10806
10810
|
if (postToolResultUserNote) {
|
|
10807
10811
|
// Appended after the tool_result user turn so the wire order is
|
|
10808
10812
|
// assistant(tool_use) → user(tool_result) → user(intervention).
|
|
10809
|
-
//
|
|
10810
|
-
//
|
|
10813
|
+
// Also carries the doom-loop self-heal guidance — see
|
|
10814
|
+
// decideDoomLoopSelfHeal above.
|
|
10811
10815
|
history.push({ role: LOOP_SELF_NOTE_ROLE, content: postToolResultUserNote });
|
|
10812
10816
|
}
|
|
10817
|
+
// 신호뿐인 턴 · 섞인 턴(정상 디스패치 · 부분 거부 · 통째 거부의 수신 확인) 모두 — 종결 신호가 이 턴에 «받아들여졌다».
|
|
10818
|
+
if (!hardStopText && pendingCalls.some(isTerminalCall)) terminalSignalDispatched = true;
|
|
10819
|
+
// TUI-GOAL-LOOP-FRICTION(#63) — 종결 신호뿐인 턴 ⊕ 같은 턴에 쓴 답 = 이 턴이 최종 답이다.
|
|
10820
|
+
// 다음 모델 턴을 열면 할 말이 없는 모델이 빈 턴을 되풀이하고 `[NO FINAL SYNTHESIS]` 가 붙는다(10-15 22:36Z 표본).
|
|
10821
|
+
// 이 턴에 답이 없으면 종전처럼 다음 턴을 연다(앞 라운드 글은 «하겠습니다» 류 서술일 수 있다 — 모델이 답을 쓰게).
|
|
10822
|
+
if (terminalOnlyTurn && !hardStopText && !postToolResultUserNote && turnText.trim().length > 0) {
|
|
10823
|
+
const answer = turnText;
|
|
10824
|
+
debug.log('goal.loop', 'terminal-signal-finish', {
|
|
10825
|
+
turn, maxTurns, tools: pendingCalls.map((call) => call.name), answerChars: answer.length,
|
|
10826
|
+
}, { level: 'info' });
|
|
10827
|
+
if (answer !== fullText) handlers.onText('', answer);
|
|
10828
|
+
emitTurnComplete(answer);
|
|
10829
|
+
return answer;
|
|
10830
|
+
}
|
|
10813
10831
|
if (hardStopText) {
|
|
10814
10832
|
// W5-E (2026-05-03 PM) — Force-synthesis no-tools pass. Before
|
|
10815
10833
|
// emitting the [SYNTHESIS IGNORED] / [ACTION IGNORED] / [VERIFY
|
|
@@ -10845,7 +10863,7 @@ export async function streamLLMWithTools(
|
|
|
10845
10863
|
// fix shape (no-tools synthesis with prior tool_results as
|
|
10846
10864
|
// context) lifts the empty reply to substantive answer.
|
|
10847
10865
|
const isForceSynthesisFamily =
|
|
10848
|
-
|
|
10866
|
+
codexBehaviorGuards || modelFamily === 'gemini';
|
|
10849
10867
|
const shouldForceSynthesis =
|
|
10850
10868
|
isForceSynthesisFamily
|
|
10851
10869
|
&& !isUserInterventionRequired
|
|
@@ -11013,7 +11031,7 @@ export async function streamLLMWithTools(
|
|
|
11013
11031
|
let synthesizedText: string | null = null;
|
|
11014
11032
|
const shouldForceSynthesisOnBudget =
|
|
11015
11033
|
loopTermination === 'budget-exhausted'
|
|
11016
|
-
&& (
|
|
11034
|
+
&& (codexBehaviorGuards || modelFamily === 'gemini')
|
|
11017
11035
|
&& !forceSynthesisAttempted;
|
|
11018
11036
|
if (shouldForceSynthesisOnBudget) {
|
|
11019
11037
|
forceSynthesisAttempted = true;
|
|
@@ -11894,7 +11912,7 @@ export function getProviderForConfig(
|
|
|
11894
11912
|
// union without a case here fails loud at first call.
|
|
11895
11913
|
throw new Error(`unknown provider: ${provider as string}`);
|
|
11896
11914
|
}
|
|
11897
|
-
import { getModelFamily } from './models/prompts.js';
|
|
11915
|
+
import { getModelFamily, usesCodexBehaviorGuards } from './models/prompts.js';
|
|
11898
11916
|
import type { ModelFamily } from './models/prompts.js';
|
|
11899
11917
|
|
|
11900
11918
|
// COMPAT(llm-facade-openai-sampling-fields) · 기존 llm.ts 공개 API 유지.
|