@iowarp/clio-coder 0.3.4 → 0.3.7
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 +65 -2
- package/CONTRIBUTING.md +6 -6
- package/README.md +16 -5
- package/dist/{acp-S5R4RR5B.js → acp-SK4MD6MM.js} +11 -11
- package/dist/{agents-P6DMMVZY.js → agents-2FN2K6ME.js} +33 -26
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-2XCZLPKS.js → auth-QIYZWM5I.js} +15 -15
- package/dist/{chunk-EKMEHE4H.js → chunk-33YXPOE3.js} +2 -3
- package/dist/{chunk-VAWWTKDP.js → chunk-3HAPLH5M.js} +11 -11
- package/dist/{chunk-YCWGATWI.js → chunk-465YSENW.js} +3 -3
- package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
- package/dist/{chunk-UZHIZC5S.js → chunk-4DWFMQDR.js} +61 -76
- package/dist/{chunk-ZWMF7253.js → chunk-5C3AQNDW.js} +328 -9
- package/dist/{chunk-22NAGB7X.js → chunk-5C77SEEY.js} +5 -94
- package/dist/{chunk-WPQLXFOZ.js → chunk-5FR74PWO.js} +3 -2
- package/dist/{chunk-35MKKU5R.js → chunk-5UJ6ECTS.js} +18 -10
- package/dist/{chunk-BRXQQJFP.js → chunk-6M7VS3J3.js} +571 -50
- package/dist/{chunk-QQK64KLB.js → chunk-6TUKSZVF.js} +141 -23
- package/dist/{chunk-N4CZJQRK.js → chunk-AB4XIIVB.js} +8 -6
- package/dist/{chunk-KRPY7NTG.js → chunk-BMWK7ZIZ.js} +14 -20
- package/dist/{chunk-4BPJXDWC.js → chunk-C4JBQ5SR.js} +30 -14
- package/dist/{chunk-ZYKPLLNQ.js → chunk-CEYBNUGC.js} +821 -83
- package/dist/{chunk-VEZEGCGW.js → chunk-D4MDIG46.js} +20 -18
- package/dist/chunk-DJNLUABN.js +843 -0
- package/dist/{chunk-BP4OYD6A.js → chunk-DMD2AGVS.js} +21 -2
- package/dist/{chunk-KOHPCX4K.js → chunk-DOOEX22V.js} +2 -2
- package/dist/chunk-DQA7QLMD.js +123 -0
- package/dist/chunk-DR52UMZW.js +21 -0
- package/dist/{chunk-3HZ5RWN2.js → chunk-EBEFWSGL.js} +9 -7
- package/dist/{chunk-EDRHSCIE.js → chunk-EELBMBT6.js} +128 -13
- package/dist/{chunk-HV5X7OR2.js → chunk-EOOQZZDE.js} +16 -14
- package/dist/{chunk-WR67VIZY.js → chunk-FOT2FX5J.js} +63 -5
- package/dist/{chunk-BPGS2WCQ.js → chunk-GEYXPTRF.js} +2 -1
- package/dist/{chunk-FYYLNIL5.js → chunk-GH5622CP.js} +2 -2
- package/dist/{chunk-BEY543CS.js → chunk-GOXNB3AO.js} +5 -2
- package/dist/chunk-GWS3VEIW.js +195 -0
- package/dist/{chunk-G4BMMOKF.js → chunk-HVDIIIQW.js} +2 -2
- package/dist/chunk-HWUFFB6L.js +83 -0
- package/dist/{chunk-X6COSD2O.js → chunk-J7PIKKWC.js} +8 -436
- package/dist/{chunk-NILBFAPG.js → chunk-JNXPYBB4.js} +2 -2
- package/dist/{chunk-4VP4KH3K.js → chunk-JRIO5UD2.js} +4 -4
- package/dist/{chunk-K6WL7QZT.js → chunk-JTSEDYVQ.js} +7 -7
- package/dist/{chunk-QKMUKYO7.js → chunk-KCMKRQX4.js} +236 -84
- package/dist/chunk-KZ2H5X4G.js +1026 -0
- package/dist/{chunk-A2GZF7DC.js → chunk-LADCF22A.js} +13 -13
- package/dist/chunk-LCGCVYZ4.js +57 -0
- package/dist/chunk-M4AKACEO.js +382 -0
- package/dist/{chunk-POHLU5DW.js → chunk-M6L6IDJG.js} +3 -3
- package/dist/{chunk-4JUF2NNX.js → chunk-MXI6J5JF.js} +7 -7
- package/dist/{chunk-X4RCMKVQ.js → chunk-NDINPTJ4.js} +2 -2
- package/dist/{chunk-TTNYS3EA.js → chunk-OB5HIGJY.js} +1 -1
- package/dist/{chunk-7RXG6QRZ.js → chunk-OBMAI2DP.js} +61 -840
- package/dist/{chunk-5M54SPOL.js → chunk-ODFEOB4F.js} +161 -5
- package/dist/chunk-PD3MESLB.js +242 -0
- package/dist/{chunk-ED4KHGC3.js → chunk-PPAMZ32Z.js} +9 -2
- package/dist/{chunk-VMNQ6OZA.js → chunk-QCTRSGHQ.js} +963 -786
- package/dist/chunk-RVG5JXAL.js +41 -0
- package/dist/{chunk-RD5U66HV.js → chunk-SROCI7ZU.js} +7 -7
- package/dist/{chunk-MFFY33HR.js → chunk-THKY7CD7.js} +466 -205
- package/dist/{chunk-34475P3I.js → chunk-TSHXZTOQ.js} +5 -4
- package/dist/{chunk-PCZJO5TI.js → chunk-UFQ3F4FW.js} +13 -178
- package/dist/{chunk-AD2SYQYC.js → chunk-UHXRNZ2J.js} +121 -3
- package/dist/chunk-UND3GU2L.js +103 -0
- package/dist/{chunk-QQL5RT5M.js → chunk-UUANF5CR.js} +2323 -2114
- package/dist/{chunk-VJWL6YS5.js → chunk-UUVG37B4.js} +2 -2
- package/dist/chunk-UVDSQ6LW.js +472 -0
- package/dist/{chunk-QWU7ZBO7.js → chunk-VQNODYQ4.js} +215 -56
- package/dist/chunk-VREKEFLL.js +37 -0
- package/dist/{chunk-2TZWSW76.js → chunk-WHGPSPT5.js} +2 -2
- package/dist/{chunk-TW3WDMVS.js → chunk-WHJYKASB.js} +2 -2
- package/dist/{chunk-MEQ45TQ4.js → chunk-WJHBC77E.js} +21 -7
- package/dist/{chunk-HXG4IURW.js → chunk-X2KV5FXT.js} +2 -2
- package/dist/{chunk-YHZX5GEU.js → chunk-XAKHZX5N.js} +2 -2
- package/dist/{chunk-2LZI5CAG.js → chunk-XEGB6BCN.js} +228 -36
- package/dist/{chunk-E25LMLRW.js → chunk-YD734TPH.js} +2 -2
- package/dist/{verifiers-4UUM6TEE.js → chunk-YTYFXUI3.js} +121 -372
- package/dist/{chunk-3JLKSKD7.js → chunk-ZGH7FGS5.js} +17 -7
- package/dist/{chunk-VSNATDE6.js → chunk-ZZMN5OM4.js} +2 -2
- package/dist/cli/index.js +34 -32
- package/dist/{clio-J5JIOIDS.js → clio-WBVQEBKO.js} +7 -7
- package/dist/{code-nav-AXCXSBHX.js → code-nav-FGGFIE7L.js} +7 -7
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-KELWS457.js → components-F7OEATSO.js} +5 -5
- package/dist/{config-OEBMIN2U.js → config-TRBL3RCF.js} +48 -41
- package/dist/{configure-PUQOSIXQ.js → configure-OLCVPHNM.js} +17 -17
- package/dist/{context-URSXPBCK.js → context-MJIJ6GOX.js} +12 -12
- package/dist/{context-EKDCKUUZ.js → context-WFPKQSM6.js} +26 -9
- package/dist/{context-MGSE4Z2T.js → context-XEWE3MOJ.js} +44 -37
- package/dist/{context-clear-KDAJRNUK.js → context-clear-KNOS2JPB.js} +44 -37
- package/dist/{context-index-BZ4UYMTC.js → context-index-SSR5ECNE.js} +3 -3
- package/dist/{context-working-set-SBKMPPI2.js → context-working-set-EUXAZI6N.js} +14 -13
- package/dist/{dispatch-runner-MSWN72NK.js → dispatch-runner-B7MTOVKL.js} +321 -60
- package/dist/{docs-2C2LTVT2.js → docs-FLJTIDSE.js} +5 -5
- package/dist/{doctor-7BSE27PJ.js → doctor-RN4YKO2X.js} +15 -15
- package/dist/{eval-IZGDOO4H.js → eval-RUBJVSNQ.js} +52 -236
- package/dist/{evidence-SR7WXB5B.js → evidence-JZNBUOQZ.js} +39 -33
- package/dist/{evolve-K7VE2CBX.js → evolve-FJVC4KKI.js} +39 -33
- package/dist/{extensions-QVDOHDGJ.js → extensions-IQL36S7K.js} +5 -5
- package/dist/{fleet-7XMJNQNF.js → fleet-BDKYJFCP.js} +243 -370
- package/dist/fleet-commands-ZFIWZSB3.js +70 -0
- package/dist/fleet-graph-Y6HPXIVF.js +125 -0
- package/dist/fleet-new-RDVJLHHH.js +48 -0
- package/dist/{fleet-preflight-AQNAH644.js → fleet-preflight-BHSNPBMH.js} +2 -2
- package/dist/fleet-validate-BIYREGIK.js +79 -0
- package/dist/{init-JGNPAYXT.js → init-LQUB5COQ.js} +57 -48
- package/dist/library-NJAHIGG4.js +217 -0
- package/dist/memory-OG6HOYKM.js +472 -0
- package/dist/{models-ZMMLFJNN.js → models-5ZG5XY7J.js} +23 -22
- package/dist/{monitor-2F3T5KHP.js → monitor-TJ7AMTGB.js} +69 -35
- package/dist/{orchestrator-ORHT43JB.js → orchestrator-WZYB54DM.js} +4868 -1189
- package/dist/{paths-UXLN5YYZ.js → paths-XUC7GS6E.js} +5 -5
- package/dist/{reset-NXGTYNUO.js → reset-PXQT45IY.js} +8 -8
- package/dist/{run-RF4WJGMT.js → run-FQ74YF62.js} +82 -62
- package/dist/{share-UT3W6E4M.js → share-FW7SVCL3.js} +34 -10
- package/dist/{skills-PSACKC5Q.js → skills-7E7IRB3R.js} +25 -9
- package/dist/{skills-eval-WJSI55RZ.js → skills-eval-LI75W6OK.js} +43 -35
- package/dist/{targets-PIIRAOYS.js → targets-4CIFKCTW.js} +27 -24
- package/dist/{terminal-lease-ULWXWNVY.js → terminal-lease-WUZY7ZV5.js} +5 -4
- package/dist/{uninstall-FZCQCDKC.js → uninstall-7FV7IP4E.js} +5 -5
- package/dist/{upgrade-346TZ6AV.js → upgrade-K2HVIVMQ.js} +21 -20
- package/dist/{usage-6KKXR32N.js → usage-GTZELZQX.js} +159 -59
- package/dist/verifiers-RLAHT27O.js +336 -0
- package/dist/{verify-X5HDROLA.js → verify-BX3BRKH5.js} +7 -6
- package/dist/{wiki-generate-7STOCIFZ.js → wiki-generate-ASIFASCN.js} +58 -48
- package/dist/worker/entry.js +98 -84
- package/dist/{workspace-G4ZWUIPR.js → workspace-ZJ6BFM3Q.js} +4 -4
- package/docs/README.md +4 -3
- package/docs/acp.md +1 -1
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/artifact-placement.md +1 -2
- package/docs/artifact-versions.md +10 -6
- package/docs/built-in-agents.md +26 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +90 -8
- package/docs/configuration-and-targets.md +90 -2
- package/docs/context-engine.md +4 -2
- package/docs/context-working-set.md +4 -4
- package/docs/development-pipeline.md +1 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +4 -4
- package/docs/documentation-guide.md +4 -4
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +4 -45
- package/docs/evidence-and-memory.md +70 -10
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +4 -1
- package/docs/extensions-and-sharing.md +6 -2
- package/docs/fleet-demo-runbook.md +2 -2
- package/docs/fleet-dispatch.md +224 -11
- package/docs/git-commit-provenance.md +2 -2
- package/docs/glossary.md +1 -1
- package/docs/installation-and-lifecycle.md +2 -2
- package/docs/middleware-and-components.md +20 -2
- package/docs/model-catalog.md +1 -1
- package/docs/observability.md +55 -8
- package/docs/proactive-memory.md +26 -16
- package/docs/prompt-envelope-and-tools.md +4 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +83 -65
- package/docs/resource-library.md +59 -0
- package/docs/safety-model.md +29 -7
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +37 -1
- package/docs/skills-marketplace.md +16 -3
- package/docs/tool-usage.md +14 -7
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +38 -4
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +7 -4
- package/src/cli/agents.ts +2 -3
- package/src/cli/argv.ts +14 -1
- package/src/cli/fleet-commands.ts +37 -0
- package/src/cli/fleet-graph.ts +102 -0
- package/src/cli/fleet-new.ts +36 -0
- package/src/cli/fleet-preflight.ts +121 -0
- package/src/cli/fleet-validate.ts +30 -0
- package/src/cli/fleet.ts +188 -335
- package/src/cli/index.ts +4 -2
- package/src/cli/library.ts +190 -0
- package/src/cli/memory.ts +272 -10
- package/src/cli/modes/json-stream.ts +2 -2
- package/src/cli/modes/print.ts +12 -1
- package/src/cli/run.ts +22 -2
- package/src/cli/share.ts +13 -1
- package/src/cli/targets.ts +12 -3
- package/src/cli/usage.ts +160 -20
- package/src/core/bus-events.ts +7 -0
- package/src/core/commit-attribution.ts +4 -4
- package/src/core/config.ts +130 -0
- package/src/core/defaults.ts +81 -0
- package/src/core/response-model-id.ts +134 -0
- package/src/core/toml.ts +62 -0
- package/src/core/workspace-files.ts +0 -1
- package/src/domains/agents/builtins/architect.md +2 -1
- package/src/domains/agents/builtins/oracle.md +33 -0
- package/src/domains/agents/catalog.ts +18 -5
- package/src/domains/agents/fleet-contract.ts +278 -16
- package/src/domains/agents/index.ts +14 -0
- package/src/domains/agents/recipe.ts +54 -14
- package/src/domains/agents/result-contract.ts +242 -5
- package/src/domains/config/classify.ts +4 -0
- package/src/domains/context/bootstrap.ts +36 -27
- package/src/domains/context/project-metadata.ts +19 -63
- package/src/domains/context/prompt-context.ts +8 -0
- package/src/domains/context/working-set/policies/index.ts +3 -4
- package/src/domains/dispatch/active-route-planner.ts +14 -0
- package/src/domains/dispatch/backoff.ts +2 -1
- package/src/domains/dispatch/budget-envelope.ts +396 -0
- package/src/domains/dispatch/capability-match.ts +1 -0
- package/src/domains/dispatch/checkout-writer-lease.ts +175 -0
- package/src/domains/dispatch/contract.ts +36 -0
- package/src/domains/dispatch/delegation-plan.ts +167 -0
- package/src/domains/dispatch/execution-plan.ts +76 -5
- package/src/domains/dispatch/execution-role.ts +3 -1
- package/src/domains/dispatch/execution-scheduler.ts +183 -67
- package/src/domains/dispatch/extension.ts +339 -36
- package/src/domains/dispatch/fleet-gate.ts +14 -0
- package/src/domains/dispatch/fleet-plan.ts +63 -3
- package/src/domains/dispatch/fleet-run.ts +737 -0
- package/src/domains/dispatch/gate-role-prompts.ts +9 -0
- package/src/domains/dispatch/host-verification.ts +178 -0
- package/src/domains/dispatch/index.ts +38 -0
- package/src/domains/dispatch/intent.ts +159 -0
- package/src/domains/dispatch/orphan-recovery.ts +1 -0
- package/src/domains/dispatch/receipt-integrity.ts +12 -4
- package/src/domains/dispatch/state.ts +37 -3
- package/src/domains/dispatch/types.ts +61 -9
- package/src/domains/dispatch/validation.ts +80 -6
- package/src/domains/dispatch/worker-spawn.ts +14 -3
- package/src/domains/eval/metrics/evidence.ts +0 -116
- package/src/domains/eval/metrics/invariants.ts +1 -1
- package/src/domains/eval/runners/clio-run.ts +1 -10
- package/src/domains/eval/runners/external-command.ts +2 -29
- package/src/domains/eval/schema/suite.ts +0 -7
- package/src/domains/eval/suites/run.ts +1 -7
- package/src/domains/evidence/trust-status.ts +10 -1
- package/src/domains/memory/index.ts +22 -0
- package/src/domains/memory/operations.ts +58 -1
- package/src/domains/memory/promotion.ts +281 -0
- package/src/domains/memory/prompt-section.ts +25 -5
- package/src/domains/memory/proposal.ts +51 -7
- package/src/domains/memory/task-bank.ts +3 -2
- package/src/domains/memory/task-memory-handoff.ts +181 -24
- package/src/domains/memory/task-memory-policy.ts +3 -1
- package/src/domains/memory/types.ts +37 -0
- package/src/domains/memory/validate.ts +178 -0
- package/src/domains/middleware/index.ts +15 -0
- package/src/domains/middleware/memory-intervention.ts +35 -25
- package/src/domains/middleware/runtime.ts +6 -0
- package/src/domains/middleware/skills-reminder.ts +19 -4
- package/src/domains/middleware/stalled-turn.ts +43 -1
- package/src/domains/middleware/types.ts +10 -0
- package/src/domains/middleware/watchdog.ts +281 -0
- package/src/domains/observability/contract.ts +9 -2
- package/src/domains/observability/cost.ts +31 -4
- package/src/domains/observability/extension.ts +2 -2
- package/src/domains/observability/index.ts +10 -0
- package/src/domains/observability/out-of-turn-usage.ts +223 -0
- package/src/domains/providers/index.ts +3 -0
- package/src/domains/providers/model-discovery.ts +9 -0
- package/src/domains/providers/runtime-resolution.ts +38 -1
- package/src/domains/providers/runtimes/common/probe-helpers.ts +97 -16
- package/src/domains/providers/types/context-window-slots.ts +18 -0
- package/src/domains/providers/types/runtime-descriptor.ts +3 -1
- package/src/domains/resources/index.ts +20 -0
- package/src/domains/resources/library.ts +326 -0
- package/src/domains/resources/skills/marketplace.ts +37 -12
- package/src/domains/safety/call-target.ts +211 -14
- package/src/domains/safety/decision-presentation.ts +268 -0
- package/src/domains/safety/redaction.ts +73 -0
- package/src/domains/session/context-ledger.ts +10 -1
- package/src/domains/session/decision-board.ts +4 -0
- package/src/domains/session/entries.ts +3 -0
- package/src/domains/session/handoff.ts +629 -0
- package/src/domains/session/history.ts +68 -19
- package/src/domains/session/usage.ts +24 -7
- package/src/domains/share/archive.ts +67 -2
- package/src/engine/acp/event-mapper.ts +7 -0
- package/src/engine/acp/server.ts +29 -2
- package/src/engine/apis/lmstudio.ts +25 -4
- package/src/engine/apis/openai-completions.ts +147 -22
- package/src/engine/claude/sdk-runtime.ts +8 -2
- package/src/engine/claude/tool-safety.ts +13 -0
- package/src/engine/loop-guard.ts +27 -3
- package/src/engine/worker-events.ts +4 -3
- package/src/engine/worker-runtime.ts +59 -54
- package/src/entry/orchestrator.ts +55 -1
- package/src/interactive/bus-notices.ts +26 -0
- package/src/interactive/chat-loop-messages.ts +22 -0
- package/src/interactive/chat-loop.ts +248 -1
- package/src/interactive/chat-renderer.ts +41 -3
- package/src/interactive/clio-editor.ts +44 -7
- package/src/interactive/context-overlay.ts +43 -5
- package/src/interactive/cost-overlay.ts +70 -11
- package/src/interactive/council-dispatch.ts +30 -0
- package/src/interactive/council-grid.ts +213 -0
- package/src/interactive/council.ts +99 -0
- package/src/interactive/dispatch-board.ts +471 -50
- package/src/interactive/fleet-run-preview.ts +307 -0
- package/src/interactive/footer/notifications.ts +219 -0
- package/src/interactive/footer/widgets.ts +13 -0
- package/src/interactive/handoff-round.ts +56 -0
- package/src/interactive/interactive-application.ts +49 -2
- package/src/interactive/interactive-event-projection.ts +9 -1
- package/src/interactive/interactive-input-runtime.ts +11 -1
- package/src/interactive/interactive-presentation.ts +11 -1
- package/src/interactive/interactive-slash-runtime.ts +52 -2
- package/src/interactive/interactive-subscriptions.ts +14 -2
- package/src/interactive/memory-overlay.ts +89 -4
- package/src/interactive/oracle.ts +179 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +7 -1
- package/src/interactive/overlay-frame.ts +5 -2
- package/src/interactive/overlay-general-openers.ts +230 -2
- package/src/interactive/overlay-key-routing.ts +58 -2
- package/src/interactive/overlay-lifecycle.ts +52 -5
- package/src/interactive/overlay-permission-lifecycle.ts +33 -8
- package/src/interactive/overlay-resource-openers.ts +11 -3
- package/src/interactive/overlay-session-lifecycle.ts +234 -2
- package/src/interactive/overlay-transitions.ts +11 -0
- package/src/interactive/overlays/ask-user.ts +74 -30
- package/src/interactive/overlays/decisions.ts +3 -1
- package/src/interactive/overlays/fleet-run-approval.ts +208 -0
- package/src/interactive/overlays/handoff-review.ts +185 -0
- package/src/interactive/overlays/library-install-confirm.ts +151 -0
- package/src/interactive/overlays/list-overlay.ts +168 -2
- package/src/interactive/overlays/settings.ts +101 -4
- package/src/interactive/overlays/side-question.ts +139 -0
- package/src/interactive/overlays/skills-hub.ts +401 -15
- package/src/interactive/permission-hint.ts +35 -0
- package/src/interactive/permission-overlay.ts +95 -45
- package/src/interactive/renderers/tool-execution.ts +19 -49
- package/src/interactive/session-last-turn.ts +8 -1
- package/src/interactive/session-usage-reseed.ts +36 -10
- package/src/interactive/side-question.ts +171 -0
- package/src/interactive/slash-commands.ts +434 -7
- package/src/interactive/slash-spec.ts +19 -6
- package/src/interactive/status/summary.ts +5 -0
- package/src/interactive/status/types.ts +5 -0
- package/src/interactive/terminal-lease.ts +1 -0
- package/src/interactive/theme/tokens.ts +30 -0
- package/src/interactive/turn-context.ts +96 -23
- package/src/interactive/turn-middleware.ts +16 -1
- package/src/interactive/turn-runtime.ts +37 -8
- package/src/interactive/turn-state.ts +3 -0
- package/src/interactive/watchdog-run.ts +75 -0
- package/src/interactive/worker-progress.ts +440 -0
- package/src/interactive/worker-share.ts +56 -1
- package/src/interactive/worker-stream.ts +58 -110
- package/src/tools/agent-tools.ts +28 -3
- package/src/tools/ask-user.ts +21 -1
- package/src/tools/bootstrap.ts +3 -0
- package/src/tools/compete-worktrees.ts +13 -79
- package/src/tools/context/index.ts +2 -2
- package/src/tools/dispatch-admission.ts +242 -8
- package/src/tools/dispatch-arguments.ts +65 -1
- package/src/tools/dispatch-event-text.ts +19 -0
- package/src/tools/dispatch-plan.ts +136 -6
- package/src/tools/dispatch-runner.ts +319 -13
- package/src/tools/dispatch-types.ts +20 -1
- package/src/tools/dispatch.ts +96 -3
- package/src/tools/monitor.ts +31 -0
- package/src/tools/profiles.ts +18 -4
- package/src/tools/registry.ts +15 -5
- package/src/tools/result-disposition.ts +156 -0
- package/src/tools/result-shaping.ts +59 -1
- package/src/tools/task-worktree.ts +238 -0
- package/src/tools/verify/authoring.ts +116 -55
- package/src/tools/verify/scripts.ts +62 -0
- package/src/tools/worker-evidence.ts +21 -1
- package/src/worker/spec-contract.ts +44 -3
- package/dist/chunk-EFADSJET.js +0 -18
- package/dist/chunk-HC4CLZ2Y.js +0 -68
- package/dist/memory-4ALKDJ4Q.js +0 -246
- package/src/domains/eval/metrics/chaos-stream.ts +0 -93
package/src/cli/run.ts
CHANGED
|
@@ -28,7 +28,7 @@ import { SafetyDomainModule } from "../domains/safety/index.js";
|
|
|
28
28
|
import { SchedulingDomainModule } from "../domains/scheduling/index.js";
|
|
29
29
|
import { SessionDomainModule } from "../domains/session/index.js";
|
|
30
30
|
import type { ImageContent } from "../engine/types.js";
|
|
31
|
-
import { assistantTextFromEvent } from "../tools/dispatch-event-text.js";
|
|
31
|
+
import { assistantTextFromEvent, receiptResponseModelIdObservationLabel } from "../tools/dispatch-event-text.js";
|
|
32
32
|
import { isToolProfileName } from "../tools/profiles.js";
|
|
33
33
|
import { parseRunCliArgs, type RunCliArgs } from "./args.js";
|
|
34
34
|
import { runClioCommand } from "./clio.js";
|
|
@@ -393,8 +393,27 @@ async function runDispatch(
|
|
|
393
393
|
let memorySection = "";
|
|
394
394
|
try {
|
|
395
395
|
const records = loadMemoryRecordsSync(clioDataDir());
|
|
396
|
+
const boundProfileName = parsed.agentProfile ?? effectiveSettings.workers.agentBindings[parsed.agentId];
|
|
397
|
+
const boundProfile = boundProfileName ? effectiveSettings.workers.profiles[boundProfileName] : undefined;
|
|
398
|
+
const configuredRuntime = (targetId: string | null | undefined): string | undefined =>
|
|
399
|
+
effectiveSettings.targets.find((target) => target.id === targetId)?.runtime;
|
|
400
|
+
const profileRuntimeId = configuredRuntime(boundProfile?.target);
|
|
401
|
+
// The memory section is compiled before fleet routing settles. Admit a
|
|
402
|
+
// runtime-scoped record only when every permitted initial and fallback
|
|
403
|
+
// route is constrained to the same runtime.
|
|
404
|
+
const memoryRuntimeId =
|
|
405
|
+
parsed.target !== undefined
|
|
406
|
+
? configuredRuntime(parsed.target)
|
|
407
|
+
: boundProfileName !== undefined
|
|
408
|
+
? parsed.agentRuntime === profileRuntimeId
|
|
409
|
+
? profileRuntimeId
|
|
410
|
+
: undefined
|
|
411
|
+
: parsed.agentRuntime;
|
|
396
412
|
memorySection = buildMemoryPromptSection(records, {
|
|
413
|
+
scopes: ["global", "repo", "runtime", "agent"],
|
|
397
414
|
activeRepository: canonicalMemoryRepositoryIdentity(process.cwd()),
|
|
415
|
+
activeRuntime: memoryRuntimeId === undefined ? null : { kind: "runtime", key: memoryRuntimeId },
|
|
416
|
+
activeAgent: { kind: "agent", key: parsed.agentId },
|
|
398
417
|
}).section;
|
|
399
418
|
} catch (err) {
|
|
400
419
|
process.stderr.write(
|
|
@@ -488,7 +507,8 @@ function formatReceipt(r: RunReceipt): string {
|
|
|
488
507
|
const reasoning =
|
|
489
508
|
typeof r.reasoningTokenCount === "number" && r.reasoningTokenCount > 0 ? ` reasoning=${r.reasoningTokenCount}` : "";
|
|
490
509
|
const failure = r.failureMessage ? ` error=${r.failureMessage}` : "";
|
|
491
|
-
|
|
510
|
+
const responseModelIdObservation = receiptResponseModelIdObservationLabel(r);
|
|
511
|
+
return `receipt: ${r.runId} agent=${r.agentId} exit=${r.exitCode} target=${r.targetId} requested_model_id=${r.wireModelId}${responseModelIdObservation ? ` ${responseModelIdObservation}` : ""} tokens=${r.tokenCount}${reasoning}${failure} start=${r.startedAt} end=${r.endedAt}`;
|
|
492
512
|
}
|
|
493
513
|
|
|
494
514
|
function mapExitCode(r: RunReceipt): number {
|
package/src/cli/share.ts
CHANGED
|
@@ -15,7 +15,7 @@ const HELP = `clio-coder share <command>
|
|
|
15
15
|
Export and import portable Clio project/resource archives.
|
|
16
16
|
|
|
17
17
|
Commands:
|
|
18
|
-
clio-coder share export --out <path> [--project|--user|--both] [--context] [--prompts] [--skills] [--settings] [--extensions]
|
|
18
|
+
clio-coder share export --out <path> [--project|--user|--both] [--context] [--prompts] [--skills] [--agents] [--fleets] [--settings] [--extensions]
|
|
19
19
|
clio-coder share import <path> [--dry-run] [--force] [--project|--user] [--json]
|
|
20
20
|
clio-coder share inspect <path> [--json]
|
|
21
21
|
|
|
@@ -36,6 +36,8 @@ interface Parsed {
|
|
|
36
36
|
includeContext?: boolean;
|
|
37
37
|
includePrompts?: boolean;
|
|
38
38
|
includeSkills?: boolean;
|
|
39
|
+
includeAgents?: boolean;
|
|
40
|
+
includeFleets?: boolean;
|
|
39
41
|
includeSettings?: boolean;
|
|
40
42
|
includeExtensions?: boolean;
|
|
41
43
|
}
|
|
@@ -93,6 +95,12 @@ function parse(argv: ReadonlyArray<string>): Parsed | null {
|
|
|
93
95
|
case "--skills":
|
|
94
96
|
out.includeSkills = true;
|
|
95
97
|
break;
|
|
98
|
+
case "--agents":
|
|
99
|
+
out.includeAgents = true;
|
|
100
|
+
break;
|
|
101
|
+
case "--fleets":
|
|
102
|
+
out.includeFleets = true;
|
|
103
|
+
break;
|
|
96
104
|
case "--settings":
|
|
97
105
|
out.includeSettings = true;
|
|
98
106
|
break;
|
|
@@ -103,6 +111,8 @@ function parse(argv: ReadonlyArray<string>): Parsed | null {
|
|
|
103
111
|
out.includeContext = true;
|
|
104
112
|
out.includePrompts = true;
|
|
105
113
|
out.includeSkills = true;
|
|
114
|
+
out.includeAgents = true;
|
|
115
|
+
out.includeFleets = true;
|
|
106
116
|
out.includeSettings = true;
|
|
107
117
|
out.includeExtensions = true;
|
|
108
118
|
break;
|
|
@@ -152,6 +162,8 @@ function exportOptions(parsed: Parsed): ShareExportOptions {
|
|
|
152
162
|
...(parsed.includeContext !== undefined ? { includeContext: parsed.includeContext } : {}),
|
|
153
163
|
...(parsed.includePrompts !== undefined ? { includePrompts: parsed.includePrompts } : {}),
|
|
154
164
|
...(parsed.includeSkills !== undefined ? { includeSkills: parsed.includeSkills } : {}),
|
|
165
|
+
...(parsed.includeAgents !== undefined ? { includeAgents: parsed.includeAgents } : {}),
|
|
166
|
+
...(parsed.includeFleets !== undefined ? { includeFleets: parsed.includeFleets } : {}),
|
|
155
167
|
...(parsed.includeSettings !== undefined ? { includeSettings: parsed.includeSettings } : {}),
|
|
156
168
|
...(parsed.includeExtensions !== undefined ? { includeExtensions: parsed.includeExtensions } : {}),
|
|
157
169
|
};
|
package/src/cli/targets.ts
CHANGED
|
@@ -1028,10 +1028,19 @@ export function residentModelsSummary(states: TargetStatus["discoveredModelState
|
|
|
1028
1028
|
* capability the target reported. Saying so is the difference between a number
|
|
1029
1029
|
* a user can plan against and one they cannot.
|
|
1030
1030
|
*/
|
|
1031
|
-
export function formatContextWindow(
|
|
1031
|
+
export function formatContextWindow(
|
|
1032
|
+
status: Pick<TargetStatus, "capabilities" | "contextWindowProvenance"> &
|
|
1033
|
+
Partial<Pick<TargetStatus, "target" | "discoveredModelStates">>,
|
|
1034
|
+
): string {
|
|
1032
1035
|
const window = status.capabilities.contextWindow;
|
|
1033
|
-
|
|
1034
|
-
|
|
1036
|
+
if (status.contextWindowProvenance === "runtime-default") return `ctx ${window} (unverified runtime default)`;
|
|
1037
|
+
// A llama.cpp window that is one slot's share of `--ctx-size` names the
|
|
1038
|
+
// split, so `ctx 196608` is not mistaken for the whole server (issue #187).
|
|
1039
|
+
const slots = status.target?.defaultModel
|
|
1040
|
+
? status.discoveredModelStates?.[status.target.defaultModel]?.contextSlots
|
|
1041
|
+
: undefined;
|
|
1042
|
+
return slots && Math.floor(slots.totalContextSize / slots.slots) === window
|
|
1043
|
+
? `ctx ${window} (${slots.totalContextSize} / ${slots.slots} slots)`
|
|
1035
1044
|
: `ctx ${window}`;
|
|
1036
1045
|
}
|
|
1037
1046
|
|
package/src/cli/usage.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { readdir, readFile, stat } from "node:fs/promises";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
addResponseModelIdObservationCount,
|
|
5
|
+
emptyResponseModelIdObservationCounts,
|
|
6
|
+
type ResponseModelIdObservationCounts,
|
|
7
|
+
responseModelIdObservationCountsLabel,
|
|
8
|
+
} from "../core/response-model-id.js";
|
|
3
9
|
import { clioDataDir, clioStateDir } from "../core/xdg.js";
|
|
4
10
|
import { loadMemoryRecordsSync, type MemoryRecord } from "../domains/memory/index.js";
|
|
5
11
|
import { readEvidenceIndex } from "../domains/observability/evidence-index.js";
|
|
12
|
+
import { type OutOfTurnUsageRow, readOutOfTurnUsageRows } from "../domains/observability/out-of-turn-usage.js";
|
|
6
13
|
import { loadSkills } from "../domains/resources/index.js";
|
|
7
14
|
import {
|
|
8
15
|
type LedgerUsageCall,
|
|
@@ -17,9 +24,10 @@ import { formatColumns, printError } from "./shared.js";
|
|
|
17
24
|
const HELP = `clio-coder usage report [--repo <path>] [--days <n>] [--json]
|
|
18
25
|
|
|
19
26
|
Cross-session usage analyzer (experimental, read-only). Reads the local usage
|
|
20
|
-
archive (receipts, session ledgers,
|
|
21
|
-
and reports facts plus improvement opportunities,
|
|
22
|
-
counts. Nothing is written or stored; suggestions are
|
|
27
|
+
archive (receipts, session ledgers, the out-of-turn usage store, audit rows,
|
|
28
|
+
evidence index, memory store) and reports facts plus improvement opportunities,
|
|
29
|
+
every line citing ids and counts. Nothing is written or stored; suggestions are
|
|
30
|
+
printed only.
|
|
23
31
|
|
|
24
32
|
Flags:
|
|
25
33
|
--repo <path> restrict sessions (and runs via the run ledger) to one repo
|
|
@@ -88,6 +96,58 @@ function emptyUsageTotals(): UsageTotals {
|
|
|
88
96
|
};
|
|
89
97
|
}
|
|
90
98
|
|
|
99
|
+
function addResponseModelIdObservation(counts: ResponseModelIdObservationCounts, call: LedgerUsageCall): void {
|
|
100
|
+
addResponseModelIdObservationCount(counts, call.responseModelIdObservation, call.apiCalls ?? 1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* How the folded calls split between the session's own turns and the rounds
|
|
105
|
+
* that were billed beside it. A `/btw` side question and a `/handoff` round are
|
|
106
|
+
* real spend and belong in the token and cost totals, but neither is a turn:
|
|
107
|
+
* they never entered the session. `turns` therefore subtracts them from the
|
|
108
|
+
* folded row count, which is exactly what the `/cost` overlay does.
|
|
109
|
+
*/
|
|
110
|
+
interface CallOrigins {
|
|
111
|
+
rows: number;
|
|
112
|
+
sideQuestions: number;
|
|
113
|
+
handoffs: number;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function emptyCallOrigins(): CallOrigins {
|
|
117
|
+
return { rows: 0, sideQuestions: 0, handoffs: 0 };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function turnsOf(origins: CallOrigins): number {
|
|
121
|
+
return origins.rows - origins.sideQuestions - origins.handoffs;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function hasLabelledCall(origins: CallOrigins): boolean {
|
|
125
|
+
return origins.sideQuestions > 0 || origins.handoffs > 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function addOutOfTurnRow(origins: CallOrigins, row: OutOfTurnUsageRow): void {
|
|
129
|
+
origins.rows += 1;
|
|
130
|
+
if (row.label === "side-question") origins.sideQuestions += 1;
|
|
131
|
+
else origins.handoffs += 1;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** The out-of-turn store keeps its own usage shape; fold it as one completed call. */
|
|
135
|
+
function outOfTurnUsageCall(row: OutOfTurnUsageRow): LedgerUsageCall {
|
|
136
|
+
return {
|
|
137
|
+
providerId: row.target,
|
|
138
|
+
attributedModelId: row.attributedModelId,
|
|
139
|
+
requestedModelId: row.attributedModelId,
|
|
140
|
+
responseModelIdObservation: { state: "not-observed" },
|
|
141
|
+
input: row.usage.input,
|
|
142
|
+
output: row.usage.output,
|
|
143
|
+
cacheRead: row.usage.cacheRead,
|
|
144
|
+
cacheWrite: row.usage.cacheWrite,
|
|
145
|
+
reasoningTokens: row.usage.reasoning,
|
|
146
|
+
totalTokens: row.usage.totalTokens,
|
|
147
|
+
costUsd: row.usage.costUsd,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
91
151
|
function addUsageCall(totals: UsageTotals, call: LedgerUsageCall): void {
|
|
92
152
|
totals.apiCalls += call.apiCalls ?? 1;
|
|
93
153
|
totals.input += call.input;
|
|
@@ -240,6 +300,13 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
|
|
|
240
300
|
(receipt) => repoRunIds === null || repoRunIds.has(receipt.runId),
|
|
241
301
|
);
|
|
242
302
|
const sessions = await readSessions(stateDir, windowStart, now, repoHash, diagnostics);
|
|
303
|
+
// Side questions and handoff rounds append nothing to the session ledger by
|
|
304
|
+
// design, so their spend lives in its own store and is folded in here.
|
|
305
|
+
const outOfTurn = readOutOfTurnUsageRows(stateDir);
|
|
306
|
+
for (const error of outOfTurn.errors) diagnostics.notes.push(error);
|
|
307
|
+
const outOfTurnRows = outOfTurn.rows.filter(
|
|
308
|
+
(row) => inWindow(row.timestamp, windowStart, now) && (repoHash === undefined || row.repoIdentity === repoHash),
|
|
309
|
+
);
|
|
243
310
|
const auditRows = await readAuditRows(stateDir);
|
|
244
311
|
diagnostics.malformedAuditRows = auditRows.errors.length;
|
|
245
312
|
const auditInWindow = auditRows.rows.filter((row) => row.ts !== null && inWindow(row.ts, windowStart, now));
|
|
@@ -321,21 +388,50 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
|
|
|
321
388
|
// Token and cost facts fold the same per-call usage the `/cost` overlay
|
|
322
389
|
// reseeds from, through the same session-domain function, so the report and
|
|
323
390
|
// the overlay cannot disagree about what a session spent.
|
|
324
|
-
|
|
391
|
+
// Keyed by the model id accounting attributes the call to. A reported LM
|
|
392
|
+
// Link peer id gets its own row, while an observed omission becomes unknown.
|
|
393
|
+
// Requested ids and observation-state counts remain alongside that row.
|
|
394
|
+
const usageByModel = new Map<
|
|
395
|
+
string,
|
|
396
|
+
{
|
|
397
|
+
providerId: string;
|
|
398
|
+
attributedModelId: string;
|
|
399
|
+
requestedModelIds: Set<string>;
|
|
400
|
+
responseModelIdObservationCounts: ResponseModelIdObservationCounts;
|
|
401
|
+
totals: UsageTotals;
|
|
402
|
+
}
|
|
403
|
+
>();
|
|
325
404
|
const usageTotals = emptyUsageTotals();
|
|
405
|
+
const callOrigins = emptyCallOrigins();
|
|
406
|
+
const foldCall = (call: LedgerUsageCall): void => {
|
|
407
|
+
addUsageCall(usageTotals, call);
|
|
408
|
+
const key = `${call.providerId}::${call.attributedModelId}`;
|
|
409
|
+
const entry = usageByModel.get(key) ?? {
|
|
410
|
+
providerId: call.providerId,
|
|
411
|
+
attributedModelId: call.attributedModelId,
|
|
412
|
+
requestedModelIds: new Set<string>(),
|
|
413
|
+
responseModelIdObservationCounts: emptyResponseModelIdObservationCounts(),
|
|
414
|
+
totals: emptyUsageTotals(),
|
|
415
|
+
};
|
|
416
|
+
entry.requestedModelIds.add(call.requestedModelId);
|
|
417
|
+
addResponseModelIdObservation(entry.responseModelIdObservationCounts, call);
|
|
418
|
+
addUsageCall(entry.totals, call);
|
|
419
|
+
usageByModel.set(key, entry);
|
|
420
|
+
};
|
|
326
421
|
for (const session of sessions) {
|
|
327
422
|
for (const call of session.usageCalls) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const entry = usageByModel.get(key) ?? {
|
|
331
|
-
providerId: call.providerId,
|
|
332
|
-
modelId: call.modelId,
|
|
333
|
-
totals: emptyUsageTotals(),
|
|
334
|
-
};
|
|
335
|
-
addUsageCall(entry.totals, call);
|
|
336
|
-
usageByModel.set(key, entry);
|
|
423
|
+
foldCall(call);
|
|
424
|
+
callOrigins.rows += 1;
|
|
337
425
|
}
|
|
338
426
|
}
|
|
427
|
+
for (const row of outOfTurnRows) {
|
|
428
|
+
foldCall(outOfTurnUsageCall(row));
|
|
429
|
+
addOutOfTurnRow(callOrigins, row);
|
|
430
|
+
}
|
|
431
|
+
// Token and cost facts need one of their two inputs on disk. A machine whose
|
|
432
|
+
// session store is gone can still have recorded out-of-turn spend, and
|
|
433
|
+
// dropping those rows would report money that was spent as nothing at all.
|
|
434
|
+
const usageMeasurable = presence.sessionsPresent || outOfTurnRows.length > 0;
|
|
339
435
|
const usageRows = [...usageByModel.values()].sort(
|
|
340
436
|
(a, b) => b.totals.totalTokens - a.totals.totalTokens || a.providerId.localeCompare(b.providerId),
|
|
341
437
|
);
|
|
@@ -417,10 +513,32 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
|
|
|
417
513
|
if (presence.receiptsPresent) emit({ kind: "fact", fact: "dispatch-runs", value: receipts.length });
|
|
418
514
|
else emit({ kind: "fact", fact: "receipt-store-missing", path: presence.receiptsPath });
|
|
419
515
|
emit({ kind: "fact", fact: "audit-tool-calls", value: auditToolCalls.length, blocked: auditBlocked.length });
|
|
420
|
-
if (
|
|
421
|
-
|
|
516
|
+
if (usageMeasurable) {
|
|
517
|
+
// The origin split is emitted only when something out of turn was
|
|
518
|
+
// recorded, so a report over an archive with no `/btw` or `/handoff`
|
|
519
|
+
// round in it stays byte-identical to what it printed before.
|
|
520
|
+
emit({
|
|
521
|
+
kind: "fact",
|
|
522
|
+
fact: "tokens",
|
|
523
|
+
...usageTotals,
|
|
524
|
+
...(hasLabelledCall(callOrigins)
|
|
525
|
+
? {
|
|
526
|
+
turns: turnsOf(callOrigins),
|
|
527
|
+
sideQuestions: callOrigins.sideQuestions,
|
|
528
|
+
handoffs: callOrigins.handoffs,
|
|
529
|
+
}
|
|
530
|
+
: {}),
|
|
531
|
+
});
|
|
422
532
|
for (const row of usageRows) {
|
|
423
|
-
emit({
|
|
533
|
+
emit({
|
|
534
|
+
kind: "fact",
|
|
535
|
+
fact: "model-usage",
|
|
536
|
+
providerId: row.providerId,
|
|
537
|
+
attributedModelId: row.attributedModelId,
|
|
538
|
+
requestedModelIds: [...row.requestedModelIds].sort(),
|
|
539
|
+
responseModelIdObservationCounts: row.responseModelIdObservationCounts,
|
|
540
|
+
...row.totals,
|
|
541
|
+
});
|
|
424
542
|
}
|
|
425
543
|
}
|
|
426
544
|
for (const [tool, totals] of topTools) emit({ kind: "fact", fact: "top-tool", tool, ...totals });
|
|
@@ -471,22 +589,44 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
|
|
|
471
589
|
out(` receipt store missing at ${presence.receiptsPath}`);
|
|
472
590
|
}
|
|
473
591
|
out(` audited tool calls in window: ${auditToolCalls.length} (${auditBlocked.length} blocked/denied)`);
|
|
474
|
-
if (
|
|
592
|
+
if (usageMeasurable) {
|
|
475
593
|
out(
|
|
476
594
|
` tokens in window: ${usageTotals.totalTokens} over ${usageTotals.apiCalls} model calls (input ${usageTotals.input}, output ${usageTotals.output}, cache read ${usageTotals.cacheRead}, cache write ${usageTotals.cacheWrite}, reasoning ${usageTotals.reasoningTokens})`,
|
|
477
595
|
);
|
|
596
|
+
if (hasLabelledCall(callOrigins)) {
|
|
597
|
+
// Only printed when a labelled call is in the window. Over an archive
|
|
598
|
+
// with none, these three lines would say nothing the line above does
|
|
599
|
+
// not already say, and their absence keeps the older output intact.
|
|
600
|
+
out(` turns in window: ${turnsOf(callOrigins)}`);
|
|
601
|
+
if (callOrigins.sideQuestions > 0) out(` side questions in window: ${callOrigins.sideQuestions}`);
|
|
602
|
+
if (callOrigins.handoffs > 0) out(` handoffs in window: ${callOrigins.handoffs}`);
|
|
603
|
+
}
|
|
478
604
|
out(` provider-reported cost in window: $${usageTotals.costUsd.toFixed(4)}`);
|
|
479
605
|
}
|
|
480
606
|
if (usageRows.length > 0) {
|
|
481
607
|
out("");
|
|
482
|
-
out(" tokens by model (from session ledgers
|
|
608
|
+
out(" tokens by attributed model (from session ledgers and provider-reported usage)");
|
|
483
609
|
process.stdout.write(
|
|
484
610
|
indent(
|
|
485
611
|
formatColumns([
|
|
486
|
-
[
|
|
612
|
+
[
|
|
613
|
+
"provider",
|
|
614
|
+
"attributed model",
|
|
615
|
+
"requested model ids",
|
|
616
|
+
"response model id observation",
|
|
617
|
+
"calls",
|
|
618
|
+
"input",
|
|
619
|
+
"output",
|
|
620
|
+
"cache read",
|
|
621
|
+
"reasoning",
|
|
622
|
+
"tokens",
|
|
623
|
+
"cost",
|
|
624
|
+
],
|
|
487
625
|
...usageRows.map((row) => [
|
|
488
626
|
row.providerId,
|
|
489
|
-
row.
|
|
627
|
+
row.attributedModelId,
|
|
628
|
+
[...row.requestedModelIds].sort().join(","),
|
|
629
|
+
responseModelIdObservationCountsLabel(row.responseModelIdObservationCounts),
|
|
490
630
|
String(row.totals.apiCalls),
|
|
491
631
|
String(row.totals.input),
|
|
492
632
|
String(row.totals.output),
|
package/src/core/bus-events.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import type { AgentAudience } from "../domains/agents/spec.js";
|
|
16
16
|
import type { ConfigDiff } from "../domains/config/classify.js";
|
|
17
|
+
import type { RunToolBudgetEnvelope } from "../domains/dispatch/budget-envelope.js";
|
|
17
18
|
import type {
|
|
18
19
|
DispatchRequestOrigin,
|
|
19
20
|
RunKind,
|
|
@@ -480,10 +481,14 @@ export interface DispatchRunIdentity {
|
|
|
480
481
|
wireModelId: string;
|
|
481
482
|
runtimeId: string;
|
|
482
483
|
runtimeKind: RunKind;
|
|
484
|
+
/** Admitted invocation budget provenance for native workers. */
|
|
485
|
+
budget?: RunToolBudgetEnvelope | undefined;
|
|
483
486
|
/** Fleet node id the run was placed on; absent renders as the local node. */
|
|
484
487
|
node?: string | undefined;
|
|
485
488
|
/** Review/compete gate role and cycle, for fleet board badges. */
|
|
486
489
|
gate?: { role: string; cycle: number } | undefined;
|
|
490
|
+
/** Council group presentation data for the Fleet Runs board. */
|
|
491
|
+
council?: { group: string; label: string; color?: string; round: number } | undefined;
|
|
487
492
|
/** Dead-node failover hops recorded on this run's chain so far. */
|
|
488
493
|
rerouteCount?: number | undefined;
|
|
489
494
|
/** Model context window in tokens, for the per-worker context meter. */
|
|
@@ -569,6 +574,8 @@ export interface DispatchTerminalStats {
|
|
|
569
574
|
exitCode: number;
|
|
570
575
|
/** Honest activity record aggregated from the run's tool telemetry; null when the receipt predates it. */
|
|
571
576
|
toolActivity: ToolActivitySummary | null;
|
|
577
|
+
/** Host-run declared verification status when the request included checks. */
|
|
578
|
+
hostVerification?: "verified" | "rejected" | "skipped";
|
|
572
579
|
}
|
|
573
580
|
|
|
574
581
|
/** Published on {@link BusChannels.DispatchCompleted} when a run finalizes as succeeded. */
|
|
@@ -16,7 +16,7 @@ export const CLIO_COMMIT_TRAILERS = {
|
|
|
16
16
|
} as const;
|
|
17
17
|
|
|
18
18
|
export interface CommitReceiptEvidence {
|
|
19
|
-
version:
|
|
19
|
+
version: 19;
|
|
20
20
|
algorithm: "sha256";
|
|
21
21
|
digest: string;
|
|
22
22
|
/** The receipt was checked against its run-ledger envelope. */
|
|
@@ -58,7 +58,7 @@ const KNOWN_CLIO_TRAILERS = new Set(
|
|
|
58
58
|
);
|
|
59
59
|
|
|
60
60
|
function isClioTrailer(key: string): boolean {
|
|
61
|
-
return KNOWN_CLIO_TRAILERS.has(key) || key.startsWith("clio-evidence:receipt-
|
|
61
|
+
return KNOWN_CLIO_TRAILERS.has(key) || key.startsWith("clio-evidence:receipt-v19/sha256:");
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/**
|
|
@@ -87,7 +87,7 @@ function trailerBlockStart(lines: ReadonlyArray<string>): number | null {
|
|
|
87
87
|
|
|
88
88
|
function receiptTrailer(receipt: CommitReceiptEvidence | undefined): string | null {
|
|
89
89
|
if (
|
|
90
|
-
receipt?.version !==
|
|
90
|
+
receipt?.version !== 19 ||
|
|
91
91
|
receipt.algorithm !== "sha256" ||
|
|
92
92
|
receipt.integrityValid !== true ||
|
|
93
93
|
receipt.directlyRelevant !== true ||
|
|
@@ -95,7 +95,7 @@ function receiptTrailer(receipt: CommitReceiptEvidence | undefined): string | nu
|
|
|
95
95
|
) {
|
|
96
96
|
return null;
|
|
97
97
|
}
|
|
98
|
-
return `Clio-Evidence: receipt-
|
|
98
|
+
return `Clio-Evidence: receipt-v19/sha256:${receipt.digest}`;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
/**
|
package/src/core/config.ts
CHANGED
|
@@ -19,7 +19,9 @@ import {
|
|
|
19
19
|
ACTIVE_AGENT_AUTOMATION_ROLES,
|
|
20
20
|
ACTIVE_ROUTING_POSTURES,
|
|
21
21
|
ACTIVE_ROUTING_ROLES,
|
|
22
|
+
COUNCIL_MEMBER_LABEL_PATTERN,
|
|
22
23
|
DEFAULT_SETTINGS,
|
|
24
|
+
THEME_NAMED_COLORS,
|
|
23
25
|
THINKING_LEVELS,
|
|
24
26
|
type ThinkingLevel,
|
|
25
27
|
} from "./defaults.js";
|
|
@@ -915,6 +917,37 @@ function validateMemorySettings(issues: Issues, value: unknown): ClioSettings["m
|
|
|
915
917
|
return out;
|
|
916
918
|
}
|
|
917
919
|
|
|
920
|
+
/**
|
|
921
|
+
* The watchdog block. `target` and `cadenceToolCalls` stay absent rather than
|
|
922
|
+
* taking sentinel values: an absent target means the session's active target,
|
|
923
|
+
* and an absent cadence means the watchdog fires only at turn end. A written
|
|
924
|
+
* default for either would turn "not configured" into a configuration.
|
|
925
|
+
*/
|
|
926
|
+
function validateWatchdogSettings(issues: Issues, value: unknown): ClioSettings["watchdog"] {
|
|
927
|
+
const out = cloneValue(DEFAULT_SETTINGS.watchdog);
|
|
928
|
+
if (!isPlainObject(value)) {
|
|
929
|
+
issues.add("watchdog", `expected a map, got ${describe(value)}`);
|
|
930
|
+
return out;
|
|
931
|
+
}
|
|
932
|
+
issues.unknownKeys("watchdog", value, ["enabled", "target", "cadenceToolCalls"]);
|
|
933
|
+
if ("enabled" in value) {
|
|
934
|
+
const enabled = expectBoolean(issues, "watchdog.enabled", value.enabled);
|
|
935
|
+
if (enabled !== undefined) out.enabled = enabled;
|
|
936
|
+
}
|
|
937
|
+
if ("target" in value && value.target !== null) {
|
|
938
|
+
const target = expectString(issues, "watchdog.target", value.target);
|
|
939
|
+
if (target !== undefined) {
|
|
940
|
+
if (target.trim().length === 0) issues.add("watchdog.target", "expected a non-empty target id");
|
|
941
|
+
else out.target = target.trim();
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
if ("cadenceToolCalls" in value && value.cadenceToolCalls !== null) {
|
|
945
|
+
const cadence = expectInteger(issues, "watchdog.cadenceToolCalls", value.cadenceToolCalls, { min: 1 });
|
|
946
|
+
if (cadence !== undefined) out.cadenceToolCalls = cadence;
|
|
947
|
+
}
|
|
948
|
+
return out;
|
|
949
|
+
}
|
|
950
|
+
|
|
918
951
|
function validateKeybindings(issues: Issues, value: unknown): ClioSettings["keybindings"] {
|
|
919
952
|
if (!isPlainObject(value)) {
|
|
920
953
|
issues.add("keybindings", `expected a map, got ${describe(value)}`);
|
|
@@ -954,6 +987,7 @@ const TOP_LEVEL_KEYS = [
|
|
|
954
987
|
"orchestrator",
|
|
955
988
|
"background",
|
|
956
989
|
"memory",
|
|
990
|
+
"watchdog",
|
|
957
991
|
"workers",
|
|
958
992
|
"fleet",
|
|
959
993
|
"routing",
|
|
@@ -964,6 +998,7 @@ const TOP_LEVEL_KEYS = [
|
|
|
964
998
|
"theme",
|
|
965
999
|
"terminal",
|
|
966
1000
|
"skills",
|
|
1001
|
+
"library",
|
|
967
1002
|
"attribution",
|
|
968
1003
|
"delegation",
|
|
969
1004
|
"keybindings",
|
|
@@ -1030,6 +1065,25 @@ export function validateSettings(raw: unknown): SettingsValidationResult {
|
|
|
1030
1065
|
const v = expectStringArray(issues, "runtimePlugins", raw.runtimePlugins);
|
|
1031
1066
|
if (v !== undefined) settings.runtimePlugins = v;
|
|
1032
1067
|
}
|
|
1068
|
+
if ("library" in raw) {
|
|
1069
|
+
if (!isPlainObject(raw.library)) {
|
|
1070
|
+
issues.add("library", `expected a map, got ${describe(raw.library)}`);
|
|
1071
|
+
} else {
|
|
1072
|
+
issues.unknownKeys("library", raw.library, ["catalog", "remote", "confirmedRemote", "sync"]);
|
|
1073
|
+
for (const key of ["catalog", "remote", "confirmedRemote"] as const) {
|
|
1074
|
+
const value = raw.library[key];
|
|
1075
|
+
if (value === undefined) continue;
|
|
1076
|
+
if (value !== null && typeof value !== "string")
|
|
1077
|
+
issues.add(`library.${key}`, `expected a string or null, got ${describe(value)}`);
|
|
1078
|
+
else settings.library[key] = value as string | null;
|
|
1079
|
+
}
|
|
1080
|
+
if (raw.library.sync !== undefined) {
|
|
1081
|
+
if (typeof raw.library.sync !== "boolean")
|
|
1082
|
+
issues.add("library.sync", `expected a boolean, got ${describe(raw.library.sync)}`);
|
|
1083
|
+
else settings.library.sync = raw.library.sync;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1033
1087
|
|
|
1034
1088
|
if ("orchestrator" in raw) {
|
|
1035
1089
|
settings.orchestrator = validateWorkerTarget(
|
|
@@ -1050,6 +1104,7 @@ export function validateSettings(raw: unknown): SettingsValidationResult {
|
|
|
1050
1104
|
);
|
|
1051
1105
|
}
|
|
1052
1106
|
if ("memory" in raw) settings.memory = validateMemorySettings(issues, raw.memory);
|
|
1107
|
+
if ("watchdog" in raw) settings.watchdog = validateWatchdogSettings(issues, raw.watchdog);
|
|
1053
1108
|
|
|
1054
1109
|
// Fleet nodes validate before workers so profile node pins can be checked
|
|
1055
1110
|
// against the configured node ids.
|
|
@@ -1146,6 +1201,7 @@ export function validateSettings(raw: unknown): SettingsValidationResult {
|
|
|
1146
1201
|
issues.unknownKeys("workers", raw.workers, [
|
|
1147
1202
|
"default",
|
|
1148
1203
|
"profiles",
|
|
1204
|
+
"rosters",
|
|
1149
1205
|
"agentBindings",
|
|
1150
1206
|
"maxRetries",
|
|
1151
1207
|
"onPermission",
|
|
@@ -1187,6 +1243,75 @@ export function validateSettings(raw: unknown): SettingsValidationResult {
|
|
|
1187
1243
|
settings.workers.profiles = profiles;
|
|
1188
1244
|
}
|
|
1189
1245
|
}
|
|
1246
|
+
if ("rosters" in raw.workers) {
|
|
1247
|
+
if (!isPlainObject(raw.workers.rosters)) {
|
|
1248
|
+
issues.add("workers.rosters", `expected a map, got ${describe(raw.workers.rosters)}`);
|
|
1249
|
+
} else {
|
|
1250
|
+
const rosters: ClioSettings["workers"]["rosters"] = {};
|
|
1251
|
+
for (const [rawName, rawRoster] of Object.entries(raw.workers.rosters)) {
|
|
1252
|
+
const name = rawName.trim();
|
|
1253
|
+
const path = `workers.rosters.${name}`;
|
|
1254
|
+
if (!name) {
|
|
1255
|
+
issues.add("workers.rosters", "empty roster name");
|
|
1256
|
+
continue;
|
|
1257
|
+
}
|
|
1258
|
+
if (!isPlainObject(rawRoster)) {
|
|
1259
|
+
issues.add(path, `expected a map, got ${describe(rawRoster)}`);
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1262
|
+
issues.unknownKeys(path, rawRoster, ["members"]);
|
|
1263
|
+
if (!Array.isArray(rawRoster.members)) {
|
|
1264
|
+
issues.add(`${path}.members`, "expected a list");
|
|
1265
|
+
continue;
|
|
1266
|
+
}
|
|
1267
|
+
if (rawRoster.members.length < 2 || rawRoster.members.length > 5) {
|
|
1268
|
+
issues.add(`${path}.members`, "expected 2 to 5 members");
|
|
1269
|
+
}
|
|
1270
|
+
const members: ClioSettings["workers"]["rosters"][string]["members"] = [];
|
|
1271
|
+
const labels = new Set<string>();
|
|
1272
|
+
for (const [index, rawMember] of rawRoster.members.entries()) {
|
|
1273
|
+
const memberPath = `${path}.members[${index}]`;
|
|
1274
|
+
if (!isPlainObject(rawMember)) {
|
|
1275
|
+
issues.add(memberPath, `expected a map, got ${describe(rawMember)}`);
|
|
1276
|
+
continue;
|
|
1277
|
+
}
|
|
1278
|
+
issues.unknownKeys(memberPath, rawMember, ["label", "target", "model", "thinking", "color"]);
|
|
1279
|
+
const label = expectString(issues, `${memberPath}.label`, rawMember.label);
|
|
1280
|
+
const target = expectString(issues, `${memberPath}.target`, rawMember.target);
|
|
1281
|
+
if (label !== undefined && !COUNCIL_MEMBER_LABEL_PATTERN.test(label)) {
|
|
1282
|
+
issues.add(`${memberPath}.label`, "expected [a-z][a-z0-9_-]{0,31}");
|
|
1283
|
+
}
|
|
1284
|
+
if (label !== undefined && labels.has(label)) issues.add(`${memberPath}.label`, "duplicate label");
|
|
1285
|
+
if (label !== undefined) labels.add(label);
|
|
1286
|
+
if (target !== undefined && !settings.targets.some((entry) => entry.id === target)) {
|
|
1287
|
+
issues.add(`${memberPath}.target`, `unknown target '${target}'`);
|
|
1288
|
+
}
|
|
1289
|
+
const model =
|
|
1290
|
+
rawMember.model === undefined ? undefined : expectString(issues, `${memberPath}.model`, rawMember.model);
|
|
1291
|
+
const thinking =
|
|
1292
|
+
rawMember.thinking === undefined
|
|
1293
|
+
? undefined
|
|
1294
|
+
: expectEnum(issues, `${memberPath}.thinking`, rawMember.thinking, THINKING_LEVELS);
|
|
1295
|
+
const color =
|
|
1296
|
+
rawMember.color === undefined ? undefined : expectString(issues, `${memberPath}.color`, rawMember.color);
|
|
1297
|
+
if (color !== undefined && !THEME_NAMED_COLORS.includes(color as never) && !/^#[0-9a-fA-F]{6}$/u.test(color)) {
|
|
1298
|
+
issues.add(`${memberPath}.color`, "expected a theme named color or 6-digit hex color");
|
|
1299
|
+
}
|
|
1300
|
+
if (label === undefined || target === undefined) continue;
|
|
1301
|
+
members.push({
|
|
1302
|
+
label,
|
|
1303
|
+
target,
|
|
1304
|
+
...(model ? { model } : {}),
|
|
1305
|
+
...(thinking ? { thinking } : {}),
|
|
1306
|
+
...(color ? { color } : {}),
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1309
|
+
if (rawRoster.members.length >= 2 && rawRoster.members.length <= 5 && members.length === rawRoster.members.length)
|
|
1310
|
+
rosters[name] = { members };
|
|
1311
|
+
}
|
|
1312
|
+
settings.workers.rosters = rosters;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1190
1315
|
if ("agentBindings" in raw.workers) {
|
|
1191
1316
|
if (!isPlainObject(raw.workers.agentBindings)) {
|
|
1192
1317
|
issues.add("workers.agentBindings", `expected a map, got ${describe(raw.workers.agentBindings)}`);
|
|
@@ -1318,6 +1443,7 @@ export function validateSettings(raw: unknown): SettingsValidationResult {
|
|
|
1318
1443
|
"tuiMode",
|
|
1319
1444
|
"fullscreenScrollbar",
|
|
1320
1445
|
"smoothStreaming",
|
|
1446
|
+
"notify",
|
|
1321
1447
|
]);
|
|
1322
1448
|
if ("showTerminalProgress" in raw.terminal) {
|
|
1323
1449
|
const v = expectBoolean(issues, "terminal.showTerminalProgress", raw.terminal.showTerminalProgress);
|
|
@@ -1343,6 +1469,10 @@ export function validateSettings(raw: unknown): SettingsValidationResult {
|
|
|
1343
1469
|
if (v === "off" || v === "auto" || v === "on") settings.terminal.smoothStreaming = v;
|
|
1344
1470
|
else if (v !== undefined) issues.add("terminal.smoothStreaming", "expected off, auto, or on");
|
|
1345
1471
|
}
|
|
1472
|
+
if ("notify" in raw.terminal) {
|
|
1473
|
+
const v = expectBoolean(issues, "terminal.notify", raw.terminal.notify);
|
|
1474
|
+
if (v !== undefined) settings.terminal.notify = v;
|
|
1475
|
+
}
|
|
1346
1476
|
}
|
|
1347
1477
|
}
|
|
1348
1478
|
|