elanous 0.2.24 → 0.2.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +1 -0
- package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +36 -0
- package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +148 -0
- package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1454-a9c338f5bb556f42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8532.a86e99acf9b761cb.js → 1516.83dd2c1b86b4e507.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{89849432.9eaa2f4c9c010965.js → 16e57f67.3ea19e893461e611.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1505.5826671109111e75.js → 1743.563d3168e95825ef.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +24 -0
- package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +32 -0
- package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2846.d6a433b8663819a5.js +309 -0
- package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{5967-c0a80f8ffe5d4050.js → 3259-86f3be56e43eaf6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5578.ac963634373b28c6.js → 4084.15ecaf4240bd9e77.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8438.ee7f0df3b3f6fcb4.js → 4204.a409ab6250c0f6a8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +8 -0
- package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7905.b230b9d06cb4ad5d.js → 4593.10f5b9bd702d4a6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +104 -0
- package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{8569.b853a8daa8f31d12.js → 5081.a240b63fad28663a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2528.0af5c0e1fad88df6.js → 5408.377c8c543635b81f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9502-32c5dc22e8f120f5.js → 5492-e05e26a033ba80d2.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/5785-ea8d2c633b6688e3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/599-a914cc0468f56143.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +23 -0
- package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5974.360f8441eb0ac1ec.js → 6196.34d6b229079e9e28.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +64 -0
- package/apps/pwa/out/_next/static/chunks/{ce383d63.d2ede338788ed18e.js → 65ebff95.081daeff622d238e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +2 -0
- package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{83cfc5c8.349535543c1548b6.js → 6def8a8e.c81f9ca41028eccf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2721.bc9a8f36bd85c07a.js → 7483.ba01c6c209b81bba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{6702.ebbd165d5e4a4a14.js → 7752.5cbdd0b433c54af9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8925-2abfb48af477fb7f.js → 8085-1e5fce59500a2cc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{b4e12462-5fab4a813a63dadd.js → 83a80514-b897b64df43ce108.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +93 -0
- package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{8264.00e434fbd02e9311.js → 8578.dff22d988cc2b106.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +115 -0
- package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +41 -0
- package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +74 -0
- package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +94 -0
- package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7518.49161e8f5814abdb.js → 9311.24c8f5ea793253dd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9976.8f28864317639fe6.js → 94.4cfed21c0b781a06.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +90 -0
- package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{0e3acd34.d42b2ef87fdf4234.js → 973cbf1b.3bbcf2b41548eca7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6571-926ddf024a6ad5df.js → 9917-9e26abc5f7772735.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +79 -0
- package/apps/pwa/out/_next/static/chunks/{740.90b31555290236a9.js → 9974.e77b4ff4884557b3.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{4c5e95ce.83e9b16add6fcd8c.js → ab4d57c2.e90bc2cb31949045.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-a1ce306364f08da9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-07110da72c45e68f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2d76d4a7eae91bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e5a9302c105725a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-20662900d6b4b455.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-f707a509515ac50c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-6a16a48d1aa6e91f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/{page-26345242e4049f55.js → page-fcb06e305f515527.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-39f82acf619cca23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-7c2c8f81b185f9c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ae7aff07e32676bb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-482c60c1bc540d0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-7cb996c1aa08b6f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-623e08fe4477d606.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-db460cd8aecb8490.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-ff27902d0b11ef4f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-8397a5c6ca569bf4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1917ea87ea71ab6b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-25a302273b054fd7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-670510eda8b9443f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4bb7556e2e97a750.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-b92caddb5c715f30.js → page-15c0a4095baddfba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-4eb96fc7241c2456.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d64ff212dc55d03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-7f096248993fc2d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e47fc72049149a38.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-f7d808e31e005895.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-5c2b24b5496dad73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-76cdb531668b5191.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d376e0c83edc041a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-87b88f551f421d8b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-dab163b338e3b966.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-08019efef111ed2e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-0260ffc7eda50db1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-980ce6fe36ad95eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-99c4e6c7345a9156.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-0ab42e0f05823013.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{53746282.1be36038d1abd949.js → e117f801.e92bf10242653497.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{0673cc54.8e2ef1c23e49e190.js → f4dfbfc0.a69fb12f854882aa.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/graphs/release/release-loop.yaml +5 -5
- package/graphs/steward/recipes.yaml +4 -0
- package/graphs/steward/steward.yaml +10 -1
- package/package.json +1 -1
- package/scripts/bench-report.ts +46 -1
- package/scripts/ci-typecheck-changed.ts +88 -7
- package/scripts/coord-msg-bridge.ts +209 -0
- package/scripts/coord-post.sh +40 -7
- package/scripts/coord-requests-bridge.ts +10 -5
- package/scripts/expose-rubric-suggest.ts +1 -1
- package/scripts/measure-tsc-affected-roots.ts +10 -1
- package/scripts/release-loop/auto-approve-node.ts +6 -0
- package/scripts/release-loop/export-check-node.ts +8 -5
- package/scripts/release-loop/gate-closure.ts +286 -0
- package/scripts/release-loop/gate-node.ts +73 -13
- package/scripts/release-loop/gate-partial.ts +34 -6
- package/scripts/release-loop/node-verdict.ts +7 -2
- package/scripts/release-loop/ops-upgrade-node.ts +63 -42
- package/scripts/release-loop/publish-node.ts +6 -0
- package/scripts/release-loop/resume-release.ts +37 -10
- package/scripts/release-loop/resume.ts +69 -4
- package/scripts/tsc-baseline-cache.ts +28 -3
- package/scripts/usage-rollup.ts +27 -13
- package/scripts/ux-sim.ts +30 -1
- package/skills/youtube-master/scripts/main.ts +4 -1
- package/skills/youtube-master/src/obsidian.ts +9 -0
- package/src/agent/task-notification.ts +30 -1
- package/src/agent-substrate/acp-implementer.ts +14 -7
- package/src/agent-substrate/pr-reviewer.ts +30 -10
- package/src/agent-substrate/review-observation.ts +9 -2
- package/src/agent-substrate/self-review-cli.ts +154 -16
- package/src/boot/daemon-tools/self-implement.ts +72 -4
- package/src/budget/cost-tier-advisor.ts +91 -0
- package/src/budget/llm-cost.ts +5 -1
- package/src/budget/shadow-arms.ts +77 -0
- package/src/budget/types.ts +5 -3
- package/src/budget/unified-usage.ts +172 -8
- package/src/cli/control-cli.ts +29 -0
- package/src/cli/doctor-cli.ts +106 -3
- package/src/cli/friendly-errors.ts +113 -0
- package/src/cli/intake-cli.ts +3 -1
- package/src/cli/memory-cli.ts +182 -0
- package/src/cli/model-watch-cli.ts +4 -1
- package/src/cli/msg-cli.ts +15 -5
- package/src/cli/pr-cli.ts +53 -0
- package/src/cli/pr-land-overlap-evidence.ts +18 -10
- package/src/cli/pr-land-pod-shadow.ts +54 -0
- package/src/cli/release-cli.ts +41 -12
- package/src/cli/release-run-if-ready.ts +11 -0
- package/src/cli/resource-cli.ts +48 -0
- package/src/cli/retro-cli.ts +12 -3
- package/src/cli/seat-cli.ts +121 -0
- package/src/cli/seat-requests-cli.ts +25 -0
- package/src/cli/self-utterances-cli.ts +140 -0
- package/src/cli/tasks-cli.ts +168 -14
- package/src/cli/usage-cli.ts +3 -1
- package/src/compact/verify-probe.ts +23 -3
- package/src/context-card/cell.ts +40 -0
- package/src/context-card/index.ts +50 -0
- package/src/control/control-status.ts +30 -1
- package/src/dashboard/boot-timing.ts +35 -0
- package/src/dashboard/index.ts +86 -24
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +26 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +10 -138
- package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
- package/src/debug/log-diet.ts +16 -4
- package/src/debug/log.ts +1 -1
- package/src/domains/morning-essential.ts +18 -3
- package/src/domains/release-tool.ts +29 -8
- package/src/domains/surface-events.ts +16 -0
- package/src/elanous-config-dir.ts +2 -2
- package/src/execution-loop/launch-gate.ts +158 -2
- package/src/fleet/host-doctor.ts +446 -0
- package/src/goals/judge.ts +20 -6
- package/src/graph-runner/runner.ts +12 -6
- package/src/graph-wizard/archetypes.ts +14 -8
- package/src/graph-wizard/generate.ts +77 -1
- package/src/grok.ts +13 -7
- package/src/harness/harness-cli-command.ts +102 -51
- package/src/harness/harness-stop.ts +93 -19
- package/src/index.ts +52 -179
- package/src/instance/current.ts +2 -6
- package/src/instance/resolve.ts +5 -6
- package/src/intake-plane/collect-github.ts +7 -2
- package/src/intake-plane/lens.ts +46 -4
- package/src/intake-plane/requirement-funnel.ts +53 -1
- package/src/intelligence-map/catalog-feed.ts +119 -0
- package/src/intelligence-map/model-watch-intake.ts +40 -0
- package/src/intelligence-map/model-watch-mission.ts +14 -1
- package/src/llm/open-weight-discipline.ts +21 -0
- package/src/llm/openai-sampling-fields.ts +89 -0
- package/src/llm/runtime-model-family.ts +61 -0
- package/src/llm/zai-coding-plan.ts +27 -1
- package/src/llm.ts +17 -97
- package/src/machines/machine-ledger.ts +31 -3
- package/src/maturity/cli-maturity.ts +13 -3
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/msg/msg-store.ts +69 -7
- package/src/nexus/api/http-server.ts +22 -0
- package/src/oauth/codex-account-rotation.ts +4 -1
- package/src/oauth/codex-account-store.ts +20 -7
- package/src/oauth/codex-quota-policy.ts +33 -4
- package/src/ops/overview-collect.ts +3 -2
- package/src/ops/overview-owner.ts +29 -0
- package/src/plugin-hooks/shell-hook.ts +17 -2
- package/src/plugin-missions/evaluator-runner.ts +18 -2
- package/src/plugins/install/plugin-install.ts +11 -1
- package/src/preview/terminal.ts +15 -5
- package/src/project/project-store.ts +20 -0
- package/src/prompt-enhance/enhance.ts +11 -0
- package/src/release-loop/auto-start.ts +7 -5
- package/src/release-loop/checklist.ts +52 -5
- package/src/release-loop/feature-store.ts +10 -9
- package/src/release-loop/gate-shards.ts +4 -0
- package/src/release-loop/light-rc.ts +84 -13
- package/src/release-loop/merged-pr-checklist.ts +35 -5
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/seat-loop/duty-ledger.ts +64 -0
- package/src/seat-loop/seat-loop.ts +5 -1
- package/src/self-dev/decompose.ts +37 -3
- package/src/self-dev/dev-pipeline.ts +32 -7
- package/src/self-dev/draft-residue.ts +16 -6
- package/src/self-dev/draft-sweep.ts +75 -18
- package/src/self-dev/fabric-decompose-adapter.ts +9 -2
- package/src/self-dev/orchestrate.ts +6 -2
- package/src/self-dev/run-supervisor.ts +72 -8
- package/src/self-implement/gate-cli.ts +29 -10
- package/src/self-implement/gate-remote.ts +4 -1
- package/src/self-implement/goal-author.ts +15 -29
- package/src/self-implement/goal-command-execution.ts +26 -0
- package/src/self-implement/goal-new-paths.ts +42 -0
- package/src/self-implement/host-regate.ts +124 -30
- package/src/self-implement/importer-test-index.ts +3 -1
- package/src/self-implement/l8-merge-queue.ts +80 -2
- package/src/self-implement/merge-train.ts +19 -0
- package/src/self-implement/off-diff-evidence.ts +40 -1
- package/src/self-implement/orchestrator.ts +90 -20
- package/src/self-implement/premise-review.ts +159 -0
- package/src/self-implement/pwa-import-graph.ts +194 -7
- package/src/self-implement/regate-detail.ts +79 -0
- package/src/self-implement/review-deferred-to-host.ts +21 -0
- package/src/self-implement/rework-budget-judgment.ts +23 -3
- package/src/self-implement/running-runs.ts +2 -2
- package/src/self-implement/scope-adjacency.ts +23 -0
- package/src/self-implement/seams.ts +42 -7
- package/src/self-implement/self-implement-runtime.ts +126 -21
- package/src/session/index.ts +14 -4
- package/src/session-runtime/index.ts +55 -11
- package/src/skills/tools/agent.ts +16 -1
- package/src/skills/tools/persistent-grounding.ts +11 -1
- package/src/skills/tools/shell.ts +33 -1
- package/src/steward/rejudge-tick.ts +142 -0
- package/src/task-agent/board.ts +92 -3
- package/src/task-agent/card-evidence.ts +88 -1
- package/src/task-agent/cover.ts +85 -1
- package/src/task-agent/live-moves.ts +14 -6
- package/src/task-agent/parent-host.ts +27 -3
- package/src/task-agent/rejudge-on-head.ts +370 -29
- package/src/task-agent/review-result-capture.ts +67 -2
- package/src/task-agent/shadow.ts +148 -21
- package/src/task-agent/task-hand.ts +22 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +14 -0
- package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +122 -0
- package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +23 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +53 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +236 -28
- package/src/tool-runtime/tool-search-runtime.ts +25 -0
- package/src/tui.ts +20 -1
- package/src/user-config.ts +21 -63
- package/src/ux-sim/fault-cred-expiry.ts +100 -0
- package/src/ux-sim/fault-pod-death.ts +74 -0
- package/src/ux-sim/fault-pool-cap.ts +81 -0
- package/src/version/packed-revision.json +1 -1
- package/src/webclone/qa-table.ts +22 -0
- package/apps/pwa/out/_next/static/chunks/0a09e062-34f747a17d8d8c2e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +0 -77
- package/apps/pwa/out/_next/static/chunks/1325-dc3f3c21eb181cb4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +0 -34
- package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +0 -24
- package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1669-da843ed73aa301f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +0 -36
- package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +0 -122
- package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +0 -62
- package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/272-0eed0fb0aab716b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +0 -149
- package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3961-aaae04ed1d32622f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +0 -309
- package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5313.1697309c532b9856.js +0 -2
- package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +0 -74
- package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +0 -64
- package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +0 -32
- package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +0 -93
- package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +0 -148
- package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +0 -226
- package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +0 -27
- package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +0 -115
- package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +0 -8
- package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +0 -23
- package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +0 -90
- package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +0 -41
- package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +0 -287
- package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +0 -79
- package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +0 -104
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-3b9fc39362473ae7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f2b62c19ca68fef8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d7602d489edf5f37.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-24282bf9f90031a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-8b7c5ab6b5bc8d64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-4eb84d454f8c3415.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-b2e494bdad57fcb5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-c0ab229673a8b0eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-3e2b45f3c36dbac4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c22aa511b28743ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-bf88c0f558d8ef54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-52fec523e5b5d3ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-67723dfdcde92b31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-22725e2570f1126b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1891335950d68b70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-3267af1ebdc73cf5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-c314b75c11234998.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-9f9c85415f61782b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-c1d4276059085587.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-833aab587f26ad4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8526c17ae38e6a50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-f998637a8402115c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-b7bb53828b17b335.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-1b1850de0257e46d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6f23159fedb41f67.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1d809a87139dd024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-da9e570234d481fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-8ce3a38e210b810a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-57ffeeb6019440fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-abbb417bf514630b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2c2b3f29cec1efa4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-9369279f72fc7b51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-64861f14039499c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ddc4c93efd8ab94b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-901a1391b81053bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-68d9bbaac9841a58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-b5c0c996f329371e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-89881ccbcf728978.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-0e87a803b3d7165e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-58d4e5cb30ef4871.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-02ce4c3b5f39e4d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-e620d1bb8eadcec2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-acf868c64d77f950.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-54fa605fa6dba457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-bc79f0833533fa84.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d5c4398eea03d8f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-b2763b10dc6b3836.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +0 -1
- /package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Cost-tier advisor — when forecast says warn/throttle, suggest one step down
|
|
2
|
+
// (premium → balanced → economy). Tier table values are estimates until
|
|
3
|
+
// MODEL-BENCH replaces them.
|
|
4
|
+
|
|
5
|
+
import { debug } from '../debug/log.js';
|
|
6
|
+
import type { ForecastResult } from './forecaster.js';
|
|
7
|
+
|
|
8
|
+
export type CostTier = 'premium' | 'balanced' | 'economy';
|
|
9
|
+
|
|
10
|
+
export const COST_TIERS: Record<CostTier, {
|
|
11
|
+
label: string;
|
|
12
|
+
stages: { authoring: string; implement: string; review: string; judge: string };
|
|
13
|
+
usdPerTaskEstimate: number;
|
|
14
|
+
qualityRisk: string;
|
|
15
|
+
source: 'estimate';
|
|
16
|
+
}> = {
|
|
17
|
+
premium: {
|
|
18
|
+
label: '프리미엄',
|
|
19
|
+
stages: {
|
|
20
|
+
authoring: 'claude-opus-4-7',
|
|
21
|
+
implement: 'gpt-6-astra',
|
|
22
|
+
review: 'claude-opus-4-7',
|
|
23
|
+
judge: 'grok-4.7',
|
|
24
|
+
},
|
|
25
|
+
usdPerTaskEstimate: 1.2,
|
|
26
|
+
qualityRisk: '낮음 — 최고 품질 유지',
|
|
27
|
+
source: 'estimate',
|
|
28
|
+
},
|
|
29
|
+
balanced: {
|
|
30
|
+
label: '균형',
|
|
31
|
+
stages: {
|
|
32
|
+
authoring: 'claude-sonnet-4-6',
|
|
33
|
+
implement: 'gpt-5.6-terra',
|
|
34
|
+
review: 'claude-sonnet-4-6',
|
|
35
|
+
judge: 'grok-4.6',
|
|
36
|
+
},
|
|
37
|
+
usdPerTaskEstimate: 0.45,
|
|
38
|
+
qualityRisk: '중간 — 대부분 작업에 충분',
|
|
39
|
+
source: 'estimate',
|
|
40
|
+
},
|
|
41
|
+
economy: {
|
|
42
|
+
label: '절약',
|
|
43
|
+
stages: {
|
|
44
|
+
authoring: 'claude-haiku-4-5',
|
|
45
|
+
implement: 'gpt-6-luna',
|
|
46
|
+
review: 'gemini-2.5-flash',
|
|
47
|
+
judge: 'gemini-3.5-flash-lite',
|
|
48
|
+
},
|
|
49
|
+
usdPerTaskEstimate: 0.12,
|
|
50
|
+
qualityRisk: '높음 — 단순·반복 작업에 적합',
|
|
51
|
+
source: 'estimate',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const DOWN_ONE: Record<CostTier, CostTier | null> = {
|
|
56
|
+
premium: 'balanced',
|
|
57
|
+
balanced: 'economy',
|
|
58
|
+
economy: null,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export function adviseCostTier(input: {
|
|
62
|
+
current: CostTier;
|
|
63
|
+
forecast: Pick<ForecastResult, 'recommendation' | 'usedPercent' | 'atCurrentPaceReachesLimitAt'>;
|
|
64
|
+
}): {
|
|
65
|
+
from: CostTier;
|
|
66
|
+
to: CostTier;
|
|
67
|
+
savingPercent: number;
|
|
68
|
+
qualityRisk: string;
|
|
69
|
+
reason: string;
|
|
70
|
+
} | null {
|
|
71
|
+
const { current, forecast } = input;
|
|
72
|
+
if (forecast.recommendation === 'safe') return null;
|
|
73
|
+
|
|
74
|
+
const to = DOWN_ONE[current];
|
|
75
|
+
if (!to) return null;
|
|
76
|
+
|
|
77
|
+
const fromTier = COST_TIERS[current];
|
|
78
|
+
const toTier = COST_TIERS[to];
|
|
79
|
+
const savingPercent = Math.round((1 - toTier.usdPerTaskEstimate / fromTier.usdPerTaskEstimate) * 100);
|
|
80
|
+
const reason = `예산 사용 ${forecast.usedPercent}% · 예측 ${forecast.recommendation} → ${toTier.label}로 내리면 약 ${savingPercent}% 절감`;
|
|
81
|
+
|
|
82
|
+
debug.log('budget.cost-tier', 'advised', { from: current, to, savingPercent });
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
from: current,
|
|
86
|
+
to,
|
|
87
|
+
savingPercent,
|
|
88
|
+
qualityRisk: toTier.qualityRisk,
|
|
89
|
+
reason,
|
|
90
|
+
};
|
|
91
|
+
}
|
package/src/budget/llm-cost.ts
CHANGED
|
@@ -24,7 +24,11 @@ export interface LlmPricingUsd {
|
|
|
24
24
|
longContext?: { thresholdTokens: number; inputPerM: number; outputPerM: number; cacheReadPerM?: number; cacheWritePerM?: number };
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/** AWS Bedrock Global Standard prices, USD per million tokens (AWS pricing API, ap-northeast-2).
|
|
27
|
+
/** AWS Bedrock Global Standard prices, USD per million tokens (AWS pricing API, ap-northeast-2).
|
|
28
|
+
* ⛔ BEDROCK-COST-LEDGER(0.2.26) — mantle-openai 비-Anthropic Bedrock id(`openai.gpt-6-sol`·`zai.glm-5` 등
|
|
29
|
+
* `src/llm/bedrock.ts` BEDROCK_MODELS 의 `route:'mantle-openai'` 행)는 여기에 행이 «없다»: 단가 수치 근거가
|
|
30
|
+
* 하나도 확보되지 않았다. 근거 없는 id는 `isBedrockPricingModel` 게이트(`claude-` 시작)를 지나지 않아
|
|
31
|
+
* `unknownCost()` 로 `kind:'unknown'` 에 머문다 — 0원으로 꾸미지 않는다. */
|
|
28
32
|
export const BEDROCK_PRICING_USD: Readonly<Record<string, LlmPricingUsd>> = {
|
|
29
33
|
'claude-haiku-5-5': { inputPerM: 0.1, outputPerM: 0.5, cacheWritePerM: 0.125, cacheReadPerM: 0.01 },
|
|
30
34
|
'claude-sonnet-5-5': { inputPerM: 2, outputPerM: 10, cacheWritePerM: 2.5, cacheReadPerM: 0.1 },
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Shadow-arm launch plan — estimate which candidate models fit today's
|
|
2
|
+
// shadow budget. Plans only: no live LLM calls.
|
|
3
|
+
|
|
4
|
+
import { debug } from '../debug/log.js';
|
|
5
|
+
import { estimateLlmCost } from './llm-cost.js';
|
|
6
|
+
|
|
7
|
+
export type ShadowStage = 'authoring' | 'implement' | 'review' | 'judge';
|
|
8
|
+
|
|
9
|
+
export type ShadowDifficulty = 'small' | 'medium' | 'umbrella' | 'rework';
|
|
10
|
+
|
|
11
|
+
export interface PlanShadowArmsInput {
|
|
12
|
+
stage: ShadowStage;
|
|
13
|
+
difficulty: ShadowDifficulty;
|
|
14
|
+
inputTokens: number;
|
|
15
|
+
expectedOutputTokens: number;
|
|
16
|
+
candidates: string[];
|
|
17
|
+
spentTodayUsd: number;
|
|
18
|
+
dailyCapUsd: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ShadowArmFire {
|
|
22
|
+
model: string;
|
|
23
|
+
estUsd: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ShadowArmSkipped {
|
|
27
|
+
model: string;
|
|
28
|
+
reason: 'over-daily-cap' | 'unknown-price';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ShadowArmsPlan {
|
|
32
|
+
fire: ShadowArmFire[];
|
|
33
|
+
skipped: ShadowArmSkipped[];
|
|
34
|
+
remainingUsd: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function planShadowArms(input: PlanShadowArmsInput): ShadowArmsPlan {
|
|
38
|
+
const fire: ShadowArmFire[] = [];
|
|
39
|
+
const skipped: ShadowArmSkipped[] = [];
|
|
40
|
+
let remainingUsd = input.dailyCapUsd - input.spentTodayUsd;
|
|
41
|
+
let overDailyCap = false;
|
|
42
|
+
|
|
43
|
+
for (const model of input.candidates) {
|
|
44
|
+
// Once the cap is crossed, every later arm is over-daily-cap — even one
|
|
45
|
+
// whose price is unknown (the cap decision comes first).
|
|
46
|
+
if (overDailyCap) {
|
|
47
|
+
skipped.push({ model, reason: 'over-daily-cap' });
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const estimate = estimateLlmCost({
|
|
51
|
+
model,
|
|
52
|
+
inputTokens: input.inputTokens,
|
|
53
|
+
outputTokens: input.expectedOutputTokens,
|
|
54
|
+
});
|
|
55
|
+
if (estimate.kind !== 'known') {
|
|
56
|
+
skipped.push({ model, reason: 'unknown-price' });
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (estimate.usd > remainingUsd) {
|
|
60
|
+
skipped.push({ model, reason: 'over-daily-cap' });
|
|
61
|
+
overDailyCap = true;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
fire.push({ model, estUsd: estimate.usd });
|
|
65
|
+
remainingUsd -= estimate.usd;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
debug.log('budget.shadow-arms', 'planned', {
|
|
69
|
+
stage: input.stage,
|
|
70
|
+
difficulty: input.difficulty,
|
|
71
|
+
fire: fire.length,
|
|
72
|
+
skipped: skipped.length,
|
|
73
|
+
remainingUsd,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return { fire, skipped, remainingUsd };
|
|
77
|
+
}
|
package/src/budget/types.ts
CHANGED
|
@@ -158,8 +158,9 @@ export type ResetCreditExpiryAxis =
|
|
|
158
158
|
| { readonly status: 'expired'; readonly expiresAt: string; readonly hasUnknownExpiry: boolean };
|
|
159
159
|
|
|
160
160
|
export interface AccountUsageRow {
|
|
161
|
-
/** `zai` = GLM Coding Plan(ZAI-CODING-PLAN-PROVIDER) — `ZAI_API_KEY` 가 있을 때만 행이 생긴다.
|
|
162
|
-
|
|
161
|
+
/** `zai` = GLM Coding Plan(ZAI-CODING-PLAN-PROVIDER) — `ZAI_API_KEY` 가 있을 때만 행이 생긴다.
|
|
162
|
+
* `claude` = Claude Code 구독(CLAUDE-USAGE-WINDOW) — OAuth 토큰이 있을 때만 행이 생긴다. */
|
|
163
|
+
readonly provider: 'codex' | 'claude' | 'grok' | 'openrouter' | 'zai';
|
|
163
164
|
readonly accountName: string;
|
|
164
165
|
readonly accountCount: number;
|
|
165
166
|
readonly soleAccount: boolean;
|
|
@@ -173,7 +174,8 @@ export interface AccountUsageRow {
|
|
|
173
174
|
export interface UnifiedUsageReport {
|
|
174
175
|
readonly rows: readonly AccountUsageRow[];
|
|
175
176
|
/** `zai` 는 키가 있을 때만 실린다(없으면 종전 JSON 과 같다). */
|
|
176
|
-
|
|
177
|
+
/** `claude` 도 토큰이 있을 때만 실린다(없으면 종전 JSON 과 같다). */
|
|
178
|
+
readonly accountCounts: Readonly<Record<'codex' | 'grok' | 'openrouter', number>> & { readonly claude?: number; readonly zai?: number };
|
|
177
179
|
/** GLM Coding Plan 상세(창 · 우리 적산 · 잔액 사용 · 마지막 한도 코드) — 키가 있을 때만. */
|
|
178
180
|
readonly zaiCodingPlan?: import('../llm/zai-coding-plan.js').ZaiUsageView;
|
|
179
181
|
}
|
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
// Codex: enumerate known account names, fetch each via the existing
|
|
4
4
|
// ProviderFetcher with CODEX_HOME on the child env only.
|
|
5
5
|
// Grok: this wiring has no multi-account list — 0 or 1 current-credential row.
|
|
6
|
-
// Claude
|
|
6
|
+
// Claude Code (2026-10-11 CLAUDE-USAGE-WINDOW): subscription row — 5-hour window
|
|
7
|
+
// (credits axis) + 7-day window (subscription axis), from the OAuth usage endpoint.
|
|
8
|
+
// Gemini is intentionally out of this landing.
|
|
7
9
|
|
|
8
10
|
import { createCodexFetcher, type CodexFetcherOpts } from './fetchers/codex.js';
|
|
11
|
+
import { createClaudeFetcher, resolveClaudeAccessToken } from './fetchers/claude.js';
|
|
9
12
|
import {
|
|
10
13
|
fetchGrokUsage,
|
|
11
14
|
GROK_SUBSCRIPTION_AXIS,
|
|
@@ -20,6 +23,7 @@ import { loadTokens } from '../oauth/store.js';
|
|
|
20
23
|
import { envLiteral } from '../platform/env-literal.js';
|
|
21
24
|
import { describeResetCreditExpiry } from './codex-reset-credit-state.js';
|
|
22
25
|
import { visibleWidth } from '../tui.js';
|
|
26
|
+
import { debug } from '../debug/log.js';
|
|
23
27
|
import { listCodexResetCredits, type CodexResetCreditsResult } from './codex-reset-credits.js';
|
|
24
28
|
import {
|
|
25
29
|
buildZaiUsageView, fetchZaiQuota, getZaiApiKey, readZaiLedger,
|
|
@@ -28,6 +32,7 @@ import {
|
|
|
28
32
|
import type {
|
|
29
33
|
AccountUsageRow,
|
|
30
34
|
CreditAxis,
|
|
35
|
+
RateWindow,
|
|
31
36
|
ResetCreditExpiryAxis,
|
|
32
37
|
SubscriptionAxis,
|
|
33
38
|
UnifiedUsageReport,
|
|
@@ -59,25 +64,179 @@ export interface UnifiedUsageDeps {
|
|
|
59
64
|
readonly zaiKey?: () => string | undefined;
|
|
60
65
|
readonly fetchZaiQuota?: () => Promise<ZaiQuotaResult>;
|
|
61
66
|
readonly readZaiLedger?: () => ZaiLedgerRecord[];
|
|
67
|
+
/** Claude Code OAuth 토큰 해석 심 — 없으면 조회를 안 탄다(토큰 없음 = 행 없음). */
|
|
68
|
+
readonly resolveClaudeToken?: () => string | null;
|
|
69
|
+
/** Claude 사용량 조회 심 — `createClaudeFetcher().fetch()` 모양. */
|
|
70
|
+
readonly fetchClaude?: () => Promise<UsageSnapshot>;
|
|
71
|
+
/** 캐시 «아래»의 원 조회 심 — 주면 15분/5분 캐시를 거친다(`fetchClaude` 는 캐시를 우회한다). */
|
|
72
|
+
readonly fetchClaudeUncached?: () => Promise<UsageSnapshot>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** 공급자별 실패 격리(2026-10-11) — collector 가 «try 밖에서» 던지면 그 공급자만 한 error 행으로 바꾼다.
|
|
76
|
+
* ⛔ 종전 `Promise.all` 은 한 공급자의 예외(예: 키 조회 seam throw)가 usage «전체» 를 죽였다.
|
|
77
|
+
* `allSettled` 로 바꾸고 rejected 는 여기서 한 행으로 접는다 — 다른 공급자 행은 그대로 산다. */
|
|
78
|
+
type ZaiOutcome = { rows: AccountUsageRow[]; view: ZaiUsageView };
|
|
79
|
+
|
|
80
|
+
function isolateProviderRows(
|
|
81
|
+
provider: AccountUsageRow['provider'],
|
|
82
|
+
settled: PromiseSettledResult<AccountUsageRow[] | ZaiOutcome | null>,
|
|
83
|
+
): { rows: AccountUsageRow[]; zai: ZaiOutcome | null } {
|
|
84
|
+
if (settled.status === 'fulfilled') {
|
|
85
|
+
const value = settled.value;
|
|
86
|
+
if (value === null) return { rows: [], zai: null };
|
|
87
|
+
if (Array.isArray(value)) return { rows: value, zai: null };
|
|
88
|
+
return { rows: value.rows, zai: value };
|
|
89
|
+
}
|
|
90
|
+
const detail = settled.reason instanceof Error ? settled.reason.message : String(settled.reason);
|
|
91
|
+
debug.log('usage', 'provider-failed', { provider, detail });
|
|
92
|
+
return {
|
|
93
|
+
rows: [{
|
|
94
|
+
provider,
|
|
95
|
+
accountName: 'default',
|
|
96
|
+
accountCount: 1,
|
|
97
|
+
soleAccount: true,
|
|
98
|
+
credits: { status: 'error', detail },
|
|
99
|
+
subscription: { status: 'unavailable', reason: 'query-does-not-supply' },
|
|
100
|
+
resetCredits: { status: 'unavailable', detail },
|
|
101
|
+
}],
|
|
102
|
+
zai: null,
|
|
103
|
+
};
|
|
62
104
|
}
|
|
63
105
|
|
|
64
106
|
export async function collectUnifiedUsage(deps: UnifiedUsageDeps = {}): Promise<UnifiedUsageReport> {
|
|
65
|
-
const [
|
|
107
|
+
const [codexSettled, claudeSettled, grokSettled, openRouterSettled, zaiSettled] = await Promise.allSettled([
|
|
66
108
|
collectCodexRows(deps),
|
|
109
|
+
collectClaudeRows(deps),
|
|
67
110
|
collectGrokRows(deps),
|
|
68
111
|
collectOpenRouterRows(deps),
|
|
69
112
|
collectZaiRows(deps),
|
|
70
113
|
]);
|
|
114
|
+
const codex = isolateProviderRows('codex', codexSettled);
|
|
115
|
+
const claude = isolateProviderRows('claude', claudeSettled);
|
|
116
|
+
const grok = isolateProviderRows('grok', grokSettled);
|
|
117
|
+
const openRouter = isolateProviderRows('openrouter', openRouterSettled);
|
|
118
|
+
const zai = isolateProviderRows('zai', zaiSettled);
|
|
119
|
+
const zaiRows = zai.zai?.rows ?? zai.rows;
|
|
71
120
|
return {
|
|
72
|
-
rows: [...
|
|
121
|
+
rows: [...codex.rows, ...claude.rows, ...grok.rows, ...openRouter.rows, ...zaiRows],
|
|
73
122
|
accountCounts: {
|
|
74
|
-
codex:
|
|
75
|
-
grok:
|
|
76
|
-
openrouter:
|
|
123
|
+
codex: codex.rows.length,
|
|
124
|
+
grok: grok.rows.length,
|
|
125
|
+
openrouter: openRouter.rows.length,
|
|
126
|
+
// ⛔ claude 도 토큰이 없으면(행 0) 칸을 안 싣는다 — 종전 JSON·문면과 바이트 동일(0행 ≠ 0% 사용).
|
|
127
|
+
...(claude.rows.length > 0 ? { claude: claude.rows.length } : {}),
|
|
77
128
|
// ⛔ 키가 없으면 칸 자체를 안 싣는다 — 종전 JSON·문면과 바이트 동일.
|
|
78
|
-
|
|
129
|
+
// 종전과 같게: 조회가 성공했으면(창이 비어도) zai 1 · 실패해 error 행만 남았어도 1(실패 행도 센다).
|
|
130
|
+
...(zai.zai || zai.rows.length > 0 ? { zai: 1 } : {}),
|
|
79
131
|
},
|
|
80
|
-
...(zai ? { zaiCodingPlan: zai.view } : {}),
|
|
132
|
+
...(zai.zai ? { zaiCodingPlan: zai.zai.view } : {}),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** 실 OAuth usage 엔드포인트는 5~10분 간격에도 429 를 낸다(fetchers/claude.ts 머리말 · 기본 주기 15분).
|
|
137
|
+
* nexus `/api/usage` 는 30초 캐시로 이 조립을 부르므로, 기본 조회 경로(심 없음)는 성공 스냅숏을 15분 재사용한다. */
|
|
138
|
+
const CLAUDE_USAGE_CACHE_MS = 15 * 60_000;
|
|
139
|
+
/** 실패(429 등)도 5분 재사용한다 — 429 가 이어지는 동안 30초마다 다시 치지 않게. */
|
|
140
|
+
const CLAUDE_USAGE_FAILURE_CACHE_MS = 5 * 60_000;
|
|
141
|
+
type ClaudeUsageCacheEntry = { readonly at: number; readonly token: string } & (
|
|
142
|
+
| { readonly ok: true; readonly snap: UsageSnapshot }
|
|
143
|
+
| { readonly ok: false; readonly error: unknown });
|
|
144
|
+
let claudeUsageCache: ClaudeUsageCacheEntry | null = null;
|
|
145
|
+
|
|
146
|
+
/** 시험 전용 — 모듈 캐시를 비운다. */
|
|
147
|
+
export function resetClaudeUsageCacheForTest(): void {
|
|
148
|
+
claudeUsageCache = null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function fetchClaudeCached(token: string, nowMs: number, fetchRaw: () => Promise<UsageSnapshot>): Promise<UsageSnapshot> {
|
|
152
|
+
const c = claudeUsageCache;
|
|
153
|
+
// 캐시 키 = 토큰 — 토큰이 바뀌면(재로그인·계정 교체) 옛 계정 값을 새 행으로 보이지 않는다.
|
|
154
|
+
if (c && c.token === token && nowMs - c.at < (c.ok ? CLAUDE_USAGE_CACHE_MS : CLAUDE_USAGE_FAILURE_CACHE_MS)) {
|
|
155
|
+
if (c.ok) return c.snap;
|
|
156
|
+
throw c.error;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const snap = await fetchRaw();
|
|
160
|
+
claudeUsageCache = { at: nowMs, token, ok: true, snap };
|
|
161
|
+
return snap;
|
|
162
|
+
} catch (error) {
|
|
163
|
+
claudeUsageCache = { at: nowMs, token, ok: false, error };
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Claude Code 구독 행 — 5시간 창(credits 축) ⊕ 7일 창(subscription 축).
|
|
169
|
+
* ⛔ 토큰이 없으면 행을 «안» 만든다(0행 ≠ 0% 사용) — openrouter·zai 키와 같은 접기. */
|
|
170
|
+
async function collectClaudeRows(deps: UnifiedUsageDeps): Promise<AccountUsageRow[]> {
|
|
171
|
+
// ⛔ 시험 런타임은 심이 없으면 «토큰 없음»으로 본다 — 실제 자격 파일을 읽으면
|
|
172
|
+
// 심을 모르는 옛 시험이 실제 네트워크를 치게 된다(openrouter·zai 키와 같은 이유).
|
|
173
|
+
const resolveToken = deps.resolveClaudeToken
|
|
174
|
+
?? (process.env.NODE_ENV === 'test' ? () => null : resolveClaudeAccessToken);
|
|
175
|
+
let token: string | null;
|
|
176
|
+
try {
|
|
177
|
+
token = resolveToken();
|
|
178
|
+
} catch (err) {
|
|
179
|
+
// 자격 파일이 깨진 경우를 «토큰 없음»과 가를 수 있게 관측만 남긴다(행은 안 만든다).
|
|
180
|
+
debug.log('usage', 'claude-token-resolve-failed', { detail: err instanceof Error ? err.message : String(err) });
|
|
181
|
+
token = null;
|
|
182
|
+
}
|
|
183
|
+
if (!token) return [];
|
|
184
|
+
const base = {
|
|
185
|
+
provider: 'claude' as const,
|
|
186
|
+
accountName: 'default',
|
|
187
|
+
accountCount: 1,
|
|
188
|
+
soleAccount: true,
|
|
189
|
+
resetCredits: { status: 'not-applicable' } as const,
|
|
190
|
+
};
|
|
191
|
+
const tokenKey = token;
|
|
192
|
+
const fetchClaude = deps.fetchClaude ?? (() => fetchClaudeCached(
|
|
193
|
+
tokenKey, (deps.now ?? Date.now)(), deps.fetchClaudeUncached ?? (() => createClaudeFetcher().fetch())));
|
|
194
|
+
try {
|
|
195
|
+
const snap = await fetchClaude();
|
|
196
|
+
const fiveHour = snap.windows.find((w) => w.model === undefined && w.kind === 'session');
|
|
197
|
+
const weekly = snap.windows.find((w) => w.model === undefined && w.kind === 'weekly');
|
|
198
|
+
return [{ ...base, credits: claudeCreditsFromWindow(fiveHour), subscription: claudeSubscriptionFromWindow(weekly) }];
|
|
199
|
+
} catch (err) {
|
|
200
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
201
|
+
debug.log('usage', 'claude-fetch-failed', { detail });
|
|
202
|
+
return [{
|
|
203
|
+
...base,
|
|
204
|
+
credits: { status: 'error', detail },
|
|
205
|
+
subscription: { status: 'unavailable', reason: 'query-does-not-supply' },
|
|
206
|
+
}];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function claudeCreditsFromWindow(window: RateWindow | undefined): CreditAxis {
|
|
211
|
+
const periodEnd = window && isValidEpochMs(window.resetsAt) ? new Date(window.resetsAt) : null;
|
|
212
|
+
const periodStartEpoch = periodEnd !== null && window !== undefined && isPositiveFinite(window.windowMinutes)
|
|
213
|
+
? periodEnd.getTime() - window.windowMinutes * 60_000
|
|
214
|
+
: null;
|
|
215
|
+
const periodStart = periodStartEpoch !== null && isValidDateMs(periodStartEpoch) ? new Date(periodStartEpoch) : null;
|
|
216
|
+
return {
|
|
217
|
+
status: 'ok',
|
|
218
|
+
usedPercent: window ? window.used : null,
|
|
219
|
+
periodType: window?.kind ?? null,
|
|
220
|
+
periodStart: periodStart?.toISOString() ?? null,
|
|
221
|
+
periodEnd: periodEnd?.toISOString() ?? null,
|
|
222
|
+
monthlyLimit: null,
|
|
223
|
+
used: window ? window.used : null,
|
|
224
|
+
onDemandCap: null,
|
|
225
|
+
onDemandUsed: null,
|
|
226
|
+
prepaidBalance: null,
|
|
227
|
+
balance: null,
|
|
228
|
+
hasCredits: null,
|
|
229
|
+
unlimited: null,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function claudeSubscriptionFromWindow(window: RateWindow | undefined): SubscriptionAxis {
|
|
234
|
+
if (!window) return { status: 'unavailable', reason: 'query-does-not-supply' };
|
|
235
|
+
return {
|
|
236
|
+
status: 'available',
|
|
237
|
+
remainingPercent: window.remainingPercent,
|
|
238
|
+
resetsAt: window.resetsAt,
|
|
239
|
+
windowKind: window.kind,
|
|
81
240
|
};
|
|
82
241
|
}
|
|
83
242
|
|
|
@@ -429,6 +588,11 @@ export function formatUnifiedUsage(report: UnifiedUsageReport): string {
|
|
|
429
588
|
const count = report.accountCounts[provider];
|
|
430
589
|
lines.push(` ${provider} accounts=${count}${count === 1 ? ' (하나뿐)' : count === 0 ? ' (없음)' : ''}`);
|
|
431
590
|
}
|
|
591
|
+
// ⛔ claude 토큰이 없으면 줄을 안 낸다 — 종전 문면과 바이트 동일.
|
|
592
|
+
if (report.accountCounts.claude !== undefined) {
|
|
593
|
+
const count = report.accountCounts.claude;
|
|
594
|
+
lines.push(` claude accounts=${count}${count === 1 ? ' (하나뿐)' : ''} (Claude Code 구독 · 5시간 창 ⊕ 7일 창)`);
|
|
595
|
+
}
|
|
432
596
|
// ⛔ 키가 없으면 줄을 안 낸다 — 종전 문면과 바이트 동일.
|
|
433
597
|
if (report.accountCounts.zai !== undefined) lines.push(` zai accounts=${report.accountCounts.zai} (GLM Coding Plan)`);
|
|
434
598
|
lines.push(' provider account accounts credits.usedPercent credits.window window-resets-in reset-credit-expiry subscription');
|
package/src/cli/control-cli.ts
CHANGED
|
@@ -31,6 +31,35 @@ function reasonFor(error: unknown, token?: string): string {
|
|
|
31
31
|
return token ? message.replaceAll(token, '[redacted]') : message;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/** Doctor's read-only live source. One malformed Nexus machine row invalidates the whole
|
|
35
|
+
* reading: doctor reports unmeasured rather than treating a partial registry as complete. */
|
|
36
|
+
export async function listMachineResources(options: { primaryUrl?: string; queryToken?: string; port?: string; root?: string; fetch?: (input: URL | RequestInfo, init?: RequestInit) => Promise<Response> } = {}): Promise<ResourceView[]> {
|
|
37
|
+
const portOverride = options.port ?? (process.env.ELANOUS_CONTROL_PORT?.trim() || undefined);
|
|
38
|
+
const primary = await resolvePrimary({
|
|
39
|
+
role: 'query',
|
|
40
|
+
...(options.root ? { root: options.root } : {}),
|
|
41
|
+
config: { url: options.primaryUrl, tokens: options.queryToken ? { query: options.queryToken } : undefined },
|
|
42
|
+
...(portOverride !== undefined ? { port: Number(portOverride) } : {}),
|
|
43
|
+
});
|
|
44
|
+
const token = primary.token;
|
|
45
|
+
if (!token) throw new Error('control query token unavailable');
|
|
46
|
+
const url = new URL('/v1/resources', primary.url);
|
|
47
|
+
url.searchParams.set('kind', 'machine');
|
|
48
|
+
const response = await (options.fetch ?? globalThis.fetch)(url, {
|
|
49
|
+
headers: { authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(5000),
|
|
50
|
+
});
|
|
51
|
+
if (!response.ok) throw new Error(`control HTTP ${response.status}`);
|
|
52
|
+
const body: unknown = await response.json();
|
|
53
|
+
if (!body || typeof body !== 'object' || !('resources' in body) || !Array.isArray(body.resources) ||
|
|
54
|
+
body.resources.some((row: unknown) => !row || typeof row !== 'object' ||
|
|
55
|
+
(row as ResourceView).kind !== 'machine' || typeof (row as ResourceView).machine !== 'string' ||
|
|
56
|
+
typeof (row as ResourceView).name !== 'string' || typeof (row as ResourceView).expired !== 'boolean' ||
|
|
57
|
+
!((row as ResourceView).attrs && typeof (row as ResourceView).attrs === 'object'))) {
|
|
58
|
+
throw new Error('invalid machine resource response');
|
|
59
|
+
}
|
|
60
|
+
return body.resources as ResourceView[];
|
|
61
|
+
}
|
|
62
|
+
|
|
34
63
|
export async function runResourcesQuery(options: { where?: string; kind?: string; port?: string; primaryUrl?: string; queryToken?: string; json?: boolean }): Promise<number> {
|
|
35
64
|
let base = '';
|
|
36
65
|
let token: string | undefined;
|
package/src/cli/doctor-cli.ts
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
type ReadinessReport,
|
|
28
28
|
type SubstrateSignals,
|
|
29
29
|
} from './doctor-readiness.js';
|
|
30
|
-
import { debug } from '../debug/log.js';
|
|
30
|
+
import { debug, redactSecretText } from '../debug/log.js';
|
|
31
31
|
import { resolveDaemonEndpoint, type ResolveDaemonEndpointOpts } from '../nexus/daemon-endpoint.js';
|
|
32
32
|
import { applyDoctorFixes, applyGitInstall, applyServiceRestart, applySudoFixes, planDoctorFixes, type DoctorFixDeps, type DoctorFixItem } from './doctor-fix.js';
|
|
33
33
|
import { ADVISABLE_DOCTOR_FIX_IDS, adviseDoctorFixes, type DoctorAdvice } from './doctor-llm-assist.js';
|
|
@@ -40,6 +40,10 @@ import type { LlmInventory } from '../llm/local-manager/types.js';
|
|
|
40
40
|
import { buildDoctorBundle } from './doctor-bundle.js';
|
|
41
41
|
import { uploadDoctorBundle } from './doctor-bundle-upload.js';
|
|
42
42
|
import { checkNodeModules, formatNodeModulesCheck, nodeModulesTrees } from './doctor-node-modules.js';
|
|
43
|
+
import { formatHostDoctorLines, runHostDoctor, type HostDoctorExpected, type HostDoctorOptions, type HostDoctorRemote } from '../fleet/host-doctor.js';
|
|
44
|
+
import { listMachineResources } from './control-cli.js';
|
|
45
|
+
import type { ResourceView } from '../control-plane/ledger.js';
|
|
46
|
+
import { loadMachineLedger } from '../machines/machine-ledger.js';
|
|
43
47
|
|
|
44
48
|
function defaultCheckPythonEnv(): { status: 'ok' | 'fixable' | 'manual'; evidence: string; remedy?: string } {
|
|
45
49
|
const c = checkPythonEnv(false);
|
|
@@ -198,9 +202,18 @@ export interface DoctorCliDeps extends DoctorOptions, Pick<DoctorFixDeps, 'home'
|
|
|
198
202
|
/** Inject the upload transport and consent for isolated CLI tests. */
|
|
199
203
|
uploadFetch?: typeof globalThis.fetch;
|
|
200
204
|
confirmBundleUpload?: (message: string) => Promise<boolean>;
|
|
205
|
+
/** `doctor host` 원격 실행(시험 seam) — 기본 = ssh BatchMode · `local` 이면 이 기계. */
|
|
206
|
+
hostDoctorRemote?: HostDoctorRemote;
|
|
207
|
+
/** `doctor host` 가 대조할 HQ 실측값(설치 판 · 이미지 핀) — 없으면 해당 점검은 unmeasured. */
|
|
208
|
+
hostDoctorExpected?: HostDoctorExpected;
|
|
209
|
+
/** HQ membership readings; injected tests need no live Nexus. */
|
|
210
|
+
hostDoctorMembership?: () => Promise<NonNullable<HostDoctorOptions['membership']>>;
|
|
211
|
+
/** Nexus machine query seam; tests can exercise the default assembly without contacting a live service. */
|
|
212
|
+
hostDoctorMachineResources?: () => Promise<ResourceView[]>;
|
|
201
213
|
}
|
|
202
214
|
|
|
203
215
|
const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..');
|
|
216
|
+
const observationError = (error: unknown): string => redactSecretText(error instanceof Error ? error.message : String(error)).slice(0, 200);
|
|
204
217
|
const tavilyNames = new Set(['TAVILY_API_KEY', 'TAVILY_KEY']);
|
|
205
218
|
|
|
206
219
|
function defaultCodeRevision(): string | undefined {
|
|
@@ -1206,6 +1219,52 @@ function formatDoctorAdvice(advice: DoctorAdvice): string {
|
|
|
1206
1219
|
].join('\n');
|
|
1207
1220
|
}
|
|
1208
1221
|
|
|
1222
|
+
function formatDoctorAdviceProposal(advice: DoctorAdvice, report: DoctorReport): { text: string; itemId: string; observedValue: string } | null {
|
|
1223
|
+
const proposal = advice.ok ? advice.order[0] : undefined;
|
|
1224
|
+
if (!proposal) return null;
|
|
1225
|
+
const observation = report.readiness?.items.find((item) => item.id === proposal.readinessId);
|
|
1226
|
+
if (!observation) return null;
|
|
1227
|
+
const observedValue = `${observation.status}: ${observation.evidence}`;
|
|
1228
|
+
return {
|
|
1229
|
+
itemId: proposal.readinessId,
|
|
1230
|
+
observedValue,
|
|
1231
|
+
text: [
|
|
1232
|
+
`LLM 제안: ${proposal.why}`,
|
|
1233
|
+
`운영 팩 항목 id: ${proposal.readinessId}`,
|
|
1234
|
+
`현재 관측값: ${observedValue}`,
|
|
1235
|
+
].join('\n'),
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
async function recordDoctorAdviceResponse(
|
|
1240
|
+
proposal: { itemId: string; observedValue: string },
|
|
1241
|
+
accepted: boolean,
|
|
1242
|
+
): Promise<void> {
|
|
1243
|
+
debug.log('doctor.advise', accepted ? 'accepted' : 'rejected', {
|
|
1244
|
+
itemId: proposal.itemId,
|
|
1245
|
+
observedValue: proposal.observedValue,
|
|
1246
|
+
applied: 0,
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
async function presentDoctorAdviceProposal(
|
|
1251
|
+
advice: DoctorAdvice,
|
|
1252
|
+
report: DoctorReport,
|
|
1253
|
+
deps: DoctorCliDeps,
|
|
1254
|
+
json: boolean,
|
|
1255
|
+
announce: (text: string) => void,
|
|
1256
|
+
): Promise<{ proposal: { itemId: string; observedValue: string }; response: boolean | null; text: string } | null> {
|
|
1257
|
+
const formatted = formatDoctorAdviceProposal(advice, report);
|
|
1258
|
+
if (!formatted) return null;
|
|
1259
|
+
const proposal = { itemId: formatted.itemId, observedValue: formatted.observedValue };
|
|
1260
|
+
const interactive = deps.adviceInteractive ?? (process.stdin.isTTY === true && (json ? process.stderr.isTTY === true : process.stdout.isTTY === true));
|
|
1261
|
+
if (!interactive) return { proposal, response: null, text: formatted.text };
|
|
1262
|
+
announce(formatted.text);
|
|
1263
|
+
const accepted = await (deps.confirmAdvice ?? ((message) => confirmDoctorAdvice(message, json)))('이 제안을 수락할까요? [y/N] ');
|
|
1264
|
+
await recordDoctorAdviceResponse(proposal, accepted);
|
|
1265
|
+
return { proposal, response: accepted, text: `${formatted.text}\n응답: ${accepted ? '수락' : '거절'}` };
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1209
1268
|
async function confirmDoctorAdvice(message: string, json: boolean): Promise<boolean> {
|
|
1210
1269
|
const prompt = createInterface({ input: process.stdin, output: json ? process.stderr : process.stdout });
|
|
1211
1270
|
try { return /^(y|yes)$/i.test((await prompt.question(message)).trim()); }
|
|
@@ -1240,6 +1299,43 @@ export function registerDoctorCommand(program: Command, deps: DoctorCliDeps = {}
|
|
|
1240
1299
|
out.log(json ? JSON.stringify(opts.all ? checks : checks[0], null, 2) : checks.map(formatNodeModulesCheck).join('\n'));
|
|
1241
1300
|
if (checks.some((check) => check.status !== 'ok')) setExitCode(1);
|
|
1242
1301
|
});
|
|
1302
|
+
doctor.command('host')
|
|
1303
|
+
.description('Check whether a fleet host stands ready (read-only; membership needs a repository checkout and a named remote worker)')
|
|
1304
|
+
.argument('<host>', "SSH name in fleet intent; an unknown name fails membership; 'local' checks readiness without membership")
|
|
1305
|
+
.option('--role <role>', 'host role: worker or hq', 'worker')
|
|
1306
|
+
.option('--json', 'structured output')
|
|
1307
|
+
.action(async (host: string, opts: { role: string; json?: boolean }, command: Command) => {
|
|
1308
|
+
if (opts.role !== 'worker' && opts.role !== 'hq') {
|
|
1309
|
+
err.error('--role must be worker or hq');
|
|
1310
|
+
setExitCode(1);
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
const json = opts.json === true || command.parent?.opts().json === true;
|
|
1314
|
+
let membership: HostDoctorOptions['membership'];
|
|
1315
|
+
if (opts.role === 'worker' && host !== 'local') {
|
|
1316
|
+
if (deps.hostDoctorMembership) membership = await deps.hostDoctorMembership();
|
|
1317
|
+
else {
|
|
1318
|
+
let intent: NonNullable<HostDoctorOptions['membership']>['intent'] = null;
|
|
1319
|
+
let machines: NonNullable<HostDoctorOptions['membership']>['machines'] = null;
|
|
1320
|
+
let parentHosts: NonNullable<HostDoctorOptions['membership']>['parentHosts'] = null;
|
|
1321
|
+
let intentError: string | undefined;
|
|
1322
|
+
let machinesError: string | undefined;
|
|
1323
|
+
let parentHostsError: string | undefined;
|
|
1324
|
+
try { intent = loadMachineLedger(deps.repositoryRoot ?? repositoryRoot); } catch (error) { intentError = observationError(error); }
|
|
1325
|
+
try { machines = await (deps.hostDoctorMachineResources ?? listMachineResources)(); } catch (error) { machinesError = observationError(error); }
|
|
1326
|
+
try {
|
|
1327
|
+
// UserConfig permits one parent object or an array of parent objects, never a bare host string.
|
|
1328
|
+
const configured = (deps.userConfig ?? (deps.getUserConfig ?? getUserConfig)()).taskAgent?.parentHost;
|
|
1329
|
+
if (configured === null) parentHostsError = 'taskAgent.parentHost is null';
|
|
1330
|
+
else parentHosts = configured === undefined ? [] : Array.isArray(configured) ? configured : [configured];
|
|
1331
|
+
} catch (error) { parentHostsError = observationError(error); }
|
|
1332
|
+
membership = { intent, machines, parentHosts, intentError, machinesError, parentHostsError };
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
const report = runHostDoctor({ host, role: opts.role, remote: deps.hostDoctorRemote, expected: deps.hostDoctorExpected, membership });
|
|
1336
|
+
out.log(json ? JSON.stringify(report, null, 2) : formatHostDoctorLines(report).join('\n'));
|
|
1337
|
+
if (!report.ok) setExitCode(1);
|
|
1338
|
+
});
|
|
1243
1339
|
doctor
|
|
1244
1340
|
.option('--credentials', 'show per-credential details in human-readable output')
|
|
1245
1341
|
.option('--bundle', 'write a redacted diagnostics archive for support')
|
|
@@ -1383,10 +1479,17 @@ export function registerDoctorCommand(program: Command, deps: DoctorCliDeps = {}
|
|
|
1383
1479
|
// Planning never writes; existing repairs require --yes, while git alone can use affirmative TTY consent.
|
|
1384
1480
|
const plan = planDoctorFixes(fixes);
|
|
1385
1481
|
const advice = opts.advise ? await requestDoctorAdvice(report, plan, deps) : undefined;
|
|
1482
|
+
const proposal = advice && !opts.fix ? await presentDoctorAdviceProposal(advice, report, deps, opts.json === true, (text) => {
|
|
1483
|
+
if (opts.json) err.error(text);
|
|
1484
|
+
else out.log(text);
|
|
1485
|
+
}) : null;
|
|
1386
1486
|
if (!opts.fix) {
|
|
1387
1487
|
out.log(opts.json
|
|
1388
|
-
? JSON.stringify({ ...report, advise: advice }, null, 2)
|
|
1389
|
-
: [
|
|
1488
|
+
? JSON.stringify({ ...report, advise: advice, ...(proposal ? { adviceProposal: { itemId: proposal.proposal.itemId, observedValue: proposal.proposal.observedValue, response: proposal.response } } : {}) }, null, 2)
|
|
1489
|
+
: [
|
|
1490
|
+
formatDoctorReport(report, { credentials: opts.credentials }),
|
|
1491
|
+
proposal?.response === null ? proposal.text : proposal ? `응답: ${proposal.response ? '수락' : '거절'}` : formatDoctorAdvice(advice!),
|
|
1492
|
+
].join('\n'));
|
|
1390
1493
|
if (report.requiredMissing?.length) setExitCode(1);
|
|
1391
1494
|
return;
|
|
1392
1495
|
}
|