elanous 0.2.21 → 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-111cabe4d1fd69ae.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/{MObU8ujkMciAKr6ljAV05 → 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/catalog/catalog.yaml +1 -1
- package/graphs/drafts/recipes.yaml +2 -2
- 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/graphs/test-diet/recipes.yaml +3 -0
- package/graphs/test-diet/test-diet.yaml +3 -1
- package/package.json +4 -1
- package/scripts/bench-report.ts +82 -3
- package/scripts/ci-typecheck-changed.ts +10 -1
- package/scripts/f-session-monitor.ts +69 -0
- package/scripts/hq/hq-fence-wrapper.sh +148 -0
- package/scripts/hq/standby-snapshot.ts +7 -3
- package/scripts/knowledge-compress.ts +11 -0
- package/scripts/lib/typecheck-ratchet.ts +51 -0
- package/scripts/nightly-docops.ts +90 -3
- 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/research-coo-admin-dates.ts +39 -0
- package/scripts/rhythm/daily.ts +51 -2
- package/scripts/rhythm/weekly.ts +3 -2
- package/scripts/skills/public-check.ts +7 -2
- package/scripts/smart-merge/resync-shadow.ts +5 -3
- package/scripts/test-diet/lib.ts +81 -1
- package/scripts/test-diet/node.ts +48 -2
- package/scripts/tsc-main-safety-net.ts +189 -0
- package/scripts/usage-rollup.ts +8 -4
- package/scripts/verify-coo-admin-evidence.ts +83 -0
- package/src/acp/client.ts +4 -2
- package/src/acp/codex-plugins.ts +48 -6
- package/src/agent/monad-agent-turn.ts +67 -5
- package/src/agent/run-context.ts +14 -0
- package/src/agent/tool-profile.ts +28 -2
- package/src/agent-env/profile.ts +25 -5
- package/src/agent-mission/acp-judge.ts +8 -2
- package/src/agent-mission/capabilities-cli.ts +16 -1
- package/src/agent-mission/driver.ts +27 -13
- package/src/agent-mission/pr-review-watch.ts +6 -2
- package/src/agent-mission/review-loop.ts +33 -5
- package/src/agent-mission/supervisor-metrics.ts +17 -2
- package/src/agent-substrate/acp-reviewer.ts +25 -9
- package/src/agent-substrate/pr-reviewer.ts +175 -32
- package/src/agent-substrate/review-intent.ts +106 -5
- 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 +238 -20
- 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 +30 -11
- package/src/away/release-watch.ts +47 -8
- package/src/boot/acp-server.ts +4 -7
- package/src/boot/acp-socket-path.ts +7 -0
- package/src/briefing/brief-items.ts +123 -22
- package/src/chat/index.ts +13 -3
- package/src/cli/agent-cli.ts +20 -0
- package/src/cli/brief-cli.ts +46 -22
- package/src/cli/cli-user-error.ts +9 -2
- package/src/cli/config-classify.ts +83 -0
- package/src/cli/control-cli.ts +14 -0
- package/src/cli/decisions-cli.ts +26 -16
- package/src/cli/log-event-names.ts +3 -0
- package/src/cli/logs-cli.ts +1 -0
- package/src/cli/logs-model-input.ts +1 -1
- 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 +94 -9
- package/src/cli/pr-land-overlap-evidence.ts +131 -0
- package/src/cli/release-cli.ts +74 -15
- package/src/cli/self-update.ts +173 -10
- package/src/cli/skills-cli.ts +12 -3
- package/src/cli/tasks-cli.ts +241 -28
- package/src/connectors/types.ts +6 -6
- package/src/context-bus/context-first.ts +51 -2
- package/src/context-bus/context-now-surfaces.ts +29 -0
- package/src/context-bus/coord-events.ts +32 -4
- package/src/context-bus/long-term-memory.ts +26 -7
- package/src/context-bus/nightly-condense.ts +170 -21
- package/src/control/control-status.ts +87 -0
- package/src/control-plane/light-member.ts +5 -3
- package/src/control-plane/member.ts +172 -7
- package/src/core-turn/run-goal-loop.ts +108 -3
- 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 +14 -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/decisions/decision-cards.ts +20 -1
- package/src/decisions/decision-ledger.ts +11 -8
- package/src/decisions/web-push-decision-cards.ts +19 -3
- package/src/discord-self-message.ts +2 -2
- package/src/display/coordinator.ts +25 -2
- package/src/domains/coo-admin-dates.evidence.json +876 -0
- package/src/domains/coo-admin-tool.ts +75 -14
- package/src/domains/cron-match.ts +1 -0
- package/src/domains/ops-status.ts +53 -0
- package/src/domains/outbound-alert.ts +41 -7
- 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/exec-requests/planner.ts +6 -0
- 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-kinds/registry.ts +6 -6
- package/src/graph-runner/graph-cli.ts +34 -2
- package/src/graph-runner/graph-run-api.ts +7 -0
- package/src/graph-runner/graph-tick.ts +73 -12
- package/src/graph-runner/runner.ts +94 -13
- package/src/graph-unify/wf-to-graph.ts +79 -0
- package/src/graph-wizard/generate.ts +34 -2
- package/src/graph-wizard/steps.ts +13 -0
- package/src/harness/dispatch-backpressure.ts +259 -0
- package/src/harness/harness-cli-command.ts +227 -50
- package/src/harness/harness-queue.ts +58 -14
- package/src/harness/harness-seams.ts +2 -20
- package/src/harness/harness-substrate-default.ts +72 -1
- package/src/harness/launch-advice.ts +23 -0
- 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 +199 -71
- 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/conclusion-compress.ts +93 -0
- package/src/knowledge/kgs/pack.ts +5 -2
- package/src/knowledge/kgs/sqlite-store.ts +15 -0
- package/src/knowledge/know-find.ts +9 -2
- package/src/knowledge/query.ts +20 -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 +332 -51
- package/src/loops/budget.ts +150 -0
- package/src/loops/neighbor-runtime.ts +88 -0
- package/src/loops/orchestrator/author-depth.ts +29 -11
- package/src/loops/orchestrator/overlap.ts +7 -1
- package/src/loops/orchestrator/resync-shadow.ts +1 -1
- package/src/loops/orchestrator/seat-share.ts +6 -49
- package/src/loops/orchestrator/tick.ts +35 -2
- package/src/loops/orchestrator/traffic.ts +6 -80
- package/src/loops/registry.ts +5 -0
- package/src/market/publish.ts +17 -1
- package/src/market/signed-index.ts +42 -0
- package/src/maturity/feature-maturity.ts +2 -1
- 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/mss/logging/redaction.ts +17 -0
- 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/draft-metrics.ts +22 -8
- package/src/nexus/api/error-reports.ts +30 -8
- package/src/nexus/api/graph-peer-edit.ts +77 -0
- package/src/nexus/api/graph-wizard-api.ts +9 -1
- package/src/nexus/api/graphs-api.ts +145 -7
- package/src/nexus/api/http-server.ts +101 -8
- package/src/nexus/api/loop-resources.ts +42 -0
- package/src/nexus/api/outbound-report.ts +8 -3
- package/src/nexus/api/plugins-market.ts +24 -0
- package/src/nexus/api/telegram-trigger-bot.ts +6 -3
- package/src/nexus/index.ts +13 -2
- package/src/nexus/outbound/format.ts +2 -0
- package/src/nexus/outbound/router.ts +198 -13
- package/src/oauth/claude-pty-maturity.ts +24 -0
- package/src/oauth/codex-account-rotation.ts +16 -18
- package/src/oauth/codex-account-store.ts +134 -5
- package/src/oauth/fallback-chain.ts +50 -15
- 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/market-bundle.ts +9 -0
- package/src/plugins/maker/plugin-maker.ts +32 -21
- package/src/plugins/maker/wizard-generate.ts +87 -9
- package/src/policy/llm-policy.ts +24 -6
- 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-board.ts +27 -0
- package/src/release-loop/checklist.ts +62 -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-address/seat-address.ts +1 -0
- package/src/seat-loop/seat-loop.ts +208 -21
- package/src/seat-loop/seat-report.ts +29 -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 +157 -11
- package/src/self-dev/dev-pipeline.ts +18 -1
- package/src/self-dev/draft-residue.ts +463 -0
- package/src/self-dev/draft-sweep.ts +195 -17
- 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 +9 -133
- package/src/self-dev/review-provider-fallback.ts +179 -0
- package/src/self-dev/run-store.ts +1 -3
- package/src/self-dev/run-supervisor.ts +8 -23
- 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/harness-policy-gates.ts +7 -5
- package/src/self-implement/headless-elanous-driver.ts +11 -9
- package/src/self-implement/host-regate.ts +148 -43
- package/src/self-implement/l8-merge-queue.ts +147 -13
- 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 +201 -43
- 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 +41 -6
- package/src/self-implement/self-implement-cli.ts +6 -0
- 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/shell-env-bootstrap.ts +19 -4
- 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 +29 -10
- package/src/storage/file-lock.ts +40 -4
- package/src/task-agent/actions.ts +4 -0
- package/src/task-agent/card-evidence.ts +59 -13
- package/src/task-agent/completion-evidence.ts +31 -3
- package/src/task-agent/cover.ts +61 -0
- 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 +222 -12
- 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 +118 -7
- package/src/task-agent/task-hand.ts +138 -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 +203 -28
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +259 -36
- package/src/task-orchestrator/surfaces/self-implement.ts +11 -0
- package/src/telegram-commands.ts +8 -0
- package/src/telegram-project-command.ts +6 -0
- 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/typecheck-ratchet.ts +2 -1
- package/src/user-config.ts +167 -28
- 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/executor.ts +24 -2
- package/src/workflow-runtime/triggers/registry.ts +27 -0
- package/src/workflow-runtime/triggers/schedule-source.ts +30 -3
- 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-c97eba9fb72a9a5e.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-ff55a35b202c0f94.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-995ea9f5ef33d71e.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/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-59fedea50d13c762.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-f1762140ef9a96b1.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-7581825d511a64c0.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/9497-b0e758d1cd4ae8d7.js +0 -1
- 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-937c92292a4ab4f0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d781be3e3a9cfd74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b0a80997903852d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-2b1263165630d9c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea998f7f5d156bea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-33c328b64ca508f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-e2d6bed48ac20120.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-544dd4bd4847eeb7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-3ee191319bf97d87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e4bcb2c503dab04b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-300897dcbbd5ed76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a449f1ed472b81c2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-9045094d6d3b5cd0.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-c06673596849ef45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-103fa3191c1b2e08.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-9f81233f29dcd409.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-be8b4615c919e36c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-c685b104e0dfa609.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-8d693331cfbb6add.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-cef4f30a4c22fae1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66ea1b54fc83fa15.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-7a12f61be4a579d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-c85b0589591a99c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-725a4da02dd129eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8cc707bd09a497d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-90b55be1f15ce0e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cb16606e08be65db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-16dc64b74ed6a40a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-21bec4afeb2f0917.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-dc39ee7a36d26385.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-84ae759f76053672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-3db58ddb61fe2be9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c5315e30f3528dc4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-2fe368efb6de3b6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8d04132dd0ac5e10.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-f23484de467c9ea3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-c69762987b751174.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-5456692bda39aafb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d75f7cd65845ce98.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-5603f5e568b25ce3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-d2cc0f4e89f42028.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-a6eb73b8a4840f1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-c0a3f4d10edb83fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6c0b88068c143f15.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-7f8d7fcdf058a845.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-22163556cd38bc88.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-141436fd26dd56fc.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/e81df11490b4413b.css +0 -1
- /package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_ssgManifest.js +0 -0
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// so ALL outbound routes through elanous's delivery channels. Send-only;
|
|
9
9
|
// auth via bearer (acp-token).
|
|
10
10
|
//
|
|
11
|
-
// Body: { text: string, markdown?: boolean, kind?: string }
|
|
11
|
+
// Body: { text: string, markdown?: boolean, kind?: string, role?: string }
|
|
12
12
|
// kind routes per-channel since R6 Phase 1 (2026-07-07): the body is
|
|
13
13
|
// handed to routeOutbound (src/nexus/outbound/router.ts) which fans out
|
|
14
14
|
// to telegram/discord/pushcut per the `outbound` user-config section.
|
|
@@ -53,6 +53,7 @@ interface OutboundBody {
|
|
|
53
53
|
text?: string;
|
|
54
54
|
markdown?: boolean;
|
|
55
55
|
kind?: string;
|
|
56
|
+
role?: string;
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
function json(body: unknown, status: number): Response {
|
|
@@ -85,10 +86,14 @@ export async function handleOutboundReport(req: Request, metaApi: MetaApiOpts, r
|
|
|
85
86
|
const cfg = getUserConfig();
|
|
86
87
|
const kind = typeof body.kind === 'string' ? body.kind : 'report';
|
|
87
88
|
try {
|
|
88
|
-
//
|
|
89
|
+
// routeOutbound dispatches via the channel adapter registry; legacy fan-out
|
|
90
|
+
// remains per-channel fail-soft and `delivered` = any channel ok.
|
|
89
91
|
// Producers (outbound-alert.ts deliver()) gate their direct-telegram
|
|
90
92
|
// fallback on this top-level boolean — keep it stable.
|
|
91
|
-
const
|
|
93
|
+
const role = typeof body.role === 'string' && /^[a-zA-Z0-9_-]{1,80}$/.test(body.role) ? body.role : undefined;
|
|
94
|
+
// A request that names a role intends that role's recipients — never fall back to the kind route silently.
|
|
95
|
+
if (body.role !== undefined && role === undefined) return json({ error: 'invalid-role' }, 400);
|
|
96
|
+
const result = await routeOutbound(cfg, { text, markdown: body.markdown ?? true, kind, ...(role ? { role } : {}) }, routerDeps);
|
|
92
97
|
const clientFallback = req.headers.get('X-Elanous-Client-Fallback') === 'direct';
|
|
93
98
|
const source = req.headers.get('X-Elanous-Outbound-Source') ?? 'daemon-http';
|
|
94
99
|
if (result.delivered || !clientFallback) observeDaemonSend(cfg, text, kind, result, source);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { listWizardDrafts, saveWizardDraft, type WizardResearchDraft } from '../../plugins/maker/wizard-generate.js';
|
|
2
3
|
import { dirname, join } from 'node:path';
|
|
3
4
|
import { elanousStateRoot } from '../../autopilot/state-paths.js';
|
|
4
5
|
import { debug } from '../../debug/log.js';
|
|
@@ -120,6 +121,29 @@ export function handlePluginsIndexGet(req: Request, opts: MetaApiOpts, root?: st
|
|
|
120
121
|
return jsonResponse(readMarketIndex(root, configuredTrustedKeys(configPath)));
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
export function handlePluginWizardList(req: Request, opts: MetaApiOpts, root = elanousStateRoot()): Response {
|
|
125
|
+
if (!checkAuth(req, opts)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
126
|
+
return jsonResponse({ plugins: listWizardDrafts(join(root, 'plugins-local')) });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function handlePluginWizardSave(req: Request, opts: MetaApiOpts, root = elanousStateRoot()): Promise<Response> {
|
|
130
|
+
if (!checkAuth(req, opts)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
131
|
+
let body: unknown;
|
|
132
|
+
try { body = await req.json(); } catch { return jsonResponse({ error: 'bad_request' }, 400); }
|
|
133
|
+
if (!body || typeof body !== 'object' || Array.isArray(body)) return jsonResponse({ error: 'bad_request' }, 400);
|
|
134
|
+
const input = body as { name?: unknown; draft?: unknown; regenerate?: unknown };
|
|
135
|
+
if (typeof input.name !== 'string' || !/^[a-z0-9][a-z0-9-]{1,31}$/.test(input.name) ||
|
|
136
|
+
!input.draft || typeof input.draft !== 'object' || Array.isArray(input.draft) ||
|
|
137
|
+
(input.regenerate !== undefined && typeof input.regenerate !== 'boolean')) return jsonResponse({ error: 'bad_request' }, 400);
|
|
138
|
+
try {
|
|
139
|
+
saveWizardDraft(join(root, 'plugins-local'), input.name, input.draft as WizardResearchDraft, input.regenerate === true);
|
|
140
|
+
return jsonResponse({ name: input.name, saved: true });
|
|
141
|
+
} catch (error) {
|
|
142
|
+
const reason = error instanceof Error ? error.message : 'invalid draft';
|
|
143
|
+
return jsonResponse({ error: 'invalid_wizard_draft', reason: /already exists|research draft/.test(reason) ? reason : 'invalid draft' }, 422);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
123
147
|
export function handlePluginsGet(req: Request, opts: MetaApiOpts, root?: string): Response {
|
|
124
148
|
if (!checkAuth(req, opts)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
125
149
|
return jsonResponse(listInstalledPlugins(root));
|
|
@@ -36,6 +36,7 @@ import { parseTelegramEndpoint, isOwnInstanceEndpoint, matchesBot } from '../../
|
|
|
36
36
|
import { createTelegramStreamSink } from '../../session/streaming/telegram-stream-sink.js';
|
|
37
37
|
import { splitMarkdownForTelegram } from '../../telegram-format.js';
|
|
38
38
|
import { formatTablesAndRules } from '../../discord-markdown.js';
|
|
39
|
+
import { receiveChannelEvent } from '../outbound/router.js';
|
|
39
40
|
|
|
40
41
|
export interface NexusTelegramTriggerBotOpts {
|
|
41
42
|
/** Bot token (without `Bot ` prefix). Production reads
|
|
@@ -117,11 +118,13 @@ export function createTelegramTriggerLogger(
|
|
|
117
118
|
* comment) so the wire is a near-identity with `raw` carrying the
|
|
118
119
|
* full payload (messageId · isDm) for debugging. */
|
|
119
120
|
export function toTelegramEvent(tap: TgTriggerEvent): TelegramEvent {
|
|
121
|
+
const envelope = receiveChannelEvent('telegram', tap);
|
|
122
|
+
if (!envelope || envelope instanceof Promise) throw new Error('telegram connector cannot normalize accepted tap');
|
|
120
123
|
return {
|
|
121
124
|
kind: tap.kind,
|
|
122
|
-
chat: tap.chat,
|
|
123
|
-
user: tap.user,
|
|
124
|
-
body:
|
|
125
|
+
chat: envelope.channel ?? tap.chat,
|
|
126
|
+
user: envelope.senderId ?? tap.user,
|
|
127
|
+
body: envelope.text,
|
|
125
128
|
...(tap.command !== undefined ? { command: tap.command } : {}),
|
|
126
129
|
raw: tap,
|
|
127
130
|
};
|
package/src/nexus/index.ts
CHANGED
|
@@ -410,6 +410,8 @@ export interface RunNexusOptions {
|
|
|
410
410
|
* detachForTesting; production runs always start the server. Tests
|
|
411
411
|
* that DO want the server can pass false explicitly. */
|
|
412
412
|
skipHttpServer?: boolean;
|
|
413
|
+
/** Test seam: replaces the daily error-report prune timer (the boot prune still runs for real). */
|
|
414
|
+
errorReportPruneScheduleForTesting?: (tick: () => void, ms: number) => { unref?: () => void };
|
|
413
415
|
/** Override starting port for the HTTP server. Defaults to 31415. */
|
|
414
416
|
httpStartPort?: number;
|
|
415
417
|
/** Control-plane port; passing 0 also enables an isolated listener in detached tests. */
|
|
@@ -1266,6 +1268,13 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
|
|
|
1266
1268
|
// 60s 틱마다 grace 유예 초과 구독자를 left 로 이탈 확정(reconcileSessionPresence).
|
|
1267
1269
|
// cleared in shutdown hook.
|
|
1268
1270
|
let presenceSweepHandle: ReturnType<typeof setInterval> | undefined;
|
|
1271
|
+
// ERROR-REPORT-PRUNE-TICK — 30-day error-report retention must not wait for the next receipt:
|
|
1272
|
+
// prune once at boot and once a day (unconditional · fail-soft · unref). Cleared in shutdown hook.
|
|
1273
|
+
let errorReportPrune: { stop(): void } | undefined;
|
|
1274
|
+
try {
|
|
1275
|
+
const { startErrorReportPruneTick } = await import('./api/error-reports.js');
|
|
1276
|
+
errorReportPrune = startErrorReportPruneTick({ ...(opts.errorReportPruneScheduleForTesting ? { schedule: opts.errorReportPruneScheduleForTesting } : {}) });
|
|
1277
|
+
} catch (err) { console.warn(`[nexus] error-report prune wiring failed: ${(err as Error).message}`); }
|
|
1269
1278
|
// ★ UR4d — 조율자 저지연 push watcher(logs.db tail edge-trigger). opt-in·기본 OFF.
|
|
1270
1279
|
// cleared in shutdown hook(내부 타이머는 unref 이나 명시 정지).
|
|
1271
1280
|
let coordinatorPushWatcher: { stop(): void } | undefined;
|
|
@@ -2743,11 +2752,12 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
|
|
|
2743
2752
|
if ((getUserConfig().raw?.decisions as { cards?: unknown } | undefined)?.cards !== false && !isAutonomousRunContext()) {
|
|
2744
2753
|
try {
|
|
2745
2754
|
const { DecisionCardService } = await import('../decisions/decision-cards.js');
|
|
2746
|
-
const { webPushDecisionTransport } = await import('../decisions/web-push-decision-cards.js');
|
|
2755
|
+
const { webPushDecisionTransport, webPushUrgency } = await import('../decisions/web-push-decision-cards.js');
|
|
2747
2756
|
const { listSubscriptions } = await import('../web-push/subscriptions.js');
|
|
2748
2757
|
const { DecisionLedger } = await import('../decisions/decision-ledger.js');
|
|
2749
2758
|
const ledger = new DecisionLedger();
|
|
2750
|
-
const service = new DecisionCardService({ transport: webPushDecisionTransport(ledger), ownerIds: [], ledger
|
|
2759
|
+
const service = new DecisionCardService({ transport: webPushDecisionTransport(ledger), ownerIds: [], ledger,
|
|
2760
|
+
sendFilter: (entry, now) => webPushUrgency(entry, now) !== 'not-urgent', deferredReason: webPushUrgency });
|
|
2751
2761
|
await service.tick();
|
|
2752
2762
|
webPushDecisionTimer = setInterval(() => {
|
|
2753
2763
|
void service.tick().catch((error: unknown) => {
|
|
@@ -3382,6 +3392,7 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
|
|
|
3382
3392
|
if (replayArmerHandle) { clearInterval(replayArmerHandle); replayArmerHandle = undefined; }
|
|
3383
3393
|
// §P2 — stop the session presence grace sweeper.
|
|
3384
3394
|
if (presenceSweepHandle) { clearInterval(presenceSweepHandle); presenceSweepHandle = undefined; }
|
|
3395
|
+
if (errorReportPrune) { errorReportPrune.stop(); errorReportPrune = undefined; }
|
|
3385
3396
|
// ★ UR4d — stop the coordinator low-latency push watcher(logs.db tail + debounce).
|
|
3386
3397
|
if (coordinatorPushWatcher) { try { coordinatorPushWatcher.stop(); } catch { /* ignore */ } coordinatorPushWatcher = undefined; }
|
|
3387
3398
|
// Phase 2 (2026-05-13) — dispose the TOX boot handle. dispose()
|
|
@@ -43,8 +43,66 @@ import {
|
|
|
43
43
|
export { chunkForDiscord } from './format.js';
|
|
44
44
|
export type { OutboundChannelType, OutboundMsg } from './format.js';
|
|
45
45
|
|
|
46
|
+
/** The adapter's capability declaration is explicit: a feature is unavailable unless
|
|
47
|
+
* the connector implements it. Send-only webhooks must not claim inbound support. */
|
|
48
|
+
export interface ChannelCapabilities {
|
|
49
|
+
send: boolean;
|
|
50
|
+
receive: boolean;
|
|
51
|
+
thread: boolean;
|
|
52
|
+
topic: boolean;
|
|
53
|
+
persona: boolean;
|
|
54
|
+
channelLifecycle: boolean;
|
|
55
|
+
permissions: boolean;
|
|
56
|
+
commands: boolean;
|
|
57
|
+
attachments: boolean;
|
|
58
|
+
buttons: boolean;
|
|
59
|
+
choices: boolean;
|
|
60
|
+
deliveryConfirmation: boolean;
|
|
61
|
+
rateLimit: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ChannelEnvelope {
|
|
65
|
+
text: string;
|
|
66
|
+
kind: string;
|
|
67
|
+
channel?: string;
|
|
68
|
+
senderId?: string;
|
|
69
|
+
messageId?: string | number;
|
|
70
|
+
threadId?: string;
|
|
71
|
+
topicId?: string;
|
|
72
|
+
persona?: { name: string; avatarUrl?: string };
|
|
73
|
+
attachments?: readonly { url: string; name?: string }[];
|
|
74
|
+
buttons?: readonly { label: string; value: string }[];
|
|
75
|
+
choices?: readonly { label: string; value: string }[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Plugin contract; optional operations may only be advertised when implemented.
|
|
79
|
+
* `send` returns the same ChannelResult shape used by the existing delivery ledger. */
|
|
80
|
+
export interface ChannelAdapter {
|
|
81
|
+
readonly type: string;
|
|
82
|
+
readonly capabilities: ChannelCapabilities;
|
|
83
|
+
send(config: OutboundChannelConfig, message: OutboundMsg, cfg: UserConfig, deps: RouterDeps): Promise<ChannelResult>;
|
|
84
|
+
receive?: (payload: unknown) => ChannelEnvelope | null | Promise<ChannelEnvelope | null>;
|
|
85
|
+
createChannel?: (name: string) => Promise<string>;
|
|
86
|
+
archiveChannel?: (id: string) => Promise<void>;
|
|
87
|
+
checkPermission?: (action: string) => Promise<boolean>;
|
|
88
|
+
registerCommands?: (commands: readonly string[]) => Promise<void>;
|
|
89
|
+
confirmDelivery?: (messageId: string) => Promise<boolean>;
|
|
90
|
+
retryAfterMs?: (result: ChannelResult) => number | undefined;
|
|
91
|
+
/** Validate a plugin's channel entry before it becomes eligible for routing.
|
|
92
|
+
* Unknown or invalid entries stay disabled rather than falling back to a different channel. */
|
|
93
|
+
parseConfig?: (raw: Record<string, unknown>) => OutboundChannelConfig | undefined;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Existing bot receive paths can normalize an accepted event through the same
|
|
97
|
+
* adapter contract before dispatching to their unchanged workflow/chat handlers. */
|
|
98
|
+
export function receiveChannelEvent(type: string, payload: unknown): ChannelEnvelope | null | Promise<ChannelEnvelope | null> {
|
|
99
|
+
const adapter = outboundAdapters.get(type) ?? installedAdapters.get(type);
|
|
100
|
+
if (!adapter?.capabilities.receive || !adapter.receive) return null;
|
|
101
|
+
return adapter.receive(payload);
|
|
102
|
+
}
|
|
103
|
+
|
|
46
104
|
export interface OutboundChannelConfig {
|
|
47
|
-
type: OutboundChannelType;
|
|
105
|
+
type: OutboundChannelType | (string & {});
|
|
48
106
|
/** discord: full webhook URL (required). pushcut: webhook URL — when
|
|
49
107
|
* omitted the adapter falls back to the API-key client
|
|
50
108
|
* (~/.elanous/pushcut.json) with `notification`. */
|
|
@@ -54,6 +112,24 @@ export interface OutboundChannelConfig {
|
|
|
54
112
|
notification?: string;
|
|
55
113
|
}
|
|
56
114
|
|
|
115
|
+
/** Connector providers register while the host is running; unregister on plugin
|
|
116
|
+
* deactivation. Built-ins cannot be replaced by a plugin or removed. */
|
|
117
|
+
const installedAdapters = new Map<string, ChannelAdapter>();
|
|
118
|
+
export function registerOutboundAdapter(adapter: ChannelAdapter): () => void {
|
|
119
|
+
if (!/^[a-z][a-z0-9-]*$/.test(adapter.type) || outboundAdapters.has(adapter.type) || installedAdapters.has(adapter.type)
|
|
120
|
+
|| !adapter.capabilities.send || typeof adapter.send !== 'function' || typeof adapter.parseConfig !== 'function'
|
|
121
|
+
|| (adapter.capabilities.receive && typeof adapter.receive !== 'function')
|
|
122
|
+
|| (adapter.capabilities.channelLifecycle && (typeof adapter.createChannel !== 'function' || typeof adapter.archiveChannel !== 'function'))
|
|
123
|
+
|| (adapter.capabilities.permissions && typeof adapter.checkPermission !== 'function')
|
|
124
|
+
|| (adapter.capabilities.commands && typeof adapter.registerCommands !== 'function')
|
|
125
|
+
|| (adapter.capabilities.deliveryConfirmation && typeof adapter.confirmDelivery !== 'function')
|
|
126
|
+
|| (adapter.capabilities.rateLimit && typeof adapter.retryAfterMs !== 'function')) {
|
|
127
|
+
throw new Error(`invalid or duplicate outbound connector: ${adapter.type}`);
|
|
128
|
+
}
|
|
129
|
+
installedAdapters.set(adapter.type, adapter);
|
|
130
|
+
return () => { if (installedAdapters.get(adapter.type) === adapter) installedAdapters.delete(adapter.type); };
|
|
131
|
+
}
|
|
132
|
+
|
|
57
133
|
export interface OutboundFanoutConfig {
|
|
58
134
|
channels: OutboundChannelConfig[];
|
|
59
135
|
/** kind → channel types. A kind missing here falls back to
|
|
@@ -62,6 +138,11 @@ export interface OutboundFanoutConfig {
|
|
|
62
138
|
routes?: Record<string, string[]>;
|
|
63
139
|
/** 외출 중 kind → channel types. 미지정 kind는 awayRoutes.default, 이것도 없으면 기존 routes를 유지한다. */
|
|
64
140
|
awayRoutes?: Record<string, string[]>;
|
|
141
|
+
/** Optional primary/fallback per message kind or role; legacy routes remain fan-out. */
|
|
142
|
+
primary?: Record<string, string>;
|
|
143
|
+
fallback?: Record<string, string>;
|
|
144
|
+
/** Optional role → eligible channel types; no role retains kind routes. */
|
|
145
|
+
roleRoutes?: Record<string, string[]>;
|
|
65
146
|
}
|
|
66
147
|
|
|
67
148
|
export interface ChannelResult {
|
|
@@ -95,6 +176,8 @@ export interface RouterDeps {
|
|
|
95
176
|
/** 롱콘텐츠 spill 주입(테스트/대체). 기본 = spillLongContent(S3 게이트·fail-soft).
|
|
96
177
|
* 긴 본문을 S3 업로드+링크로 대체 → 전 메신저가 짧은 링크 버전을 받음. */
|
|
97
178
|
spill?: (text: string) => { text: string; spilled: boolean; url?: string };
|
|
179
|
+
/** Test/host supplied connector registry; built-ins remain the default. */
|
|
180
|
+
adapters?: ReadonlyMap<string, ChannelAdapter>;
|
|
98
181
|
}
|
|
99
182
|
|
|
100
183
|
/** Parse the sparse `outbound` section. Malformed input → undefined
|
|
@@ -109,7 +192,16 @@ export function normalizeOutbound(raw: unknown): OutboundFanoutConfig | undefine
|
|
|
109
192
|
if (!entry || typeof entry !== 'object') continue;
|
|
110
193
|
const ch = entry as Record<string, unknown>;
|
|
111
194
|
const type = ch.type;
|
|
112
|
-
if (type !== 'telegram' && type !== 'discord' && type !== 'pushcut')
|
|
195
|
+
if (type !== 'telegram' && type !== 'discord' && type !== 'pushcut') {
|
|
196
|
+
if (typeof type === 'string') {
|
|
197
|
+
const connector = installedAdapters.get(type);
|
|
198
|
+
try {
|
|
199
|
+
const parsed = connector?.parseConfig?.(ch);
|
|
200
|
+
if (parsed?.type === type) channels.push(parsed);
|
|
201
|
+
} catch { /* invalid plugin config is not a routable channel */ }
|
|
202
|
+
}
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
113
205
|
const webhookUrl = typeof ch.webhookUrl === 'string' && ch.webhookUrl.trim()
|
|
114
206
|
? ch.webhookUrl.trim() : undefined;
|
|
115
207
|
const notification = typeof ch.notification === 'string' && ch.notification.trim()
|
|
@@ -132,7 +224,18 @@ export function normalizeOutbound(raw: unknown): OutboundFanoutConfig | undefine
|
|
|
132
224
|
};
|
|
133
225
|
const routes = parseRoutes(o.routes);
|
|
134
226
|
const awayRoutes = parseRoutes(o.awayRoutes);
|
|
135
|
-
|
|
227
|
+
const roleRoutes = parseRoutes(o.roleRoutes);
|
|
228
|
+
const parseSelection = (value: unknown): Record<string, string> | undefined => {
|
|
229
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
|
|
230
|
+
return Object.fromEntries(Object.entries(value as Record<string, unknown>)
|
|
231
|
+
// Keep a selection even when its channel is not configured: an explicit main/backup must
|
|
232
|
+
// never silently turn back into legacy fan-out (it is reported as not-routed instead).
|
|
233
|
+
.filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1].trim().length > 0));
|
|
234
|
+
};
|
|
235
|
+
const primary = parseSelection(o.primary);
|
|
236
|
+
const fallback = parseSelection(o.fallback);
|
|
237
|
+
return { channels, ...(routes ? { routes } : {}), ...(awayRoutes ? { awayRoutes } : {}),
|
|
238
|
+
...(roleRoutes ? { roleRoutes } : {}), ...(primary ? { primary } : {}), ...(fallback ? { fallback } : {}) };
|
|
136
239
|
}
|
|
137
240
|
|
|
138
241
|
/** Resolve the channel list for one message kind. No/empty config →
|
|
@@ -148,14 +251,14 @@ export function resolveChannels(
|
|
|
148
251
|
return outbound.channels.filter(ch => route.includes(ch.type));
|
|
149
252
|
}
|
|
150
253
|
|
|
151
|
-
async function deliverTelegram(
|
|
254
|
+
async function deliverTelegram(_ch: OutboundChannelConfig, msg: OutboundMsg, cfg: UserConfig, deps: RouterDeps): Promise<ChannelResult> {
|
|
152
255
|
const fmt = formatForChannel('telegram', msg);
|
|
153
256
|
const send = deps.telegramSend ?? sendTelegramReport;
|
|
154
257
|
const ok = await send(cfg, fmt.text, { markdown: fmt.markdown ?? msg.markdown, fetchImpl: deps.fetchImpl, kind: msg.kind });
|
|
155
258
|
return ok ? { type: 'telegram', ok: true } : { type: 'telegram', ok: false, error: 'not-configured' };
|
|
156
259
|
}
|
|
157
260
|
|
|
158
|
-
async function deliverDiscord(ch: OutboundChannelConfig, msg: OutboundMsg, deps: RouterDeps): Promise<ChannelResult> {
|
|
261
|
+
async function deliverDiscord(ch: OutboundChannelConfig, msg: OutboundMsg, _cfg: UserConfig, deps: RouterDeps): Promise<ChannelResult> {
|
|
159
262
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
160
263
|
// webhookUrl guaranteed by normalizeOutbound; guard for direct callers.
|
|
161
264
|
if (!ch.webhookUrl) return { type: 'discord', ok: false, error: 'missing-webhook-url' };
|
|
@@ -172,7 +275,7 @@ async function deliverDiscord(ch: OutboundChannelConfig, msg: OutboundMsg, deps:
|
|
|
172
275
|
return { type: 'discord', ok: true };
|
|
173
276
|
}
|
|
174
277
|
|
|
175
|
-
async function deliverPushcut(ch: OutboundChannelConfig, msg: OutboundMsg, deps: RouterDeps): Promise<ChannelResult> {
|
|
278
|
+
async function deliverPushcut(ch: OutboundChannelConfig, msg: OutboundMsg, _cfg: UserConfig, deps: RouterDeps): Promise<ChannelResult> {
|
|
176
279
|
const fmt = formatForChannel('pushcut', msg);
|
|
177
280
|
const title = fmt.title ?? `elanous ${msg.kind}`;
|
|
178
281
|
if (ch.webhookUrl) {
|
|
@@ -194,6 +297,40 @@ async function deliverPushcut(ch: OutboundChannelConfig, msg: OutboundMsg, deps:
|
|
|
194
297
|
return r.ok ? { type: 'pushcut', ok: true } : { type: 'pushcut', ok: false, error: r.reason ?? 'pushcut-failed' };
|
|
195
298
|
}
|
|
196
299
|
|
|
300
|
+
/** Built-in channel connectors. Telegram and Discord receive adapters normalize
|
|
301
|
+
* already-authorized trigger taps; the webhook and Pushcut senders do not poll. */
|
|
302
|
+
export const outboundAdapters: ReadonlyMap<string, ChannelAdapter> = new Map<string, ChannelAdapter>([
|
|
303
|
+
['telegram', { type: 'telegram', capabilities: {
|
|
304
|
+
send: true, receive: true, thread: false, topic: false, persona: false,
|
|
305
|
+
channelLifecycle: false, permissions: false, commands: false, attachments: false,
|
|
306
|
+
buttons: false, choices: false, deliveryConfirmation: false, rateLimit: false,
|
|
307
|
+
}, send: deliverTelegram, receive: (payload): ChannelEnvelope | null => {
|
|
308
|
+
if (!payload || typeof payload !== 'object') return null;
|
|
309
|
+
const tap = payload as Record<string, unknown>;
|
|
310
|
+
if (typeof tap.body !== 'string' || typeof tap.kind !== 'string' || typeof tap.chat !== 'string') return null;
|
|
311
|
+
return { text: tap.body, kind: tap.kind, channel: tap.chat,
|
|
312
|
+
...(typeof tap.user === 'string' ? { senderId: tap.user } : {}),
|
|
313
|
+
...(typeof tap.messageId === 'number' ? { messageId: tap.messageId } : {}) };
|
|
314
|
+
} }],
|
|
315
|
+
['discord', { type: 'discord', capabilities: {
|
|
316
|
+
send: true, receive: true, thread: false, topic: false, persona: false,
|
|
317
|
+
channelLifecycle: false, permissions: false, commands: false, attachments: false,
|
|
318
|
+
buttons: false, choices: false, deliveryConfirmation: false, rateLimit: false,
|
|
319
|
+
}, send: deliverDiscord, receive: (payload): ChannelEnvelope | null => {
|
|
320
|
+
if (!payload || typeof payload !== 'object') return null;
|
|
321
|
+
const tap = payload as Record<string, unknown>;
|
|
322
|
+
if (typeof tap.body !== 'string' || typeof tap.kind !== 'string' || typeof tap.channel !== 'string') return null;
|
|
323
|
+
return { text: tap.body, kind: tap.kind, channel: tap.channel,
|
|
324
|
+
...(typeof tap.user === 'string' ? { senderId: tap.user } : {}),
|
|
325
|
+
...(typeof tap.messageId === 'string' ? { messageId: tap.messageId } : {}) };
|
|
326
|
+
} }],
|
|
327
|
+
['pushcut', { type: 'pushcut', capabilities: {
|
|
328
|
+
send: true, receive: false, thread: false, topic: false, persona: false,
|
|
329
|
+
channelLifecycle: false, permissions: false, commands: false, attachments: false,
|
|
330
|
+
buttons: false, choices: false, deliveryConfirmation: false, rateLimit: false,
|
|
331
|
+
}, send: deliverPushcut }],
|
|
332
|
+
]);
|
|
333
|
+
|
|
197
334
|
/** Fan one message out to every routed channel. Per-channel fail-soft —
|
|
198
335
|
* a throwing adapter records `{ok:false}` and never blocks siblings.
|
|
199
336
|
* 구조: 채널별 포맷(format.ts) + 중복 발사 제어·배송 원장(delivery-ledger.ts).
|
|
@@ -228,27 +365,75 @@ export async function routeOutbound(cfg: UserConfig, msg: OutboundMsg, deps: Rou
|
|
|
228
365
|
|
|
229
366
|
// 상태 파일이 없거나 읽기에 실패하면 기존 kind 경로를 그대로 사용한다.
|
|
230
367
|
let list = resolveChannels(outbound, msg.kind);
|
|
368
|
+
// Whether the route that decided `list` is explicitly empty — that means «suppress», which is
|
|
369
|
+
// different from a route whose channels are simply not configured.
|
|
370
|
+
const kindRoute = outbound ? (outbound.routes?.[msg.kind] ?? outbound.routes?.default) : undefined;
|
|
371
|
+
let explicitlyEmpty = kindRoute !== undefined && kindRoute.length === 0;
|
|
372
|
+
const role = msg.role;
|
|
373
|
+
const roleRoute = role ? outbound?.roleRoutes?.[role] : undefined;
|
|
374
|
+
if (roleRoute && outbound) {
|
|
375
|
+
list = outbound.channels.filter(ch => roleRoute.includes(ch.type));
|
|
376
|
+
explicitlyEmpty = roleRoute.length === 0;
|
|
377
|
+
}
|
|
231
378
|
if (outbound?.awayRoutes) {
|
|
232
379
|
try {
|
|
233
380
|
if (readPresence().away) {
|
|
234
381
|
const awayRoute = outbound.awayRoutes[msg.kind] ?? outbound.awayRoutes.default;
|
|
235
382
|
// kind 도 default 도 없으면 기존 경로로 · 명시적인 빈 배열은 기존 routes 와 같은 규칙(채널 0)을 따른다.
|
|
236
383
|
if (awayRoute !== undefined) {
|
|
237
|
-
|
|
384
|
+
// Away mode narrows the route; it never widens a role's allowed channels.
|
|
385
|
+
list = outbound.channels.filter(ch => awayRoute.includes(ch.type) && (!roleRoute || roleRoute.includes(ch.type)));
|
|
386
|
+
// A role's explicitly empty route stays suppressed while away.
|
|
387
|
+
explicitlyEmpty = awayRoute.length === 0 || roleRoute?.length === 0;
|
|
238
388
|
try { debug.log('outbound.send', 'away-route', { kind: msg.kind, channels: list.map(ch => ch.type) }); } catch { /* 관측 실패는 발송 결과에 영향 없음 */ }
|
|
239
389
|
}
|
|
240
390
|
}
|
|
241
391
|
} catch { /* 상태 조회 실패 — 기존 경로 유지 */ }
|
|
242
392
|
}
|
|
243
|
-
const
|
|
393
|
+
const send = async (ch: OutboundChannelConfig): Promise<ChannelResult> => {
|
|
244
394
|
try {
|
|
245
|
-
|
|
246
|
-
if (
|
|
247
|
-
|
|
395
|
+
const adapter = deps.adapters?.get(ch.type) ?? outboundAdapters.get(ch.type) ?? installedAdapters.get(ch.type);
|
|
396
|
+
if (!adapter?.capabilities.send) return { type: ch.type, ok: false, error: 'unsupported-channel' };
|
|
397
|
+
const result = await adapter.send(ch, outMsg, cfg, deps);
|
|
398
|
+
// A connector may not impersonate another channel or echo credentials
|
|
399
|
+
// through the response. Legacy built-in result fields stay unchanged.
|
|
400
|
+
if (!outboundAdapters.has(ch.type)) return { type: ch.type, ok: result.ok,
|
|
401
|
+
...(result.ok ? {} : { error: 'delivery-failed' }) };
|
|
402
|
+
return { ...result, type: ch.type };
|
|
248
403
|
} catch (e) {
|
|
249
|
-
|
|
404
|
+
// Connector exceptions may include secret-bearing URLs or configuration.
|
|
405
|
+
// Keep the old built-in error reasons unless they expose the webhook;
|
|
406
|
+
// a plugin's arbitrary configuration cannot safely be echoed at all.
|
|
407
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
408
|
+
const plugin = !outboundAdapters.has(ch.type);
|
|
409
|
+
return { type: ch.type, ok: false,
|
|
410
|
+
error: plugin || (ch.webhookUrl && reason.includes(ch.webhookUrl)) ? 'delivery-failed' : reason };
|
|
250
411
|
}
|
|
251
|
-
}
|
|
412
|
+
};
|
|
413
|
+
const primaryType = (role ? outbound?.primary?.[role] : undefined) ?? outbound?.primary?.[msg.kind] ?? outbound?.primary?.default;
|
|
414
|
+
const fallbackType = (role ? outbound?.fallback?.[role] : undefined) ?? outbound?.fallback?.[msg.kind] ?? outbound?.fallback?.default;
|
|
415
|
+
// Legacy routes still fan out. An explicit primary switches only this kind/role to ordered
|
|
416
|
+
// failover: main, then the configured backup — never the rest of the route. A selected channel
|
|
417
|
+
// that the current route does not carry is recorded as not-routed and the backup is tried.
|
|
418
|
+
// An explicitly empty route stays suppressed (no rows).
|
|
419
|
+
// Only an explicitly empty route suppresses the selection entirely (no rows).
|
|
420
|
+
const suppressed = list.length === 0 && explicitlyEmpty;
|
|
421
|
+
let channels: ChannelResult[];
|
|
422
|
+
if (suppressed) {
|
|
423
|
+
channels = [];
|
|
424
|
+
} else if (primaryType) {
|
|
425
|
+
channels = [];
|
|
426
|
+
for (const type of fallbackType && fallbackType !== primaryType ? [primaryType, fallbackType] : [primaryType]) {
|
|
427
|
+
const ch = list.find(candidate => candidate.type === type);
|
|
428
|
+
const result = ch ? await send(ch) : { type, ok: false, error: 'not-routed' };
|
|
429
|
+
channels.push(result);
|
|
430
|
+
if (result.ok) break;
|
|
431
|
+
}
|
|
432
|
+
} else {
|
|
433
|
+
// A backup without a main has nothing to back up: the allowed route already fans out to every
|
|
434
|
+
// channel it may reach, and a backup outside that route must not bypass role/away limits.
|
|
435
|
+
channels = await Promise.all(list.map(send));
|
|
436
|
+
}
|
|
252
437
|
|
|
253
438
|
// 배송 기록(리드 동기화·중복 제어 토대) — fail-soft.
|
|
254
439
|
if (ledger) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ClaudePtyMaturity =
|
|
2
|
+
| { readonly mature: true }
|
|
3
|
+
| { readonly mature: false; readonly why: 'too-few-samples' | 'completion-below-70' | 'unknown-screen-above-10' | 'intervention-above-0.2' | 'sample-unreadable' };
|
|
4
|
+
|
|
5
|
+
export type ClaudePtyMaturitySample = {
|
|
6
|
+
readonly runCount: number;
|
|
7
|
+
readonly completedCount: number;
|
|
8
|
+
readonly unknownScreenCount: number;
|
|
9
|
+
readonly interventionCount: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/** 최근 런의 계수만 판정한다. 표본을 못 읽거나 계수가 불가능하면 성숙으로 추정하지 않는다. */
|
|
13
|
+
export function judgeClaudePtyMaturity(sample: ClaudePtyMaturitySample | null | undefined): ClaudePtyMaturity {
|
|
14
|
+
if (!sample || ![sample.runCount, sample.completedCount, sample.unknownScreenCount, sample.interventionCount]
|
|
15
|
+
.every((count) => Number.isSafeInteger(count) && count >= 0)
|
|
16
|
+
|| sample.completedCount > sample.runCount || sample.unknownScreenCount > sample.runCount) {
|
|
17
|
+
return { mature: false, why: 'sample-unreadable' };
|
|
18
|
+
}
|
|
19
|
+
if (sample.runCount < 10) return { mature: false, why: 'too-few-samples' };
|
|
20
|
+
if (sample.completedCount / sample.runCount < 0.7) return { mature: false, why: 'completion-below-70' };
|
|
21
|
+
if (sample.unknownScreenCount / sample.runCount > 0.1) return { mature: false, why: 'unknown-screen-above-10' };
|
|
22
|
+
if (sample.interventionCount / sample.runCount > 0.2) return { mature: false, why: 'intervention-above-0.2' };
|
|
23
|
+
return { mature: true };
|
|
24
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// 주간 창이 찬 계정으로 계속 쏘면 런이 「구현 결손」으로 죽는다(그 어휘는 `#7123` 이 냈다).
|
|
5
5
|
//
|
|
6
6
|
// ⛔⭐⭐ **결정 다섯** (대표):
|
|
7
|
-
// ①
|
|
7
|
+
// ① 리셋권 소비는 순수 판정 밖의 적용 경로가 기존 소비 연산으로 맡는다.
|
|
8
8
|
// ② 기본 ON. config `llm.codexAccountRotation: false` 로 끈다.
|
|
9
9
|
// ③ 사람이 «명시»한 계정은 전환하지 않는다 — 의도가 이긴다.
|
|
10
10
|
// ④ 현재 사용률을 모르면 안전한 기본 계정에 고정하지 않는다 — 쓸 후보가 있으면 넘긴다.
|
|
@@ -185,23 +185,6 @@ export function decideCodexRotation(input: RotationInput): RotationDecision {
|
|
|
185
185
|
});
|
|
186
186
|
if (input.explicit) return { reason: 'explicit', candidateCount, accountThresholds };
|
|
187
187
|
if (!input.enabled) return { reason: 'disabled', candidateCount, accountThresholds, ...(input.disabledProvenance ? { disabledProvenance: input.disabledProvenance } : {}) };
|
|
188
|
-
if (input.creditPace?.active) {
|
|
189
|
-
const self = input.candidates.find((candidate) => candidate.name === input.current.name);
|
|
190
|
-
const eligible = (name: string, balance: number | undefined, hasCredits: boolean | undefined, home: string | undefined): boolean =>
|
|
191
|
-
!!home?.trim() && typeof balance === 'number' && Number.isFinite(balance) && balance > 0
|
|
192
|
-
&& hasCredits !== false && accountThresholds.some((row) => row.name === name
|
|
193
|
-
&& (row.status === 'reached' || row.status === 'threshold-reached'));
|
|
194
|
-
const currentBalance = input.currentCreditBalance ?? self?.creditBalance;
|
|
195
|
-
const currentHas = input.currentHasCredits ?? self?.hasCredits;
|
|
196
|
-
const to = otherCandidates.filter((candidate) => eligible(candidate.name, candidate.creditBalance, candidate.hasCredits, candidate.home))
|
|
197
|
-
.sort((a, b) => (b.creditBalance! - a.creditBalance!) || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))[0];
|
|
198
|
-
if (eligible(input.current.name, currentBalance, currentHas, self?.home ?? input.current.home)) {
|
|
199
|
-
return { reason: 'credit-pace', candidateCount, accountThresholds };
|
|
200
|
-
}
|
|
201
|
-
if (to) {
|
|
202
|
-
return { reason: 'credit-pace', candidateCount, accountThresholds, to };
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
188
|
const currentUsageUnknown = input.currentReached === undefined && input.currentUsedPercent == null;
|
|
206
189
|
if (input.currentReached !== true && !currentUsageUnknown && accountThresholds[0]?.status !== 'threshold-reached') {
|
|
207
190
|
return { reason: 'not-reached', candidateCount, accountThresholds };
|
|
@@ -232,6 +215,21 @@ export function decideCodexRotation(input: RotationInput): RotationDecision {
|
|
|
232
215
|
const to = usable[0];
|
|
233
216
|
if (!to) {
|
|
234
217
|
if (input.resetCreditAvailability === 'available') return { reason: 'reset-credit-available', candidateCount, accountThresholds };
|
|
218
|
+
if (input.creditPace?.active) {
|
|
219
|
+
const self = input.candidates.find((candidate) => candidate.name === input.current.name);
|
|
220
|
+
const eligible = (name: string, balance: number | undefined, hasCredits: boolean | undefined, home: string | undefined): boolean =>
|
|
221
|
+
!!home?.trim() && typeof balance === 'number' && Number.isFinite(balance) && balance > 0
|
|
222
|
+
&& hasCredits !== false && accountThresholds.some((row) => row.name === name
|
|
223
|
+
&& (row.status === 'reached' || row.status === 'threshold-reached'));
|
|
224
|
+
const currentBalance = input.currentCreditBalance ?? self?.creditBalance;
|
|
225
|
+
const currentHas = input.currentHasCredits ?? self?.hasCredits;
|
|
226
|
+
const richest = otherCandidates.filter((candidate) => eligible(candidate.name, candidate.creditBalance, candidate.hasCredits, candidate.home))
|
|
227
|
+
.sort((a, b) => (b.creditBalance! - a.creditBalance!) || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))[0];
|
|
228
|
+
if (eligible(input.current.name, currentBalance, currentHas, self?.home ?? input.current.home)) {
|
|
229
|
+
return { reason: 'credit-pace', candidateCount, accountThresholds };
|
|
230
|
+
}
|
|
231
|
+
if (richest) return { reason: 'credit-pace', candidateCount, accountThresholds, to: richest };
|
|
232
|
+
}
|
|
235
233
|
// 대표 크레딧 허가: 구독 잔량이 남은 계정이 없으면 크레딧으로 계속 — 한도가 찬 요청은 서버가 선불 크레딧으로 넘긴다.
|
|
236
234
|
// 🩸 09-28 실측: default 크레딧만 시간당 ~5,200 씩 줄고 team·third(합 ~5.5만)는 0 — «지금 계정에 머문다»만으로는
|
|
237
235
|
// 한 계정 크레딧이 바닥나면 남은 크레딧을 두고 폴백(grok)으로 갔다. ⇒ 크레딧이 «더 많이» 남은 계정으로 옮긴다.
|