@iowarp/clio-coder 0.3.0 → 0.3.2
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/CHANGELOG.md +123 -2
- package/CONTRIBUTING.md +23 -23
- package/README.md +295 -627
- package/dist/acp-BIYHVZIM.js +128 -0
- package/dist/{agents-Q4MYPMUW.js → agents-YT6SSRIT.js} +52 -27
- package/dist/assets/codewiki.json +1 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/LICENSE +21 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/cgmanifest.json +16 -0
- package/dist/assets/grammars/notices/tree-sitter-wasms/LICENSE +24 -0
- package/dist/assets/grammars/tree-sitter-c-sharp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-c.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-go.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-java.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-python.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-ruby.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-rust.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter.wasm +0 -0
- package/dist/{auth-O6HYIJ6J.js → auth-5TWEIYDN.js} +30 -15
- package/dist/chunk-2EHAIA3X.js +481 -0
- package/dist/{chunk-ME6DNWIU.js → chunk-2IR2NMPA.js} +12 -4
- package/dist/chunk-2SFS6XQE.js +122 -0
- package/dist/{chunk-KKKPTZLM.js → chunk-2STGEDFV.js} +8 -1
- package/dist/chunk-2VTFPG5O.js +48 -0
- package/dist/chunk-3I7MS7N2.js +40 -0
- package/dist/chunk-3R73A4XB.js +69 -0
- package/dist/{chunk-JPOWPFCU.js → chunk-3ZXDFGR5.js} +52 -23
- package/dist/chunk-4BJ5BYCE.js +61 -0
- package/dist/{chunk-26BZQOAD.js → chunk-4BPJXDWC.js} +161 -260
- package/dist/chunk-4KLWL3UC.js +18 -0
- package/dist/{chunk-5LDRNKX2.js → chunk-4VP4KH3K.js} +161 -262
- package/dist/chunk-4ZG3XFUR.js +77 -0
- package/dist/chunk-5B2AEOW5.js +5407 -0
- package/dist/chunk-5TSRNF4G.js +510 -0
- package/dist/{chunk-WD6AJM35.js → chunk-5UUP6MWO.js} +48 -69
- package/dist/{chunk-X3BR7HWV.js → chunk-5WIGXA4T.js} +7 -1
- package/dist/chunk-65DEGPJ6.js +52 -0
- package/dist/chunk-6EJMN2Y3.js +17 -0
- package/dist/chunk-6EJV5X2W.js +16405 -0
- package/dist/chunk-6N5PTWMY.js +136 -0
- package/dist/chunk-6XLNIQDB.js +27 -0
- package/dist/{chunk-XNISANGE.js → chunk-77VKQEHF.js} +171 -74
- package/dist/chunk-7CR24IG7.js +242 -0
- package/dist/{chunk-UWIJNAOB.js → chunk-7EYHLWU7.js} +907 -638
- package/dist/chunk-7MNJORFF.js +22 -0
- package/dist/{chunk-JWHCJDCI.js → chunk-A3CYT5EX.js} +257 -79
- package/dist/chunk-AGYYIBLL.js +1069 -0
- package/dist/chunk-AO4RKG4M.js +277 -0
- package/dist/chunk-APJ265NV.js +7410 -0
- package/dist/chunk-ARBGF5F7.js +174 -0
- package/dist/{chunk-TFSSEXL6.js → chunk-BMEMKKIT.js} +14 -4
- package/dist/{chunk-X3NE4WVW.js → chunk-BNAZZHFG.js} +7 -1
- package/dist/chunk-CBCAPZAA.js +229 -0
- package/dist/{chunk-QV47YRF4.js → chunk-CGKSTWHD.js} +7 -1
- package/dist/chunk-CMZWFGD2.js +352 -0
- package/dist/chunk-ECH6PKUQ.js +39 -0
- package/dist/{chunk-67MTHP2E.js → chunk-ED4KHGC3.js} +13 -5
- package/dist/chunk-EKMEHE4H.js +340 -0
- package/dist/{chunk-O4EJEDHO.js → chunk-EPVUXGXG.js} +50 -35
- package/dist/chunk-FCSXB6T2.js +338 -0
- package/dist/chunk-FJ3H4MN5.js +48 -0
- package/dist/chunk-FQ4SKYE4.js +29 -0
- package/dist/chunk-G2DE3C7R.js +644 -0
- package/dist/chunk-G4BMMOKF.js +182 -0
- package/dist/{chunk-7BHLZB3A.js → chunk-GGXXDWE4.js} +190 -1218
- package/dist/chunk-HC4CLZ2Y.js +68 -0
- package/dist/{chunk-E3NYWENM.js → chunk-HFSBBKSQ.js} +55 -61
- package/dist/chunk-HKIYEGME.js +30 -0
- package/dist/chunk-I4HZDVNP.js +73 -0
- package/dist/chunk-IGLFWIYI.js +161 -0
- package/dist/chunk-IHXBNWMM.js +137 -0
- package/dist/chunk-IKCO5N3L.js +162 -0
- package/dist/chunk-IR4CFBFN.js +56 -0
- package/dist/{chunk-DXQNI4PC.js → chunk-IWHMRKLL.js} +8 -1
- package/dist/{chunk-VOO7NYPP.js → chunk-J5HN4RYU.js} +27 -9
- package/dist/{chunk-4UQA7NCT.js → chunk-J5Q24KAG.js} +7 -2
- package/dist/{chunk-KBR4MZZR.js → chunk-JVCV3ICN.js} +7 -1
- package/dist/chunk-KJ5LWLOE.js +1077 -0
- package/dist/chunk-LBMZMYH2.js +285 -0
- package/dist/{chunk-3DANZDGR.js → chunk-LBNRH5WM.js} +100 -161
- package/dist/{chunk-TKHQ4DGZ.js → chunk-LZSJBIVT.js} +7358 -7414
- package/dist/{chunk-UGYAX5YI.js → chunk-M6SHUN7Q.js} +13 -8
- package/dist/chunk-MAW544W2.js +1882 -0
- package/dist/chunk-MBS4V7ZP.js +217 -0
- package/dist/{chunk-2J63S4SF.js → chunk-MFFY33HR.js} +167 -140
- package/dist/chunk-MNA4JGU4.js +255 -0
- package/dist/chunk-MQSRRFWA.js +3428 -0
- package/dist/{chunk-RQDWMVRB.js → chunk-MVVUPGPW.js} +138 -137
- package/dist/chunk-OAO4GE4M.js +619 -0
- package/dist/chunk-OHHN2SO4.js +5135 -0
- package/dist/chunk-OKGUZO2U.js +34 -0
- package/dist/{chunk-BBUH4VAA.js → chunk-OOJYHWRB.js} +60 -361
- package/dist/{chunk-D5YD55AR.js → chunk-OQ33BKR3.js} +12 -1
- package/dist/chunk-OQE5J4C6.js +73 -0
- package/dist/{chunk-AMFR5YA3.js → chunk-ORBHGJC5.js} +26 -12
- package/dist/chunk-POHLU5DW.js +1186 -0
- package/dist/chunk-QKMUKYO7.js +4961 -0
- package/dist/{chunk-7RBKDI66.js → chunk-QTYWRVRA.js} +104 -12
- package/dist/{chunk-5N2FG33Q.js → chunk-R346GLFC.js} +7 -1
- package/dist/chunk-SRF2PJNW.js +184 -0
- package/dist/chunk-SST6Z5JA.js +80 -0
- package/dist/{chunk-XV4ZJ6ZM.js → chunk-STBPMHSX.js} +473 -1194
- package/dist/{chunk-HBU5MTAM.js → chunk-SVNXH4L2.js} +7 -1
- package/dist/chunk-T6YILFSB.js +80 -0
- package/dist/chunk-TXOTCRLG.js +15 -0
- package/dist/chunk-TZTZS7QK.js +227 -0
- package/dist/chunk-UOV2BYIW.js +107 -0
- package/dist/{chunk-527KG6XR.js → chunk-V4RXGQ5Q.js} +72 -185
- package/dist/chunk-VAKQQHWR.js +434 -0
- package/dist/chunk-VG7TBQIY.js +128 -0
- package/dist/chunk-VJWL6YS5.js +244 -0
- package/dist/chunk-WEH5XRJQ.js +32 -0
- package/dist/{chunk-VPAWTYLY.js → chunk-WEPFGWHJ.js} +7 -1
- package/dist/chunk-WMSVI4G2.js +2095 -0
- package/dist/chunk-WVO7V2QY.js +797 -0
- package/dist/chunk-X4RCMKVQ.js +641 -0
- package/dist/chunk-X75S7HFS.js +374 -0
- package/dist/chunk-XN3L4EYL.js +46 -0
- package/dist/{chunk-HMYNFFY4.js → chunk-XPLRXC72.js} +7 -2
- package/dist/{chunk-PIDUD6M2.js → chunk-YCWGATWI.js} +12 -5
- package/dist/chunk-YHZX5GEU.js +193 -0
- package/dist/chunk-YXLYO42X.js +91 -0
- package/dist/{chunk-UHTSULZS.js → chunk-ZDOOVTXZ.js} +38 -73
- package/dist/chunk-ZI647VB5.js +37 -0
- package/dist/{chunk-CLJ5HLUD.js → chunk-ZWLZP4ZT.js} +25 -6
- package/dist/cli/index.js +70 -56
- package/dist/clio-4LY5K2AC.js +25 -0
- package/dist/code-nav-7AX6FYE6.js +600 -0
- package/dist/codewiki/build-worker.js +66 -0
- package/dist/compile-cache-CVJMMODC.js +18 -0
- package/dist/{components-JVHMUBEB.js → components-KELWS457.js} +31 -9
- package/dist/{config-ZFCDBMDC.js → config-GTLUW2PR.js} +104 -56
- package/dist/configure-R6A64DHX.js +42 -0
- package/dist/context-5VKGUVJJ.js +866 -0
- package/dist/{context-CDXTP2MP.js → context-JFZEJ7W5.js} +21 -13
- package/dist/{context-E3KIFVXI.js → context-RW5HC47S.js} +77 -36
- package/dist/{context-clear-3F4PLXOS.js → context-clear-6ZHBAZZT.js} +64 -30
- package/dist/{context-index-Q7YSYTR3.js → context-index-BZ4UYMTC.js} +36 -24
- package/dist/dispatch-runner-VKBRCWQC.js +1997 -0
- package/dist/{docs-YIETIWZI.js → docs-2C2LTVT2.js} +32 -13
- package/dist/doctor-KI767GSN.js +87 -0
- package/dist/{eval-B3KZZESM.js → eval-XSSNATB4.js} +93 -27
- package/dist/{evidence-V67CHM35.js → evidence-UA6AWDQQ.js} +55 -27
- package/dist/{evolve-YDZSUQYA.js → evolve-QNTFGV6Z.js} +59 -26
- package/dist/{extensions-SRG7XCAH.js → extensions-QVDOHDGJ.js} +23 -8
- package/dist/{fleet-CA2CRTVG.js → fleet-Q7UOMUSG.js} +173 -56
- package/dist/fleet-preflight-DDN536IT.js +26 -0
- package/dist/{init-2OZDJE2D.js → init-WBB65ZHQ.js} +79 -34
- package/dist/{memory-3PIQQAKX.js → memory-MD3O64RI.js} +57 -28
- package/dist/{models-DY35XI7Y.js → models-BZU34YWD.js} +49 -24
- package/dist/monitor-MEQA5C3I.js +661 -0
- package/dist/{chunk-PS4PFJQP.js → orchestrator-CGFKEP27.js} +22837 -18564
- package/dist/{paths-5OMXW7Z4.js → paths-UXLN5YYZ.js} +17 -6
- package/dist/preload-P6DGH2PZ.js +13 -0
- package/dist/{reset-PIFYNOS3.js → reset-L2FQEE3E.js} +25 -13
- package/dist/{run-3VSPP24F.js → run-IV4Q6RLN.js} +115 -63
- package/dist/{share-D36RQCXM.js → share-S5BZQC5I.js} +23 -10
- package/dist/{skills-F2MRLELY.js → skills-LQEKRDTN.js} +42 -15
- package/dist/{skills-eval-E2ZTW4PL.js → skills-eval-3DC4HEWS.js} +90 -45
- package/dist/steer-GGWFUJUD.js +77 -0
- package/dist/{targets-DZMEZAH4.js → targets-C4SSGQOB.js} +78 -60
- package/dist/terminal-lease-IT5JW2NR.js +395 -0
- package/dist/{trace-7NYCUI2J.js → trace-PNCASAXC.js} +48 -17
- package/dist/tree-sitter-HGKH6LG4.js +4673 -0
- package/dist/{uninstall-AD3JWHBB.js → uninstall-FZCQCDKC.js} +19 -8
- package/dist/{upgrade-WYYBKGDY.js → upgrade-7TT7SQ3G.js} +66 -24
- package/dist/{usage-ULIDAGFF.js → usage-GV4PKT3M.js} +71 -32
- package/dist/verify-G6V4D2G7.js +716 -0
- package/dist/version-KGEG7EPO.js +21 -0
- package/dist/web-fetch-2YHJ3KTG.js +638 -0
- package/dist/{wiki-generate-PKFIX6OB.js → wiki-generate-DQF6Z66B.js} +98 -48
- package/dist/worker/entry.js +297 -54
- package/dist/workspace-G4ZWUIPR.js +22 -0
- package/docs/README.md +29 -21
- package/docs/acp.md +191 -16
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +157 -7
- package/docs/artifact-placement.md +101 -0
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +4 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +224 -97
- package/docs/config-knobs-audit.md +1 -3
- package/docs/configuration-and-targets.md +236 -38
- package/docs/context-engine.md +34 -7
- package/docs/development-pipeline.md +102 -0
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +4 -4
- package/docs/documentation-guide.md +3 -3
- package/docs/environment-variables.md +15 -6
- package/docs/eval-runner.md +3 -3
- package/docs/evals-internal.md +2 -2
- package/docs/evidence-and-memory.md +10 -2
- package/docs/evolution.md +2 -2
- package/docs/exit-codes-and-output.md +15 -9
- package/docs/extensions-and-sharing.md +25 -18
- package/docs/fleet-demo-runbook.md +22 -23
- package/docs/fleet-dispatch.md +117 -16
- package/docs/git-commit-provenance.md +120 -0
- package/docs/glossary.md +107 -15
- package/docs/installation-and-lifecycle.md +75 -17
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +46 -15
- package/docs/observability.md +8 -5
- package/docs/performance-methodology.md +491 -0
- package/docs/pi-boundary.md +72 -0
- package/docs/proactive-memory.md +14 -14
- package/docs/prompt-envelope-and-tools.md +25 -4
- package/docs/provider-adapter-cookbook.md +57 -4
- package/docs/release-cut-checklist.md +129 -111
- package/docs/safety-model.md +28 -8
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +55 -12
- package/docs/skills-marketplace.md +12 -8
- package/docs/time-conventions.md +101 -0
- package/docs/tool-usage.md +6 -5
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +10 -7
- package/docs/tui-design.md +121 -28
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +33 -36
- package/skills/README.md +5 -6
- package/skills/coding/ast-grep/SKILL.md +136 -0
- package/skills/coding/ast-grep/evals.md +56 -0
- package/skills/coding/ast-grep/references/rule_reference.md +297 -0
- package/skills/coding/coding-standards/SKILL.md +113 -0
- package/skills/coding/coding-standards/evals.md +34 -0
- package/skills/coding/prototype/SKILL.md +86 -0
- package/skills/coding/prototype/evals.md +42 -0
- package/skills/coding/prototype/references/LOGIC.md +67 -0
- package/skills/coding/prototype/references/UI.md +112 -0
- package/skills/coding/tdd/SKILL.md +101 -0
- package/skills/coding/tdd/evals.md +41 -0
- package/skills/coding/tdd/references/mocking.md +59 -0
- package/skills/coding/tdd/references/tests.md +77 -0
- package/skills/context/context-handoff/SKILL.md +126 -0
- package/skills/context/context-handoff/evals.md +57 -0
- package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
- package/skills/context/context-prime/SKILL.md +95 -0
- package/skills/context/context-prime/evals.md +54 -0
- package/skills/git/file-ticket/SKILL.md +107 -0
- package/skills/git/file-ticket/evals.md +54 -0
- package/skills/git/fix-issue/SKILL.md +106 -0
- package/skills/git/fix-issue/evals.md +71 -0
- package/skills/git/ship/SKILL.md +92 -0
- package/skills/git/ship/evals.md +72 -0
- package/skills/meta/clio-dev/SKILL.md +91 -0
- package/skills/meta/clio-dev/evals.md +45 -0
- package/skills/meta/clio-test/SKILL.md +130 -0
- package/skills/meta/clio-test/evals.md +43 -0
- package/skills/meta/clio-test/references/harness.md +97 -0
- package/skills/meta/clio-test/references/test-map.md +59 -0
- package/skills/meta/credentials/SKILL.md +125 -0
- package/skills/meta/credentials/evals.md +104 -0
- package/skills/meta/find-skills/SKILL.md +72 -0
- package/skills/meta/find-skills/evals.md +47 -0
- package/skills/meta/herdr/SKILL.md +127 -0
- package/skills/meta/herdr/evals.md +38 -0
- package/skills/meta/skill-craft/SKILL.md +102 -0
- package/skills/meta/skill-craft/evals.md +41 -0
- package/skills/planning/architecture/SKILL.md +129 -0
- package/skills/planning/architecture/evals.md +36 -0
- package/skills/planning/backlog/SKILL.md +90 -0
- package/skills/planning/backlog/evals.md +43 -0
- package/skills/planning/prd/SKILL.md +82 -0
- package/skills/planning/prd/evals.md +49 -0
- package/skills/planning/product-intent/SKILL.md +112 -0
- package/skills/planning/product-intent/evals.md +36 -0
- package/skills/planning/tech-spec/SKILL.md +115 -0
- package/skills/planning/tech-spec/evals.md +47 -0
- package/skills/registry.yaml +136 -0
- package/skills/research/arxiv-literature/SKILL.md +104 -0
- package/skills/research/arxiv-literature/evals.md +58 -0
- package/skills/research/experiment-protocol/SKILL.md +122 -0
- package/skills/research/experiment-protocol/evals.md +91 -0
- package/skills/research/scientific-debugging/SKILL.md +119 -0
- package/skills/research/scientific-debugging/evals.md +138 -0
- package/skills/research/scientific-modernization/SKILL.md +138 -0
- package/skills/research/scientific-modernization/evals.md +84 -0
- package/skills/skill-marketplace.json +12 -20
- package/skills/workflow/design-council/SKILL.md +139 -0
- package/skills/workflow/design-council/evals.md +97 -0
- package/skills/workflow/grill-me/SKILL.md +186 -0
- package/skills/workflow/grill-me/evals.md +78 -0
- package/skills/workflow/workflow-distiller/SKILL.md +136 -0
- package/skills/workflow/workflow-distiller/evals.md +107 -0
- package/src/cli/acp.ts +115 -0
- package/src/cli/agents.ts +60 -0
- package/src/cli/args.ts +280 -0
- package/src/cli/argv.ts +170 -0
- package/src/cli/ask.ts +34 -0
- package/src/cli/auth.ts +468 -0
- package/src/cli/bootstrap-generate.ts +498 -0
- package/src/cli/clio.ts +96 -0
- package/src/cli/components.ts +195 -0
- package/src/cli/config-inspect.ts +336 -0
- package/src/cli/config.ts +72 -0
- package/src/cli/configure-interop.ts +67 -0
- package/src/cli/configure-layout.ts +172 -0
- package/src/cli/configure.ts +1525 -0
- package/src/cli/context-clear.ts +76 -0
- package/src/cli/context-index.ts +100 -0
- package/src/cli/context.ts +321 -0
- package/src/cli/default-target.ts +55 -0
- package/src/cli/docs.ts +346 -0
- package/src/cli/doctor.ts +54 -0
- package/src/cli/eval.ts +315 -0
- package/src/cli/evidence.ts +225 -0
- package/src/cli/evolve.ts +219 -0
- package/src/cli/extensions.ts +214 -0
- package/src/cli/fleet.ts +868 -0
- package/src/cli/index.ts +338 -0
- package/src/cli/init.ts +219 -0
- package/src/cli/initial-message.ts +47 -0
- package/src/cli/internal-dispatch.ts +55 -0
- package/src/cli/memory.ts +182 -0
- package/src/cli/models.ts +257 -0
- package/src/cli/modes/json-stream.ts +121 -0
- package/src/cli/modes/jsonl.ts +9 -0
- package/src/cli/modes/print.ts +604 -0
- package/src/cli/oauth-manual-input.ts +72 -0
- package/src/cli/oauth-select.ts +36 -0
- package/src/cli/output-guard.ts +48 -0
- package/src/cli/paths.ts +44 -0
- package/src/cli/provider-target.ts +113 -0
- package/src/cli/removal.ts +72 -0
- package/src/cli/reset.ts +253 -0
- package/src/cli/run.ts +497 -0
- package/src/cli/share.ts +243 -0
- package/src/cli/shared.ts +60 -0
- package/src/cli/skills-eval.ts +1240 -0
- package/src/cli/skills.ts +485 -0
- package/src/cli/steer-channel.ts +86 -0
- package/src/cli/targets.ts +1154 -0
- package/src/cli/text-layout.ts +112 -0
- package/src/cli/trace.ts +322 -0
- package/src/cli/uninstall.ts +405 -0
- package/src/cli/upgrade.ts +286 -0
- package/src/cli/usage.ts +876 -0
- package/src/cli/validate-model.ts +28 -0
- package/src/cli/version.ts +7 -0
- package/src/cli/wiki-generate.ts +510 -0
- package/src/core/agent-environment.ts +7 -0
- package/src/core/artifact-paths.ts +43 -0
- package/src/core/bash-exec.ts +313 -0
- package/src/core/boot-trace.ts +42 -0
- package/src/core/bus-events.ts +744 -0
- package/src/core/bus-trace.ts +53 -0
- package/src/core/c-header-language.ts +265 -0
- package/src/core/clio-repo.ts +78 -0
- package/src/core/commit-attribution.ts +157 -0
- package/src/core/compile-cache.ts +159 -0
- package/src/core/config.ts +1722 -0
- package/src/core/context-floor.ts +33 -0
- package/src/core/defaults.ts +659 -0
- package/src/core/domain-loader.ts +177 -0
- package/src/core/event-bus.ts +94 -0
- package/src/core/file-references.ts +282 -0
- package/src/core/git-commit-attribution.ts +362 -0
- package/src/core/guardrails.ts +185 -0
- package/src/core/headless-permission.ts +21 -0
- package/src/core/incomplete-installation.ts +45 -0
- package/src/core/init.ts +223 -0
- package/src/core/json-payload.ts +58 -0
- package/src/core/package-root.ts +54 -0
- package/src/core/path-canonical.ts +37 -0
- package/src/core/process-identity.ts +41 -0
- package/src/core/recent-models.ts +91 -0
- package/src/core/residency-protection.ts +56 -0
- package/src/core/resolve-config-value.ts +88 -0
- package/src/core/response-schema.ts +279 -0
- package/src/core/run-overrides.ts +77 -0
- package/src/core/safe-exec.ts +205 -0
- package/src/core/safe-id.ts +37 -0
- package/src/core/safe-resource-write.ts +162 -0
- package/src/core/session-routing.ts +339 -0
- package/src/core/settings-layers.ts +354 -0
- package/src/core/shared-bus.ts +8 -0
- package/src/core/shell-quote.ts +26 -0
- package/src/core/skill-activation.ts +190 -0
- package/src/core/startup-timer.ts +37 -0
- package/src/core/state-file-lock.ts +219 -0
- package/src/core/termination.ts +275 -0
- package/src/core/timers.ts +38 -0
- package/src/core/tool-names.ts +65 -0
- package/src/core/verification-scripts.ts +13 -0
- package/src/core/workspace-files.ts +492 -0
- package/src/core/xdg.ts +177 -0
- package/src/domains/agents/builtins/architect.md +4 -4
- package/src/domains/agents/builtins/coder.md +3 -2
- package/src/domains/agents/builtins/debugger.md +1 -1
- package/src/domains/agents/builtins/documenter.md +1 -1
- package/src/domains/agents/builtins/git-master.md +3 -3
- package/src/domains/agents/builtins/provenance.md +1 -1
- package/src/domains/agents/builtins/researcher.md +1 -1
- package/src/domains/agents/builtins/scout.md +1 -1
- package/src/domains/agents/builtins/tester.md +1 -1
- package/src/domains/agents/builtins/verifier.md +1 -1
- package/src/domains/agents/builtins/wiki-writer.md +1 -1
- package/src/domains/agents/catalog.ts +172 -0
- package/src/domains/agents/contract.ts +16 -0
- package/src/domains/agents/extension.ts +110 -0
- package/src/domains/agents/fleet-commands.ts +154 -0
- package/src/domains/agents/fleet-contract.ts +797 -0
- package/src/domains/agents/frontmatter.ts +40 -0
- package/src/domains/agents/index.ts +102 -0
- package/src/domains/agents/manifest.ts +6 -0
- package/src/domains/agents/recipe-schema.ts +202 -0
- package/src/domains/agents/recipe.ts +125 -0
- package/src/domains/agents/registry.ts +111 -0
- package/src/domains/agents/result-contract.ts +1265 -0
- package/src/domains/agents/spec.ts +371 -0
- package/src/domains/agents/write-boundary.ts +109 -0
- package/src/domains/components/diff.ts +99 -0
- package/src/domains/components/hash.ts +21 -0
- package/src/domains/components/index.ts +3 -0
- package/src/domains/components/scan.ts +304 -0
- package/src/domains/components/snapshot.ts +108 -0
- package/src/domains/components/types.ts +82 -0
- package/src/domains/config/agent-namespace.ts +13 -0
- package/src/domains/config/classify.ts +106 -0
- package/src/domains/config/contract.ts +22 -0
- package/src/domains/config/extension.ts +142 -0
- package/src/domains/config/index.ts +23 -0
- package/src/domains/config/keybindings.ts +200 -0
- package/src/domains/config/manifest.ts +6 -0
- package/src/domains/config/watcher.ts +41 -0
- package/src/domains/context/adoption.ts +880 -0
- package/src/domains/context/bootstrap-prompt.ts +273 -0
- package/src/domains/context/bootstrap.ts +1502 -0
- package/src/domains/context/clear.ts +91 -0
- package/src/domains/context/clio-md.ts +429 -0
- package/src/domains/context/codewiki/artifact.ts +400 -0
- package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
- package/src/domains/context/codewiki/build-worker.ts +54 -0
- package/src/domains/context/codewiki/cmake.ts +356 -0
- package/src/domains/context/codewiki/cooperative.ts +46 -0
- package/src/domains/context/codewiki/coordinator.ts +182 -0
- package/src/domains/context/codewiki/digest.ts +135 -0
- package/src/domains/context/codewiki/grammar-assets.ts +33 -0
- package/src/domains/context/codewiki/indexer.ts +1529 -0
- package/src/domains/context/codewiki/paths.ts +67 -0
- package/src/domains/context/codewiki/schema.ts +80 -0
- package/src/domains/context/codewiki/tree-sitter.ts +771 -0
- package/src/domains/context/contract.ts +68 -0
- package/src/domains/context/excluded-dirs.ts +1 -0
- package/src/domains/context/extension.ts +358 -0
- package/src/domains/context/fingerprint.ts +198 -0
- package/src/domains/context/index.ts +154 -0
- package/src/domains/context/init-options.ts +69 -0
- package/src/domains/context/manifest.ts +6 -0
- package/src/domains/context/operator-profile.ts +157 -0
- package/src/domains/context/project-metadata.ts +529 -0
- package/src/domains/context/project-rules.ts +227 -0
- package/src/domains/context/prompt-context.ts +61 -0
- package/src/domains/context/refresh.ts +178 -0
- package/src/domains/context/runtime.ts +17 -0
- package/src/domains/context/sibling-files.ts +10 -0
- package/src/domains/context/state.ts +237 -0
- package/src/domains/context/wiki/assemble.ts +303 -0
- package/src/domains/context/wiki/frontmatter.ts +210 -0
- package/src/domains/context/wiki/generate.ts +595 -0
- package/src/domains/context/wiki/layout.ts +111 -0
- package/src/domains/context/wiki/meta.ts +221 -0
- package/src/domains/context/wiki/plan-store.ts +217 -0
- package/src/domains/context/wiki/plan.ts +250 -0
- package/src/domains/context/wiki/prompts.ts +283 -0
- package/src/domains/context/wiki/staleness.ts +198 -0
- package/src/domains/dispatch/active-route-planner.ts +168 -0
- package/src/domains/dispatch/admission-queue.ts +150 -0
- package/src/domains/dispatch/admission.ts +334 -0
- package/src/domains/dispatch/agent-candidates.ts +307 -0
- package/src/domains/dispatch/agent-ledger-hub.ts +71 -0
- package/src/domains/dispatch/agent-ledger-store.ts +257 -0
- package/src/domains/dispatch/agent-ledger.ts +212 -0
- package/src/domains/dispatch/agent-plan-adapter.ts +85 -0
- package/src/domains/dispatch/assignment-events.ts +132 -0
- package/src/domains/dispatch/assignment-reconcile.ts +76 -0
- package/src/domains/dispatch/assignment-store.ts +162 -0
- package/src/domains/dispatch/assignment.ts +278 -0
- package/src/domains/dispatch/backoff.ts +59 -0
- package/src/domains/dispatch/batch-store.ts +134 -0
- package/src/domains/dispatch/batch-tracker.ts +66 -0
- package/src/domains/dispatch/capability-match.ts +155 -0
- package/src/domains/dispatch/capacity-lease.ts +413 -0
- package/src/domains/dispatch/code-step-store.ts +52 -0
- package/src/domains/dispatch/code-step.ts +387 -0
- package/src/domains/dispatch/contract.ts +278 -0
- package/src/domains/dispatch/dedup.ts +133 -0
- package/src/domains/dispatch/event-pump.ts +251 -0
- package/src/domains/dispatch/execution-handoff.ts +29 -0
- package/src/domains/dispatch/execution-plan.ts +328 -0
- package/src/domains/dispatch/execution-role.ts +277 -0
- package/src/domains/dispatch/execution-scheduler.ts +583 -0
- package/src/domains/dispatch/extension.ts +6006 -0
- package/src/domains/dispatch/failure-classification.ts +147 -0
- package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
- package/src/domains/dispatch/fleet-plan.ts +225 -0
- package/src/domains/dispatch/fleet-preflight.ts +394 -0
- package/src/domains/dispatch/gate-decisions.ts +1040 -0
- package/src/domains/dispatch/gate-role-prompts.ts +58 -0
- package/src/domains/dispatch/heartbeat.ts +27 -0
- package/src/domains/dispatch/index.ts +137 -0
- package/src/domains/dispatch/joint-route-adapter.ts +114 -0
- package/src/domains/dispatch/joint-route-resolver.ts +283 -0
- package/src/domains/dispatch/manifest.ts +6 -0
- package/src/domains/dispatch/orphan-recovery.ts +266 -0
- package/src/domains/dispatch/outcome.ts +109 -0
- package/src/domains/dispatch/phase-timing.ts +47 -0
- package/src/domains/dispatch/placement.ts +202 -0
- package/src/domains/dispatch/receipt-findings.ts +255 -0
- package/src/domains/dispatch/receipt-integrity.ts +383 -0
- package/src/domains/dispatch/recovery-candidates.ts +74 -0
- package/src/domains/dispatch/reproducibility.ts +48 -0
- package/src/domains/dispatch/reservation-store.ts +501 -0
- package/src/domains/dispatch/route-approval.ts +177 -0
- package/src/domains/dispatch/route-candidates.ts +57 -0
- package/src/domains/dispatch/route-decision.ts +1079 -0
- package/src/domains/dispatch/route-facts.ts +187 -0
- package/src/domains/dispatch/route-history.ts +238 -0
- package/src/domains/dispatch/route-observer.ts +488 -0
- package/src/domains/dispatch/route-policy.ts +327 -0
- package/src/domains/dispatch/route-quality.ts +256 -0
- package/src/domains/dispatch/route-readiness.ts +120 -0
- package/src/domains/dispatch/routing-intent.ts +287 -0
- package/src/domains/dispatch/run-identity.ts +56 -0
- package/src/domains/dispatch/scout-transition.ts +130 -0
- package/src/domains/dispatch/state.ts +302 -0
- package/src/domains/dispatch/tool-stats.ts +132 -0
- package/src/domains/dispatch/transport.ts +210 -0
- package/src/domains/dispatch/types.ts +799 -0
- package/src/domains/dispatch/validation-grounding.ts +154 -0
- package/src/domains/dispatch/validation.ts +721 -0
- package/src/domains/dispatch/worker-protocol.ts +275 -0
- package/src/domains/dispatch/worker-spawn.ts +585 -0
- package/src/domains/dispatch/write-boundary-enforcer.ts +97 -0
- package/src/domains/dispatch/write-boundary.ts +426 -0
- package/src/domains/eval/artifacts/redact.ts +42 -0
- package/src/domains/eval/artifacts/store.ts +173 -0
- package/src/domains/eval/compare/compare.ts +33 -0
- package/src/domains/eval/compare/gates.ts +66 -0
- package/src/domains/eval/compare/thresholds.ts +92 -0
- package/src/domains/eval/harness-metrics.ts +62 -0
- package/src/domains/eval/index.ts +66 -0
- package/src/domains/eval/metrics/chaos-stream.ts +93 -0
- package/src/domains/eval/metrics/context.ts +34 -0
- package/src/domains/eval/metrics/coverage.ts +21 -0
- package/src/domains/eval/metrics/evidence.ts +182 -0
- package/src/domains/eval/metrics/fleet-loop-stream.ts +196 -0
- package/src/domains/eval/metrics/invariants.ts +736 -0
- package/src/domains/eval/metrics/latency.ts +4 -0
- package/src/domains/eval/metrics/token-stream.ts +139 -0
- package/src/domains/eval/metrics/tokens.ts +51 -0
- package/src/domains/eval/metrics/tool-calls.ts +7 -0
- package/src/domains/eval/proactive-memory.ts +279 -0
- package/src/domains/eval/provenance.ts +35 -0
- package/src/domains/eval/report.ts +234 -0
- package/src/domains/eval/reports/json.ts +5 -0
- package/src/domains/eval/reports/junit.ts +23 -0
- package/src/domains/eval/reports/markdown.ts +20 -0
- package/src/domains/eval/reports/swe-jsonl.ts +16 -0
- package/src/domains/eval/reports/text.ts +25 -0
- package/src/domains/eval/run-compare.ts +274 -0
- package/src/domains/eval/runner.ts +244 -0
- package/src/domains/eval/runners/clio-run.ts +148 -0
- package/src/domains/eval/runners/context-index.ts +56 -0
- package/src/domains/eval/runners/context-init.ts +203 -0
- package/src/domains/eval/runners/external-command.ts +350 -0
- package/src/domains/eval/runtime-paths.ts +171 -0
- package/src/domains/eval/schema/artifact.ts +75 -0
- package/src/domains/eval/schema/suite.ts +235 -0
- package/src/domains/eval/schema/validate.ts +339 -0
- package/src/domains/eval/store.ts +392 -0
- package/src/domains/eval/suites/load.ts +74 -0
- package/src/domains/eval/suites/matrix.ts +19 -0
- package/src/domains/eval/suites/resolve.ts +44 -0
- package/src/domains/eval/suites/run.ts +325 -0
- package/src/domains/eval/task-file.ts +186 -0
- package/src/domains/eval/types.ts +140 -0
- package/src/domains/eval/verifiers/command.ts +27 -0
- package/src/domains/eval/verifiers/file-exists.ts +6 -0
- package/src/domains/eval/verifiers/patch.ts +22 -0
- package/src/domains/eval/workspaces/git.ts +41 -0
- package/src/domains/eval/workspaces/local.ts +17 -0
- package/src/domains/eval/workspaces/temp-copy.ts +29 -0
- package/src/domains/evidence/build.ts +1754 -0
- package/src/domains/evidence/eval.ts +605 -0
- package/src/domains/evidence/failure-attribution.ts +54 -0
- package/src/domains/evidence/finish-contract-map.ts +42 -0
- package/src/domains/evidence/index.ts +55 -0
- package/src/domains/evidence/provenance.ts +200 -0
- package/src/domains/evidence/redact.ts +81 -0
- package/src/domains/evidence/store.ts +291 -0
- package/src/domains/evidence/types.ts +325 -0
- package/src/domains/evolution/SELF_EDIT_GATE.md +91 -0
- package/src/domains/evolution/index.ts +26 -0
- package/src/domains/evolution/manifest.ts +154 -0
- package/src/domains/evolution/validate.ts +304 -0
- package/src/domains/extensions/contract.ts +22 -0
- package/src/domains/extensions/discovery.ts +193 -0
- package/src/domains/extensions/extension.ts +46 -0
- package/src/domains/extensions/index.ts +34 -0
- package/src/domains/extensions/manager.ts +30 -0
- package/src/domains/extensions/manifest.ts +6 -0
- package/src/domains/extensions/resources.ts +38 -0
- package/src/domains/extensions/state.ts +224 -0
- package/src/domains/extensions/types.ts +83 -0
- package/src/domains/interop/consent.ts +185 -0
- package/src/domains/interop/contract.ts +29 -0
- package/src/domains/interop/detect.ts +173 -0
- package/src/domains/interop/extension.ts +59 -0
- package/src/domains/interop/index.ts +34 -0
- package/src/domains/interop/manifest.ts +6 -0
- package/src/domains/interop/registry.ts +139 -0
- package/src/domains/interop/state.ts +92 -0
- package/src/domains/interop/types.ts +109 -0
- package/src/domains/lifecycle/contract.ts +11 -0
- package/src/domains/lifecycle/doctor.ts +536 -0
- package/src/domains/lifecycle/extension.ts +23 -0
- package/src/domains/lifecycle/index.ts +21 -0
- package/src/domains/lifecycle/install-method.ts +51 -0
- package/src/domains/lifecycle/manifest.ts +6 -0
- package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
- package/src/domains/lifecycle/migrations/index.ts +114 -0
- package/src/domains/lifecycle/state.ts +93 -0
- package/src/domains/lifecycle/upgrade-notice.ts +35 -0
- package/src/domains/lifecycle/version.ts +35 -0
- package/src/domains/memory/index.ts +128 -0
- package/src/domains/memory/operations.ts +143 -0
- package/src/domains/memory/prompt-section.ts +86 -0
- package/src/domains/memory/proposal.ts +180 -0
- package/src/domains/memory/store.ts +163 -0
- package/src/domains/memory/task-bank.ts +229 -0
- package/src/domains/memory/task-memory-handoff.ts +222 -0
- package/src/domains/memory/task-memory-policy.ts +602 -0
- package/src/domains/memory/task-memory-status.ts +58 -0
- package/src/domains/memory/task-memory-telemetry.ts +346 -0
- package/src/domains/memory/task-memory-trace.ts +89 -0
- package/src/domains/memory/types.ts +74 -0
- package/src/domains/memory/validate.ts +297 -0
- package/src/domains/middleware/budget.ts +216 -0
- package/src/domains/middleware/contract.ts +35 -0
- package/src/domains/middleware/dispatch-nudge.ts +469 -0
- package/src/domains/middleware/extension.ts +129 -0
- package/src/domains/middleware/hook-receipts.ts +70 -0
- package/src/domains/middleware/hooks-io.ts +186 -0
- package/src/domains/middleware/hooks.ts +432 -0
- package/src/domains/middleware/index.ts +154 -0
- package/src/domains/middleware/manifest.ts +6 -0
- package/src/domains/middleware/memory-intervention.ts +701 -0
- package/src/domains/middleware/rules.ts +42 -0
- package/src/domains/middleware/runtime.ts +333 -0
- package/src/domains/middleware/skills-reminder.ts +202 -0
- package/src/domains/middleware/snapshot.ts +71 -0
- package/src/domains/middleware/stalled-turn.ts +71 -0
- package/src/domains/middleware/task-board-reminder.ts +87 -0
- package/src/domains/middleware/task-nudge.ts +77 -0
- package/src/domains/middleware/tool-choice-control.ts +42 -0
- package/src/domains/middleware/types.ts +131 -0
- package/src/domains/middleware/validate.ts +329 -0
- package/src/domains/observability/accountability.ts +67 -0
- package/src/domains/observability/contract.ts +168 -0
- package/src/domains/observability/cost.ts +206 -0
- package/src/domains/observability/evidence-index.ts +123 -0
- package/src/domains/observability/extension.ts +281 -0
- package/src/domains/observability/index.ts +78 -0
- package/src/domains/observability/manifest.ts +10 -0
- package/src/domains/observability/metrics.ts +37 -0
- package/src/domains/observability/projection.ts +477 -0
- package/src/domains/observability/telemetry.ts +89 -0
- package/src/domains/observability/trace-store.ts +1454 -0
- package/src/domains/prompts/compiler.ts +614 -0
- package/src/domains/prompts/contract.ts +46 -0
- package/src/domains/prompts/extension.ts +336 -0
- package/src/domains/prompts/fragment-loader.ts +138 -0
- package/src/domains/prompts/fragments/identity/clio.md +5 -6
- package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
- package/src/domains/prompts/fragments/identity/self-awareness.md +19 -0
- package/src/domains/prompts/fragments/operating/contract.md +4 -41
- package/src/domains/prompts/fragments/operating/delegation.md +42 -0
- package/src/domains/prompts/fragments/operating/skills.md +26 -0
- package/src/domains/prompts/fragments/operating/worker.md +16 -0
- package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
- package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
- package/src/domains/prompts/fragments/safety/read-only.md +4 -4
- package/src/domains/prompts/fragments/safety/suggest.md +2 -2
- package/src/domains/prompts/fragments/wiki/page.md +10 -0
- package/src/domains/prompts/fragments/wiki/plan.md +10 -0
- package/src/domains/prompts/hash.ts +73 -0
- package/src/domains/prompts/index.ts +32 -0
- package/src/domains/prompts/manifest.ts +8 -0
- package/src/domains/prompts/memory-intervention.ts +57 -0
- package/src/domains/prompts/preload.ts +82 -0
- package/src/domains/providers/auth/api-key.ts +47 -0
- package/src/domains/providers/auth/backend-file.ts +79 -0
- package/src/domains/providers/auth/backend-memory.ts +72 -0
- package/src/domains/providers/auth/boot-status.ts +65 -0
- package/src/domains/providers/auth/index.ts +37 -0
- package/src/domains/providers/auth/oauth.ts +37 -0
- package/src/domains/providers/auth/storage.ts +726 -0
- package/src/domains/providers/capabilities.ts +58 -0
- package/src/domains/providers/catalog.ts +162 -0
- package/src/domains/providers/contract.ts +162 -0
- package/src/domains/providers/credentials.ts +20 -0
- package/src/domains/providers/eligibility.ts +24 -0
- package/src/domains/providers/errors.ts +64 -0
- package/src/domains/providers/extension.ts +548 -0
- package/src/domains/providers/index.ts +142 -0
- package/src/domains/providers/knowledge-base-path.ts +102 -0
- package/src/domains/providers/manifest.ts +6 -0
- package/src/domains/providers/model-capabilities.ts +136 -0
- package/src/domains/providers/model-discovery.ts +144 -0
- package/src/domains/providers/model-family.ts +32 -0
- package/src/domains/providers/model-runtime-capabilities.ts +723 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +120 -37
- package/src/domains/providers/plugins.ts +61 -0
- package/src/domains/providers/probe/fingerprint.ts +64 -0
- package/src/domains/providers/probe/http.ts +114 -0
- package/src/domains/providers/probe/reasoning.ts +111 -0
- package/src/domains/providers/registry.ts +187 -0
- package/src/domains/providers/resolver.ts +156 -0
- package/src/domains/providers/runtime-resolution.ts +720 -0
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +90 -0
- package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
- package/src/domains/providers/runtimes/builtins.ts +78 -0
- package/src/domains/providers/runtimes/claude/claude-code.ts +38 -0
- package/src/domains/providers/runtimes/claude/claude-sdk.ts +38 -0
- package/src/domains/providers/runtimes/claude/common.ts +55 -0
- package/src/domains/providers/runtimes/cloud/alcf.ts +171 -0
- package/src/domains/providers/runtimes/cloud/anthropic-max.ts +71 -0
- package/src/domains/providers/runtimes/cloud/anthropic.ts +43 -0
- package/src/domains/providers/runtimes/cloud/bedrock.ts +35 -0
- package/src/domains/providers/runtimes/cloud/deepseek.ts +50 -0
- package/src/domains/providers/runtimes/cloud/google.ts +41 -0
- package/src/domains/providers/runtimes/cloud/groq.ts +46 -0
- package/src/domains/providers/runtimes/cloud/mistral.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openai-codex.ts +49 -0
- package/src/domains/providers/runtimes/cloud/openai.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openrouter.ts +111 -0
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +164 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +474 -0
- package/src/domains/providers/runtimes/local-native/lemonade-anthropic.ts +27 -0
- package/src/domains/providers/runtimes/local-native/lemonade-openai.ts +26 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +88 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +207 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +180 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +126 -0
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +98 -0
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
- package/src/domains/providers/runtimes/local-native/ollama-native.ts +117 -0
- package/src/domains/providers/runtimes/local-native/sglang.ts +26 -0
- package/src/domains/providers/runtimes/local-native/vllm.ts +27 -0
- package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +104 -0
- package/src/domains/providers/runtimes/protocol/anthropic-messages.ts +28 -0
- package/src/domains/providers/runtimes/protocol/bedrock.ts +26 -0
- package/src/domains/providers/runtimes/protocol/google.ts +27 -0
- package/src/domains/providers/runtimes/protocol/openai-compat.ts +145 -0
- package/src/domains/providers/support.ts +241 -0
- package/src/domains/providers/thinking-control-policy.ts +85 -0
- package/src/domains/providers/types/capability-flags.ts +114 -0
- package/src/domains/providers/types/cost-provenance.ts +7 -0
- package/src/domains/providers/types/inference.ts +41 -0
- package/src/domains/providers/types/knowledge-base.ts +156 -0
- package/src/domains/providers/types/local-model-quirks.ts +216 -0
- package/src/domains/providers/types/runtime-descriptor.ts +181 -0
- package/src/domains/providers/types/target-descriptor.ts +60 -0
- package/src/domains/resources/collision.ts +92 -0
- package/src/domains/resources/common-loader.ts +140 -0
- package/src/domains/resources/contract.ts +24 -0
- package/src/domains/resources/extension.ts +59 -0
- package/src/domains/resources/index.ts +74 -0
- package/src/domains/resources/loader.ts +85 -0
- package/src/domains/resources/manifest.ts +6 -0
- package/src/domains/resources/prompts/loader.ts +246 -0
- package/src/domains/resources/prompts/substitute.ts +1 -0
- package/src/domains/resources/skills/content-hash.ts +107 -0
- package/src/domains/resources/skills/evals.ts +175 -0
- package/src/domains/resources/skills/install.ts +427 -0
- package/src/domains/resources/skills/loader.ts +985 -0
- package/src/domains/resources/skills/marketplace.ts +301 -0
- package/src/domains/resources/skills/provenance-pin.ts +115 -0
- package/src/domains/safety/action-classifier.ts +270 -0
- package/src/domains/safety/approval-axis.ts +23 -0
- package/src/domains/safety/audit.ts +493 -0
- package/src/domains/safety/autonomy.ts +174 -0
- package/src/domains/safety/call-target.ts +59 -0
- package/src/domains/safety/contract.ts +65 -0
- package/src/domains/safety/damage-control.ts +44 -0
- package/src/domains/safety/default-path-policy.ts +117 -0
- package/src/domains/safety/extension.ts +383 -0
- package/src/domains/safety/finish-contract-registration.ts +128 -0
- package/src/domains/safety/finish-contract.ts +554 -0
- package/src/domains/safety/index.ts +44 -0
- package/src/domains/safety/loop-detector.ts +143 -0
- package/src/domains/safety/manifest.ts +6 -0
- package/src/domains/safety/path-policy.ts +164 -0
- package/src/domains/safety/policy-engine.ts +994 -0
- package/src/domains/safety/project-policy.ts +391 -0
- package/src/domains/safety/protected-artifacts-registration.ts +189 -0
- package/src/domains/safety/protected-artifacts.ts +993 -0
- package/src/domains/safety/rejection-feedback.ts +102 -0
- package/src/domains/safety/rigor.ts +72 -0
- package/src/domains/safety/rule-compiler.ts +48 -0
- package/src/domains/safety/rule-pack-loader.ts +92 -0
- package/src/domains/safety/run-effects.ts +197 -0
- package/src/domains/safety/scope.ts +61 -0
- package/src/domains/scheduling/budget.ts +35 -0
- package/src/domains/scheduling/cluster.ts +175 -0
- package/src/domains/scheduling/contract.ts +30 -0
- package/src/domains/scheduling/extension.ts +91 -0
- package/src/domains/scheduling/index.ts +12 -0
- package/src/domains/scheduling/manifest.ts +6 -0
- package/src/domains/session/archive-readers.ts +208 -0
- package/src/domains/session/checkpoint.ts +38 -0
- package/src/domains/session/compaction/auto.ts +89 -0
- package/src/domains/session/compaction/branch-summary.ts +187 -0
- package/src/domains/session/compaction/compact.ts +493 -0
- package/src/domains/session/compaction/cut-point.ts +172 -0
- package/src/domains/session/compaction/defaults.ts +34 -0
- package/src/domains/session/compaction/mask-observations.ts +265 -0
- package/src/domains/session/compaction/session-entries.ts +18 -0
- package/src/domains/session/compaction/tokens.ts +148 -0
- package/src/domains/session/context-accounting.ts +583 -0
- package/src/domains/session/context-ledger.ts +362 -0
- package/src/domains/session/contract.ts +159 -0
- package/src/domains/session/cwd-fallback.ts +65 -0
- package/src/domains/session/decision-board.ts +190 -0
- package/src/domains/session/entries.ts +572 -0
- package/src/domains/session/extension.ts +403 -0
- package/src/domains/session/history.ts +172 -0
- package/src/domains/session/index.ts +84 -0
- package/src/domains/session/manager.ts +128 -0
- package/src/domains/session/manifest.ts +6 -0
- package/src/domains/session/migrations/index.ts +27 -0
- package/src/domains/session/prompt-manifest.ts +173 -0
- package/src/domains/session/protected-artifact-journal.ts +241 -0
- package/src/domains/session/protected-artifacts.ts +90 -0
- package/src/domains/session/retry.ts +230 -0
- package/src/domains/session/session-artifacts.ts +107 -0
- package/src/domains/session/task-board.ts +569 -0
- package/src/domains/session/tree/active-path.ts +137 -0
- package/src/domains/session/tree/fork.ts +159 -0
- package/src/domains/session/tree/manager.ts +128 -0
- package/src/domains/session/tree/navigator.ts +177 -0
- package/src/domains/session/tree/preview.ts +259 -0
- package/src/domains/session/usage.ts +148 -0
- package/src/domains/session/workspace/git-probe.ts +167 -0
- package/src/domains/session/workspace/index.ts +4 -0
- package/src/domains/session/workspace/project-type.ts +217 -0
- package/src/domains/session/workspace/snapshot.ts +74 -0
- package/src/domains/share/archive.ts +684 -0
- package/src/domains/share/contract.ts +9 -0
- package/src/domains/share/extension.ts +26 -0
- package/src/domains/share/index.ts +28 -0
- package/src/domains/share/manifest.ts +6 -0
- package/src/domains/user-tasks/store.ts +297 -0
- package/src/engine/acp/adapter.ts +397 -0
- package/src/engine/acp/errors.ts +128 -0
- package/src/engine/acp/event-mapper.ts +154 -0
- package/src/engine/acp/server.ts +2238 -0
- package/src/engine/acp/tool-mediator.ts +686 -0
- package/src/engine/acp/transport.ts +775 -0
- package/src/engine/acp/types.ts +196 -0
- package/src/engine/agent.ts +29 -0
- package/src/engine/ai.ts +207 -0
- package/src/engine/alcf-oauth.ts +205 -0
- package/src/engine/antigravity/subprocess-runtime.ts +205 -0
- package/src/engine/api-registry.ts +223 -0
- package/src/engine/apis/degraded-inference.ts +95 -0
- package/src/engine/apis/index.ts +16 -0
- package/src/engine/apis/llamacpp-residency.ts +292 -0
- package/src/engine/apis/lmstudio-residency.ts +76 -0
- package/src/engine/apis/lmstudio.ts +243 -0
- package/src/engine/apis/ollama-native.ts +528 -0
- package/src/engine/apis/openai-completions.ts +795 -0
- package/src/engine/apis/output-budget.ts +99 -0
- package/src/engine/apis/residency-lock.ts +29 -0
- package/src/engine/apis/residency.ts +776 -0
- package/src/engine/apis/resident-models.ts +42 -0
- package/src/engine/apis/sampling-overrides.ts +38 -0
- package/src/engine/apis/types.ts +16 -0
- package/src/engine/claude/sdk-runtime.ts +685 -0
- package/src/engine/claude/session-id.ts +5 -0
- package/src/engine/claude/subprocess-runtime.ts +316 -0
- package/src/engine/claude/tool-safety.ts +400 -0
- package/src/engine/env-api-keys.ts +98 -0
- package/src/engine/external-subprocess.ts +23 -0
- package/src/engine/gemma-channel-filter.ts +223 -0
- package/src/engine/harmony-response.ts +165 -0
- package/src/engine/instrumented-tui.ts +192 -0
- package/src/engine/loop-guard.ts +1127 -0
- package/src/engine/messages.ts +14 -0
- package/src/engine/models.ts +42 -0
- package/src/engine/oauth.ts +196 -0
- package/src/engine/pi-mono-names.ts +13 -0
- package/src/engine/prompt-templates.ts +1 -0
- package/src/engine/provider-payload.ts +272 -0
- package/src/engine/select-list.ts +53 -0
- package/src/engine/session.ts +834 -0
- package/src/engine/strip-tokenizer-sentinels.ts +125 -0
- package/src/engine/truncate.ts +9 -0
- package/src/engine/tui.ts +111 -0
- package/src/engine/types.ts +63 -0
- package/src/engine/worker-events.ts +100 -0
- package/src/engine/worker-runtime-capabilities.ts +5 -0
- package/src/engine/worker-runtime.ts +1022 -0
- package/src/engine/worker-tools.ts +208 -0
- package/src/entry/boot-options.ts +50 -0
- package/src/entry/orchestrator.ts +2011 -0
- package/src/interactive/application-controller.ts +433 -0
- package/src/interactive/bus-notices.ts +265 -0
- package/src/interactive/chat-loop-messages.ts +626 -0
- package/src/interactive/chat-loop-policy.ts +18 -0
- package/src/interactive/chat-loop.ts +1090 -0
- package/src/interactive/chat-panel.ts +1820 -0
- package/src/interactive/chat-renderer.ts +1228 -0
- package/src/interactive/clio-editor.ts +161 -0
- package/src/interactive/command-fallbacks.ts +23 -0
- package/src/interactive/command-output.ts +85 -0
- package/src/interactive/context-activity.ts +203 -0
- package/src/interactive/context-meter.ts +223 -0
- package/src/interactive/context-overlay.ts +246 -0
- package/src/interactive/cost-overlay.ts +279 -0
- package/src/interactive/dispatch-board.ts +1319 -0
- package/src/interactive/dispatch-steering.ts +86 -0
- package/src/interactive/editor-bash.ts +46 -0
- package/src/interactive/editor-steer.ts +51 -0
- package/src/interactive/editor-submit.ts +507 -0
- package/src/interactive/export-html/ansi-to-html.ts +161 -0
- package/src/interactive/export-html/index.ts +51 -0
- package/src/interactive/export-html/template.ts +45 -0
- package/src/interactive/export-html/tool-renderer.ts +54 -0
- package/src/interactive/external-editor.ts +67 -0
- package/src/interactive/follow-up-queue-panel.ts +75 -0
- package/src/interactive/footer/dashboard.ts +538 -0
- package/src/interactive/footer/notifications.ts +275 -0
- package/src/interactive/footer/widgets.ts +1264 -0
- package/src/interactive/footer-panel.ts +187 -0
- package/src/interactive/format-time.ts +97 -0
- package/src/interactive/index.ts +11 -0
- package/src/interactive/interactive-application.ts +939 -0
- package/src/interactive/interactive-event-projection.ts +385 -0
- package/src/interactive/interactive-input-runtime.ts +307 -0
- package/src/interactive/interactive-presentation.ts +584 -0
- package/src/interactive/interactive-shell.ts +388 -0
- package/src/interactive/interactive-slash-runtime.ts +554 -0
- package/src/interactive/interactive-subscriptions.ts +111 -0
- package/src/interactive/interactive-tickers.ts +183 -0
- package/src/interactive/keybinding-manager.ts +496 -0
- package/src/interactive/layout.ts +57 -0
- package/src/interactive/leader-key.ts +143 -0
- package/src/interactive/loop-guard-interrupt.ts +101 -0
- package/src/interactive/memory-overlay.ts +280 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +110 -0
- package/src/interactive/overlay-auth-lifecycle.ts +308 -0
- package/src/interactive/overlay-frame.ts +502 -0
- package/src/interactive/overlay-general-openers.ts +274 -0
- package/src/interactive/overlay-key-routing.ts +216 -0
- package/src/interactive/overlay-lifecycle.ts +426 -0
- package/src/interactive/overlay-model-selectors.ts +127 -0
- package/src/interactive/overlay-permission-lifecycle.ts +345 -0
- package/src/interactive/overlay-resource-openers.ts +112 -0
- package/src/interactive/overlay-session-lifecycle.ts +327 -0
- package/src/interactive/overlay-transitions.ts +57 -0
- package/src/interactive/overlays/agents.ts +69 -0
- package/src/interactive/overlays/ask-user.ts +921 -0
- package/src/interactive/overlays/auth-dialog.ts +221 -0
- package/src/interactive/overlays/context-reset.ts +108 -0
- package/src/interactive/overlays/cwd-fallback.ts +141 -0
- package/src/interactive/overlays/decisions.ts +300 -0
- package/src/interactive/overlays/extensions.ts +54 -0
- package/src/interactive/overlays/help-reference.ts +145 -0
- package/src/interactive/overlays/interop.ts +139 -0
- package/src/interactive/overlays/keybinding-detail.ts +90 -0
- package/src/interactive/overlays/list-overlay.ts +606 -0
- package/src/interactive/overlays/message-picker.ts +155 -0
- package/src/interactive/overlays/model-selector.ts +1109 -0
- package/src/interactive/overlays/prompts.ts +72 -0
- package/src/interactive/overlays/session-selector-search.ts +31 -0
- package/src/interactive/overlays/session-selector.ts +284 -0
- package/src/interactive/overlays/settings.ts +3451 -0
- package/src/interactive/overlays/skills-hub.ts +237 -0
- package/src/interactive/overlays/tree-selector.ts +422 -0
- package/src/interactive/permission-overlay.ts +170 -0
- package/src/interactive/render-trace.ts +534 -0
- package/src/interactive/renderers/branch-summary.ts +86 -0
- package/src/interactive/renderers/code-ink.ts +420 -0
- package/src/interactive/renderers/compaction-summary.ts +112 -0
- package/src/interactive/renderers/diff.ts +137 -0
- package/src/interactive/renderers/mermaid.ts +53 -0
- package/src/interactive/renderers/notice.ts +28 -0
- package/src/interactive/renderers/retry-status.ts +31 -0
- package/src/interactive/renderers/structured.ts +89 -0
- package/src/interactive/renderers/tool-execution.ts +1357 -0
- package/src/interactive/renderers/worker-entry.ts +280 -0
- package/src/interactive/session-last-turn.ts +186 -0
- package/src/interactive/session-switch-settlement.ts +10 -0
- package/src/interactive/session-transcript.ts +105 -0
- package/src/interactive/session-usage-reseed.ts +74 -0
- package/src/interactive/slash-autocomplete.ts +256 -0
- package/src/interactive/slash-commands.ts +1407 -0
- package/src/interactive/slash-spec.ts +424 -0
- package/src/interactive/status/controller.ts +260 -0
- package/src/interactive/status/index.ts +23 -0
- package/src/interactive/status/state-machine.ts +530 -0
- package/src/interactive/status/summary.ts +170 -0
- package/src/interactive/status/types.ts +121 -0
- package/src/interactive/status/verbs.ts +163 -0
- package/src/interactive/status/watchdog.ts +24 -0
- package/src/interactive/stdout-backpressure.ts +99 -0
- package/src/interactive/stream-pacer.ts +530 -0
- package/src/interactive/stream-pacing-policy.ts +66 -0
- package/src/interactive/tasks-overlay.ts +540 -0
- package/src/interactive/terminal-lease.ts +485 -0
- package/src/interactive/theme/components.ts +55 -0
- package/src/interactive/theme/glyphs.ts +70 -0
- package/src/interactive/theme/index.ts +15 -0
- package/src/interactive/theme/labels.ts +88 -0
- package/src/interactive/theme/rules.ts +138 -0
- package/src/interactive/theme/segments.ts +88 -0
- package/src/interactive/theme/tokens.ts +121 -0
- package/src/interactive/thinking-level-policy.ts +6 -0
- package/src/interactive/tool-prose-loop.ts +122 -0
- package/src/interactive/tool-prose-registration.ts +48 -0
- package/src/interactive/turn-context.ts +855 -0
- package/src/interactive/turn-middleware.ts +283 -0
- package/src/interactive/turn-persistence.ts +458 -0
- package/src/interactive/turn-queues.ts +181 -0
- package/src/interactive/turn-recovery.ts +323 -0
- package/src/interactive/turn-runtime.ts +869 -0
- package/src/interactive/turn-state.ts +133 -0
- package/src/interactive/view/artifacts.ts +1452 -0
- package/src/interactive/view/view-overlay.ts +735 -0
- package/src/interactive/welcome-dashboard.ts +537 -0
- package/src/interactive/worker-receipts.ts +143 -0
- package/src/interactive/worker-replay.ts +111 -0
- package/src/interactive/worker-share.ts +100 -0
- package/src/interactive/worker-stream.ts +446 -0
- package/src/interactive/workspace-facts.ts +141 -0
- package/src/tools/agent-tools.ts +402 -0
- package/src/tools/artifact.ts +103 -0
- package/src/tools/ask-user.ts +666 -0
- package/src/tools/bash.ts +204 -0
- package/src/tools/bootstrap.ts +77 -0
- package/src/tools/builtin-tool-catalog.ts +265 -0
- package/src/tools/codewiki/code-nav-surface.ts +29 -0
- package/src/tools/codewiki/code-nav.ts +549 -0
- package/src/tools/codewiki/shared.ts +118 -0
- package/src/tools/compete-worktrees.ts +898 -0
- package/src/tools/context/docs-engine.ts +630 -0
- package/src/tools/context/index.ts +514 -0
- package/src/tools/context/surface.ts +19 -0
- package/src/tools/core-bootstrap.ts +168 -0
- package/src/tools/credential-present.ts +151 -0
- package/src/tools/dispatch-admission.ts +533 -0
- package/src/tools/dispatch-arguments.ts +228 -0
- package/src/tools/dispatch-background.ts +54 -0
- package/src/tools/dispatch-event-text.ts +6 -0
- package/src/tools/dispatch-plan.ts +746 -0
- package/src/tools/dispatch-run-events.ts +238 -0
- package/src/tools/dispatch-runner.ts +2370 -0
- package/src/tools/dispatch-scout-admission.ts +295 -0
- package/src/tools/dispatch-scout.ts +461 -0
- package/src/tools/dispatch-types.ts +77 -0
- package/src/tools/dispatch.ts +244 -0
- package/src/tools/edit-diff.ts +534 -0
- package/src/tools/edit.ts +128 -0
- package/src/tools/executables.ts +22 -0
- package/src/tools/file-mutation-queue.ts +35 -0
- package/src/tools/find.ts +294 -0
- package/src/tools/grep.ts +495 -0
- package/src/tools/ignore-policy.ts +169 -0
- package/src/tools/lazy-tool.ts +60 -0
- package/src/tools/ledger.ts +206 -0
- package/src/tools/ls.ts +110 -0
- package/src/tools/monitor-surface.ts +36 -0
- package/src/tools/monitor.ts +767 -0
- package/src/tools/network-policy.ts +29 -0
- package/src/tools/observation.ts +421 -0
- package/src/tools/observers.ts +99 -0
- package/src/tools/path-utils.ts +79 -0
- package/src/tools/policy.ts +154 -0
- package/src/tools/profiles.ts +108 -0
- package/src/tools/read.ts +173 -0
- package/src/tools/registry.ts +1169 -0
- package/src/tools/result-shaping.ts +204 -0
- package/src/tools/safe-exec.ts +128 -0
- package/src/tools/spawn-hygiene.ts +182 -0
- package/src/tools/steer-surface.ts +17 -0
- package/src/tools/steer.ts +77 -0
- package/src/tools/tasks.ts +265 -0
- package/src/tools/truncate-utf8.ts +17 -0
- package/src/tools/truncate.ts +43 -0
- package/src/tools/verify/frontend.ts +687 -0
- package/src/tools/verify/index.ts +31 -0
- package/src/tools/verify/scripts.ts +108 -0
- package/src/tools/verify/surface.ts +46 -0
- package/src/tools/web-fetch-surface.ts +23 -0
- package/src/tools/web-fetch.ts +759 -0
- package/src/tools/worker-evidence.ts +215 -0
- package/src/tools/write.ts +57 -0
- package/src/utils/exif-orientation.ts +192 -0
- package/src/utils/git.ts +24 -0
- package/src/utils/image-resize.ts +148 -0
- package/src/utils/photon.ts +103 -0
- package/src/worker/control-lane.ts +22 -0
- package/src/worker/entry.ts +294 -0
- package/src/worker/event-projection.ts +56 -0
- package/src/worker/heartbeat.ts +24 -0
- package/src/worker/ledger-mirror.ts +95 -0
- package/src/worker/ndjson.ts +40 -0
- package/src/worker/protocol.ts +529 -0
- package/src/worker/resource-facts.ts +79 -0
- package/src/worker/runtime-registry.ts +12 -0
- package/src/worker/spec-contract.ts +675 -0
- package/src/worker/stdin-demux.ts +316 -0
- package/dist/acp-UMLFVA3F.js +0 -92
- package/dist/chunk-262G75JS.js +0 -35
- package/dist/chunk-6CWDTGUC.js +0 -20
- package/dist/chunk-BYEU76JP.js +0 -899
- package/dist/chunk-GNGDQYDU.js +0 -34688
- package/dist/chunk-GOTUR54M.js +0 -9
- package/dist/chunk-NI4DEJMC.js +0 -88
- package/dist/chunk-TPOCL34A.js +0 -2876
- package/dist/chunk-UU3R62TT.js +0 -128
- package/dist/clio-KIQ5SNDS.js +0 -53
- package/dist/configure-G4E3A2PG.js +0 -27
- package/dist/doctor-M5HJJZOL.js +0 -61
- package/dist/domains/agents/builtins/architect.md +0 -33
- package/dist/domains/agents/builtins/coder.md +0 -31
- package/dist/domains/agents/builtins/context-bootstrap.md +0 -38
- package/dist/domains/agents/builtins/debugger.md +0 -30
- package/dist/domains/agents/builtins/documenter.md +0 -31
- package/dist/domains/agents/builtins/git-master.md +0 -30
- package/dist/domains/agents/builtins/provenance.md +0 -30
- package/dist/domains/agents/builtins/researcher.md +0 -71
- package/dist/domains/agents/builtins/scout.md +0 -42
- package/dist/domains/agents/builtins/tester.md +0 -31
- package/dist/domains/agents/builtins/verifier.md +0 -30
- package/dist/domains/agents/builtins/wiki-writer.md +0 -41
- package/dist/fleet-preflight-CLIAX7YR.js +0 -21
- package/dist/preload-KZVHET2B.js +0 -11
- package/dist/version-ROZ6CZKH.js +0 -16
- package/docs/html/agents_blueprint.html +0 -936
- package/docs/html/alcf_blueprint.html +0 -324
- package/docs/html/architecture_blueprint.html +0 -850
- package/docs/html/commands_blueprint.html +0 -794
- package/docs/html/config_knobs_audit_blueprint.html +0 -178
- package/docs/html/configuration_blueprint.html +0 -1080
- package/docs/html/context_blueprint.html +0 -603
- package/docs/html/documentation_blueprint.html +0 -832
- package/docs/html/environment_blueprint.html +0 -404
- package/docs/html/eval_blueprint.html +0 -743
- package/docs/html/evals_internal_blueprint.html +0 -190
- package/docs/html/evolution_blueprint.html +0 -674
- package/docs/html/extensions_blueprint.html +0 -2065
- package/docs/html/fleet_dispatch_blueprint.html +0 -286
- package/docs/html/index.html +0 -919
- package/docs/html/lifecycle_blueprint.html +0 -723
- package/docs/html/memory_blueprint.html +0 -699
- package/docs/html/middleware_blueprint.html +0 -664
- package/docs/html/models_blueprint.html +0 -2366
- package/docs/html/observability_blueprint.html +0 -683
- package/docs/html/provider_adapter_blueprint.html +0 -245
- package/docs/html/safety_blueprint.html +0 -1386
- package/docs/html/shared.css +0 -571
- package/docs/html/shared.js +0 -143
- package/docs/html/skills_blueprint.html +0 -671
- package/docs/html/soak_blueprint.html +0 -182
- package/docs/html/tool_usage_blueprint.html +0 -350
- package/docs/html/tools_blueprint.html +0 -2249
- package/docs/html/trace_blueprint.html +0 -235
- package/docs/html/tui_design_blueprint.html +0 -314
- package/docs/html/validation_blueprint.html +0 -961
- package/docs/html/worker_dispatch_blueprint.html +0 -231
- package/skills/git/commit-crafting/SKILL.md +0 -79
- package/skills/git/commit-crafting/evals.md +0 -92
- package/skills/git/create-pr/SKILL.md +0 -116
- package/skills/git/create-pr/evals.md +0 -114
- package/skills/git/investigate-issue/SKILL.md +0 -139
- package/skills/git/investigate-issue/evals.md +0 -94
- package/skills/git/review-changes/SKILL.md +0 -103
- package/skills/git/review-changes/evals.md +0 -85
|
@@ -0,0 +1,1264 @@
|
|
|
1
|
+
import type { OutputVerbosity } from "../../core/defaults.js";
|
|
2
|
+
import { ToolNames } from "../../core/tool-names.js";
|
|
3
|
+
import {
|
|
4
|
+
type CostAggregate,
|
|
5
|
+
formatCostAggregate,
|
|
6
|
+
type TokenThroughputSnapshot,
|
|
7
|
+
type UsageBreakdown,
|
|
8
|
+
} from "../../domains/observability/index.js";
|
|
9
|
+
import type { ContextUsageBreakdown } from "../../domains/session/context-accounting.js";
|
|
10
|
+
import type { ContextLedger, ContextLedgerCategory } from "../../domains/session/context-ledger.js";
|
|
11
|
+
import { type TaskBoardSnapshot, taskBoardCounts } from "../../domains/session/task-board.js";
|
|
12
|
+
import { truncateToWidth, visibleWidth } from "../../engine/tui.js";
|
|
13
|
+
import { CONTEXT_CATEGORY_TOKEN, contextCategorySwatch, renderContextMeterBar } from "../context-meter.js";
|
|
14
|
+
import {
|
|
15
|
+
agentDisplayLabel,
|
|
16
|
+
type DispatchBoardRow,
|
|
17
|
+
dispatchOriginPresentation,
|
|
18
|
+
dispatchRowPrefix,
|
|
19
|
+
dispatchStatusPresentation,
|
|
20
|
+
} from "../dispatch-board.js";
|
|
21
|
+
import { buildSegmentedContextBar, CONTEXT_BAR_LABEL_WIDTH, formatFooterTokens } from "../footer-panel.js";
|
|
22
|
+
import { type AgentStatus, spinnerFrame, type TurnSummary } from "../status/index.js";
|
|
23
|
+
import {
|
|
24
|
+
type ClioTheme,
|
|
25
|
+
type ClioToken,
|
|
26
|
+
clioTheme,
|
|
27
|
+
fitUnits,
|
|
28
|
+
formatCompactMs,
|
|
29
|
+
formatContextPercent,
|
|
30
|
+
GLYPH,
|
|
31
|
+
joinChips,
|
|
32
|
+
joinSections,
|
|
33
|
+
sectionTag,
|
|
34
|
+
} from "../theme/index.js";
|
|
35
|
+
|
|
36
|
+
export interface ToolTallySnapshot {
|
|
37
|
+
tools: Readonly<Record<string, number>>;
|
|
38
|
+
errors: number;
|
|
39
|
+
active?: number;
|
|
40
|
+
truncatedResults?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Live workspace facts. Owned by the footer (the welcome header no longer repeats the branch). */
|
|
44
|
+
export interface WorkspaceFacts {
|
|
45
|
+
cwd: string;
|
|
46
|
+
branch: string | null;
|
|
47
|
+
dirty: boolean | null;
|
|
48
|
+
projectType: string | null;
|
|
49
|
+
remote: string | null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface SessionFacts {
|
|
53
|
+
name: string | null;
|
|
54
|
+
id: string | null;
|
|
55
|
+
version: string;
|
|
56
|
+
turns: number | null;
|
|
57
|
+
tokens: string | null;
|
|
58
|
+
throughput: string | null;
|
|
59
|
+
throughputDetail: string | null;
|
|
60
|
+
cost: string | null;
|
|
61
|
+
target: string | null;
|
|
62
|
+
thinking: string | null;
|
|
63
|
+
capabilities: string[] | null;
|
|
64
|
+
safety: string | null;
|
|
65
|
+
toolProfile: string | null;
|
|
66
|
+
/** Active transcript detail mode, shown in the dashboard so visibility is never implicit. */
|
|
67
|
+
outputVerbosity?: OutputVerbosity | null;
|
|
68
|
+
/**
|
|
69
|
+
* Ctrl+G armed the portable leader and is waiting for the next key. Shown
|
|
70
|
+
* because the frame between the two keystrokes was otherwise identical to
|
|
71
|
+
* the idle frame, on the fallback whose users have no working Alt to check
|
|
72
|
+
* it against.
|
|
73
|
+
*/
|
|
74
|
+
leaderArmed?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* A Ctrl+C landed on an idle empty prompt and the 500ms window that quits is
|
|
77
|
+
* open. Shown for the same reason as the leader above: the arming press left
|
|
78
|
+
* the frame identical to the idle frame, so the operator had no way to learn
|
|
79
|
+
* that a second press quits, and no way to tell the first press registered.
|
|
80
|
+
*/
|
|
81
|
+
shutdownArmed?: boolean;
|
|
82
|
+
/** Proactive-memory status; kept as one atomic fact row in the expanded dashboard. */
|
|
83
|
+
memoryIntervention?: {
|
|
84
|
+
enabled: boolean;
|
|
85
|
+
tier: "rules" | "llm";
|
|
86
|
+
size: number;
|
|
87
|
+
stepInFlight?: boolean;
|
|
88
|
+
lastDecision?: string | null;
|
|
89
|
+
} | null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Context engine telemetry. */
|
|
93
|
+
export interface ContextEngineFacts {
|
|
94
|
+
label: string | null;
|
|
95
|
+
used: number | null;
|
|
96
|
+
contextWindow: number | null;
|
|
97
|
+
toolSchemaTokens: number | null;
|
|
98
|
+
compactionThreshold: number | null;
|
|
99
|
+
compactionAuto: boolean | null;
|
|
100
|
+
compactionActive?: boolean;
|
|
101
|
+
clioMd: string | null;
|
|
102
|
+
memory: string | null;
|
|
103
|
+
extensions: { active: number; installed: number } | null;
|
|
104
|
+
breakdown?: ContextUsageBreakdown | null;
|
|
105
|
+
/** Full categorized ledger; when present the quadrant renders the richer meter. */
|
|
106
|
+
ledger?: ContextLedger | null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Dynamic agent work: the live action quadrant. */
|
|
110
|
+
export interface AgentWorkFacts {
|
|
111
|
+
statusText: string | null;
|
|
112
|
+
dispatchSummary: string | null;
|
|
113
|
+
toolTally: string;
|
|
114
|
+
dispatchRows: ReadonlyArray<DispatchBoardRow>;
|
|
115
|
+
contextActivity?: {
|
|
116
|
+
message: string;
|
|
117
|
+
detail: string | null;
|
|
118
|
+
status: "started" | "running" | "completed" | "failed";
|
|
119
|
+
} | null;
|
|
120
|
+
/** Metrics for the most recent completed turn, surfaced when the agent is idle. */
|
|
121
|
+
lastTurn: TurnSummary | null;
|
|
122
|
+
/** Session task board declared through the tasks tool; null before any plan. */
|
|
123
|
+
taskBoard?: TaskBoardSnapshot | null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Responsive bands for the expanded footer. */
|
|
127
|
+
export const EXPANDED_WIDE = 80;
|
|
128
|
+
export const EXPANDED_MID = 70;
|
|
129
|
+
export const EXPANDED_ULTRAWIDE = 120;
|
|
130
|
+
|
|
131
|
+
/** Compact footer shows the git section only when there is room for it. */
|
|
132
|
+
const COMPACT_GIT_MIN_WIDTH = 72;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The `visibleWidth` guard looks redundant against `truncateToWidth`, which
|
|
136
|
+
* measures internally, but it is not: dropping it pads wide-char truncations
|
|
137
|
+
* with a trailing space and strips a bare ANSI reset at width 0. Both are
|
|
138
|
+
* visible output, so the extra measurement stays.
|
|
139
|
+
*/
|
|
140
|
+
export function fitDashboardLine(line: string, width: number): string {
|
|
141
|
+
return visibleWidth(line) > width ? truncateToWidth(line, width, "…", true) : line;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Pad or truncate an already styled string to an exact column width. A cut is
|
|
146
|
+
* marked with an ellipsis so a clipped value ("proj 1.", "read 14 · bash 9 ")
|
|
147
|
+
* never reads as a complete fact.
|
|
148
|
+
*/
|
|
149
|
+
function cell(text: string, width: number): string {
|
|
150
|
+
const safe = Math.max(0, width);
|
|
151
|
+
const clipped = truncateToWidth(text, safe, "…", true);
|
|
152
|
+
return `${clipped}${" ".repeat(Math.max(0, safe - visibleWidth(clipped)))}`;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function joinColumns(left: string, right: string, width: number): string {
|
|
156
|
+
const safe = Math.max(0, Math.floor(width));
|
|
157
|
+
if (safe === 0) return "";
|
|
158
|
+
if (visibleWidth(right) === 0) return cell(left, safe);
|
|
159
|
+
const rightWidth = visibleWidth(right);
|
|
160
|
+
if (rightWidth >= safe) return cell(right, safe);
|
|
161
|
+
const leftBudget = Math.max(0, safe - rightWidth - 1);
|
|
162
|
+
const fittedLeft = visibleWidth(left) > leftBudget ? truncateToWidth(left, leftBudget, "…", true) : left;
|
|
163
|
+
const gap = Math.max(1, safe - visibleWidth(fittedLeft) - rightWidth);
|
|
164
|
+
return cell(`${fittedLeft}${" ".repeat(gap)}${right}`, safe);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function finiteNonNegative(value: number | null | undefined): number {
|
|
168
|
+
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* The tools row answers two different questions and used to answer only the
|
|
173
|
+
* second: what the model can reach, and what it has called. `registered` is the
|
|
174
|
+
* count of tool schemas sent to the provider this turn, so a session that has
|
|
175
|
+
* only dispatched still reports the tools it holds instead of reading "none",
|
|
176
|
+
* which said the model had no tools at all.
|
|
177
|
+
*/
|
|
178
|
+
export function formatToolTally(snapshot: ToolTallySnapshot | null | undefined, registered?: number | null): string {
|
|
179
|
+
const available =
|
|
180
|
+
typeof registered === "number" && Number.isFinite(registered) && registered > 0
|
|
181
|
+
? `${Math.floor(registered)} avail`
|
|
182
|
+
: null;
|
|
183
|
+
if (!snapshot) return `${available ?? "none"} · 0${GLYPH.error}`;
|
|
184
|
+
const entries = Object.entries(snapshot.tools)
|
|
185
|
+
.filter(([name, count]) => count > 0 && name.toLowerCase() !== "dispatch")
|
|
186
|
+
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
|
187
|
+
.slice(0, 4)
|
|
188
|
+
.map(([name, count]) => `${name} ${formatFooterTokens(count)}`);
|
|
189
|
+
const called = entries.length > 0 ? entries.join(" · ") : available !== null ? null : "none";
|
|
190
|
+
const prefix = [available, called].filter((part): part is string => part !== null).join(" · ");
|
|
191
|
+
const active =
|
|
192
|
+
typeof snapshot.active === "number" && snapshot.active > 0 ? ` · active ${formatFooterTokens(snapshot.active)}` : "";
|
|
193
|
+
const truncated =
|
|
194
|
+
typeof snapshot.truncatedResults === "number" && snapshot.truncatedResults > 0
|
|
195
|
+
? ` · trunc ${formatFooterTokens(snapshot.truncatedResults)}`
|
|
196
|
+
: "";
|
|
197
|
+
return `${prefix}${active}${truncated} · ${formatFooterTokens(snapshot.errors)}${GLYPH.error}`;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function formatUsd(value: number): string {
|
|
201
|
+
if (!Number.isFinite(value) || value <= 0) return "$0.00";
|
|
202
|
+
if (value < 0.01) return `$${value.toFixed(4)}`;
|
|
203
|
+
return `$${value.toFixed(2)}`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function gitMarker(theme: ClioTheme, dirty: boolean | null): string {
|
|
207
|
+
if (dirty === false) return theme.fg("success", "✓");
|
|
208
|
+
if (dirty === true) return theme.fg("warning", "!");
|
|
209
|
+
return theme.fg("dim", "?");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Git chip carrying a `git` label so a version-shaped branch never reads as a duplicate version. */
|
|
213
|
+
function gitChip(theme: ClioTheme, branch: string | null, dirty: boolean | null): string | null {
|
|
214
|
+
if (!branch) return null;
|
|
215
|
+
return `${theme.fg("dim", "git ")}${theme.fg("success", branch)} ${gitMarker(theme, dirty)}`;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function gitValue(theme: ClioTheme, branch: string | null, dirty: boolean | null): string | null {
|
|
219
|
+
if (!branch) return null;
|
|
220
|
+
return `${theme.fg("success", branch)} ${gitMarker(theme, dirty)}`;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** `github.com/owner/repo` → `owner/repo`; otherwise the host or the raw value, trimmed. */
|
|
224
|
+
function collapseRemote(remote: string | null): string | null {
|
|
225
|
+
if (!remote) return null;
|
|
226
|
+
const cleaned = remote
|
|
227
|
+
.replace(/^git@/, "")
|
|
228
|
+
.replace(/^[a-z]+:\/\//, "")
|
|
229
|
+
.replace(/\.git$/, "");
|
|
230
|
+
const parts = cleaned.split(/[/:]/).filter(Boolean);
|
|
231
|
+
if (parts.length >= 2) return parts.slice(-2).join("/");
|
|
232
|
+
return parts[0] ?? null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Compact primary row: workspace identity on the left and a meaningful work
|
|
237
|
+
* phase on the right. The editor rail owns model and thinking labels. The
|
|
238
|
+
* branch appears here, and only here, across the whole screen.
|
|
239
|
+
*/
|
|
240
|
+
export function compactPrimaryLine(
|
|
241
|
+
workspace: WorkspaceFacts,
|
|
242
|
+
_session: SessionFacts,
|
|
243
|
+
width: number,
|
|
244
|
+
theme: ClioTheme = clioTheme(),
|
|
245
|
+
status: AgentStatus = {
|
|
246
|
+
phase: "idle",
|
|
247
|
+
since: 0,
|
|
248
|
+
lastMeaningfulAt: 0,
|
|
249
|
+
watchdogTier: 0,
|
|
250
|
+
watchdogPeak: 0,
|
|
251
|
+
localRuntime: false,
|
|
252
|
+
},
|
|
253
|
+
toolCounts: ToolTallySnapshot = { tools: {}, errors: 0 },
|
|
254
|
+
dispatchRows: ReadonlyArray<DispatchBoardRow> = [],
|
|
255
|
+
tick = 0,
|
|
256
|
+
now = Date.now(),
|
|
257
|
+
): string {
|
|
258
|
+
const safeWidth = Math.max(1, Math.floor(width));
|
|
259
|
+
let git = safeWidth >= COMPACT_GIT_MIN_WIDTH ? gitChip(theme, workspace.branch, workspace.dirty) : null;
|
|
260
|
+
let right = buildHarnessStatePill(theme, status, toolCounts, dispatchRows, tick, now, safeWidth, true);
|
|
261
|
+
let left = joinSections(theme, [theme.fg("muted", workspace.cwd), git]);
|
|
262
|
+
|
|
263
|
+
if (visibleWidth(left) + 1 + visibleWidth(right) > safeWidth) {
|
|
264
|
+
right = buildHarnessStatePill(theme, status, toolCounts, dispatchRows, tick, now, safeWidth, false);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (git && visibleWidth(left) + 1 + visibleWidth(right) > safeWidth) {
|
|
268
|
+
git = null;
|
|
269
|
+
left = theme.fg("muted", workspace.cwd);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (visibleWidth(left) + 1 + visibleWidth(right) > safeWidth) {
|
|
273
|
+
const maxCwdWidth = Math.max(1, safeWidth - visibleWidth(right) - 1);
|
|
274
|
+
left = theme.fg("muted", truncateToWidth(workspace.cwd, maxCwdWidth, "…", true));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return joinColumns(left, right, safeWidth);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Compact secondary row: context fill + the single most important activity on
|
|
282
|
+
* the left, dispatch summary + tool tally on the right.
|
|
283
|
+
*/
|
|
284
|
+
function compactMetricChipLimit(width: number): number {
|
|
285
|
+
if (width < 48) return 1;
|
|
286
|
+
if (width < 72) return 2;
|
|
287
|
+
if (width < 100) return 4;
|
|
288
|
+
return 6;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function contextBarCellBounds(width: number): { min: number; max: number } {
|
|
292
|
+
if (width < 48) return { min: 6, max: 6 };
|
|
293
|
+
if (width < 72) return { min: 8, max: 8 };
|
|
294
|
+
if (width < 100) return { min: 12, max: 12 };
|
|
295
|
+
return { min: 14, max: 16 };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function compactContextBarWidth(width: number): number {
|
|
299
|
+
const bounds = contextBarCellBounds(width);
|
|
300
|
+
const leftHalfBudget = Math.max(0, Math.floor(width / 2));
|
|
301
|
+
const budgetCells = Math.max(0, leftHalfBudget - CONTEXT_BAR_LABEL_WIDTH);
|
|
302
|
+
const wideScale = width >= 100 ? 14 + Math.min(2, Math.max(0, Math.floor((width - 100) / 10))) : bounds.max;
|
|
303
|
+
return Math.max(bounds.min, Math.min(bounds.max, budgetCells, wideScale));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function contextBreakdownForBar(context: ContextEngineFacts): ContextUsageBreakdown | undefined {
|
|
307
|
+
const reportedUsed = finiteNonNegative(context.used);
|
|
308
|
+
const toolTokens = finiteNonNegative(context.toolSchemaTokens);
|
|
309
|
+
const source = context.breakdown;
|
|
310
|
+
if (!source) {
|
|
311
|
+
if (reportedUsed <= 0 && toolTokens <= 0) return undefined;
|
|
312
|
+
return {
|
|
313
|
+
systemPromptTokens: 0,
|
|
314
|
+
toolSchemaTokens: Math.min(toolTokens, reportedUsed),
|
|
315
|
+
messageTokens: Math.max(0, reportedUsed - toolTokens),
|
|
316
|
+
pendingUserTokens: 0,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
const system = finiteNonNegative(source.systemPromptTokens);
|
|
320
|
+
const tools = finiteNonNegative(source.toolSchemaTokens);
|
|
321
|
+
const conversation = finiteNonNegative(source.messageTokens) + finiteNonNegative(source.pendingUserTokens);
|
|
322
|
+
const total = system + tools + conversation;
|
|
323
|
+
if (reportedUsed <= 0 || total <= 0) {
|
|
324
|
+
return {
|
|
325
|
+
systemPromptTokens: system,
|
|
326
|
+
toolSchemaTokens: tools,
|
|
327
|
+
messageTokens: conversation,
|
|
328
|
+
pendingUserTokens: 0,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
if (reportedUsed >= total) {
|
|
332
|
+
return {
|
|
333
|
+
systemPromptTokens: system,
|
|
334
|
+
toolSchemaTokens: tools,
|
|
335
|
+
messageTokens: conversation + (reportedUsed - total),
|
|
336
|
+
pendingUserTokens: 0,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
const scale = reportedUsed / total;
|
|
340
|
+
return {
|
|
341
|
+
systemPromptTokens: system * scale,
|
|
342
|
+
toolSchemaTokens: tools * scale,
|
|
343
|
+
messageTokens: conversation * scale,
|
|
344
|
+
pendingUserTokens: 0,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function contextComposition(context: ContextEngineFacts): {
|
|
349
|
+
system: number;
|
|
350
|
+
tools: number;
|
|
351
|
+
chat: number;
|
|
352
|
+
free: number | null;
|
|
353
|
+
} {
|
|
354
|
+
const used = finiteNonNegative(context.used);
|
|
355
|
+
const window = finiteNonNegative(context.contextWindow);
|
|
356
|
+
const breakdown = contextBreakdownForBar(context);
|
|
357
|
+
return {
|
|
358
|
+
system: finiteNonNegative(breakdown?.systemPromptTokens),
|
|
359
|
+
tools: finiteNonNegative(breakdown?.toolSchemaTokens),
|
|
360
|
+
chat: finiteNonNegative(breakdown?.messageTokens) + finiteNonNegative(breakdown?.pendingUserTokens),
|
|
361
|
+
free: window > 0 ? Math.max(0, window - used) : null,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export function compactSecondaryLine(
|
|
366
|
+
context: ContextEngineFacts,
|
|
367
|
+
agent: AgentWorkFacts,
|
|
368
|
+
width: number,
|
|
369
|
+
theme: ClioTheme = clioTheme(),
|
|
370
|
+
status: AgentStatus = {
|
|
371
|
+
phase: "idle",
|
|
372
|
+
since: 0,
|
|
373
|
+
lastMeaningfulAt: 0,
|
|
374
|
+
watchdogTier: 0,
|
|
375
|
+
watchdogPeak: 0,
|
|
376
|
+
localRuntime: false,
|
|
377
|
+
},
|
|
378
|
+
throughput: TokenThroughputSnapshot | null = null,
|
|
379
|
+
sessionTokens: UsageBreakdown | null = null,
|
|
380
|
+
sessionCost: CostAggregate | null = null,
|
|
381
|
+
outputVerbosity?: OutputVerbosity | null,
|
|
382
|
+
leaderArmed = false,
|
|
383
|
+
shutdownArmed = false,
|
|
384
|
+
): string {
|
|
385
|
+
const safeWidth = Math.max(1, Math.floor(width));
|
|
386
|
+
const barCells = compactContextBarWidth(safeWidth);
|
|
387
|
+
let left = "";
|
|
388
|
+
if (context.ledger) {
|
|
389
|
+
// The row follows the kv grammar: dim key, muted value. An unmeasured
|
|
390
|
+
// percent renders the ?% placeholder dim because it is scaffolding for a
|
|
391
|
+
// number that has not arrived, not a measurement.
|
|
392
|
+
const percent = theme.fg(
|
|
393
|
+
context.ledger.percent !== null ? "muted" : "dim",
|
|
394
|
+
formatContextPercent(context.ledger.percent),
|
|
395
|
+
);
|
|
396
|
+
left = `${theme.fg("dim", "ctx")} ${renderContextMeterBar(context.ledger, barCells, theme)} ${percent}`;
|
|
397
|
+
} else {
|
|
398
|
+
left = buildSegmentedContextBar(theme, barCells, context.contextWindow ?? 0, contextBreakdownForBar(context));
|
|
399
|
+
}
|
|
400
|
+
const maxRightWidth = Math.max(0, safeWidth - visibleWidth(left) - 1);
|
|
401
|
+
const right = buildMetricStrip(
|
|
402
|
+
theme,
|
|
403
|
+
status,
|
|
404
|
+
throughput,
|
|
405
|
+
agent.lastTurn,
|
|
406
|
+
sessionTokens,
|
|
407
|
+
sessionCost,
|
|
408
|
+
context.used ?? undefined,
|
|
409
|
+
maxRightWidth,
|
|
410
|
+
compactMetricChipLimit(safeWidth),
|
|
411
|
+
outputVerbosity,
|
|
412
|
+
leaderArmed,
|
|
413
|
+
shutdownArmed,
|
|
414
|
+
);
|
|
415
|
+
// At the smallest widths the context meter consumes the entire secondary
|
|
416
|
+
// row, so keep a compact mode marker on the left instead of silently hiding
|
|
417
|
+
// the active transcript setting.
|
|
418
|
+
if (outputVerbosity && outputVerbosity !== "default" && visibleWidth(right) === 0) {
|
|
419
|
+
const marker = outputVerbosity === "minimal" ? "m" : outputVerbosity === "verbose" ? "v" : "d";
|
|
420
|
+
left = `${left}${theme.fg("dim", ` out:${marker}`)}`;
|
|
421
|
+
}
|
|
422
|
+
return joinColumns(left, right, safeWidth);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
type DashboardRow =
|
|
426
|
+
| { kind: "kv"; key: string; value: string | null | undefined; valueToken?: ClioToken; styled?: boolean }
|
|
427
|
+
| { kind: "status"; value: string | null | undefined }
|
|
428
|
+
| { kind: "legend"; value: string | null | undefined };
|
|
429
|
+
|
|
430
|
+
interface ExpandedQuadrantOptions {
|
|
431
|
+
width?: number;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function renderDashboardRow(theme: ClioTheme, row: DashboardRow, keyWidth: number): string | null {
|
|
435
|
+
if (!row.value) return null;
|
|
436
|
+
if (row.kind !== "kv") return row.value;
|
|
437
|
+
const key = theme.fg("dim", `${row.key.padEnd(keyWidth)} `);
|
|
438
|
+
const value = row.styled ? row.value : theme.fg(row.valueToken ?? "muted", row.value);
|
|
439
|
+
return `${key}${value}`;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function dashboardBlock(theme: ClioTheme, label: string, rows: ReadonlyArray<DashboardRow>): string[] {
|
|
443
|
+
const keyWidth = rows.reduce((max, row) => (row.kind === "kv" ? Math.max(max, row.key.length) : max), 0);
|
|
444
|
+
const body = rows
|
|
445
|
+
.map((row) => renderDashboardRow(theme, row, keyWidth))
|
|
446
|
+
.filter((row): row is string => typeof row === "string" && row.length > 0);
|
|
447
|
+
// Every quadrant tag shares one structure color. The tag names the quadrant;
|
|
448
|
+
// the color is not a per-quadrant signal, so all four render bold accentDeep
|
|
449
|
+
// rather than the old info/accent/reason/success carnival.
|
|
450
|
+
return [sectionTag(theme, "accentDeep", label.toUpperCase(), 0), ...body];
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function kv(key: string, value: string | null | undefined, valueToken: ClioToken = "muted"): DashboardRow {
|
|
454
|
+
return { kind: "kv", key, value, valueToken };
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function styledKv(key: string, value: string | null | undefined): DashboardRow {
|
|
458
|
+
return { kind: "kv", key, value, styled: true };
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function statusRow(value: string | null | undefined): DashboardRow {
|
|
462
|
+
return { kind: "status", value };
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function legendRow(value: string | null | undefined): DashboardRow {
|
|
466
|
+
return { kind: "legend", value };
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export function workspaceQuadrant(facts: WorkspaceFacts, _options: ExpandedQuadrantOptions = {}): string[] {
|
|
470
|
+
const theme = clioTheme();
|
|
471
|
+
const remote = collapseRemote(facts.remote);
|
|
472
|
+
return dashboardBlock(theme, "Workspace", [
|
|
473
|
+
kv("cwd", facts.cwd),
|
|
474
|
+
styledKv("git", gitValue(theme, facts.branch, facts.dirty)),
|
|
475
|
+
kv("type", facts.projectType),
|
|
476
|
+
kv("remote", remote),
|
|
477
|
+
]);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function sessionIdentity(facts: SessionFacts): { key: string; value: string } | null {
|
|
481
|
+
if (facts.id) return { key: "id", value: facts.id };
|
|
482
|
+
if (facts.name) return { key: "name", value: facts.name };
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function capabilitiesValue(theme: ClioTheme, capabilities: string[] | null): string | null {
|
|
487
|
+
if (!capabilities || capabilities.length === 0) return null;
|
|
488
|
+
return joinChips(
|
|
489
|
+
theme,
|
|
490
|
+
capabilities.map((capability) => theme.fg("muted", capability)),
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export function sessionQuadrant(facts: SessionFacts, options: ExpandedQuadrantOptions = {}): string[] {
|
|
495
|
+
const theme = clioTheme();
|
|
496
|
+
const identity = sessionIdentity(facts);
|
|
497
|
+
const memory = facts.memoryIntervention;
|
|
498
|
+
const memoryValue = memory
|
|
499
|
+
? fitUnits(
|
|
500
|
+
theme,
|
|
501
|
+
"",
|
|
502
|
+
[
|
|
503
|
+
theme.fg(memory.enabled ? "success" : "dim", memory.enabled ? "on" : "off"),
|
|
504
|
+
theme.fg(memory.tier === "llm" ? "reason" : "muted", `tier ${memory.tier === "llm" ? "LLM" : "rules"}`),
|
|
505
|
+
theme.fg("muted", `bank ${memory.size}`),
|
|
506
|
+
// A background step runs for tens of seconds on a small local model.
|
|
507
|
+
// Saying so is the difference between a quiet feature and a dead one.
|
|
508
|
+
...(memory.stepInFlight ? [theme.fg("reason", "working")] : []),
|
|
509
|
+
...(memory.lastDecision ? [theme.fg("dim", memory.lastDecision)] : []),
|
|
510
|
+
],
|
|
511
|
+
Math.max(1, (options.width ?? Number.POSITIVE_INFINITY) - 9),
|
|
512
|
+
)
|
|
513
|
+
: null;
|
|
514
|
+
return dashboardBlock(theme, "Session", [
|
|
515
|
+
identity ? kv(identity.key, identity.value, "accent") : statusRow(null),
|
|
516
|
+
kv("target", facts.target, "accent"),
|
|
517
|
+
kv("think", facts.thinking, "reason"),
|
|
518
|
+
styledKv("caps", capabilitiesValue(theme, facts.capabilities)),
|
|
519
|
+
// accentDeep is a structure color reserved for the section tag; the autonomy
|
|
520
|
+
// value is a plain fact and reads muted like the other neutral values.
|
|
521
|
+
kv("autonomy", facts.safety),
|
|
522
|
+
kv("profile", facts.toolProfile),
|
|
523
|
+
kv(
|
|
524
|
+
"output",
|
|
525
|
+
facts.outputVerbosity && facts.outputVerbosity !== "default" ? facts.outputVerbosity : null,
|
|
526
|
+
facts.outputVerbosity === "verbose" ? "accent" : "muted",
|
|
527
|
+
),
|
|
528
|
+
styledKv("memory", memoryValue),
|
|
529
|
+
]);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function expandedContextBarCells(width: number | undefined): number {
|
|
533
|
+
if (typeof width !== "number" || !Number.isFinite(width) || width <= 0) return 12;
|
|
534
|
+
const budget = Math.max(6, Math.floor(width) - CONTEXT_BAR_LABEL_WIDTH - 1);
|
|
535
|
+
// A wider quadrant earns a finer meter: every extra cell is real resolution,
|
|
536
|
+
// up to 24 cells so the bar never dwarfs the facts beneath it.
|
|
537
|
+
const desired = width >= 48 ? 24 : width >= 36 ? 16 : width >= 32 ? 14 : 12;
|
|
538
|
+
return Math.max(8, Math.min(24, desired, budget));
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function formatUsedWindow(used: number | null, contextWindow: number | null): string | null {
|
|
542
|
+
if (used === null || !contextWindow) return null;
|
|
543
|
+
return `${formatFooterTokens(used)} / ${formatFooterTokens(contextWindow)}`;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function formatCompaction(facts: ContextEngineFacts): string | null {
|
|
547
|
+
if (facts.compactionThreshold === null) return null;
|
|
548
|
+
const mode = facts.compactionAuto ? "auto" : "manual";
|
|
549
|
+
const threshold = Math.round(facts.compactionThreshold * 100);
|
|
550
|
+
return `${facts.compactionActive ? "active " : ""}${mode} @${threshold}%`;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function sourceState(theme: ClioTheme, facts: ContextEngineFacts): string | null {
|
|
554
|
+
const value = joinChips(theme, [
|
|
555
|
+
facts.clioMd ? theme.fg("muted", facts.clioMd) : null,
|
|
556
|
+
facts.memory ? theme.fg("muted", facts.memory) : null,
|
|
557
|
+
]);
|
|
558
|
+
return value.length > 0 ? value : null;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/** Short labels for the dense footer; the overlay carries the full names. */
|
|
562
|
+
const CONTEXT_SHORT_LABEL: Readonly<Record<ContextLedgerCategory, string>> = {
|
|
563
|
+
system: "sys",
|
|
564
|
+
tools: "tools",
|
|
565
|
+
agents: "agt",
|
|
566
|
+
skills: "skl",
|
|
567
|
+
memory: "mem",
|
|
568
|
+
project: "proj",
|
|
569
|
+
messages: "chat",
|
|
570
|
+
pending: "input",
|
|
571
|
+
reserve: "rsv",
|
|
572
|
+
free: "free",
|
|
573
|
+
streaming: "stream",
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
/** Static-side cost chips (system prompt, tools, agents, skills, memory, project), heaviest first. */
|
|
577
|
+
function ledgerSystemChips(theme: ClioTheme, ledger: ContextLedger): string {
|
|
578
|
+
const statics = new Set<ContextLedgerCategory>(["system", "tools", "agents", "skills", "memory", "project"]);
|
|
579
|
+
const chips = ledger.groups
|
|
580
|
+
.filter((group) => statics.has(group.category))
|
|
581
|
+
.sort((a, b) => b.tokens - a.tokens)
|
|
582
|
+
.slice(0, 4)
|
|
583
|
+
.map((group) =>
|
|
584
|
+
theme.fg(
|
|
585
|
+
CONTEXT_CATEGORY_TOKEN[group.category],
|
|
586
|
+
`${CONTEXT_SHORT_LABEL[group.category]} ${formatFooterTokens(group.tokens)}`,
|
|
587
|
+
),
|
|
588
|
+
);
|
|
589
|
+
return joinChips(theme, chips);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/** Conversation, autocompact reserve, and free-space chips. */
|
|
593
|
+
function ledgerChatChips(theme: ClioTheme, ledger: ContextLedger): string {
|
|
594
|
+
const chat = ledger.groups.find((group) => group.category === "messages")?.tokens ?? 0;
|
|
595
|
+
return joinChips(theme, [
|
|
596
|
+
theme.fg("accent", `chat ${formatFooterTokens(chat)}`),
|
|
597
|
+
ledger.reserveTokens > 0 ? theme.fg("dim", `rsv ${formatFooterTokens(ledger.reserveTokens)}`) : null,
|
|
598
|
+
ledger.contextWindow > 0
|
|
599
|
+
? theme.style("frame", `free ${formatFooterTokens(ledger.freeTokens)}`, { dim: true })
|
|
600
|
+
: null,
|
|
601
|
+
]);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Swatch legend covering exactly the categories present in the meter, packed
|
|
606
|
+
* into as many rows as the quadrant needs. A ledger can carry ten categories,
|
|
607
|
+
* more than one quadrant row holds, and dropping tail entries would hide
|
|
608
|
+
* whole categories, so the legend wraps by whole chips instead of clipping.
|
|
609
|
+
*/
|
|
610
|
+
function ledgerLegendRows(theme: ClioTheme, ledger: ContextLedger, width: number | undefined): string[] {
|
|
611
|
+
const chips = ledger.meter.map((group) => {
|
|
612
|
+
const labelToken: ClioToken = group.category === "free" || group.category === "reserve" ? "dim" : "muted";
|
|
613
|
+
return `${contextCategorySwatch(group.category, theme)} ${theme.fg(labelToken, CONTEXT_SHORT_LABEL[group.category])}`;
|
|
614
|
+
});
|
|
615
|
+
const budget =
|
|
616
|
+
typeof width === "number" && Number.isFinite(width) && width > 0 ? Math.floor(width) : Number.POSITIVE_INFINITY;
|
|
617
|
+
const rows: string[] = [];
|
|
618
|
+
let current = "";
|
|
619
|
+
for (const chip of chips) {
|
|
620
|
+
const candidate = current.length > 0 ? `${current} ${chip}` : chip;
|
|
621
|
+
if (current.length > 0 && visibleWidth(candidate) > budget) {
|
|
622
|
+
rows.push(current);
|
|
623
|
+
current = chip;
|
|
624
|
+
} else {
|
|
625
|
+
current = candidate;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
if (current.length > 0) rows.push(current);
|
|
629
|
+
return rows;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function ledgerBar(theme: ClioTheme, ledger: ContextLedger, cells: number): string {
|
|
633
|
+
const percent = theme.fg(ledger.percent !== null ? "muted" : "dim", formatContextPercent(ledger.percent));
|
|
634
|
+
return `${renderContextMeterBar(ledger, cells, theme)} ${percent}`;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
export function contextQuadrant(facts: ContextEngineFacts, options: ExpandedQuadrantOptions = {}): string[] {
|
|
638
|
+
const theme = clioTheme();
|
|
639
|
+
const ledger = facts.ledger ?? null;
|
|
640
|
+
const hasLedger = ledger !== null && ledger.contextWindow > 0;
|
|
641
|
+
const barCells = expandedContextBarCells(options.width);
|
|
642
|
+
|
|
643
|
+
let bar: string;
|
|
644
|
+
let fill: string;
|
|
645
|
+
let chatFree: string;
|
|
646
|
+
let legendRows: string[];
|
|
647
|
+
if (hasLedger && ledger) {
|
|
648
|
+
bar = ledgerBar(theme, ledger, barCells);
|
|
649
|
+
fill = ledgerSystemChips(theme, ledger);
|
|
650
|
+
chatFree = ledgerChatChips(theme, ledger);
|
|
651
|
+
legendRows = ledgerLegendRows(theme, ledger, options.width);
|
|
652
|
+
} else {
|
|
653
|
+
const composition = contextComposition(facts);
|
|
654
|
+
fill = joinChips(theme, [
|
|
655
|
+
composition.system > 0 ? theme.fg("info", `sys ${formatFooterTokens(composition.system)}`) : null,
|
|
656
|
+
composition.tools > 0 ? theme.fg("warning", `tools ${formatFooterTokens(composition.tools)}`) : null,
|
|
657
|
+
]);
|
|
658
|
+
chatFree = joinChips(theme, [
|
|
659
|
+
composition.chat > 0 ? theme.fg("accent", formatFooterTokens(composition.chat)) : null,
|
|
660
|
+
composition.free !== null
|
|
661
|
+
? theme.style("frame", `free ${formatFooterTokens(composition.free)}`, { dim: true })
|
|
662
|
+
: null,
|
|
663
|
+
]);
|
|
664
|
+
bar = buildSegmentedContextBar(theme, barCells, facts.contextWindow ?? 0, contextBreakdownForBar(facts));
|
|
665
|
+
const filledChar = visibleWidth(GLYPH.contextFull) === 1 ? GLYPH.contextFull : GLYPH.barFull;
|
|
666
|
+
const freeChar = visibleWidth(GLYPH.contextFree) === 1 ? GLYPH.contextFree : GLYPH.barEmpty;
|
|
667
|
+
legendRows = [
|
|
668
|
+
`${theme.fg("info", `${filledChar} sys`)} ${theme.fg("warning", `${filledChar} tools`)} ${theme.fg("accent", `${filledChar} chat`)} ${theme.style("frame", `${freeChar} free`, { dim: true })}`,
|
|
669
|
+
];
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const usedTokens = hasLedger && ledger ? ledger.usedTokens : facts.used;
|
|
673
|
+
const windowTokens = hasLedger && ledger ? ledger.contextWindow : facts.contextWindow;
|
|
674
|
+
return dashboardBlock(theme, "Context", [
|
|
675
|
+
statusRow(bar),
|
|
676
|
+
kv("used", formatUsedWindow(usedTokens, windowTokens)),
|
|
677
|
+
fill ? styledKv("fill", fill) : statusRow(null),
|
|
678
|
+
chatFree ? styledKv("chat", chatFree) : statusRow(null),
|
|
679
|
+
kv("compact", formatCompaction(facts)),
|
|
680
|
+
styledKv("source", sourceState(theme, facts)),
|
|
681
|
+
facts.extensions && facts.extensions.installed > 0
|
|
682
|
+
? kv("ext", `${facts.extensions.active}/${facts.extensions.installed}`)
|
|
683
|
+
: statusRow(null),
|
|
684
|
+
...legendRows.map((row) => legendRow(row)),
|
|
685
|
+
]);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
function stopReasonStyle(reason: TurnSummary["stopReason"]): { glyph: string; token: ClioToken } {
|
|
689
|
+
if (reason === "error") return { glyph: GLYPH.error, token: "error" };
|
|
690
|
+
if (reason === "aborted" || reason === "cancelled") return { glyph: GLYPH.cancelled, token: "dim" };
|
|
691
|
+
if (reason === "length") return { glyph: GLYPH.warn, token: "warning" };
|
|
692
|
+
return { glyph: GLYPH.ok, token: "success" };
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Elegant single-line readout of the most recent completed turn. This is the
|
|
697
|
+
* footer home for the metrics that used to print faintly under each assistant
|
|
698
|
+
* reply: stop outcome, wall time, token in/out, reasoning, and tool work. The
|
|
699
|
+
* model is intentionally omitted because the editor rail already carries it.
|
|
700
|
+
*/
|
|
701
|
+
export function formatLastTurn(theme: ClioTheme, summary: TurnSummary): string {
|
|
702
|
+
const stop = stopReasonStyle(summary.stopReason);
|
|
703
|
+
const parts: string[] = [
|
|
704
|
+
theme.fg(stop.token, `${stop.glyph} ${formatCompactMs(summary.elapsedMs)}`),
|
|
705
|
+
theme.fg("muted", `${GLYPH.up}${summary.inputTokens} ${GLYPH.down}${summary.outputTokens}`),
|
|
706
|
+
];
|
|
707
|
+
// Zero suppresses the chip, the same rule the chat panel's turn line follows:
|
|
708
|
+
// a turn that spent no reasoning tokens states nothing by printing `r0`.
|
|
709
|
+
if (typeof summary.reasoningTokens === "number" && summary.reasoningTokens > 0) {
|
|
710
|
+
const marker =
|
|
711
|
+
summary.reasoningTokenProvenance === "estimated" || summary.reasoningTokenProvenance === "mixed" ? "≈" : "";
|
|
712
|
+
parts.push(theme.fg("reason", `r${marker}${summary.reasoningTokens}`));
|
|
713
|
+
}
|
|
714
|
+
if (summary.cacheReadTokens > 0 || summary.cacheWriteTokens > 0) {
|
|
715
|
+
parts.push(theme.fg("dim", `cache ${summary.cacheReadTokens}/${summary.cacheWriteTokens}`));
|
|
716
|
+
}
|
|
717
|
+
if (summary.toolCount > 0) {
|
|
718
|
+
const label = `${summary.toolCount} tool${summary.toolCount === 1 ? "" : "s"}`;
|
|
719
|
+
const errors = summary.toolErrorCount > 0 ? theme.fg("error", ` ${summary.toolErrorCount}${GLYPH.error}`) : "";
|
|
720
|
+
parts.push(`${theme.fg("muted", label)}${errors}`);
|
|
721
|
+
}
|
|
722
|
+
if (summary.watchdogPeak >= 2) parts.push(theme.fg("warning", "slow"));
|
|
723
|
+
if (summary.truncated) parts.push(theme.fg("warning", "trunc"));
|
|
724
|
+
return parts.join(theme.fg("dim", " · "));
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* One row per live worker: the origin glyph, the sub-process glyph when Clio
|
|
729
|
+
* started the run for itself, the agent's own name, the fleet node it landed
|
|
730
|
+
* on, its status glyph, elapsed, and the receipt id once the run has sealed
|
|
731
|
+
* one. Units are fitted whole, so a narrow quadrant closes on a dim ellipsis
|
|
732
|
+
* rather than clipping a receipt id into a string that still reads like a valid
|
|
733
|
+
* trace argument.
|
|
734
|
+
*/
|
|
735
|
+
function workerLine(theme: ClioTheme, row: DispatchBoardRow, width: number): string {
|
|
736
|
+
const presentation = dispatchStatusPresentation(row.status, { compact: true });
|
|
737
|
+
// The Activity section already promotes the fleet summary (or dispatch phase)
|
|
738
|
+
// to action orange. Worker rows remain readable without repeating that signal.
|
|
739
|
+
const token = presentation.token === "action" ? "accent" : presentation.token;
|
|
740
|
+
const units = [
|
|
741
|
+
theme.fg("muted", agentDisplayLabel(row)),
|
|
742
|
+
theme.fg("dim", row.node ?? "local"),
|
|
743
|
+
theme.fg(token, presentation.glyph),
|
|
744
|
+
theme.fg("dim", formatCompactMs(row.elapsedMs)),
|
|
745
|
+
...(row.receiptId !== undefined ? [theme.fg("dim", row.receiptId)] : []),
|
|
746
|
+
];
|
|
747
|
+
return fitUnits(theme, dispatchRowPrefix(theme, row).text, units, Math.max(1, Math.floor(width)));
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
interface ActivityQuadrantOptions extends ExpandedQuadrantOptions {
|
|
751
|
+
status?: AgentStatus;
|
|
752
|
+
toolCounts?: ToolTallySnapshot;
|
|
753
|
+
throughput?: TokenThroughputSnapshot | null;
|
|
754
|
+
sessionTokens?: UsageBreakdown | null;
|
|
755
|
+
sessionCost?: CostAggregate | null;
|
|
756
|
+
contextUsed?: number | null;
|
|
757
|
+
tick?: number;
|
|
758
|
+
now?: number;
|
|
759
|
+
maxWorkers?: number;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
function defaultIdleStatus(): AgentStatus {
|
|
763
|
+
return {
|
|
764
|
+
phase: "idle",
|
|
765
|
+
since: 0,
|
|
766
|
+
lastMeaningfulAt: 0,
|
|
767
|
+
watchdogTier: 0,
|
|
768
|
+
watchdogPeak: 0,
|
|
769
|
+
localRuntime: false,
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
function formattedThroughput(theme: ClioTheme, throughput: TokenThroughputSnapshot | null | undefined): string | null {
|
|
774
|
+
const tps = finiteNonNegative(throughput?.tokensPerSecond);
|
|
775
|
+
if (tps <= 0) return null;
|
|
776
|
+
const rounded = tps >= 10 ? Math.round(tps) : Math.round(tps * 10) / 10;
|
|
777
|
+
const parts = [theme.fg("success", `${GLYPH.speed}${rounded}/s`)];
|
|
778
|
+
const ttft = finiteNonNegative(throughput?.ttftMs);
|
|
779
|
+
if (ttft > 0) parts.push(theme.fg("muted", `ttft ${formatCompactMs(ttft)}`));
|
|
780
|
+
return joinChips(theme, parts);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
function liveTokenValue(
|
|
784
|
+
theme: ClioTheme,
|
|
785
|
+
status: AgentStatus,
|
|
786
|
+
throughput: TokenThroughputSnapshot | null | undefined,
|
|
787
|
+
lastTurn: TurnSummary | null,
|
|
788
|
+
sessionTokens: UsageBreakdown | null | undefined,
|
|
789
|
+
contextUsed: number | null | undefined,
|
|
790
|
+
): string | null {
|
|
791
|
+
const output = finiteNonNegative(throughput?.outputTokens);
|
|
792
|
+
const input =
|
|
793
|
+
finiteNonNegative(contextUsed) ||
|
|
794
|
+
finiteNonNegative(status.summary?.inputTokens) ||
|
|
795
|
+
finiteNonNegative(lastTurn?.inputTokens) ||
|
|
796
|
+
finiteNonNegative(sessionTokens?.input);
|
|
797
|
+
const parts = [
|
|
798
|
+
output > 0 ? theme.fg("success", `${GLYPH.down}${formatFooterTokens(output)}`) : null,
|
|
799
|
+
input > 0 ? theme.fg("muted", `${GLYPH.up}${formatFooterTokens(input)}`) : null,
|
|
800
|
+
];
|
|
801
|
+
const joined = joinChips(theme, parts);
|
|
802
|
+
return joined.length > 0 ? joined : null;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
function lastTurnOutcome(theme: ClioTheme, lastTurn: TurnSummary): string {
|
|
806
|
+
const stop = stopReasonStyle(lastTurn.stopReason);
|
|
807
|
+
return theme.fg(stop.token, `${stop.glyph} ${formatCompactMs(lastTurn.elapsedMs)}`);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
function lastTurnDetails(theme: ClioTheme, lastTurn: TurnSummary): string {
|
|
811
|
+
const parts: Array<string | null> = [
|
|
812
|
+
theme.fg(
|
|
813
|
+
"muted",
|
|
814
|
+
`${GLYPH.up}${formatFooterTokens(lastTurn.inputTokens)} ${GLYPH.down}${formatFooterTokens(lastTurn.outputTokens)}`,
|
|
815
|
+
),
|
|
816
|
+
lastTurn.reasoningTokens !== undefined && lastTurn.reasoningTokens > 0
|
|
817
|
+
? theme.fg(
|
|
818
|
+
"reason",
|
|
819
|
+
`r${lastTurn.reasoningTokenProvenance === "estimated" || lastTurn.reasoningTokenProvenance === "mixed" ? "≈" : ""}${formatFooterTokens(lastTurn.reasoningTokens)}`,
|
|
820
|
+
)
|
|
821
|
+
: null,
|
|
822
|
+
lastTurn.cacheReadTokens > 0 || lastTurn.cacheWriteTokens > 0
|
|
823
|
+
? theme.fg(
|
|
824
|
+
"dim",
|
|
825
|
+
`cache ${formatFooterTokens(lastTurn.cacheReadTokens)}/${formatFooterTokens(lastTurn.cacheWriteTokens)}`,
|
|
826
|
+
)
|
|
827
|
+
: null,
|
|
828
|
+
];
|
|
829
|
+
if (lastTurn.toolCount > 0) {
|
|
830
|
+
const label = `${lastTurn.toolCount} tool${lastTurn.toolCount === 1 ? "" : "s"}`;
|
|
831
|
+
const errors = lastTurn.toolErrorCount > 0 ? theme.fg("error", ` ${lastTurn.toolErrorCount}${GLYPH.error}`) : "";
|
|
832
|
+
parts.push(`${theme.fg("muted", label)}${errors}`);
|
|
833
|
+
}
|
|
834
|
+
if (lastTurn.watchdogPeak >= 2) parts.push(theme.fg("warning", "slow"));
|
|
835
|
+
if (lastTurn.truncated) parts.push(theme.fg("warning", "trunc"));
|
|
836
|
+
return joinChips(theme, parts);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
function cumulativeTokens(sessionTokens: UsageBreakdown | null | undefined): number {
|
|
840
|
+
const fallback = finiteNonNegative(sessionTokens?.input) + finiteNonNegative(sessionTokens?.output);
|
|
841
|
+
return finiteNonNegative(sessionTokens?.totalTokens) || fallback;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
function fleetValue(dispatchSummary: string | null, dispatchRows: ReadonlyArray<DispatchBoardRow>): string | null {
|
|
845
|
+
if (dispatchSummary) return dispatchSummary.replace(/^dispatch\s+/, "");
|
|
846
|
+
return dispatchRows.length > 0 ? `${dispatchRows.length} runs` : null;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
function meaningfulToolTally(value: string): string | null {
|
|
850
|
+
return /^(?:none(?: · 0✗)?|0✗)$/u.test(value.trim()) ? null : value;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
/** Task-board progress chips: `2/5 done`, with a warning chip when tasks are blocked. */
|
|
854
|
+
function taskBoardValue(theme: ClioTheme, board: TaskBoardSnapshot): string {
|
|
855
|
+
const counts = taskBoardCounts(board);
|
|
856
|
+
const progress = theme.fg(counts.open > 0 ? "muted" : "success", `${counts.completed}/${counts.total} done`);
|
|
857
|
+
const blocked = counts.blocked > 0 ? theme.fg("warning", `${counts.blocked} blocked`) : null;
|
|
858
|
+
return joinChips(theme, [progress, blocked]);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/** The board's current focus: the single active task, glyph-led like a worker row. */
|
|
862
|
+
function activeTaskLine(theme: ClioTheme, board: TaskBoardSnapshot): string | null {
|
|
863
|
+
const active = board.tasks.find((task) => task.status === "active");
|
|
864
|
+
if (!active) return null;
|
|
865
|
+
return `${theme.fg("accent", GLYPH.running)} ${theme.fg("dim", active.id)} ${theme.fg("muted", active.title)}`;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
export function activityQuadrant(facts: AgentWorkFacts, options: ActivityQuadrantOptions = {}): string[] {
|
|
869
|
+
const theme = clioTheme();
|
|
870
|
+
const maxWorkers = Math.max(0, options.maxWorkers ?? 3);
|
|
871
|
+
const status = options.status ?? defaultIdleStatus();
|
|
872
|
+
const toolCounts = options.toolCounts ?? { tools: {}, errors: 0 };
|
|
873
|
+
const statusWidth = Math.max(options.width ?? 120, 48);
|
|
874
|
+
const isStreaming = status.phase !== "idle" && status.phase !== "ended";
|
|
875
|
+
const fleetSummaryIsAction = facts.dispatchSummary !== null && status.phase !== "dispatching";
|
|
876
|
+
const rows: DashboardRow[] = [
|
|
877
|
+
statusRow(
|
|
878
|
+
buildHarnessStatePill(
|
|
879
|
+
theme,
|
|
880
|
+
status,
|
|
881
|
+
toolCounts,
|
|
882
|
+
facts.dispatchRows,
|
|
883
|
+
options.tick ?? 0,
|
|
884
|
+
options.now ?? Date.now(),
|
|
885
|
+
statusWidth,
|
|
886
|
+
true,
|
|
887
|
+
fleetSummaryIsAction,
|
|
888
|
+
),
|
|
889
|
+
),
|
|
890
|
+
];
|
|
891
|
+
if (facts.contextActivity) {
|
|
892
|
+
const token =
|
|
893
|
+
facts.contextActivity.status === "failed"
|
|
894
|
+
? "error"
|
|
895
|
+
: facts.contextActivity.status === "completed"
|
|
896
|
+
? "success"
|
|
897
|
+
: "accent";
|
|
898
|
+
rows.push(kv("context", facts.contextActivity.message, token));
|
|
899
|
+
if (facts.contextActivity.detail) rows.push(kv("ctx detail", facts.contextActivity.detail, "dim"));
|
|
900
|
+
}
|
|
901
|
+
if (isStreaming && facts.statusText) rows.push(kv("state", facts.statusText, "accent"));
|
|
902
|
+
if (isStreaming) {
|
|
903
|
+
rows.push(styledKv("speed", formattedThroughput(theme, options.throughput)));
|
|
904
|
+
rows.push(
|
|
905
|
+
styledKv(
|
|
906
|
+
"live",
|
|
907
|
+
liveTokenValue(theme, status, options.throughput, facts.lastTurn, options.sessionTokens, options.contextUsed),
|
|
908
|
+
),
|
|
909
|
+
);
|
|
910
|
+
} else if (facts.lastTurn) {
|
|
911
|
+
rows.push(styledKv("last", lastTurnOutcome(theme, facts.lastTurn)));
|
|
912
|
+
rows.push(styledKv("turn", lastTurnDetails(theme, facts.lastTurn)));
|
|
913
|
+
rows.push(styledKv("speed", formattedThroughput(theme, options.throughput)));
|
|
914
|
+
}
|
|
915
|
+
const total = cumulativeTokens(options.sessionTokens);
|
|
916
|
+
rows.push(total > 0 ? styledKv("totals", theme.fg("muted", `Σ${formatFooterTokens(total)}`)) : statusRow(null));
|
|
917
|
+
// Null until something has actually been priced, and an absent row is the
|
|
918
|
+
// only honest rendering of that. See formatCostAggregate.
|
|
919
|
+
const cost = formatCostAggregate(options.sessionCost);
|
|
920
|
+
rows.push(cost === null ? statusRow(null) : styledKv("cost", theme.fg("muted", cost)));
|
|
921
|
+
rows.push(kv("fleet", fleetValue(facts.dispatchSummary, facts.dispatchRows), fleetSummaryIsAction ? "action" : "dim"));
|
|
922
|
+
// Every worker up to the panel bound gets its own row; what the bound cuts is
|
|
923
|
+
// counted out loud instead of vanishing, so the row count an operator sees
|
|
924
|
+
// always reconciles with the `fleet` line above it.
|
|
925
|
+
const workerWidth = options.width !== undefined && Number.isFinite(options.width) ? options.width : 48;
|
|
926
|
+
for (const row of facts.dispatchRows.slice(0, maxWorkers)) rows.push(statusRow(workerLine(theme, row, workerWidth)));
|
|
927
|
+
const hiddenWorkers = facts.dispatchRows.length - maxWorkers;
|
|
928
|
+
if (hiddenWorkers > 0) rows.push(statusRow(theme.fg("dim", `+${hiddenWorkers} more`)));
|
|
929
|
+
if (facts.taskBoard && facts.taskBoard.tasks.length > 0) {
|
|
930
|
+
rows.push(styledKv("tasks", taskBoardValue(theme, facts.taskBoard)));
|
|
931
|
+
rows.push(statusRow(activeTaskLine(theme, facts.taskBoard)));
|
|
932
|
+
}
|
|
933
|
+
rows.push(kv("tools", meaningfulToolTally(facts.toolTally)));
|
|
934
|
+
return dashboardBlock(theme, "Activity", rows);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Zip two quadrant blocks into a side-by-side row, padding the shorter block so
|
|
939
|
+
* both columns stay aligned, and clamping each cell to its column width.
|
|
940
|
+
*/
|
|
941
|
+
export function zipColumns(
|
|
942
|
+
left: string[],
|
|
943
|
+
right: string[],
|
|
944
|
+
leftWidth: number,
|
|
945
|
+
rightWidth: number,
|
|
946
|
+
sep: string,
|
|
947
|
+
): string[] {
|
|
948
|
+
const rowCount = Math.max(left.length, right.length);
|
|
949
|
+
const lines: string[] = [];
|
|
950
|
+
for (let i = 0; i < rowCount; i += 1) {
|
|
951
|
+
lines.push(`${cell(left[i] ?? "", leftWidth)}${sep}${cell(right[i] ?? "", rightWidth)}`);
|
|
952
|
+
}
|
|
953
|
+
return lines;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
export function zipColumnBlocks(blocks: ReadonlyArray<string[]>, widths: ReadonlyArray<number>, sep: string): string[] {
|
|
957
|
+
const rowCount = blocks.reduce((max, block) => Math.max(max, block.length), 0);
|
|
958
|
+
const lines: string[] = [];
|
|
959
|
+
for (let row = 0; row < rowCount; row += 1) {
|
|
960
|
+
const cells = blocks.map((block, index) => cell(block[row] ?? "", widths[index] ?? 0));
|
|
961
|
+
lines.push(cells.join(sep));
|
|
962
|
+
}
|
|
963
|
+
return lines;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
type HarnessPhasePresentation = {
|
|
967
|
+
glyph: string;
|
|
968
|
+
label: string;
|
|
969
|
+
token: ClioToken;
|
|
970
|
+
live: boolean;
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
function shortToolLabel(status: AgentStatus, width: number): string {
|
|
974
|
+
const name = status.tool?.toolName?.trim();
|
|
975
|
+
if (name === ToolNames.AskUser) return width < 72 ? "ask" : "waiting for user";
|
|
976
|
+
if (!name || width < 72) return "tool";
|
|
977
|
+
const nameWidth = width >= 100 ? 18 : 12;
|
|
978
|
+
// The pill label is never padded; truncate without pad so the tool name is
|
|
979
|
+
// followed by a single space before the badge, not a column of blanks.
|
|
980
|
+
return `tool ${truncateToWidth(name, nameWidth, "…", false)}`;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
function harnessPhasePresentation(status: AgentStatus, width: number, now: number): HarnessPhasePresentation {
|
|
984
|
+
const ultraNarrow = width < 48;
|
|
985
|
+
switch (status.phase) {
|
|
986
|
+
case "idle":
|
|
987
|
+
return { glyph: GLYPH.queued, label: "idle", token: "muted", live: false };
|
|
988
|
+
case "preparing":
|
|
989
|
+
return { glyph: GLYPH.phaseWaiting, label: "prep", token: "info", live: true };
|
|
990
|
+
case "waiting_model":
|
|
991
|
+
return { glyph: GLYPH.phaseWaiting, label: "waiting", token: "info", live: true };
|
|
992
|
+
case "thinking":
|
|
993
|
+
return { glyph: GLYPH.phaseThinking, label: "thinking", token: "reason", live: true };
|
|
994
|
+
case "writing":
|
|
995
|
+
return { glyph: GLYPH.phaseWriting, label: "writing", token: "accent", live: true };
|
|
996
|
+
case "tool_running":
|
|
997
|
+
return { glyph: GLYPH.phaseTool, label: shortToolLabel(status, width), token: "accent", live: true };
|
|
998
|
+
case "tool_blocked":
|
|
999
|
+
// Attention states hold a static glyph rather than spinning: the work
|
|
1000
|
+
// has paused for a human, so the pill should not read as live progress.
|
|
1001
|
+
// The phase fires only on PermissionRequested, so the pill names the
|
|
1002
|
+
// wait for confirmation; "blocked" would contradict the ask overlay.
|
|
1003
|
+
return { glyph: GLYPH.phaseBlocked, label: "confirm", token: "warning", live: false };
|
|
1004
|
+
case "retrying": {
|
|
1005
|
+
const attempt = status.retry?.attempt ?? 0;
|
|
1006
|
+
const maxAttempts = status.retry?.maxAttempts ?? 0;
|
|
1007
|
+
return {
|
|
1008
|
+
glyph: GLYPH.phaseRetry,
|
|
1009
|
+
label: ultraNarrow ? "retry" : `retry ${attempt}/${maxAttempts}`,
|
|
1010
|
+
token: "warning",
|
|
1011
|
+
live: false,
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
case "compacting":
|
|
1015
|
+
return { glyph: GLYPH.phaseCompact, label: "compacting", token: "reason", live: true };
|
|
1016
|
+
case "dispatching":
|
|
1017
|
+
return { glyph: GLYPH.phaseDispatch, label: "dispatch", token: "action", live: true };
|
|
1018
|
+
case "stuck": {
|
|
1019
|
+
const seconds = Math.max(0, Math.floor((now - status.since) / 1000));
|
|
1020
|
+
return { glyph: GLYPH.warn, label: ultraNarrow ? "stuck" : `stuck ${seconds}s`, token: "error", live: false };
|
|
1021
|
+
}
|
|
1022
|
+
case "ended":
|
|
1023
|
+
return { glyph: GLYPH.ok, label: "done", token: "success", live: false };
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
function activeWorkerRows(rows: ReadonlyArray<DispatchBoardRow>): ReadonlyArray<DispatchBoardRow> {
|
|
1028
|
+
return rows.filter((row) => row.status === "running" || row.status === "stale" || row.status === "enqueued");
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* The live worker count, split by who asked once more than one kind is running:
|
|
1033
|
+
* `◇1 ◆3` says the operator has one run of their own alongside three the model
|
|
1034
|
+
* started, which `fleet 4` cannot. A single kind keeps the plain count, and so
|
|
1035
|
+
* does a set holding a run whose origin never reached the projection, because a
|
|
1036
|
+
* split that cannot name every active run would report a total that is short.
|
|
1037
|
+
*
|
|
1038
|
+
* The chip keeps one color. Its token says the fleet is busy; origin is carried
|
|
1039
|
+
* by glyph shape, which is the same pair the board rows and the transcript
|
|
1040
|
+
* blocks use.
|
|
1041
|
+
*/
|
|
1042
|
+
function activeWorkerChip(rows: ReadonlyArray<DispatchBoardRow>): string {
|
|
1043
|
+
const active = activeWorkerRows(rows);
|
|
1044
|
+
const counts = new Map<string, number>();
|
|
1045
|
+
for (const row of active) {
|
|
1046
|
+
const glyph = dispatchOriginPresentation(row)?.glyph;
|
|
1047
|
+
if (glyph === undefined) return `fleet ${active.length}`;
|
|
1048
|
+
counts.set(glyph, (counts.get(glyph) ?? 0) + 1);
|
|
1049
|
+
}
|
|
1050
|
+
if (counts.size < 2) return `fleet ${active.length}`;
|
|
1051
|
+
const order = [GLYPH.workerHuman, GLYPH.workerAgent, GLYPH.workerInternal];
|
|
1052
|
+
return order
|
|
1053
|
+
.filter((glyph) => counts.has(glyph))
|
|
1054
|
+
.map((glyph) => `${glyph}${counts.get(glyph)}`)
|
|
1055
|
+
.join(" ");
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
function harnessBadge(
|
|
1059
|
+
theme: ClioTheme,
|
|
1060
|
+
status: AgentStatus,
|
|
1061
|
+
toolCounts: ToolTallySnapshot,
|
|
1062
|
+
dispatchRows: ReadonlyArray<DispatchBoardRow>,
|
|
1063
|
+
fleetSummaryIsAction = false,
|
|
1064
|
+
): string {
|
|
1065
|
+
const workers = activeWorkerRows(dispatchRows).length;
|
|
1066
|
+
const activeTools = finiteNonNegative(toolCounts.active);
|
|
1067
|
+
// Active fleet work is a Clio-signature state; it gets the action color.
|
|
1068
|
+
if (workers > 0) {
|
|
1069
|
+
const token = status.phase === "dispatching" ? "muted" : fleetSummaryIsAction ? "accent" : "action";
|
|
1070
|
+
return theme.fg(token, activeWorkerChip(dispatchRows));
|
|
1071
|
+
}
|
|
1072
|
+
const badgeText = activeTools > 0 ? `tools ${activeTools}` : null;
|
|
1073
|
+
return badgeText ? theme.fg("muted", badgeText) : "";
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
function outputVerbosityLabel(verbosity: OutputVerbosity): string {
|
|
1077
|
+
return verbosity === "minimal" ? "min" : verbosity === "verbose" ? "verbose" : "default";
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
export function buildHarnessStatePill(
|
|
1081
|
+
theme: ClioTheme,
|
|
1082
|
+
status: AgentStatus,
|
|
1083
|
+
toolCounts: ToolTallySnapshot,
|
|
1084
|
+
dispatchRows: ReadonlyArray<DispatchBoardRow>,
|
|
1085
|
+
tick: number,
|
|
1086
|
+
now: number,
|
|
1087
|
+
width: number,
|
|
1088
|
+
showBadge = true,
|
|
1089
|
+
fleetSummaryIsAction = false,
|
|
1090
|
+
): string {
|
|
1091
|
+
const safeWidth = Math.max(1, Math.floor(width));
|
|
1092
|
+
const badge =
|
|
1093
|
+
showBadge && safeWidth >= 48 ? harnessBadge(theme, status, toolCounts, dispatchRows, fleetSummaryIsAction) : "";
|
|
1094
|
+
// Idleness is absence of work, not a phase worth narrating. If a tool or
|
|
1095
|
+
// fleet remains live while the harness settles, keep that activity without
|
|
1096
|
+
// prefixing it with an idle glyph.
|
|
1097
|
+
if (status.phase === "idle") return badge;
|
|
1098
|
+
const phase = harnessPhasePresentation(status, safeWidth, now);
|
|
1099
|
+
// A live phase leads with the animated spinner; the spinner stands in for the
|
|
1100
|
+
// static phase glyph rather than sitting beside it. Static glyphs render only
|
|
1101
|
+
// for the attention states and ended forms; idle returned quietly above.
|
|
1102
|
+
const lead = phase.live ? spinnerFrame(tick) : phase.glyph;
|
|
1103
|
+
const mainPill = theme.style(phase.token, `${lead} ${phase.label}`);
|
|
1104
|
+
return badge ? `${mainPill} ${theme.fg("dim", "·")} ${badge}` : mainPill;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* Drop order for the metric strip. The chip budget and the width budget both cut
|
|
1109
|
+
* from the highest rank down, so one ordering decides what an 80-column footer
|
|
1110
|
+
* keeps.
|
|
1111
|
+
*
|
|
1112
|
+
* The session total sits alone at the top. It is measured, it does not depend on
|
|
1113
|
+
* pricing, and it does not go stale between turns, which is not true of anything
|
|
1114
|
+
* else on the strip. At 80 columns the budget is four chips and the per-turn
|
|
1115
|
+
* detail used to spend all of it, so a session holding 9.7k measured tokens
|
|
1116
|
+
* showed none of them.
|
|
1117
|
+
*/
|
|
1118
|
+
const CHIP_RANK_SHUTDOWN = -2;
|
|
1119
|
+
const CHIP_RANK_LEADER = -1;
|
|
1120
|
+
const CHIP_RANK_TOTALS = 0;
|
|
1121
|
+
const CHIP_RANK_DETAIL = 1;
|
|
1122
|
+
const CHIP_RANK_DEFERRED = 2;
|
|
1123
|
+
|
|
1124
|
+
interface RankedChip {
|
|
1125
|
+
text: string;
|
|
1126
|
+
rank: number;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
function pushChip(chips: RankedChip[], text: string | null, rank: number): void {
|
|
1130
|
+
if (typeof text === "string" && text.length > 0) chips.push({ text, rank });
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* Cut the strip to the chip budget and then to the width, dropping the
|
|
1135
|
+
* lowest-priority chip still standing each time. Within one rank the rightmost
|
|
1136
|
+
* goes first, which keeps the surviving chips in the order they were built.
|
|
1137
|
+
*/
|
|
1138
|
+
function selectChips(
|
|
1139
|
+
theme: ClioTheme,
|
|
1140
|
+
chips: ReadonlyArray<RankedChip>,
|
|
1141
|
+
chipLimit: number,
|
|
1142
|
+
maxWidth: number,
|
|
1143
|
+
): string[] {
|
|
1144
|
+
const dropOrder = chips
|
|
1145
|
+
.map((chip, index) => ({ rank: chip.rank, index }))
|
|
1146
|
+
.sort((a, b) => b.rank - a.rank || b.index - a.index);
|
|
1147
|
+
const dropped = new Set<number>();
|
|
1148
|
+
const surviving = (): string[] => chips.filter((_, index) => !dropped.has(index)).map((chip) => chip.text);
|
|
1149
|
+
for (const { index } of dropOrder) {
|
|
1150
|
+
if (chips.length - dropped.size <= chipLimit && visibleWidth(joinChips(theme, surviving())) <= maxWidth) break;
|
|
1151
|
+
dropped.add(index);
|
|
1152
|
+
}
|
|
1153
|
+
return surviving();
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
export function buildMetricStrip(
|
|
1157
|
+
theme: ClioTheme,
|
|
1158
|
+
status: AgentStatus,
|
|
1159
|
+
throughput: TokenThroughputSnapshot | null | undefined,
|
|
1160
|
+
lastTurn: TurnSummary | null | undefined,
|
|
1161
|
+
sessionTokens: UsageBreakdown | null | undefined,
|
|
1162
|
+
sessionCost: CostAggregate | null | undefined,
|
|
1163
|
+
liveInputTokens: number | null | undefined,
|
|
1164
|
+
maxWidth: number,
|
|
1165
|
+
maxChipsCount = 6,
|
|
1166
|
+
outputVerbosity?: OutputVerbosity | null,
|
|
1167
|
+
leaderArmed = false,
|
|
1168
|
+
shutdownArmed = false,
|
|
1169
|
+
): string {
|
|
1170
|
+
const safeMaxWidth = Math.max(0, Math.floor(maxWidth));
|
|
1171
|
+
if (safeMaxWidth <= 0) return "";
|
|
1172
|
+
const isStreaming = status.phase !== "idle" && status.phase !== "ended";
|
|
1173
|
+
const meaningfulVerbosity = outputVerbosity && outputVerbosity !== "default" ? outputVerbosity : null;
|
|
1174
|
+
if (!isStreaming && !lastTurn && !meaningfulVerbosity && !leaderArmed && !shutdownArmed) return "";
|
|
1175
|
+
|
|
1176
|
+
const candidates: Array<string | null> = [];
|
|
1177
|
+
/** Per-turn detail that ranks below the session totals when the strip is cut. */
|
|
1178
|
+
const deferred: Array<string | null> = [];
|
|
1179
|
+
if (isStreaming) {
|
|
1180
|
+
const tps = finiteNonNegative(throughput?.tokensPerSecond);
|
|
1181
|
+
const rounded = tps > 0 ? (tps >= 10 ? Math.round(tps) : Math.round(tps * 10) / 10) : null;
|
|
1182
|
+
candidates.push(rounded !== null ? theme.fg("success", `${GLYPH.speed}${rounded}/s`) : null);
|
|
1183
|
+
|
|
1184
|
+
const liveOutput = finiteNonNegative(throughput?.outputTokens);
|
|
1185
|
+
candidates.push(liveOutput > 0 ? theme.fg("success", `${GLYPH.down}${formatFooterTokens(liveOutput)}`) : null);
|
|
1186
|
+
|
|
1187
|
+
const ttftMs = finiteNonNegative(throughput?.ttftMs);
|
|
1188
|
+
candidates.push(ttftMs > 0 ? theme.fg("muted", `ttft ${formatCompactMs(ttftMs)}`) : null);
|
|
1189
|
+
|
|
1190
|
+
const inputTokens =
|
|
1191
|
+
finiteNonNegative(liveInputTokens) ||
|
|
1192
|
+
finiteNonNegative(status.summary?.inputTokens) ||
|
|
1193
|
+
finiteNonNegative(lastTurn?.inputTokens) ||
|
|
1194
|
+
finiteNonNegative(sessionTokens?.input);
|
|
1195
|
+
candidates.push(inputTokens > 0 ? theme.fg("muted", `${GLYPH.up}${formatFooterTokens(inputTokens)}`) : null);
|
|
1196
|
+
} else if (lastTurn) {
|
|
1197
|
+
const stop = stopReasonStyle(lastTurn.stopReason);
|
|
1198
|
+
candidates.push(theme.fg(stop.token, `${stop.glyph} ${formatCompactMs(lastTurn.elapsedMs)}`));
|
|
1199
|
+
candidates.push(
|
|
1200
|
+
theme.fg(
|
|
1201
|
+
"muted",
|
|
1202
|
+
`${GLYPH.up}${formatFooterTokens(lastTurn.inputTokens)} ${GLYPH.down}${formatFooterTokens(lastTurn.outputTokens)}`,
|
|
1203
|
+
),
|
|
1204
|
+
);
|
|
1205
|
+
candidates.push(
|
|
1206
|
+
lastTurn.reasoningTokens !== undefined && lastTurn.reasoningTokens > 0
|
|
1207
|
+
? theme.fg(
|
|
1208
|
+
"reason",
|
|
1209
|
+
`r${lastTurn.reasoningTokenProvenance === "estimated" || lastTurn.reasoningTokenProvenance === "mixed" ? "≈" : ""}${formatFooterTokens(lastTurn.reasoningTokens)}`,
|
|
1210
|
+
)
|
|
1211
|
+
: null,
|
|
1212
|
+
);
|
|
1213
|
+
// Held back so the session totals below outrank them. The chip list is cut
|
|
1214
|
+
// to `maxChipsCount` before it is measured, and with cache and tools ahead
|
|
1215
|
+
// of the totals an 80-column terminal spent the whole budget on per-turn
|
|
1216
|
+
// detail: the cost field disappeared from the footer at the exact moment
|
|
1217
|
+
// it acquired a value, while `/cost` on the same session read `cost
|
|
1218
|
+
// unknown`. Two surfaces, two answers, because of a slice.
|
|
1219
|
+
deferred.push(
|
|
1220
|
+
lastTurn.cacheReadTokens > 0 || lastTurn.cacheWriteTokens > 0
|
|
1221
|
+
? theme.fg(
|
|
1222
|
+
"dim",
|
|
1223
|
+
`cache ${formatFooterTokens(lastTurn.cacheReadTokens)}/${formatFooterTokens(lastTurn.cacheWriteTokens)}`,
|
|
1224
|
+
)
|
|
1225
|
+
: null,
|
|
1226
|
+
);
|
|
1227
|
+
if (lastTurn.toolCount > 0) {
|
|
1228
|
+
const label = `${lastTurn.toolCount} tool${lastTurn.toolCount === 1 ? "" : "s"}`;
|
|
1229
|
+
const errors = lastTurn.toolErrorCount > 0 ? theme.fg("error", ` ${lastTurn.toolErrorCount}${GLYPH.error}`) : "";
|
|
1230
|
+
deferred.push(`${theme.fg("muted", label)}${errors}`);
|
|
1231
|
+
} else {
|
|
1232
|
+
deferred.push(null);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
if (meaningfulVerbosity) deferred.push(theme.fg("muted", `out ${outputVerbosityLabel(meaningfulVerbosity)}`));
|
|
1236
|
+
|
|
1237
|
+
const fallbackTotal = finiteNonNegative(sessionTokens?.input) + finiteNonNegative(sessionTokens?.output);
|
|
1238
|
+
const cumulativeTotal = finiteNonNegative(sessionTokens?.totalTokens) || fallbackTotal;
|
|
1239
|
+
const totalChip = cumulativeTotal > 0 ? theme.fg("muted", `Σ${formatFooterTokens(cumulativeTotal)}`) : null;
|
|
1240
|
+
// Null when nothing priced these tokens, and an absent chip is the honest
|
|
1241
|
+
// rendering of that. `$0.00` on a session that had made no call was a number
|
|
1242
|
+
// nothing measured, and `cost unknown` beside a real Σ read as doubt about
|
|
1243
|
+
// the tokens. See formatCostAggregate.
|
|
1244
|
+
const cost = formatCostAggregate(sessionCost);
|
|
1245
|
+
const costChip = cost === null ? null : theme.fg("muted", cost);
|
|
1246
|
+
|
|
1247
|
+
const chipLimit = Math.max(0, Math.floor(maxChipsCount));
|
|
1248
|
+
const chips: RankedChip[] = [];
|
|
1249
|
+
// Ranked above every measurement: the strip is cut by dropping the
|
|
1250
|
+
// lowest-ranked chip, and these two are the answer to "did that key
|
|
1251
|
+
// register". The quit hint outranks the leader because its window is
|
|
1252
|
+
// 500ms wide and the leader's is open until the next keystroke.
|
|
1253
|
+
// Two rungs rather than one: the strip drops a chip it cannot fit whole, and
|
|
1254
|
+
// a terminal narrow enough to lose the sentence is exactly the one where the
|
|
1255
|
+
// operator most needs to be told the press registered.
|
|
1256
|
+
const shutdownHint = safeMaxWidth >= 20 ? "Ctrl+C again to quit" : "Ctrl+C again";
|
|
1257
|
+
pushChip(chips, shutdownArmed ? theme.fg("warning", shutdownHint) : null, CHIP_RANK_SHUTDOWN);
|
|
1258
|
+
pushChip(chips, leaderArmed ? theme.fg("accent", "leader armed") : null, CHIP_RANK_LEADER);
|
|
1259
|
+
for (const chip of candidates) pushChip(chips, chip, CHIP_RANK_DETAIL);
|
|
1260
|
+
pushChip(chips, totalChip, CHIP_RANK_TOTALS);
|
|
1261
|
+
pushChip(chips, costChip, CHIP_RANK_DETAIL);
|
|
1262
|
+
for (const chip of deferred) pushChip(chips, chip, CHIP_RANK_DEFERRED);
|
|
1263
|
+
return joinChips(theme, selectChips(theme, chips, chipLimit, safeMaxWidth));
|
|
1264
|
+
}
|