elanous 0.2.22 → 0.2.23
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/NOTICE +7 -0
- package/README.md +32 -22
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/chunks/{119fc678.6f591cdb84ca5791.js → 0673cc54.8e2ef1c23e49e190.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{a9f2b54d-40c16bd0efdb04b8.js → 0a09e062-34f747a17d8d8c2e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{f8626309.a4e5d362b1d55e59.js → 0e3acd34.d42b2ef87fdf4234.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +77 -0
- package/apps/pwa/out/_next/static/chunks/{7175-350f4ce2873bc038.js → 1325-dc3f3c21eb181cb4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +34 -0
- package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +24 -0
- package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6767.8e6c5f6e744fcd9f.js → 1505.5826671109111e75.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 1669-da843ed73aa301f5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +36 -0
- package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +122 -0
- package/apps/pwa/out/_next/static/chunks/2528.0af5c0e1fad88df6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +62 -0
- package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/272-b23d2e92161d11fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7899.597af4a9996c907f.js → 2721.bc9a8f36bd85c07a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +149 -0
- package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3961-fbef064c213b2b18.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +309 -0
- package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{d70879db.c66c56a95a91efc6.js → 4c5e95ce.83e9b16add6fcd8c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6158.566c890adc06a459.js → 5313.1697309c532b9856.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{79b78388.663188133449d707.js → 53746282.1be36038d1abd949.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5578.ac963634373b28c6.js +286 -0
- package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5967-c0a80f8ffe5d4050.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 5974.360f8441eb0ac1ec.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +74 -0
- package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6571-926ddf024a6ad5df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +64 -0
- package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9832.2ab2e818013574c7.js → 6702.ebbd165d5e4a4a14.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +32 -0
- package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +24 -0
- package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +93 -0
- package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 740.90b31555290236a9.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +148 -0
- package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{9070.067c106528ec1ae6.js → 7518.49161e8f5814abdb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +27 -0
- package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +115 -0
- package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7905.b230b9d06cb4ad5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8194.484f51e273d9abd2.js → 8264.00e434fbd02e9311.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{088d8e8a.8069543d082bec12.js → 83cfc5c8.349535543c1548b6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +23 -0
- package/apps/pwa/out/_next/static/chunks/{1948.5f35b39eef222a94.js → 8438.ee7f0df3b3f6fcb4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4588.ad3364cb7fb97ada.js → 8532.a86e99acf9b761cb.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/8569.b853a8daa8f31d12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8925-2abfb48af477fb7f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{88729267.9c6c000157c83f2f.js → 89849432.9eaa2f4c9c010965.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +90 -0
- package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +94 -0
- package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +41 -0
- package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +287 -0
- package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +79 -0
- package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3522-1de1319d028ac89c.js → 9502-32c5dc22e8f120f5.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{7630.2b9a68659053ff4e.js → 9976.8f28864317639fe6.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d5341ac96203a983.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-0160ab83c8685a12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-55c631c032dcc47e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-ad3bd8084048bee4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e6784759a2531031.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-5c5d0e370f495ef6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-c325e21543cd48a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/{page-80ed511e02c81412.js → page-6168a7c43e6ef8f5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-31417d3604154a6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-e9606dc0bdec9305.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-a648bc464c9dc754.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-25bb425afdb27541.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-32d72fdef1afe11a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-d27b794c8ba76bbb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-2bd9ce9c020d02d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a34096245e63b9f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-22170f4f00a15496.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-4cc66d22ca4ec502.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-83b14c729fcea837.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-6e2781c523dad761.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-26dd415c8f13f341.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-ccdb83ed40c8d724.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-7ad3de8fa06fdea9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-015c02c4fec4023e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-6b0ae5b5c42f6d2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-786111f30b6f0969.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-48fb31810693c357.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e17cce5e2ed0fee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-cb154acadb025414.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-16258e956ea93fc2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-c2dd2b19c93f90ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f35dd1dd96ae87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-d3c007c8a0ddd7ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7837ce2aacb97b04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7350ee93f4fe1033.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-00723458575f2b19.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-745d9b6c015076f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-736d33c7414a8a1a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-119be9a0444d2482.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-fa806c018833e332.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-c782041b5f5199ba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-d431fbdea6ad93dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-0c056abff82b9891.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-242d668e4fbf72c4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-847c3de6ca8a4416.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-81dd0d8ae923ed72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-74e69ba2c8e970d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-70038f41ae7cf931.js +1 -0
- package/apps/pwa/out/_next/static/chunks/b4e12462-5fab4a813a63dadd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → ce383d63.d2ede338788ed18e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{framework-5c169757551134ed.js → framework-b2763b10dc6b3836.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +1 -0
- package/apps/pwa/out/_next/static/css/5619d59e87eddf66.css +1 -0
- package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +1 -0
- package/apps/pwa/out/_next/static/{aBi6EyMtLsrl7J8eH4kF7 → rfkMm4movqkqMebBrCXiR}/_buildManifest.js +1 -1
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +24 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +24 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/catalog/models/anthropic/claude-haiku-5-5.yaml +32 -0
- package/catalog/models/anthropic/claude-opus-5-5.yaml +5 -0
- package/catalog/models/anthropic/claude-sonnet-5-5.yaml +31 -0
- package/catalog/models/anthropic/claude-sonnet-5.yaml +8 -2
- package/catalog/models/openai/gpt-6-astra.yaml +6 -0
- package/catalog/models/openai/gpt-6-luna.yaml +6 -0
- package/catalog/models/openai/gpt-6-sol.yaml +6 -0
- package/graphs/log-horizon/log-horizon-watch.yaml +25 -0
- package/graphs/log-horizon/recipes.yaml +3 -0
- package/graphs/release/recipes.yaml +1 -1
- package/graphs/release/release-loop.yaml +6 -2
- package/graphs/release-rehearsal/recipes.yaml +12 -0
- package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
- package/package.json +4 -1
- package/scripts/bench-report.ts +82 -3
- package/scripts/ci-typecheck-changed.ts +10 -1
- package/scripts/hq/hq-fence-wrapper.sh +148 -0
- package/scripts/lib/typecheck-ratchet.ts +51 -0
- package/scripts/openai-relay-server.ts +5 -1
- package/scripts/release-loop/docs-node.ts +258 -43
- package/scripts/release-loop/gate-method.ts +59 -0
- package/scripts/release-loop/gate-node.ts +73 -7
- package/scripts/release-loop/gate-wall.ts +208 -0
- package/scripts/release-loop/known-issues-node.ts +53 -8
- package/scripts/release-loop/publish-at.ts +14 -0
- package/scripts/release-loop/publish-node.ts +17 -2
- package/scripts/release-loop/resume-release.ts +34 -4
- package/scripts/release-loop/resume.ts +53 -0
- package/scripts/release-loop/shard-plan.ts +3 -11
- package/scripts/release-loop/tui-node-checks.ts +22 -0
- package/scripts/release-loop/unattended-release.ts +8 -1
- package/scripts/rhythm/daily.ts +51 -2
- package/scripts/rhythm/weekly.ts +3 -2
- package/scripts/tsc-main-safety-net.ts +189 -0
- package/scripts/usage-rollup.ts +8 -4
- package/src/acp/codex-plugins.ts +48 -6
- package/src/agent/monad-agent-turn.ts +67 -5
- package/src/agent/run-context.ts +10 -0
- package/src/agent/tool-profile.ts +28 -2
- package/src/agent-mission/acp-judge.ts +8 -2
- package/src/agent-mission/capabilities-cli.ts +16 -1
- package/src/agent-mission/driver.ts +1 -1
- package/src/agent-mission/pr-review-watch.ts +6 -2
- package/src/agent-mission/review-loop.ts +33 -5
- package/src/agent-substrate/acp-reviewer.ts +17 -8
- package/src/agent-substrate/pr-reviewer.ts +164 -28
- package/src/agent-substrate/review-intent.ts +6 -4
- package/src/agent-substrate/self-review-cli.ts +111 -16
- package/src/agent-substrate/shard-boundary-intent.ts +92 -26
- package/src/ask-user-question/pending-questions.ts +8 -2
- package/src/autopilot/build/llm-conflict-merge.ts +216 -12
- package/src/autopilot/codebase-grounding.ts +44 -0
- package/src/autopilot/llm-control-brain.ts +13 -1
- package/src/autopilot/mission-codebase-gate.ts +8 -77
- package/src/autopilot/pr-manager.ts +12 -3
- package/src/boot/acp-server.ts +4 -7
- package/src/boot/acp-socket-path.ts +7 -0
- package/src/briefing/brief-items.ts +21 -13
- package/src/chat/index.ts +12 -3
- package/src/cli/agent-cli.ts +20 -0
- package/src/cli/brief-cli.ts +27 -21
- package/src/cli/cli-user-error.ts +9 -2
- package/src/cli/log-event-names.ts +3 -0
- package/src/cli/logs-cli.ts +1 -0
- package/src/cli/mcp-login.ts +111 -37
- package/src/cli/plugin-cli.ts +21 -1
- package/src/cli/pod-cli.ts +26 -0
- package/src/cli/pr-cli.ts +30 -2
- package/src/cli/pr-land-overlap-evidence.ts +131 -0
- package/src/cli/release-cli.ts +53 -11
- package/src/cli/self-update.ts +173 -10
- package/src/cli/skills-cli.ts +12 -3
- package/src/cli/tasks-cli.ts +133 -27
- package/src/context-bus/context-first.ts +51 -2
- package/src/context-bus/context-now-surfaces.ts +13 -2
- package/src/context-bus/long-term-memory.ts +3 -1
- package/src/context-bus/nightly-condense.ts +3 -2
- package/src/core-turn/run-goal-loop.ts +86 -2
- package/src/dashboard/chat-fold.ts +20 -0
- package/src/dashboard/first-screen-band.ts +151 -1
- package/src/dashboard/index.ts +27 -5
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +5 -3
- package/src/dashboard/stale-install-check.ts +13 -2
- package/src/dashboard/turn-stream-formatter.ts +25 -0
- package/src/debug/log-diet.ts +159 -0
- package/src/debug/log.ts +52 -17
- package/src/display/coordinator.ts +25 -2
- package/src/domains/coo-admin-tool.ts +27 -0
- package/src/domains/cron-match.ts +1 -0
- package/src/domains/outbound-alert.ts +17 -6
- package/src/domains/release-tool.ts +119 -10
- package/src/domains/schedule-registry.ts +10 -7
- package/src/domains/schedule-runner.ts +1 -0
- package/src/elanous-config-dir.ts +2 -2
- package/src/elanous-daemon.ts +3 -3
- package/src/execution-loop/launch-gate.ts +1 -1
- package/src/expression/i18n/messages.en.ts +5 -0
- package/src/expression/i18n/messages.ja.ts +5 -0
- package/src/expression/i18n/messages.ko.ts +5 -0
- package/src/expression/i18n/messages.zh.ts +5 -0
- package/src/expression/i18n/types.ts +8 -0
- package/src/github/pr-labels.ts +1 -0
- package/src/graph-runner/runner.ts +54 -5
- package/src/harness/dispatch-backpressure.ts +259 -0
- package/src/harness/harness-cli-command.ts +107 -28
- package/src/harness/harness-seams.ts +2 -20
- package/src/harness/harness-substrate-default.ts +72 -1
- package/src/harness/nested-elanous-policy.ts +4 -2
- package/src/hq/fence-wrapper.ts +7 -0
- package/src/hq/hq.ts +33 -2
- package/src/hq/lease.ts +13 -0
- package/src/hq/seats.ts +114 -18
- package/src/index.ts +163 -64
- package/src/intake-plane/collect-github.ts +19 -1
- package/src/intake-plane/digest.ts +45 -20
- package/src/intake-plane/lens.ts +36 -8
- package/src/intelligence-map/model-alias.ts +6 -0
- package/src/intelligence-map/model-catalog.ts +41 -0
- package/src/knowledge/kgs/pack.ts +5 -2
- package/src/knowledge/kgs/sqlite-store.ts +15 -0
- package/src/knowledge/tools/knowledge-query.ts +20 -2
- package/src/knowledge/write.ts +234 -2
- package/src/llm/bedrock-provider.ts +175 -0
- package/src/llm/bedrock.ts +345 -0
- package/src/llm/provider-credentials.ts +3 -1
- package/src/llm.ts +306 -35
- package/src/loops/budget.ts +150 -0
- package/src/loops/orchestrator/seat-share.ts +6 -49
- package/src/loops/orchestrator/traffic.ts +5 -81
- package/src/market/signed-index.ts +42 -0
- package/src/mcp/mcp-oauth.ts +136 -17
- package/src/model-tier/llm-tier-map.ts +48 -4
- package/src/models/prompts.ts +22 -1
- package/src/mss/logging/horizon-watch.ts +168 -0
- package/src/mss/logging/log-store.ts +204 -15
- package/src/native-tool-catalog.ts +1 -1
- package/src/nexus/api/consult-requests.ts +7 -10
- package/src/nexus/api/discord-trigger-bot.ts +6 -3
- package/src/nexus/api/error-reports.ts +30 -8
- package/src/nexus/api/http-server.ts +8 -0
- package/src/nexus/api/loop-resources.ts +42 -0
- package/src/nexus/api/outbound-report.ts +8 -3
- package/src/nexus/api/telegram-trigger-bot.ts +6 -3
- package/src/nexus/index.ts +10 -0
- package/src/nexus/outbound/format.ts +2 -0
- package/src/nexus/outbound/router.ts +198 -13
- package/src/oauth/codex-account-rotation.ts +16 -18
- package/src/oauth/codex-account-store.ts +134 -5
- package/src/oauth/fallback-chain.ts +28 -6
- package/src/onboarding.ts +2 -1
- package/src/plugins/adapters/claude-package.ts +4 -12
- package/src/plugins/core/capability-policy.ts +141 -0
- package/src/plugins/core/host.ts +21 -8
- package/src/plugins/core/manifest.ts +19 -2
- package/src/plugins/core/trust-store.ts +15 -0
- package/src/plugins/core/types.ts +12 -0
- package/src/plugins/install/market-fetch.ts +68 -16
- package/src/plugins/install/plugin-install.ts +187 -16
- package/src/plugins/maker/plugin-maker.ts +25 -20
- package/src/plugins/maker/wizard-generate.ts +16 -2
- package/src/policy/llm-policy.ts +14 -1
- package/src/process/pid-liveness.ts +1 -1
- package/src/prompt-cache/openai.ts +10 -6
- package/src/prompt-cache/openrouter.ts +94 -0
- package/src/prompt-enhance/enhance.ts +46 -5
- package/src/prompt-library/family-prompt-coverage.ts +1 -0
- package/src/prompt-library/universal-preamble.ts +2 -2
- package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
- package/src/registry/loader.ts +6 -1
- package/src/release-loop/checklist.ts +24 -9
- package/src/release-loop/feature-store.ts +3 -0
- package/src/release-loop/gate-shards.ts +48 -4
- package/src/release-loop/landed-to-green.ts +81 -0
- package/src/release-loop/light-rc.ts +11 -1
- package/src/release-loop/merged-pr-checklist.ts +10 -0
- package/src/release-loop/placement.ts +91 -22
- package/src/release-loop/rehearsal.ts +317 -0
- package/src/release-loop/release-schedule.ts +13 -1
- package/src/release-loop/rubric-types.ts +1 -0
- package/src/release-loop/rubric.ts +2 -2
- package/src/retro/daily.ts +23 -9
- package/src/seat-loop/seat-loop.ts +34 -1
- package/src/seat-loop/traffic-signal.ts +44 -0
- package/src/self-dev/ask-launch-flow.ts +2 -2
- package/src/self-dev/dev-cli.ts +67 -3
- package/src/self-dev/dev-pipeline.ts +4 -6
- package/src/self-dev/draft-residue.ts +463 -0
- package/src/self-dev/draft-sweep.ts +151 -10
- package/src/self-dev/draft-triage-rules.ts +27 -1
- package/src/self-dev/launch-preflight-text.ts +549 -0
- package/src/self-dev/launch-preflight.ts +10 -545
- package/src/self-dev/orchestrate-cli.ts +57 -2
- package/src/self-dev/orchestrate-summary-line.ts +13 -0
- package/src/self-dev/orchestrate.ts +8 -135
- package/src/self-dev/review-provider-fallback.ts +115 -19
- package/src/self-dev/run-store.ts +1 -3
- package/src/self-dev/run-supervisor.ts +3 -22
- package/src/self-dev/run-types.ts +178 -0
- package/src/self-dev/shard-aggregate.ts +61 -13
- package/src/self-dev/shard-plan.ts +5 -1
- package/src/self-dev/shard-run.ts +23 -5
- package/src/self-dev/supervisor-verdict-edges.ts +2 -4
- package/src/self-implement/blocked-draft-policy.ts +3 -19
- package/src/self-implement/draft-on-stop-mode.ts +18 -0
- package/src/self-implement/follow-up-goals.ts +114 -38
- package/src/self-implement/gate-baseline-reap.ts +157 -0
- package/src/self-implement/gate-baseline.ts +78 -16
- package/src/self-implement/gate-cli.ts +12 -2
- package/src/self-implement/gate-remote.ts +17 -6
- package/src/self-implement/goal-author.ts +24 -4
- package/src/self-implement/goal-digest.ts +19 -0
- package/src/self-implement/graph-overlay-condition.ts +4 -0
- package/src/self-implement/headless-elanous-driver.ts +11 -9
- package/src/self-implement/host-regate.ts +120 -29
- package/src/self-implement/l8-merge-queue.ts +67 -5
- package/src/self-implement/merge-train.ts +131 -0
- package/src/self-implement/off-diff-evidence.ts +9 -0
- package/src/self-implement/orchestrator.ts +133 -16
- package/src/self-implement/review-finding-recurrence.ts +28 -0
- package/src/self-implement/rework-policy.ts +2 -1
- package/src/self-implement/round-summary-card.ts +63 -0
- package/src/self-implement/run-ledger.ts +4 -3
- package/src/self-implement/run-step-projection.ts +147 -0
- package/src/self-implement/run-stop.ts +1 -1
- package/src/self-implement/seams.ts +36 -3
- package/src/self-implement/self-implement-cli.ts +3 -1
- package/src/self-implement/train-gate-remote.ts +158 -0
- package/src/session-runtime/index.ts +10 -1
- package/src/session-runtime/retry-api.ts +11 -1
- package/src/skills/gift-install.ts +119 -0
- package/src/skills/runner.ts +59 -2
- package/src/skills/skill-feedback.ts +31 -1
- package/src/skills/skill-tier.ts +1 -0
- package/src/smart-wizard/capability-index.ts +231 -0
- package/src/smart-wizard/rung.ts +74 -0
- package/src/steward/launch.ts +20 -9
- package/src/steward/triage.ts +4 -2
- package/src/storage/file-lock.ts +8 -1
- package/src/task-agent/actions.ts +4 -0
- package/src/task-agent/card-evidence.ts +59 -13
- package/src/task-agent/judge.ts +4 -3
- package/src/task-agent/land-worktree.ts +201 -0
- package/src/task-agent/live-move-history.ts +133 -0
- package/src/task-agent/live-moves.ts +106 -19
- package/src/task-agent/parent-host.ts +117 -8
- package/src/task-agent/rejudge-on-head.ts +297 -0
- package/src/task-agent/review-result-capture.ts +218 -0
- package/src/task-agent/shadow.ts +103 -7
- package/src/task-agent/task-hand.ts +136 -11
- package/src/task-orchestrator/surfaces/pod-child-providers.ts +29 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +16 -2
- package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +93 -12
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +25 -2
- package/src/task-orchestrator/surfaces/pod-pool.ts +66 -14
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +259 -36
- package/src/task-orchestrator/surfaces/self-implement.ts +6 -2
- package/src/telegram-service.ts +5 -1
- package/src/telegram.ts +17 -4
- package/src/time/format.ts +13 -4
- package/src/tool-runtime/goal-author-runtime.ts +1 -0
- package/src/tool-runtime/self-cognition-catalog.ts +23 -0
- package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
- package/src/user-config.ts +132 -24
- package/src/ux-sim/slash-menu-frames.ts +168 -0
- package/src/version/packed-revision.json +1 -1
- package/src/web-terminal/preview-tap-registry.ts +5 -2
- package/src/workflow-runtime/triggers/scheduler.ts +1 -0
- package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
- package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
- package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
- package/apps/pwa/out/_next/static/chunks/1307-08b716476f1d50af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
- package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
- package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
- package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
- package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
- package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
- package/apps/pwa/out/_next/static/chunks/2489-d238d3e2eb5b2bf5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
- package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3857-5985236d9307f676.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
- package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
- package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
- package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5633-d6852385000738ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
- package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-5b9e8a45a5b0c823.js +0 -1
- package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
- package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
- package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
- package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
- package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
- package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
- package/apps/pwa/out/_next/static/chunks/8857-aa1cc4ac90af4d40.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
- package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9247-55bcfbb0e8057f59.js +0 -1
- package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
- package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-88459e0903da2803.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d85c43f46f58716b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-4e645600579ae952.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-87edbfd19117823b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7f0c2b7801ac6a54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-bf1f030a9d1adffd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-cbaf66b1e1804adf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-9f5610caaa06178c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-ec8f3575e339de74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-86d753e460f1a989.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-4166a7d51cf0a57d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-2a19c5cd3b562580.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-b6a09cde2e07521a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-f7eae1518ca0c353.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-456a8573ad811381.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-8462d6a543cbb2d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-2974cdfb87c0f9c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-f927ffa25f3c86d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-abd86cd832aaa011.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-79daf68f6256adaa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8c3f168fc3f91939.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-786fb4504d0f2fa9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-75209f14597dcb8f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-bf30affe3a85af7e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1187a44b7515434b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-3d0910185a66ed54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f401ee1dd5a26e25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-5dfe7604fd842784.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-76cf838050a8d681.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-7ec8e289b4c14df6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-8c8ac17d52be2a79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-d359ab048d63a9d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-b8b345c880bf78d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-f151cc10ad026940.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9875f103057da433.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-9789328af9a9aa62.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-bf495a1e284f4e00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-a263d94bca4be22a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-3962eab8ec58d16e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-9abcfac07e02a542.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-bee49f927c333abb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-bac2d56dcb02d955.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-937cbcc13176295c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d09495594f7f480d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-69cb93d1a2e57e0e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-72ec543928d67c3e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-82906eeda0186a7b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
- package/apps/pwa/out/_next/static/css/f2bd5257e6af88d8.css +0 -1
- /package/apps/pwa/out/_next/static/{aBi6EyMtLsrl7J8eH4kF7 → rfkMm4movqkqMebBrCXiR}/_ssgManifest.js +0 -0
package/src/llm.ts
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import { createHash } from 'node:crypto';
|
|
6
6
|
import type { LLMUsage } from './prompt-cache/types.js';
|
|
7
|
+
import { applyOpenRouterCacheControl, openRouterPromptCacheFamily } from './prompt-cache/openrouter.js';
|
|
8
|
+
import { detectLocale, type Locale } from './expression/locale.js';
|
|
9
|
+
import { format, getMessages } from './expression/i18n/index.js';
|
|
7
10
|
import type { ModelRole } from './user-config.js';
|
|
8
11
|
// ⭐ grok 자격 해석 — 구독(OAuth) 1순위 · API 키 2순위. ACP 경로와 «같은» 규칙.
|
|
9
12
|
import { isGrokUnauthorized, refreshGrokSubscriptionToken, resolveFreshGrokCredential, resolveGrokCredential } from './grok/credential.js';
|
|
@@ -16,7 +19,7 @@ import {
|
|
|
16
19
|
getGeminiApiKey, GEMINI_MODEL,
|
|
17
20
|
DEFAULT_PROVIDER,
|
|
18
21
|
} from './config.js';
|
|
19
|
-
import { debug, redactSecrets } from './debug/log.js';
|
|
22
|
+
import { debug, redactSecrets, redactSecretText } from './debug/log.js';
|
|
20
23
|
import { llmUsageCostFields } from './budget/llm-cost.js';
|
|
21
24
|
import { ToolCallTiming } from './chat/tool-call-timing.js';
|
|
22
25
|
import {
|
|
@@ -37,8 +40,9 @@ import {
|
|
|
37
40
|
type ProviderFallbackTerminalVerdict,
|
|
38
41
|
} from './session-runtime/retry-policy.js';
|
|
39
42
|
import { fetchApiWithRetry, OverloadFailoverError, type FetchApiWithRetryOpts } from './session-runtime/retry-api.js';
|
|
43
|
+
import { BedrockProvider, isBedrockCompatibleModel, makeBedrockProvider } from './llm/bedrock-provider.js';
|
|
40
44
|
import { resolveModelAlias } from './intelligence-map/model-alias.js';
|
|
41
|
-
import { reasoningEffortCeiling as reasoningEffortCeilingOf } from './intelligence-map/model-catalog.js';
|
|
45
|
+
import { BUILTIN_CATALOG, reasoningEffortCeiling as reasoningEffortCeilingOf } from './intelligence-map/model-catalog.js';
|
|
42
46
|
import { inferProviderFromModel as registryInferProviderFromModel } from './registry/normalize.js';
|
|
43
47
|
import { closestMatches } from './tool-name-suggest.js';
|
|
44
48
|
import { undoTurnRuntime } from './tool-runtime/undo-turn-runtime.js';
|
|
@@ -86,6 +90,8 @@ export type ToolResultContentItem =
|
|
|
86
90
|
* - `reasoningDetails`: OpenRouter `reasoning_details[]` — 2026-09-23 · Kimi K3·GLM 은 도구 루프에서 이전 추론을
|
|
87
91
|
* 되돌려 받아야 한다(Kimi 공식 문서: 「K3 는 다중 턴·도구 호출 루프에서 필수」 · OpenRouter 가 이 배열로 통일). */
|
|
88
92
|
export interface ProviderToolMeta { thoughtSignature?: string; reasoningDetails?: Array<Record<string, unknown>> }
|
|
93
|
+
/** OR-TOOLARGS-REPAIR — 깨진 도구 인자의 요약(원문은 싣지 않는다 · 길이와 끝난 이유만). */
|
|
94
|
+
export interface ToolArgsInvalid { chars: number; finishReason: string | null }
|
|
89
95
|
|
|
90
96
|
export type ContentBlock =
|
|
91
97
|
| { type: 'text'; text: string }
|
|
@@ -274,6 +280,10 @@ export type LLMStreamEvent =
|
|
|
274
280
|
* ("Function call is missing a thought_signature"). Other
|
|
275
281
|
* providers ignore this field. */
|
|
276
282
|
providerMeta?: ProviderToolMeta;
|
|
283
|
+
/** OR-TOOLARGS-REPAIR (2026-10-10) — 인자 JSON 이 깨져(잘림·문법 오류) 파싱에 실패했다는 표지.
|
|
284
|
+
* ⛔ OpenRouter 경로(`parseOpenAISSELines` 의 `flagInvalidToolArgs`)에서만 실린다 — 다른 공급자는 종전대로
|
|
285
|
+
* `{}` 로 대체되고 이 칸이 없다. 실리면 `args` 는 `{}` 이고, 도구 루프는 실행하지 않고 오류 결과를 돌려준다. */
|
|
286
|
+
argsInvalid?: ToolArgsInvalid;
|
|
277
287
|
}
|
|
278
288
|
/** Reasoning-summary delta from Codex Responses API (gpt-5 family).
|
|
279
289
|
* `summary_part_added` is a separator marking the boundary between
|
|
@@ -322,6 +332,8 @@ export interface LLMOpts {
|
|
|
322
332
|
temperature?: number;
|
|
323
333
|
maxTokens?: number;
|
|
324
334
|
signal?: AbortSignal;
|
|
335
|
+
/** Override the text-stream idle watchdog per request (milliseconds). */
|
|
336
|
+
streamIdleTimeoutMs?: number;
|
|
325
337
|
/** Optional per-request usage telemetry from the provider stream. */
|
|
326
338
|
onUsage?(usage: LLMUsage): void;
|
|
327
339
|
/** Optional model role attached to this request's usage observation. */
|
|
@@ -370,7 +382,9 @@ export interface LLMOpts {
|
|
|
370
382
|
/** Prompt-caching toggle. Honored by Anthropic (attaches
|
|
371
383
|
* cache_control markers on system + tools + 2nd-to-last history
|
|
372
384
|
* message) and OpenAI (passes stream_options.include_usage so
|
|
373
|
-
* the automatic cache telemetry reaches us).
|
|
385
|
+
* the automatic cache telemetry reaches us). OpenRouter `anthropic/*` ·
|
|
386
|
+
* `moonshotai/*` get part-level cache_control on system (first 2) + last 2
|
|
387
|
+
* messages (`src/prompt-cache/openrouter.ts`). Default `true`.
|
|
374
388
|
* Pass `false` for tests that pin the legacy wire shape. */
|
|
375
389
|
promptCache?: boolean;
|
|
376
390
|
/** Cache TTL tier. `'5m'` (default) is the ephemeral tier; `'1h'`
|
|
@@ -1109,7 +1123,12 @@ function parseHarmonyHeader(header: string): { channel: HarmonyChannel; toolName
|
|
|
1109
1123
|
* unit tests — no fetch dependency. */
|
|
1110
1124
|
export async function* parseOpenAISSELines(
|
|
1111
1125
|
lines: AsyncIterable<string> | Iterable<string>,
|
|
1126
|
+
/** OR-TOOLARGS-REPAIR (2026-10-10) — `flagInvalidToolArgs` 가 참이면(OpenRouter 경로) 인자 JSON 파싱 실패를
|
|
1127
|
+
* `{}` 로 «조용히» 바꾸지 않고 `argsInvalid` 표지를 단다(도구 루프가 실행을 막는다) ⊕ 관측을 남긴다.
|
|
1128
|
+
* ⛔ 생략·거짓이면 종전과 바이트 동일(다른 공급자 무변경). */
|
|
1129
|
+
parseOpts: { flagInvalidToolArgs?: boolean } = {},
|
|
1112
1130
|
): AsyncGenerator<LLMStreamEvent, void, unknown> {
|
|
1131
|
+
const flagInvalidToolArgs = parseOpts.flagInvalidToolArgs === true;
|
|
1113
1132
|
const { parseOpenAIUsage } = await import('./prompt-cache/openai.js');
|
|
1114
1133
|
// Indexed by `tc.index` (OpenAI standard) — partial-chunk streaming
|
|
1115
1134
|
// assembles into a single accumulator per index. Gemini OpenAI-compat
|
|
@@ -1126,10 +1145,25 @@ export async function* parseOpenAISSELines(
|
|
|
1126
1145
|
reasoningDetailsAttached = true;
|
|
1127
1146
|
return [...reasoningDetailsAcc.values()];
|
|
1128
1147
|
};
|
|
1129
|
-
const yieldAccum = (acc: OpenAIToolCallAccum): LLMStreamEvent | null => {
|
|
1148
|
+
const yieldAccum = (acc: OpenAIToolCallAccum, finishReason: string | null): LLMStreamEvent | null => {
|
|
1130
1149
|
if (!acc.name) return null;
|
|
1131
1150
|
let args: Record<string, unknown> = {};
|
|
1132
|
-
|
|
1151
|
+
let argsInvalid: ToolArgsInvalid | undefined;
|
|
1152
|
+
try {
|
|
1153
|
+
args = acc.argsJson ? JSON.parse(acc.argsJson) : {};
|
|
1154
|
+
} catch {
|
|
1155
|
+
// 종전: `{}` 로 대체해 도구가 엉뚱한 기본값으로 돌았다(조용한 실패). OpenRouter 경로만 표지를 단다.
|
|
1156
|
+
if (flagInvalidToolArgs) {
|
|
1157
|
+
argsInvalid = { chars: acc.argsJson.length, finishReason };
|
|
1158
|
+
debug.log('llm.openrouter', 'tool-args-invalid', {
|
|
1159
|
+
tool: acc.name,
|
|
1160
|
+
chars: acc.argsJson.length,
|
|
1161
|
+
finishReason,
|
|
1162
|
+
// 원문은 앞 몇십 자만 · 비밀 가림.
|
|
1163
|
+
head: redactSecretText(acc.argsJson.slice(0, 60)),
|
|
1164
|
+
}, { level: 'warn' });
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1133
1167
|
const reasoningDetails = takeReasoningDetails();
|
|
1134
1168
|
const meta: ProviderToolMeta = {
|
|
1135
1169
|
...(acc.thoughtSignature !== undefined ? { thoughtSignature: acc.thoughtSignature } : {}),
|
|
@@ -1141,6 +1175,7 @@ export async function* parseOpenAISSELines(
|
|
|
1141
1175
|
name: acc.name,
|
|
1142
1176
|
args,
|
|
1143
1177
|
...(Object.keys(meta).length > 0 ? { providerMeta: meta } : {}),
|
|
1178
|
+
...(argsInvalid !== undefined ? { argsInvalid } : {}),
|
|
1144
1179
|
};
|
|
1145
1180
|
};
|
|
1146
1181
|
// Per-stream Harmony filter — routes `<|channel|>final` content to
|
|
@@ -1242,7 +1277,7 @@ export async function* parseOpenAISSELines(
|
|
|
1242
1277
|
// (or omit id on continuation frags), so this only triggers on
|
|
1243
1278
|
// the Gemini complete-frag pattern.
|
|
1244
1279
|
if (accum && tc.id && accum.id && tc.id !== accum.id && accum.argsJson.length > 0) {
|
|
1245
|
-
const ev = yieldAccum(accum);
|
|
1280
|
+
const ev = yieldAccum(accum, null);
|
|
1246
1281
|
if (ev) yield ev;
|
|
1247
1282
|
accum = undefined;
|
|
1248
1283
|
toolCalls.delete(idx);
|
|
@@ -1293,8 +1328,17 @@ export async function* parseOpenAISSELines(
|
|
|
1293
1328
|
(choice.finish_reason === 'tool_calls'
|
|
1294
1329
|
|| (choice.finish_reason && toolCalls.size > 0))
|
|
1295
1330
|
) {
|
|
1331
|
+
// OR-TOOLARGS-REPAIR — 출력 상한에서 잘린 턴(`length`)의 도구 호출은 인자가 온전해 보여도 «잘렸을 수 있다».
|
|
1332
|
+
// 관측만 남긴다(파싱 실패면 yieldAccum 이 `argsInvalid` 로 막는다). 상한 조정은 범위 밖.
|
|
1333
|
+
if (flagInvalidToolArgs && choice.finish_reason === 'length' && toolCalls.size > 0) {
|
|
1334
|
+
debug.log('llm.openrouter', 'tool-args-maybe-truncated', {
|
|
1335
|
+
finishReason: 'length',
|
|
1336
|
+
tools: [...toolCalls.values()].map((tc) => tc.name),
|
|
1337
|
+
chars: [...toolCalls.values()].map((tc) => tc.argsJson.length),
|
|
1338
|
+
}, { level: 'warn' });
|
|
1339
|
+
}
|
|
1296
1340
|
for (const [, tc] of toolCalls) {
|
|
1297
|
-
const ev = yieldAccum(tc);
|
|
1341
|
+
const ev = yieldAccum(tc, typeof choice.finish_reason === 'string' ? choice.finish_reason : null);
|
|
1298
1342
|
if (ev) yield ev;
|
|
1299
1343
|
}
|
|
1300
1344
|
toolCalls.clear();
|
|
@@ -1329,6 +1373,7 @@ function retryOptsFor(
|
|
|
1329
1373
|
}
|
|
1330
1374
|
|
|
1331
1375
|
function inferOpenAIProviderName(url: string): string {
|
|
1376
|
+
if (/^https?:\/\/openrouter\.ai(?::\d+)?(?:\/|$)/i.test(url)) return 'openrouter';
|
|
1332
1377
|
if (url.includes('x.ai')) return 'grok';
|
|
1333
1378
|
if (url.includes('openai.com')) return 'openai';
|
|
1334
1379
|
if (url.includes('localhost') || url.includes('127.0.0.1')) return 'local';
|
|
@@ -1383,7 +1428,9 @@ async function* streamOpenAIEvents(
|
|
|
1383
1428
|
let textChars = 0;
|
|
1384
1429
|
let toolCalls = 0;
|
|
1385
1430
|
try {
|
|
1386
|
-
|
|
1431
|
+
// OR-TOOLARGS-REPAIR — 깨진 도구 인자 표지는 OpenRouter 엔드포인트에서만 켠다(다른 공급자 무변경).
|
|
1432
|
+
const flagInvalidToolArgs = inferOpenAIProviderName(url) === 'openrouter';
|
|
1433
|
+
for await (const ev of parseOpenAISSELines(sseLineStream(response.body!), flagInvalidToolArgs ? { flagInvalidToolArgs } : {})) {
|
|
1387
1434
|
if (ev.type === 'text') textChars += ev.delta.length;
|
|
1388
1435
|
else if (ev.type === 'tool_call') toolCalls++;
|
|
1389
1436
|
yield ev;
|
|
@@ -2420,12 +2467,29 @@ export function dedupeToolsByName(tools: LLMToolSpec[] | undefined): LLMToolSpec
|
|
|
2420
2467
|
return out.length === tools.length ? tools : out;
|
|
2421
2468
|
}
|
|
2422
2469
|
|
|
2423
|
-
|
|
2470
|
+
/** OpenRouter's Moonshot/Kimi tool schema accepts a bare $ref and single-schema items. */
|
|
2471
|
+
export function sanitizeToolSchemaForKimi(schema: unknown): unknown {
|
|
2472
|
+
if (Array.isArray(schema)) return schema.map(sanitizeToolSchemaForKimi);
|
|
2473
|
+
if (!schema || typeof schema !== 'object') return schema;
|
|
2474
|
+
const record = schema as Record<string, unknown>;
|
|
2475
|
+
if ('$ref' in record) return { $ref: record.$ref };
|
|
2476
|
+
return Object.fromEntries(Object.entries(record).map(([key, value]) => [
|
|
2477
|
+
key,
|
|
2478
|
+
sanitizeToolSchemaForKimi(key === 'items' && Array.isArray(value) ? value[0] : value),
|
|
2479
|
+
]));
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2482
|
+
export function toOpenAITools(tools: LLMToolSpec[] | undefined, kimi = false): any[] | undefined {
|
|
2424
2483
|
const unique = dedupeToolsByName(tools);
|
|
2425
2484
|
if (!unique || unique.length === 0) return undefined;
|
|
2426
2485
|
return unique.map(t => ({
|
|
2427
2486
|
type: 'function',
|
|
2428
|
-
function: {
|
|
2487
|
+
function: {
|
|
2488
|
+
name: t.name, description: t.description,
|
|
2489
|
+
parameters: kimi
|
|
2490
|
+
? sanitizeToolSchemaForKimi(strictifyToolSchema(t.parameters))
|
|
2491
|
+
: strictifyToolSchema(t.parameters),
|
|
2492
|
+
},
|
|
2429
2493
|
}));
|
|
2430
2494
|
}
|
|
2431
2495
|
|
|
@@ -3904,6 +3968,7 @@ export const PROVIDERS: Record<string, LLMProvider> = {
|
|
|
3904
3968
|
streamChat: (messages, opts = {}) => makeOpenRouterProvider({ provider: 'openrouter' }).streamChat!(messages, opts),
|
|
3905
3969
|
chat: (messages, opts = {}) => makeOpenRouterProvider({ provider: 'openrouter' }).chat!(messages, opts),
|
|
3906
3970
|
},
|
|
3971
|
+
bedrock: BedrockProvider, // 명시 선택 전용 — 자동 순서·폴백 체인에 «안» 넣는다(src/llm/bedrock-provider.ts)
|
|
3907
3972
|
};
|
|
3908
3973
|
|
|
3909
3974
|
const AUTOMATIC_PROVIDER_ORDER = ['grok', 'anthropic', 'gemini', 'local'] as const;
|
|
@@ -4085,12 +4150,13 @@ export function decideProviderForConfig(
|
|
|
4085
4150
|
return { provider, model: selectedModel, auth: baseUrl || getLocalLLMUrl() ? 'local' : 'none' };
|
|
4086
4151
|
case 'openrouter':
|
|
4087
4152
|
return { provider, model: selectedModel, auth: apiKey || getOpenRouterApiKey() ? 'apikey' : 'none' };
|
|
4153
|
+
case 'bedrock': return { provider, model: selectedModel, auth: authKindForProvider('bedrock', selectedModel) };
|
|
4088
4154
|
}
|
|
4089
4155
|
throw new Error(`unknown provider: ${provider as string}`);
|
|
4090
4156
|
}
|
|
4091
4157
|
|
|
4092
4158
|
function isKnownProviderName(provider: string): provider is ConcreteProviderName {
|
|
4093
|
-
return provider === 'grok' || provider === 'openai' || provider === 'openai-codex' || provider === 'anthropic' || provider === 'gemini' || provider === 'local' || provider === 'openrouter';
|
|
4159
|
+
return provider === 'grok' || provider === 'openai' || provider === 'openai-codex' || provider === 'anthropic' || provider === 'gemini' || provider === 'local' || provider === 'openrouter' || provider === 'bedrock';
|
|
4094
4160
|
}
|
|
4095
4161
|
|
|
4096
4162
|
function authKindForProvider(provider: string, model: string, apiKey?: string): ProviderDecisionAuth {
|
|
@@ -4105,6 +4171,7 @@ function authKindForProvider(provider: string, model: string, apiKey?: string):
|
|
|
4105
4171
|
if (provider === 'anthropic') return getAnthropicApiKey() ? 'apikey' : 'none';
|
|
4106
4172
|
if (provider === 'gemini') return getGeminiApiKey() ? 'apikey' : 'none';
|
|
4107
4173
|
if (provider === 'openrouter') return getOpenRouterApiKey() ? 'apikey' : 'none';
|
|
4174
|
+
if (provider === 'bedrock') return BedrockProvider.available() ? 'apikey' : 'none';
|
|
4108
4175
|
if (provider === 'openai-codex') {
|
|
4109
4176
|
try {
|
|
4110
4177
|
return codexOAuthAvailable() ? 'oauth' : 'none';
|
|
@@ -4124,6 +4191,7 @@ function defaultModelForProvider(provider: ConcreteProviderName): string {
|
|
|
4124
4191
|
case 'gemini': return GEMINI_MODEL;
|
|
4125
4192
|
case 'local': return LOCAL_LLM_MODEL;
|
|
4126
4193
|
case 'openrouter': return OPENROUTER_MODEL;
|
|
4194
|
+
case 'bedrock': return BedrockProvider.defaultModel;
|
|
4127
4195
|
}
|
|
4128
4196
|
throw new Error(`unknown provider: ${provider as string}`);
|
|
4129
4197
|
}
|
|
@@ -4247,7 +4315,7 @@ export function getProvider(model?: string): LLMProvider {
|
|
|
4247
4315
|
if (adapted && PROVIDERS[adapted]) return PROVIDERS[adapted]!;
|
|
4248
4316
|
// Unknown prefix — look up by exact name match on defaults
|
|
4249
4317
|
for (const p of Object.values(PROVIDERS)) {
|
|
4250
|
-
if (p.defaultModel === resolved) return p;
|
|
4318
|
+
if (p.name !== 'bedrock' && p.defaultModel === resolved) return p; // bedrock 은 명시 선택 전용
|
|
4251
4319
|
}
|
|
4252
4320
|
}
|
|
4253
4321
|
|
|
@@ -4374,6 +4442,7 @@ export function buildMessagesWithContext(
|
|
|
4374
4442
|
|
|
4375
4443
|
// Re-export converters so tests/adapters can assert wire-format correctness.
|
|
4376
4444
|
export { toOpenAIMessage, toOpenAIMessages, toAnthropicMessage, systemToAnthropicString };
|
|
4445
|
+
export { usesAdaptiveThinking, mapReasoningLevelToAnthropicThinking, mapReasoningLevelToAnthropicEffort, sseLineStream, retryOptsFor }; // src/llm/bedrock-provider.ts
|
|
4377
4446
|
|
|
4378
4447
|
/**
|
|
4379
4448
|
* Best-effort classification of whether a model accepts image inputs.
|
|
@@ -4430,7 +4499,10 @@ export function isLikelyVisionModel(model: string | undefined): boolean {
|
|
|
4430
4499
|
* Convenience wrapper — stream chunks via a callback, returning the full text.
|
|
4431
4500
|
* Mirrors the existing `streamGrok()` signature in chat.ts for drop-in use.
|
|
4432
4501
|
*/
|
|
4433
|
-
|
|
4502
|
+
// ⭐ OPENROUTER-OPTIMIZE G9 — `reportedCostUsd`(OpenRouter `usage.cost`)도 싣는다. 빠지면 `stream-llm` 행이
|
|
4503
|
+
// 실청구액을 잃고 카탈로그 추정(대개 `cost.kind=unknown`)으로 떨어진다(리뷰·저작 행 실측).
|
|
4504
|
+
// 합산은 토큰 칸과 같은 규약이다 — OpenAI 호환 스트림은 `usage` 를 마지막 청크에 «한 번» 싣는다(누적 반복 보고 아님).
|
|
4505
|
+
type ObservedUsage = Pick<LLMUsage, 'inputTokens' | 'outputTokens' | 'cacheReadInputTokens' | 'cacheCreationInputTokens' | 'reportedCostUsd'>;
|
|
4434
4506
|
|
|
4435
4507
|
type ProviderTextResult =
|
|
4436
4508
|
| { ok: true; full: string; usage: ObservedUsage | 'unmeasured' }
|
|
@@ -4438,7 +4510,7 @@ type ProviderTextResult =
|
|
|
4438
4510
|
|
|
4439
4511
|
function accumulateUsage(usage: ObservedUsage | undefined, received: LLMUsage): ObservedUsage {
|
|
4440
4512
|
const total = { ...usage };
|
|
4441
|
-
for (const field of ['inputTokens', 'outputTokens', 'cacheReadInputTokens', 'cacheCreationInputTokens'] as const) {
|
|
4513
|
+
for (const field of ['inputTokens', 'outputTokens', 'cacheReadInputTokens', 'cacheCreationInputTokens', 'reportedCostUsd'] as const) {
|
|
4442
4514
|
if (received[field] !== undefined) total[field] = (total[field] ?? 0) + received[field];
|
|
4443
4515
|
}
|
|
4444
4516
|
return total;
|
|
@@ -4468,17 +4540,40 @@ async function consumeProviderText(
|
|
|
4468
4540
|
// Preserve the provider or callback error that caused this close.
|
|
4469
4541
|
}
|
|
4470
4542
|
};
|
|
4543
|
+
const idleMs = opts.streamIdleTimeoutMs ?? (
|
|
4544
|
+
usesLongReasoningIdle(getModelFamily(opts.model ?? provider.defaultModel), provider.name)
|
|
4545
|
+
? STREAM_IDLE_TIMEOUT_MS_REASONING : STREAM_IDLE_TIMEOUT_MS
|
|
4546
|
+
);
|
|
4471
4547
|
|
|
4472
4548
|
while (true) {
|
|
4473
|
-
let
|
|
4549
|
+
let idleTimer: ReturnType<typeof setTimeout> | undefined;
|
|
4550
|
+
let step: { idle: true } | { idle: false; result: IteratorResult<string | LLMStreamEvent> };
|
|
4474
4551
|
try {
|
|
4475
|
-
step = await
|
|
4552
|
+
step = await Promise.race([
|
|
4553
|
+
iterator.next().then((result) => ({ idle: false as const, result })),
|
|
4554
|
+
new Promise<{ idle: true }>((resolve) => {
|
|
4555
|
+
idleTimer = setTimeout(() => resolve({ idle: true }), idleMs);
|
|
4556
|
+
}),
|
|
4557
|
+
]);
|
|
4476
4558
|
} catch (error) {
|
|
4477
4559
|
await closeIterator();
|
|
4478
4560
|
return { ok: false, full, error };
|
|
4561
|
+
} finally {
|
|
4562
|
+
if (idleTimer !== undefined) clearTimeout(idleTimer);
|
|
4563
|
+
}
|
|
4564
|
+
if (step.idle) {
|
|
4565
|
+
debug.log('llm', 'stream-idle-timeout', {
|
|
4566
|
+
provider: provider.name, model: opts.model ?? provider.defaultModel,
|
|
4567
|
+
idleMs, receivedChars: full.length, site: 'stream-llm',
|
|
4568
|
+
});
|
|
4569
|
+
const error = new Error(`stream idle timeout after ${idleMs}ms`);
|
|
4570
|
+
error.name = 'StreamIdleTimeoutError';
|
|
4571
|
+
// An async generator can leave return() pending behind a stalled next().
|
|
4572
|
+
void closeIterator();
|
|
4573
|
+
return { ok: false, full, error };
|
|
4479
4574
|
}
|
|
4480
|
-
if (step.done) return { ok: true, full, usage: usage ?? 'unmeasured' };
|
|
4481
|
-
const event = typeof step.value === 'string' ? { type: 'text' as const, delta: step.value } : step.value;
|
|
4575
|
+
if (step.result.done) return { ok: true, full, usage: usage ?? 'unmeasured' };
|
|
4576
|
+
const event = typeof step.result.value === 'string' ? { type: 'text' as const, delta: step.result.value } : step.result.value;
|
|
4482
4577
|
if (event.type === 'usage') {
|
|
4483
4578
|
usage = accumulateUsage(usage, event.usage);
|
|
4484
4579
|
try {
|
|
@@ -4504,11 +4599,11 @@ export async function streamLLM(
|
|
|
4504
4599
|
onChunk: (delta: string, full: string) => void,
|
|
4505
4600
|
opts: LLMOpts & { provider?: LLMProvider; initialProvider?: LLMProvider; onResolvedProvider?: (provider: string, model: string) => void } = {},
|
|
4506
4601
|
): Promise<string> {
|
|
4602
|
+
const started = Date.now();
|
|
4507
4603
|
let activeProvider = opts.provider ?? opts.initialProvider ?? resolveDefaultProvider(opts.model);
|
|
4508
4604
|
const attemptedProviders = new Set<string>([activeProvider.name]);
|
|
4509
4605
|
let blockedProviders: ProviderFallbackAttempt[] = [];
|
|
4510
4606
|
let modelOverride = opts.model;
|
|
4511
|
-
const started = Date.now();
|
|
4512
4607
|
|
|
4513
4608
|
while (true) {
|
|
4514
4609
|
const finalized = finalizeStreamingProviderModel(
|
|
@@ -4527,6 +4622,7 @@ export async function streamLLM(
|
|
|
4527
4622
|
maxTokens: opts.maxTokens,
|
|
4528
4623
|
temperature: opts.temperature,
|
|
4529
4624
|
}, { level: 'info' });
|
|
4625
|
+
// Keep text-only stream failures on streamLLM's existing provider fallback path.
|
|
4530
4626
|
const consumed = await consumeProviderText(
|
|
4531
4627
|
activeProvider,
|
|
4532
4628
|
messages,
|
|
@@ -4544,6 +4640,7 @@ export async function streamLLM(
|
|
|
4544
4640
|
logAgentTurnUsage(activeModel, consumed.usage, { providerName: activeProvider.name, site: 'stream-llm', role: opts.usageRole });
|
|
4545
4641
|
} catch { /* best-effort observation */ }
|
|
4546
4642
|
}
|
|
4643
|
+
debug.log('llm', 'outcome', { provider: activeProvider.name, status: 'ok', kind: 'streamLLM', durationMs: Date.now() - started });
|
|
4547
4644
|
debug.log('llm.router.done', 'streamLLM', {
|
|
4548
4645
|
provider: activeProvider.name,
|
|
4549
4646
|
model: activeModel,
|
|
@@ -4579,7 +4676,10 @@ export async function streamLLM(
|
|
|
4579
4676
|
message: reason,
|
|
4580
4677
|
...(isAuthRejectionError(err) ? { authRejected: true } : {}),
|
|
4581
4678
|
}, { level: 'error' });
|
|
4582
|
-
if (opts.provider)
|
|
4679
|
+
if (opts.provider) {
|
|
4680
|
+
debug.log('llm', 'outcome', { provider: activeProvider.name, status: 'error', kind: 'streamLLM', durationMs: Date.now() - started });
|
|
4681
|
+
throw err;
|
|
4682
|
+
}
|
|
4583
4683
|
const remaining = remainingFallbackProviderNames(attemptedProviders, opts);
|
|
4584
4684
|
const verdict = decideProviderFallback({
|
|
4585
4685
|
err,
|
|
@@ -4604,6 +4704,7 @@ export async function streamLLM(
|
|
|
4604
4704
|
continue;
|
|
4605
4705
|
}
|
|
4606
4706
|
if (verdict.action === 'stop') {
|
|
4707
|
+
debug.log('llm', 'outcome', { provider: activeProvider.name, status: 'error', kind: 'streamLLM', durationMs: Date.now() - started });
|
|
4607
4708
|
debug.log('llm.router', 'provider-fallback-stop', {
|
|
4608
4709
|
blockedProviders,
|
|
4609
4710
|
category: verdict.category,
|
|
@@ -4622,6 +4723,7 @@ export async function streamLLM(
|
|
|
4622
4723
|
...(fallback ? { skippedFallbackProvider: fallback.name, emittedChars: full.length } : {}),
|
|
4623
4724
|
}, { level: 'error' });
|
|
4624
4725
|
onChunk(finalDelta, finalText);
|
|
4726
|
+
debug.log('llm', 'outcome', { provider: activeProvider.name, status: 'fallback-exhausted', kind: 'streamLLM', durationMs: Date.now() - started });
|
|
4625
4727
|
return finalText;
|
|
4626
4728
|
}
|
|
4627
4729
|
}
|
|
@@ -5019,6 +5121,15 @@ const LOCAL_TOOL_DISCIPLINE = [
|
|
|
5019
5121
|
'- 범위 읽기만으로 판단할 수 없을 때에만 전체 읽기를 선택하고, 읽은 뒤에는 다음 행동을 계속 결정하라.',
|
|
5020
5122
|
].join('\n');
|
|
5021
5123
|
|
|
5124
|
+
/** OpenRouter(`openrouter/…`) GLM·Kimi·Qwen 전용 도구 호출 규율 — 다른 군 상수와 합성하지 않는 독립 상수. */
|
|
5125
|
+
export const OPEN_WEIGHT_TOOL_DISCIPLINE = [
|
|
5126
|
+
'[open-weight tool-use discipline]',
|
|
5127
|
+
'- 도구로 할 수 있는 일은 이번 응답에서 바로 도구를 호출하라. "먼저 읽겠다" 또는 "확인하겠다" 같은 계획만 말하고 응답을 끝내지 마라.',
|
|
5128
|
+
'- 작업을 시작하는 첫 응답에는 도구 호출이 하나 이상 있어야 한다.',
|
|
5129
|
+
'- 도구 호출 인자는 해당 도구의 스키마에 맞는 JSON 으로 내라.',
|
|
5130
|
+
'- 충분한 근거가 모이면 도구 호출 없이 최종 답을 평문으로 써서 끝내라.',
|
|
5131
|
+
].join('\n');
|
|
5132
|
+
|
|
5022
5133
|
/** 모델군 → 그 군에 주입할 툴 규율(없으면 `null`). **능력 술어 판** — 2026-08-14.
|
|
5023
5134
|
*
|
|
5024
5135
|
* ⛔ **왜 `if` 세 개가 아니라 이 표인가**: codex·grok·local 이 각각 「같은 모양의 if」로 붙어 있었고,
|
|
@@ -5040,6 +5151,7 @@ const TOOL_DISCIPLINE_BY_FAMILY: Record<ModelFamily, string | null> = {
|
|
|
5040
5151
|
codex: CODEX_TOOL_DISCIPLINE,
|
|
5041
5152
|
grok: GROK_TOOL_DISCIPLINE,
|
|
5042
5153
|
local: LOCAL_TOOL_DISCIPLINE,
|
|
5154
|
+
'open-weight': OPEN_WEIGHT_TOOL_DISCIPLINE,
|
|
5043
5155
|
// ⬇ 아래 넷은 「아직 안 쟀다」이지 「필요 없다」가 아니다.
|
|
5044
5156
|
// `other` 가 0인 것은 ***아무도 other 를 안 쟀기 때문***이고, 실제 자식 하나가 오늘 `other` 였다(`[S]` 실측).
|
|
5045
5157
|
claude: null,
|
|
@@ -5217,6 +5329,19 @@ function appendFinalSynthesisNotice(existingText: string, notice: string): strin
|
|
|
5217
5329
|
return existingText.length > 0 ? `${existingText}\n\n${notice}` : notice;
|
|
5218
5330
|
}
|
|
5219
5331
|
|
|
5332
|
+
export function buildNoFinalSynthesisLead(
|
|
5333
|
+
reason: 'empty-turn' | 'budget-exhausted',
|
|
5334
|
+
toolCallCount: number,
|
|
5335
|
+
locale?: Locale,
|
|
5336
|
+
): string {
|
|
5337
|
+
if (reason === 'empty-turn') {
|
|
5338
|
+
return (locale ?? detectLocale()) === 'ko'
|
|
5339
|
+
? '답을 끝까지 쓰지 못했습니다 — 빈 응답이 이어졌습니다. 질문을 좁혀 다시 물어 주세요(예: 무엇 하나만).'
|
|
5340
|
+
: 'I could not finish the answer — repeated empty responses stopped the reply. Please ask a narrower question (for example, just one thing).';
|
|
5341
|
+
}
|
|
5342
|
+
return format(getMessages(locale).chatNoSynthesisLead ?? getMessages('en').chatNoSynthesisLead!, { n: toolCallCount });
|
|
5343
|
+
}
|
|
5344
|
+
|
|
5220
5345
|
function buildNoFinalSynthesisNotice(reason: 'empty-turn' | 'budget-exhausted'): string {
|
|
5221
5346
|
const why = reason === 'empty-turn'
|
|
5222
5347
|
? 'The model stopped after repeated empty turns.'
|
|
@@ -7744,6 +7869,7 @@ export function selectIntentClassificationMessages(messages: readonly LLMMessage
|
|
|
7744
7869
|
message.content === CODEX_TOOL_DISCIPLINE
|
|
7745
7870
|
|| message.content === GROK_TOOL_DISCIPLINE
|
|
7746
7871
|
|| message.content === LOCAL_TOOL_DISCIPLINE
|
|
7872
|
+
|| message.content === OPEN_WEIGHT_TOOL_DISCIPLINE
|
|
7747
7873
|
)
|
|
7748
7874
|
));
|
|
7749
7875
|
}
|
|
@@ -7956,12 +8082,13 @@ export async function streamLLMWithTools(
|
|
|
7956
8082
|
// the caller — no per-turn duplication when the caller persists new messages.
|
|
7957
8083
|
// Adapters fold multiple system messages, so this composes with (does not
|
|
7958
8084
|
// mutate) the caller's persona/system prompt.
|
|
7959
|
-
// ⭐
|
|
8085
|
+
// ⭐ 각 모델군의 규율은 같은 해소 지점에서 선택한다.
|
|
7960
8086
|
// 대표 2026-08-14: *"claude 제외 다른 LLM 들이 공용화가 많아 보이고, 오히려 claude 일 때
|
|
7961
8087
|
// 옵션화를 해야 하는 게 아닌지"* ⊕ `[S]` 와 합의한 축 분담(축② = 능력 술어는 `[T]` 소유).
|
|
7962
|
-
// ⛔
|
|
8088
|
+
// ⛔ 기존 군의 문면은 «바이트 하나» 안 바뀐다(테스트가 전송분으로 문다).
|
|
7963
8089
|
const toolDiscipline = resolveToolDiscipline(modelFamily);
|
|
7964
8090
|
if (toolDiscipline !== null) {
|
|
8091
|
+
debug.log('llm.tool-discipline', 'injected', { modelFamily, model: effectiveModel, chars: toolDiscipline.length });
|
|
7965
8092
|
// ⛔ **상수를 «그대로» 싣는다 — 합성하지 마라.**
|
|
7966
8093
|
// `selectIntentClassificationMessages` 가 «정확 일치»로 이 메시지를 걸러 내므로,
|
|
7967
8094
|
// 여기서 한 글자라도 덧붙이면 ***분류기 셋이 다시 «오염»된다***(그 함수 주석에 실측이 있다).
|
|
@@ -8305,6 +8432,7 @@ export async function streamLLMWithTools(
|
|
|
8305
8432
|
name: string;
|
|
8306
8433
|
args: Record<string, unknown>;
|
|
8307
8434
|
providerMeta?: ProviderToolMeta;
|
|
8435
|
+
argsInvalid?: ToolArgsInvalid;
|
|
8308
8436
|
}> = [];
|
|
8309
8437
|
const turnStartedAt = Date.now();
|
|
8310
8438
|
debug.log('llm.router', 'tool-loop.turn.start', {
|
|
@@ -8520,6 +8648,7 @@ export async function streamLLMWithTools(
|
|
|
8520
8648
|
name: ev.name,
|
|
8521
8649
|
args: ev.args,
|
|
8522
8650
|
...(ev.providerMeta !== undefined ? { providerMeta: ev.providerMeta } : {}),
|
|
8651
|
+
...(ev.argsInvalid !== undefined ? { argsInvalid: ev.argsInvalid } : {}),
|
|
8523
8652
|
});
|
|
8524
8653
|
} else if (ev.type === 'reasoning') {
|
|
8525
8654
|
// Forward to the optional reasoning handler. Codex Responses
|
|
@@ -8660,11 +8789,12 @@ export async function streamLLMWithTools(
|
|
|
8660
8789
|
if (pendingCalls.length === 0 && turnText.length === 0) {
|
|
8661
8790
|
if (emptyRetries >= MAX_EMPTY_RETRIES) {
|
|
8662
8791
|
const notice = buildNoFinalSynthesisNotice('empty-turn');
|
|
8663
|
-
const
|
|
8792
|
+
const visibleText = finalizeVisibleAssistantText(
|
|
8664
8793
|
appendFinalSynthesisNotice(fullText, notice),
|
|
8665
8794
|
notice,
|
|
8666
8795
|
sawToolRound,
|
|
8667
8796
|
);
|
|
8797
|
+
const finalText = `${buildNoFinalSynthesisLead('empty-turn', toolCallHistory.length)}\n\n${visibleText}`;
|
|
8668
8798
|
handlers.onText('', finalText);
|
|
8669
8799
|
debug.log('llm.router', 'tool-loop.empty-turn.give-up', {
|
|
8670
8800
|
turn, emptyRetries, finalTextInjected: true,
|
|
@@ -9558,6 +9688,22 @@ export async function streamLLMWithTools(
|
|
|
9558
9688
|
return { result: stub, isError: true, phaseRejected: false };
|
|
9559
9689
|
}
|
|
9560
9690
|
}
|
|
9691
|
+
// OR-TOOLARGS-REPAIR (2026-10-10) — 인자 JSON 이 깨진 호출(OpenRouter 경로만 표지가 붙는다)은
|
|
9692
|
+
// ⛔ 실행하지 않는다. 종전엔 `{}` 로 실행돼 도구가 기본값으로 돌고 모델은 «성공»을 받았다.
|
|
9693
|
+
// 기존 dispatch 오류 결과 모양(`{ error }` ⊕ isError)으로 돌려 모델이 다시 부르게 한다.
|
|
9694
|
+
if (call.argsInvalid !== undefined) {
|
|
9695
|
+
debug.log('llm.router', 'tool-loop.tool-args-invalid.blocked', {
|
|
9696
|
+
turn,
|
|
9697
|
+
tool: call.name,
|
|
9698
|
+
chars: call.argsInvalid.chars,
|
|
9699
|
+
finishReason: call.argsInvalid.finishReason,
|
|
9700
|
+
}, { level: 'warn' });
|
|
9701
|
+
return {
|
|
9702
|
+
result: { error: buildInvalidToolArgsMessage(call.argsInvalid) },
|
|
9703
|
+
isError: true,
|
|
9704
|
+
phaseRejected: false,
|
|
9705
|
+
};
|
|
9706
|
+
}
|
|
9561
9707
|
// Codex-family same-args dedup guard (fix L-2). Scope is
|
|
9562
9708
|
// EXPLORATORY_TOOLS only — repeating Bash/RunShell/Edit/Write
|
|
9563
9709
|
// is often legitimate (retry after a fix, apply-then-verify,
|
|
@@ -10639,11 +10785,14 @@ export async function streamLLMWithTools(
|
|
|
10639
10785
|
});
|
|
10640
10786
|
}
|
|
10641
10787
|
const emittedText = synthesizedText ?? noticeWithFallback;
|
|
10642
|
-
const
|
|
10788
|
+
const visibleText = finalizeVisibleAssistantText(
|
|
10643
10789
|
appendFinalSynthesisNotice(fullText, emittedText),
|
|
10644
10790
|
emittedText,
|
|
10645
10791
|
loopTermination === 'aborted' ? false : sawToolRound,
|
|
10646
10792
|
);
|
|
10793
|
+
const finalText = loopTermination === 'budget-exhausted' && synthesizedText === null
|
|
10794
|
+
? `${buildNoFinalSynthesisLead(loopTermination, toolCallHistory.length)}\n\n${visibleText}`
|
|
10795
|
+
: visibleText;
|
|
10647
10796
|
// Skip post-emit when synthesis was already streamed live AND
|
|
10648
10797
|
// finalText matches synthesizedText. Emit when synthesis failed
|
|
10649
10798
|
// (fallback notice) OR finalization enriched the text.
|
|
@@ -10788,13 +10937,21 @@ function makeOpenAICompatProvider(
|
|
|
10788
10937
|
if (!apiKey && !grokSub) {
|
|
10789
10938
|
throw new Error(`${name} unavailable: configure apiKey via \`elanous setup\``);
|
|
10790
10939
|
}
|
|
10791
|
-
const
|
|
10940
|
+
const activeModel = opts.model || model;
|
|
10941
|
+
const tools = toOpenAITools(opts.tools, name === 'openrouter' && openRouterWireModel(activeModel).startsWith('moonshotai/'));
|
|
10942
|
+
// OR-TOOLCHOICE-PASS (2026-10-10) — OpenRouter 경로만 호출자 toolChoice 를 싣는다.
|
|
10943
|
+
// ⛔ grok/openai 호환 경로는 손대지 않는다(무회귀). toolChoice 가 없거나 tools 가 없으면 키 자체를 안 싣는다.
|
|
10944
|
+
const toolChoice = name === 'openrouter' && tools
|
|
10945
|
+
? openRouterToolChoice(openRouterWireModel(activeModel), opts.toolChoice)
|
|
10946
|
+
: undefined;
|
|
10947
|
+
if (toolChoice !== undefined) {
|
|
10948
|
+
debug.log('llm.openrouter', 'tool-choice-sent', { model: openRouterWireModel(activeModel), requested: opts.toolChoice, toolChoice });
|
|
10949
|
+
}
|
|
10792
10950
|
// Image-pipeline P3.5 — gate the synthetic follow-up workaround
|
|
10793
10951
|
// on the userMessage axis for the active model + brand. `name`
|
|
10794
10952
|
// is 'grok' or 'openai' for makeOpenAICompatProvider callers.
|
|
10795
10953
|
// P-3 §6.9 (2026-05-07) — same lookup also gates user-message
|
|
10796
10954
|
// image blocks in the wire.
|
|
10797
|
-
const activeModel = opts.model || model;
|
|
10798
10955
|
const brand = name as Parameters<typeof isVisionCapableModel>[0];
|
|
10799
10956
|
const followup = isVisionCapableModel(brand, activeModel, 'userMessage');
|
|
10800
10957
|
// 구독이 있으면 «엔드포인트와 자격이 통째로» 바뀐다(cli-chat-proxy + Bearer).
|
|
@@ -10806,16 +10963,41 @@ function makeOpenAICompatProvider(
|
|
|
10806
10963
|
if (useSub) {
|
|
10807
10964
|
debug.log('llm.grok', 'credential', { kind: useSub.kind, source: useSub.source, baseUrl: useSub.baseUrl, via: 'compat-provider' });
|
|
10808
10965
|
}
|
|
10966
|
+
let wireMessages = messages.flatMap((m) => toOpenAIMessages(m, {
|
|
10967
|
+
acceptToolImagesViaFollowup: followup,
|
|
10968
|
+
acceptUserMessageImages: followup,
|
|
10969
|
+
...(name === 'openrouter' ? { echoReasoningDetails: true } : {}),
|
|
10970
|
+
}));
|
|
10971
|
+
// OR-ANTHROPIC-CACHE (2026-10-10) — OpenRouter 뒤 anthropic/* · moonshotai/* 만 cache_control 중단점을 싣는다.
|
|
10972
|
+
// ⛔ 다른 OpenRouter 모델과 grok/openai/local 호환 경로는 이 분기를 안 탄다 — 본문 바이트 동일(무회귀).
|
|
10973
|
+
const cacheFamily = name === 'openrouter' ? openRouterPromptCacheFamily(openRouterWireModel(activeModel)) : null;
|
|
10974
|
+
if (cacheFamily) {
|
|
10975
|
+
if (opts.promptCache === false) {
|
|
10976
|
+
debug.log('llm.openrouter', 'prompt-cache', { model: openRouterWireModel(activeModel), applied: false, reason: 'promptCache:false' });
|
|
10977
|
+
} else {
|
|
10978
|
+
const { getDefaultCacheTTL } = await import('./config.js');
|
|
10979
|
+
const ttl = opts.promptCacheTTL ?? getDefaultCacheTTL();
|
|
10980
|
+
const plan = applyOpenRouterCacheControl(wireMessages, { family: cacheFamily, ttl });
|
|
10981
|
+
wireMessages = plan.messages;
|
|
10982
|
+
debug.log('llm.openrouter', 'prompt-cache', {
|
|
10983
|
+
model: openRouterWireModel(activeModel), applied: plan.breakpoints > 0, family: cacheFamily,
|
|
10984
|
+
ttl: cacheFamily === 'anthropic' ? ttl : '5m',
|
|
10985
|
+
breakpoints: plan.breakpoints, system: plan.systemBreakpoints, tail: plan.tailBreakpoints,
|
|
10986
|
+
});
|
|
10987
|
+
}
|
|
10988
|
+
}
|
|
10989
|
+
// OR-STICKY-ROUTING (2026-10-10) — 같은 세션/런의 요청을 같은 상류로 고정해 캐시 적중을 지킨다.
|
|
10990
|
+
// ⛔ openrouter 만, 그리고 키가 있을 때만 싣는다 — 키가 없거나 다른 provider 면 본문·헤더 바이트 동일(무회귀).
|
|
10991
|
+
const sticky = name === 'openrouter' ? openRouterStickySessionKey(opts.sessionId, process.env.ELANOUS_RUN_ID) : null;
|
|
10992
|
+
if (sticky) {
|
|
10993
|
+
debug.log('llm.openrouter', 'sticky-routing', { model: openRouterWireModel(activeModel), source: sticky.source, hashed: sticky.hashed });
|
|
10994
|
+
}
|
|
10809
10995
|
yield* streamOpenAIEvents(
|
|
10810
10996
|
useSub ? `${useSub.baseUrl}/chat/completions` : resolvedUrl,
|
|
10811
10997
|
useSub ? useSub.token : apiKey,
|
|
10812
10998
|
{
|
|
10813
10999
|
model: wire.model ? wire.model(activeModel) : activeModel,
|
|
10814
|
-
messages:
|
|
10815
|
-
acceptToolImagesViaFollowup: followup,
|
|
10816
|
-
acceptUserMessageImages: followup,
|
|
10817
|
-
...(name === 'openrouter' ? { echoReasoningDetails: true } : {}),
|
|
10818
|
-
})),
|
|
11000
|
+
messages: wireMessages,
|
|
10819
11001
|
...(() => {
|
|
10820
11002
|
const fields = openAiCompatSamplingFields(brand, activeModel, opts.temperature ?? 0.3, opts.maxTokens ?? 2048);
|
|
10821
11003
|
// ⛔ 2026-09-23 — OpenRouter 뒤의 추론 모델(kimi·glm·qwen …)은 기본 0.3 을 강제하면 안 된다:
|
|
@@ -10829,10 +11011,16 @@ function makeOpenAICompatProvider(
|
|
|
10829
11011
|
return fields;
|
|
10830
11012
|
})(),
|
|
10831
11013
|
...(tools ? { tools } : {}),
|
|
11014
|
+
...(toolChoice !== undefined ? { tool_choice: toolChoice } : {}),
|
|
10832
11015
|
...(wire.extraBody ?? {}),
|
|
11016
|
+
// OpenRouter alone resolves per-call effort against the configured level and catalog default.
|
|
11017
|
+
...(name === 'openrouter'
|
|
11018
|
+
? openRouterReasoningField(activeModel, opts.reasoningEffort, cfg.reasoningLevel)
|
|
11019
|
+
: {}),
|
|
11020
|
+
...(sticky ? { session_id: sticky.key } : {}),
|
|
10833
11021
|
},
|
|
10834
11022
|
opts.signal,
|
|
10835
|
-
useSub ? useSub.headers : wire.headers,
|
|
11023
|
+
useSub ? useSub.headers : (sticky ? { ...wire.headers, 'x-session-id': sticky.key } : wire.headers),
|
|
10836
11024
|
);
|
|
10837
11025
|
},
|
|
10838
11026
|
async *chat(messages, opts = {}) { yield* textOnly(this.streamChat!(messages, opts)); },
|
|
@@ -10852,7 +11040,18 @@ function makeOpenRouterProvider(cfg: UCLLMConfig): LLMProvider {
|
|
|
10852
11040
|
OPENROUTER_API_URL,
|
|
10853
11041
|
{ ...cfg, apiKey: cfg.apiKey || getOpenRouterApiKey() },
|
|
10854
11042
|
// ⭐ BACKLOG C7 — `usage:{include:true}` 면 마지막 청크 `usage.cost` 에 «실제 청구액»이 온다(추정 아님).
|
|
10855
|
-
{
|
|
11043
|
+
{
|
|
11044
|
+
model: openRouterWireModel, headers: { 'X-Title': 'elanous' }, omitDefaultTemperature: true, omitMaxTokens: true,
|
|
11045
|
+
extraBody: {
|
|
11046
|
+
usage: { include: true },
|
|
11047
|
+
provider: {
|
|
11048
|
+
require_parameters: true,
|
|
11049
|
+
allow_fallbacks: true,
|
|
11050
|
+
...(cfg.openrouter?.providerPreferences && typeof cfg.openrouter.providerPreferences === 'object' && !Array.isArray(cfg.openrouter.providerPreferences)
|
|
11051
|
+
? cfg.openrouter.providerPreferences : {}),
|
|
11052
|
+
},
|
|
11053
|
+
},
|
|
11054
|
+
},
|
|
10856
11055
|
);
|
|
10857
11056
|
// ⛔ 2026-09-23 — OpenRouter 의 `max_tokens` 는 «추론 토큰까지» 센다. 호환 경로 기본값 2048 이면 추론 모델이
|
|
10858
11057
|
// 본문·도구 호출에 닿기 전에 잘렸다(실측 glm-5.3: 2048 → finish=length). 오전 판은 바닥 16384 를 뒀고,
|
|
@@ -10861,11 +11060,77 @@ function makeOpenRouterProvider(cfg: UCLLMConfig): LLMProvider {
|
|
|
10861
11060
|
return inner;
|
|
10862
11061
|
}
|
|
10863
11062
|
|
|
11063
|
+
/** OR-TOOLARGS-REPAIR — 깨진 도구 인자 호출에 돌려주는 오류 문면(도구는 실행되지 않았다). */
|
|
11064
|
+
export function buildInvalidToolArgsMessage(info: ToolArgsInvalid): string {
|
|
11065
|
+
const truncated = info.finishReason === 'length';
|
|
11066
|
+
return `tool arguments were not valid JSON (${info.chars} chars` +
|
|
11067
|
+
(info.finishReason ? `, finish_reason=${info.finishReason}` : '') +
|
|
11068
|
+
`${truncated ? ' — the output was cut off at the length limit' : ' — truncated or malformed?'}). ` +
|
|
11069
|
+
'The tool was NOT executed. Re-issue the call with complete, valid JSON arguments' +
|
|
11070
|
+
(truncated ? ' (keep the payload smaller, e.g. split a large write into several calls).' : '.');
|
|
11071
|
+
}
|
|
11072
|
+
|
|
11073
|
+
/** OR-TOOLCHOICE-PASS — LLMOpts.toolChoice → OpenRouter `tool_choice` (`toChatToolChoice` 재사용).
|
|
11074
|
+
* ⚠️ Kimi(moonshotai/*)는 thinking 모드에서 강제 선택(required·특정 도구)을 400 으로 거부한다
|
|
11075
|
+
* (openclaw moonshot-thinking.ts:100-108 와 같은 처리) ⇒ 강제는 'auto' 로 내린다. */
|
|
11076
|
+
export function openRouterToolChoice(wireModel: string, tc: ToolChoice | undefined): unknown {
|
|
11077
|
+
const chat = toChatToolChoice(tc);
|
|
11078
|
+
if (chat === undefined) return undefined;
|
|
11079
|
+
if (wireModel.startsWith('moonshotai/') && chat !== 'auto' && chat !== 'none') return 'auto';
|
|
11080
|
+
return chat;
|
|
11081
|
+
}
|
|
11082
|
+
|
|
11083
|
+
/** OR-STICKY-ROUTING — OpenRouter 고정 라우팅 키. 본문 최상위 `session_id` ⊕ 헤더 `x-session-id` 로 싣는다
|
|
11084
|
+
* (hermes plugins/model-providers/openrouter build_extra_body: 본문 session_id 를 «라우팅 키»로 직접 쓰고 첫 성공
|
|
11085
|
+
* 요청부터 고정 · openclaw openai-completions-transport: openrouter 는 `x-session-id` 헤더 — `x-session-affinity` 는
|
|
11086
|
+
* openrouter 가 아닌 호환 게이트웨이용이라 여기선 안 쓴다).
|
|
11087
|
+
* 키 우선순위: 호출자의 대화 `sessionId` → 하니스 런 `ELANOUS_RUN_ID`. 둘 다 없으면 null(아무것도 안 싣는다).
|
|
11088
|
+
* 128자를 넘거나 허용 밖 문자가 있으면 sha256 앞 32자로 접는다(원문 id 를 상류에 안 흘린다는 부수 효과). */
|
|
11089
|
+
export function openRouterStickySessionKey(
|
|
11090
|
+
sessionId: string | undefined,
|
|
11091
|
+
runId: string | undefined,
|
|
11092
|
+
): { key: string; source: 'session' | 'run'; hashed: boolean } | null {
|
|
11093
|
+
// 공백뿐이면 «없음». 검사·해시는 원문 그대로 — 다듬으면 ' sess ' 와 'sess' 가 같은 키가 된다.
|
|
11094
|
+
const s = sessionId && sessionId.trim() ? sessionId : undefined;
|
|
11095
|
+
const r = runId && runId.trim() ? runId : undefined;
|
|
11096
|
+
const raw = s ?? r;
|
|
11097
|
+
if (!raw) return null;
|
|
11098
|
+
const source = s ? 'session' : 'run';
|
|
11099
|
+
if (raw.length <= 128 && /^[A-Za-z0-9._:-]+$/.test(raw)) return { key: raw, source, hashed: false };
|
|
11100
|
+
return { key: `elanous-${createHash('sha256').update(raw).digest('hex').slice(0, 32)}`, source, hashed: true };
|
|
11101
|
+
}
|
|
11102
|
+
|
|
10864
11103
|
/** `openrouter/moonshotai/kimi-k3` → `moonshotai/kimi-k3`. 접두가 없으면 그대로. */
|
|
10865
11104
|
export function openRouterWireModel(model: string): string {
|
|
10866
11105
|
return model.startsWith('openrouter/') ? model.slice('openrouter/'.length) : model;
|
|
10867
11106
|
}
|
|
10868
11107
|
|
|
11108
|
+
/** OpenRouter effort: call > resolved config (including escalation) > open-weight default.
|
|
11109
|
+
* Keep the existing effort mapping; Claude-family models use verbosity instead of reasoning. */
|
|
11110
|
+
const OPENROUTER_REASONING_EFFORT: Record<string, 'low' | 'medium' | 'high'> = {
|
|
11111
|
+
minimal: 'low', low: 'low', medium: 'medium', high: 'high', xhigh: 'high', max: 'high',
|
|
11112
|
+
};
|
|
11113
|
+
function openRouterReasoningField(
|
|
11114
|
+
model: string, requested: string | undefined, configured: UCLLMConfig['reasoningLevel'],
|
|
11115
|
+
): { reasoning?: { effort: 'low' | 'medium' | 'high' }; verbosity?: 'low' | 'medium' | 'high' } {
|
|
11116
|
+
const wireModel = openRouterWireModel(model);
|
|
11117
|
+
// The catalog's model-specific open-weight verdict, not a vendor/slug prefix,
|
|
11118
|
+
// gates the default: an unregistered release may be closed-weight.
|
|
11119
|
+
const slug = wireModel.slice(wireModel.indexOf('/') + 1);
|
|
11120
|
+
const openWeight = wireModel.includes('/') && BUILTIN_CATALOG.models.some(
|
|
11121
|
+
(entry) => entry.id === slug && entry.openWeight === true,
|
|
11122
|
+
);
|
|
11123
|
+
const configEffort = configured === 'off' ? undefined : configured;
|
|
11124
|
+
const source = requested !== undefined ? 'call' : configured !== undefined ? 'config' : openWeight ? 'default' : 'none';
|
|
11125
|
+
const effort = requested ?? (configured !== undefined ? configEffort : openWeight ? 'medium' : undefined);
|
|
11126
|
+
const sent = effort !== undefined && Object.hasOwn(OPENROUTER_REASONING_EFFORT, effort)
|
|
11127
|
+
? OPENROUTER_REASONING_EFFORT[effort] : undefined;
|
|
11128
|
+
const field = sent ? (wireModel.startsWith('anthropic/') ? 'verbosity' : 'reasoning') : 'none';
|
|
11129
|
+
debug.log('llm.openrouter', 'reasoning', { model, requested: requested ?? null, sent: sent ?? null, source, field });
|
|
11130
|
+
return field === 'verbosity' ? { verbosity: sent }
|
|
11131
|
+
: field === 'reasoning' ? { reasoning: { effort: sent! } } : {};
|
|
11132
|
+
}
|
|
11133
|
+
|
|
10869
11134
|
/** Codex-specific provider. Prefers OAuth tokens from ~/.config/elanous/auth.json
|
|
10870
11135
|
* (refreshing them when within the 120s buffer) and falls back to the
|
|
10871
11136
|
* plain apiKey flow only when no tokens are on file. OAuth mode targets
|
|
@@ -11210,6 +11475,7 @@ export function inferProviderFromModel(model: string | undefined): string | null
|
|
|
11210
11475
|
* its own configured default. */
|
|
11211
11476
|
export function isModelCompatible(providerName: string, model: string | undefined): boolean {
|
|
11212
11477
|
if (!model) return true;
|
|
11478
|
+
if (providerName === 'bedrock') return isBedrockCompatibleModel(model, inferProviderFromModel);
|
|
11213
11479
|
const implied = inferProviderFromModel(model);
|
|
11214
11480
|
if (implied === null) return true; // unknown prefix — let provider handle
|
|
11215
11481
|
// openai-codex and openai accept each other's model families (gpt-*, codex-*).
|
|
@@ -11249,7 +11515,7 @@ export function anyProviderAvailable(userConfig?: UserConfig): boolean {
|
|
|
11249
11515
|
} catch { return false; }
|
|
11250
11516
|
}
|
|
11251
11517
|
} catch { /* fall through to env check */ }
|
|
11252
|
-
return Object.values(PROVIDERS).some(p => p.available());
|
|
11518
|
+
return Object.values(PROVIDERS).some(p => p.name !== 'bedrock' && p.available()); // bedrock 은 auto 후보가 아니다
|
|
11253
11519
|
}
|
|
11254
11520
|
|
|
11255
11521
|
/** 직결 배선이 없는 계열 → OpenRouter 에서 그 벤더의 대표 모델(사다리 `openrouter` 에 선 것). */
|
|
@@ -11291,6 +11557,10 @@ export function getProviderForConfig(
|
|
|
11291
11557
|
if (!isKnownProviderName(resolvedProviderName)) {
|
|
11292
11558
|
throw new Error(`unknown provider: ${resolvedProviderName}`);
|
|
11293
11559
|
}
|
|
11560
|
+
if (resolvedProviderName === 'openrouter') {
|
|
11561
|
+
// Preserve the requesting config for OpenRouter, not the config-free singleton.
|
|
11562
|
+
return makeOpenRouterProvider({ provider: 'openrouter', model: decision.model, reasoningLevel: userConfig.llm.reasoningLevel });
|
|
11563
|
+
}
|
|
11294
11564
|
return PROVIDERS[resolvedProviderName]!;
|
|
11295
11565
|
}
|
|
11296
11566
|
if (!isKnownProviderName(resolvedProviderName)) {
|
|
@@ -11330,9 +11600,10 @@ export function getProviderForConfig(
|
|
|
11330
11600
|
case 'openai-codex':
|
|
11331
11601
|
return makeCodexProvider(llm);
|
|
11332
11602
|
case 'openrouter':
|
|
11333
|
-
return makeOpenRouterProvider(userConfig.llm.provider === 'openrouter' ? llm : { provider: 'openrouter', model: decision.model });
|
|
11603
|
+
return makeOpenRouterProvider(userConfig.llm.provider === 'openrouter' ? llm : { provider: 'openrouter', model: decision.model, reasoningLevel: llm.reasoningLevel });
|
|
11334
11604
|
case 'anthropic':
|
|
11335
11605
|
return makeAnthropicProvider(llm);
|
|
11606
|
+
case 'bedrock': return makeBedrockProvider(llm);
|
|
11336
11607
|
case 'gemini':
|
|
11337
11608
|
// Wave 1 (2026-05-04) — native @google/genai SDK. Previously
|
|
11338
11609
|
// makeOpenAICompatProvider tunnel which couldn't carry
|