@iowarp/clio-coder 0.3.7 → 0.3.9
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 +80 -0
- package/README.md +13 -4
- package/dist/{acp-SK4MD6MM.js → acp-7LOELQFP.js} +13 -13
- package/dist/{agents-2FN2K6ME.js → agents-FIBG2SHA.js} +41 -37
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-QIYZWM5I.js → auth-OI4LIH2I.js} +31 -24
- package/dist/builtins-AD25UL3C.js +17 -0
- package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
- package/dist/chunk-3DPEIQKN.js +113 -0
- package/dist/{chunk-EOOQZZDE.js → chunk-3DUR4WUA.js} +19 -19
- package/dist/{chunk-WHJYKASB.js → chunk-3MRC2YSQ.js} +2 -2
- package/dist/{chunk-EBEFWSGL.js → chunk-3UUY7R3Z.js} +14 -10
- package/dist/{chunk-LADCF22A.js → chunk-3V5AYSEQ.js} +113 -54
- package/dist/{chunk-BMWK7ZIZ.js → chunk-465CC7FK.js} +16 -13
- package/dist/{chunk-5WIGXA4T.js → chunk-47CMYGET.js} +111 -4
- package/dist/{chunk-CEYBNUGC.js → chunk-4H6ULJ3H.js} +378 -36
- package/dist/{chunk-YTYFXUI3.js → chunk-4LJX2PUC.js} +9 -9
- package/dist/{chunk-DOOEX22V.js → chunk-56KB5IJP.js} +5 -5
- package/dist/{chunk-SPULKLCF.js → chunk-5DQRIYDZ.js} +2 -2
- package/dist/{chunk-TSHXZTOQ.js → chunk-5HFBWUMU.js} +23 -11
- package/dist/{chunk-5UJ6ECTS.js → chunk-5PVQ4SRS.js} +80 -8
- package/dist/{chunk-ZWLZP4ZT.js → chunk-5QKCQQ3E.js} +359 -17
- package/dist/{chunk-6M7VS3J3.js → chunk-5T7RBWN2.js} +111 -5
- package/dist/chunk-774ILSRL.js +172 -0
- package/dist/chunk-7C6RYZGQ.js +391 -0
- package/dist/{chunk-GH5622CP.js → chunk-A2NJGIB3.js} +2 -2
- package/dist/{chunk-C4JBQ5SR.js → chunk-AD7Y7STJ.js} +6 -6
- package/dist/{chunk-GEYXPTRF.js → chunk-AEYBF3TB.js} +33 -12
- package/dist/{chunk-2SFS6XQE.js → chunk-AMKHQW3C.js} +3 -2
- package/dist/{chunk-D4MDIG46.js → chunk-B5CSFE7B.js} +7 -7
- package/dist/{chunk-MXI6J5JF.js → chunk-B5XRQOLB.js} +10 -10
- package/dist/{chunk-X2KV5FXT.js → chunk-BVDVID7E.js} +2 -2
- package/dist/{chunk-JNXPYBB4.js → chunk-CA42X6KT.js} +3 -3
- package/dist/{chunk-VREKEFLL.js → chunk-D73KXYPF.js} +3 -3
- package/dist/{chunk-JTSEDYVQ.js → chunk-DG4M6ZUE.js} +7 -7
- package/dist/{chunk-DQA7QLMD.js → chunk-EBOC7MT3.js} +10 -25
- package/dist/{chunk-KZ2H5X4G.js → chunk-ECUO3KDP.js} +129 -14
- package/dist/{chunk-JRIO5UD2.js → chunk-EQ63NRB7.js} +5 -5
- package/dist/{chunk-YD734TPH.js → chunk-FALJGAWU.js} +2 -2
- package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
- package/dist/{chunk-XEGB6BCN.js → chunk-GAYUJ7LE.js} +68 -14
- package/dist/{chunk-UND3GU2L.js → chunk-H7IXIC72.js} +2 -2
- package/dist/{chunk-IR4CFBFN.js → chunk-HAY4ZE2P.js} +12 -12
- package/dist/{chunk-UVDSQ6LW.js → chunk-HCBCAYZU.js} +74 -147
- package/dist/{chunk-4DWFMQDR.js → chunk-HJB5IUKP.js} +89 -145
- package/dist/{chunk-M4AKACEO.js → chunk-HKO36JWF.js} +33 -5
- package/dist/{chunk-KCMKRQX4.js → chunk-HPCTNZM2.js} +45 -82
- package/dist/{chunk-465YSENW.js → chunk-IFBNV6H6.js} +3 -3
- package/dist/{chunk-FJ3H4MN5.js → chunk-IHKBWSXF.js} +2 -2
- package/dist/chunk-JEQQR47K.js +3025 -0
- package/dist/{chunk-FO5ZOVUY.js → chunk-KV2AOLDF.js} +27 -7
- package/dist/chunk-LU7P4LHA.js +33 -0
- package/dist/{chunk-6TUKSZVF.js → chunk-LXPJXFM5.js} +11 -11
- package/dist/{chunk-VQNODYQ4.js → chunk-MIX5N5AC.js} +488 -3668
- package/dist/chunk-MLOK6ZOS.js +2888 -0
- package/dist/{chunk-ZZMN5OM4.js → chunk-MV2VUEJC.js} +2 -2
- package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
- package/dist/{chunk-OBMAI2DP.js → chunk-N3PBVRTZ.js} +12 -388
- package/dist/{chunk-WJHBC77E.js → chunk-N5XKWMDW.js} +17 -7
- package/dist/{chunk-5C3AQNDW.js → chunk-NNNWO6F2.js} +124 -36
- package/dist/{chunk-UFQ3F4FW.js → chunk-NQ6UCCOD.js} +4 -4
- package/dist/chunk-NUGM5KR6.js +165 -0
- package/dist/{chunk-DMD2AGVS.js → chunk-NZU6YDNV.js} +20 -18
- package/dist/{chunk-WHGPSPT5.js → chunk-O6I4CIEU.js} +151 -13
- package/dist/{chunk-XN3L4EYL.js → chunk-OEDBCISO.js} +2 -2
- package/dist/{chunk-PD3MESLB.js → chunk-P3JGPQFL.js} +4 -4
- package/dist/{chunk-UHXRNZ2J.js → chunk-PNY46YEY.js} +23 -6
- package/dist/{chunk-THKY7CD7.js → chunk-PZ4I4JE2.js} +134 -29
- package/dist/{chunk-SROCI7ZU.js → chunk-QQ7EKM72.js} +5 -5
- package/dist/{chunk-QCTRSGHQ.js → chunk-R7LNVMCS.js} +91 -53
- package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
- package/dist/chunk-RKKLTLYB.js +45 -0
- package/dist/{chunk-OB5HIGJY.js → chunk-RKRLDWD3.js} +4 -1
- package/dist/{chunk-DJNLUABN.js → chunk-S4COXYBG.js} +588 -32
- package/dist/{chunk-3HAPLH5M.js → chunk-T3Z6VAAF.js} +172 -11
- package/dist/{chunk-FOT2FX5J.js → chunk-TD7UE2L5.js} +12 -10
- package/dist/{chunk-UUANF5CR.js → chunk-TEO2TLVN.js} +856 -967
- package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
- package/dist/{chunk-EELBMBT6.js → chunk-VKBMFOYV.js} +74 -15
- package/dist/chunk-VO2LKSTM.js +165 -0
- package/dist/{chunk-5C77SEEY.js → chunk-VPTUJU4P.js} +3 -3
- package/dist/{chunk-WEH5XRJQ.js → chunk-WIE7ZOSW.js} +2 -2
- package/dist/{chunk-J7PIKKWC.js → chunk-WXCJ7VME.js} +8 -8
- package/dist/{chunk-4DGYLA73.js → chunk-XDOQXGFO.js} +22 -7
- package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
- package/dist/{chunk-AB4XIIVB.js → chunk-YKOFT37S.js} +6 -6
- package/dist/chunk-YSEHGPCT.js +127 -0
- package/dist/{chunk-HFSBBKSQ.js → chunk-YW7UVM5V.js} +138 -3
- package/dist/cli/index.js +32 -32
- package/dist/{clio-WBVQEBKO.js → clio-LT5V7SSZ.js} +9 -9
- package/dist/{code-nav-FGGFIE7L.js → code-nav-LMW275PA.js} +5 -5
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-F7OEATSO.js → components-ZFA3SAER.js} +8 -8
- package/dist/{config-TRBL3RCF.js → config-RXS5T3JT.js} +98 -65
- package/dist/{configure-OLCVPHNM.js → configure-2WYWSCSD.js} +26 -22
- package/dist/{context-MJIJ6GOX.js → context-I3BTOTCS.js} +12 -12
- package/dist/{context-XEWE3MOJ.js → context-MVOORGMF.js} +54 -47
- package/dist/{context-WFPKQSM6.js → context-PALKKQYL.js} +28 -28
- package/dist/{context-clear-KNOS2JPB.js → context-clear-N2WOYZ2K.js} +53 -46
- package/dist/{context-index-SSR5ECNE.js → context-index-HNG3MOME.js} +6 -6
- package/dist/{context-working-set-EUXAZI6N.js → context-working-set-MIEVECVZ.js} +17 -18
- package/dist/{dispatch-runner-B7MTOVKL.js → dispatch-runner-VVA4SRRH.js} +90 -61
- package/dist/{docs-FLJTIDSE.js → docs-7LQ23DLM.js} +8 -8
- package/dist/doctor-TWBWFK5V.js +165 -0
- package/dist/eval-IJ5VEZDJ.js +4483 -0
- package/dist/{evidence-JZNBUOQZ.js → evidence-L5APPXNV.js} +68 -61
- package/dist/{evolve-FJVC4KKI.js → evolve-RGNKFJ52.js} +47 -40
- package/dist/{extensions-IQL36S7K.js → extensions-7WYWUX5A.js} +13 -7
- package/dist/{fleet-BDKYJFCP.js → fleet-6CNVBZZP.js} +113 -76
- package/dist/{fleet-commands-ZFIWZSB3.js → fleet-commands-L2SXSYEI.js} +10 -10
- package/dist/{fleet-graph-Y6HPXIVF.js → fleet-graph-2J3OOIPO.js} +17 -15
- package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-CZRJ4JP5.js} +5 -6
- package/dist/{fleet-validate-BIYREGIK.js → fleet-validate-C5RI6DP7.js} +20 -19
- package/dist/{init-LQUB5COQ.js → init-VBN2ACVA.js} +70 -63
- package/dist/{library-NJAHIGG4.js → library-JHGUMLY2.js} +22 -20
- package/dist/{memory-OG6HOYKM.js → memory-K4OQIYWG.js} +49 -42
- package/dist/{models-5ZG5XY7J.js → models-2NCZUWDD.js} +35 -29
- package/dist/{monitor-TJ7AMTGB.js → monitor-MMVTJABD.js} +64 -45
- package/dist/{orchestrator-WZYB54DM.js → orchestrator-ZKBPCHW6.js} +1971 -520
- package/dist/{paths-XUC7GS6E.js → paths-DBXMZMDU.js} +5 -5
- package/dist/registry-LG64LTF4.js +11 -0
- package/dist/{reset-PXQT45IY.js → reset-DD5JGOY3.js} +11 -11
- package/dist/{run-FQ74YF62.js → run-QEGNX7FL.js} +89 -83
- package/dist/{share-FW7SVCL3.js → share-JKD3BQMW.js} +20 -18
- package/dist/{skills-7E7IRB3R.js → skills-LMQIKDOZ.js} +23 -21
- package/dist/{skills-eval-LI75W6OK.js → skills-eval-I7X2774U.js} +59 -52
- package/dist/{steer-GGWFUJUD.js → steer-CF5TDANS.js} +3 -3
- package/dist/support-I7LOJLIF.js +38 -0
- package/dist/{targets-4CIFKCTW.js → targets-RUSR6B5Z.js} +77 -42
- package/dist/{terminal-lease-WUZY7ZV5.js → terminal-lease-QYVORFR4.js} +6 -4
- package/dist/{trace-PNCASAXC.js → trace-ODOQIVIW.js} +61 -6
- package/dist/{uninstall-7FV7IP4E.js → uninstall-ZJF5H5ZN.js} +8 -8
- package/dist/{upgrade-K2HVIVMQ.js → upgrade-XANW3FXB.js} +29 -26
- package/dist/{usage-GTZELZQX.js → usage-4H7ZRXQT.js} +110 -61
- package/dist/{verifiers-RLAHT27O.js → verifiers-UZXNBZEB.js} +13 -13
- package/dist/{verify-BX3BRKH5.js → verify-BVKWTNDL.js} +9 -9
- package/dist/{wiki-generate-ASIFASCN.js → wiki-generate-MY7WV2QI.js} +76 -69
- package/dist/worker/entry.js +69 -66
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +1 -1
- package/docs/artifact-versions.md +11 -5
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +23 -2
- package/docs/commands-and-modes.md +2 -2
- package/docs/configuration-and-targets.md +37 -5
- package/docs/context-engine.md +63 -4
- package/docs/documentation-coverage.md +3 -3
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +2 -0
- package/docs/eval-runner.md +262 -11
- package/docs/evals-internal.md +72 -2
- package/docs/evidence-and-memory.md +77 -12
- package/docs/evolution.md +1 -1
- package/docs/extensions-and-sharing.md +3 -1
- package/docs/fleet-dispatch.md +34 -9
- package/docs/glossary.md +21 -1
- package/docs/installation-and-lifecycle.md +1 -1
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +1 -1
- package/docs/observability.md +54 -3
- package/docs/proactive-memory.md +127 -14
- package/docs/prompt-envelope-and-tools.md +22 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +60 -41
- package/docs/safety-model.md +1 -1
- package/docs/scientific-validation.md +1 -1
- package/docs/skills-marketplace.md +1 -1
- package/docs/tool-usage.md +1 -1
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +87 -0
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +2 -2
- package/src/cli/agents.ts +1 -1
- package/src/cli/argv.ts +5 -0
- package/src/cli/config-inspect.ts +33 -6
- package/src/cli/config.ts +1 -1
- package/src/cli/configure.ts +107 -23
- package/src/cli/doctor-state-size.ts +82 -0
- package/src/cli/doctor.ts +7 -1
- package/src/cli/eval.ts +80 -16
- package/src/cli/evidence.ts +30 -25
- package/src/cli/extensions.ts +5 -1
- package/src/cli/fleet-preflight.ts +2 -12
- package/src/cli/fleet.ts +32 -3
- package/src/cli/shared.ts +1 -0
- package/src/cli/targets.ts +45 -11
- package/src/cli/trace.ts +63 -4
- package/src/cli/usage.ts +63 -14
- package/src/cli/validate-model.ts +60 -5
- package/src/core/bus-events.ts +54 -1
- package/src/core/cache-telemetry.ts +42 -0
- package/src/core/commit-attribution.ts +4 -4
- package/src/core/config.ts +18 -0
- package/src/core/defaults.ts +36 -6
- package/src/core/endpoint-key.ts +27 -0
- package/src/core/path-boundary.ts +100 -0
- package/src/core/residency-target-key.ts +25 -0
- package/src/core/response-schema.ts +36 -2
- package/src/domains/agents/extension.ts +2 -11
- package/src/domains/agents/fleet-contract.ts +30 -12
- package/src/domains/agents/recipe.ts +7 -1
- package/src/domains/agents/registry.ts +73 -5
- package/src/domains/agents/result-contract.ts +128 -17
- package/src/domains/agents/write-boundary.ts +15 -50
- package/src/domains/config/classify.ts +3 -0
- package/src/domains/context/codewiki/coordinator.ts +12 -4
- package/src/domains/context/project-rules.ts +51 -1
- package/src/domains/dispatch/admission.ts +40 -3
- package/src/domains/dispatch/assignment-reconcile.ts +22 -5
- package/src/domains/dispatch/assignment-store.ts +151 -14
- package/src/domains/dispatch/capacity-lease.ts +98 -9
- package/src/domains/dispatch/contract.ts +26 -1
- package/src/domains/dispatch/delegation-plan.ts +2 -5
- package/src/domains/dispatch/execution-plan.ts +44 -4
- package/src/domains/dispatch/execution-role.ts +9 -1
- package/src/domains/dispatch/extension.ts +309 -96
- package/src/domains/dispatch/fleet-run.ts +78 -4
- package/src/domains/dispatch/gate-role-prompts.ts +38 -0
- package/src/domains/dispatch/heartbeat.ts +32 -8
- package/src/domains/dispatch/index.ts +6 -1
- package/src/domains/dispatch/intent-requirements.ts +40 -0
- package/src/domains/dispatch/intent.ts +84 -8
- package/src/domains/dispatch/orphan-recovery.ts +5 -0
- package/src/domains/dispatch/path-scope.ts +370 -0
- package/src/domains/dispatch/receipt-integrity.ts +2 -1
- package/src/domains/dispatch/reservation-store.ts +116 -8
- package/src/domains/dispatch/state.ts +4 -0
- package/src/domains/dispatch/types.ts +14 -7
- package/src/domains/dispatch/validation.ts +6 -3
- package/src/domains/dispatch/worker-spawn.ts +25 -11
- package/src/domains/dispatch/write-boundary-enforcer.ts +62 -0
- package/src/domains/dispatch/write-boundary.ts +262 -22
- package/src/domains/eval/artifacts/store.ts +62 -0
- package/src/domains/eval/compare/behavioral.ts +224 -0
- package/src/domains/eval/compare/compare.ts +355 -2
- package/src/domains/eval/compare/envelope.ts +128 -0
- package/src/domains/eval/compare/gates.ts +24 -6
- package/src/domains/eval/compare/thresholds.ts +30 -3
- package/src/domains/eval/execution-provenance.ts +240 -0
- package/src/domains/eval/metrics/aggregate.ts +136 -0
- package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
- package/src/domains/eval/metrics/evidence.ts +79 -2
- package/src/domains/eval/metrics/tracked.ts +413 -0
- package/src/domains/eval/provenance.ts +117 -0
- package/src/domains/eval/reports/comparison.ts +128 -0
- package/src/domains/eval/reports/junit.ts +17 -3
- package/src/domains/eval/reports/markdown.ts +3 -3
- package/src/domains/eval/reports/text.ts +14 -0
- package/src/domains/eval/run-compare.ts +20 -0
- package/src/domains/eval/runners/clio-run.ts +139 -2
- package/src/domains/eval/runners/external-command.ts +28 -3
- package/src/domains/eval/schema/adapter.ts +111 -0
- package/src/domains/eval/schema/artifact.ts +20 -0
- package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
- package/src/domains/eval/schema/behavioral.ts +520 -0
- package/src/domains/eval/schema/execution-envelope.ts +194 -0
- package/src/domains/eval/schema/serving.ts +74 -0
- package/src/domains/eval/schema/suite.ts +38 -8
- package/src/domains/eval/schema/validate.ts +58 -3
- package/src/domains/eval/schema/verdict.ts +237 -0
- package/src/domains/eval/suites/resolve.ts +2 -0
- package/src/domains/eval/suites/run.ts +264 -33
- package/src/domains/eval/verifiers/command.ts +2 -1
- package/src/domains/eval/workspaces/temp-copy.ts +145 -13
- package/src/domains/evidence/build.ts +68 -21
- package/src/domains/evidence/eval.ts +2 -12
- package/src/domains/evidence/findings-markdown.ts +33 -0
- package/src/domains/evidence/index.ts +21 -0
- package/src/domains/evidence/provenance.ts +46 -11
- package/src/domains/evidence/run-trust.ts +7 -113
- package/src/domains/evidence/trust-projection.ts +274 -0
- package/src/domains/evidence/trust-status.ts +145 -17
- package/src/domains/evidence/types.ts +4 -0
- package/src/domains/extensions/compatibility.ts +285 -0
- package/src/domains/extensions/discovery.ts +126 -4
- package/src/domains/extensions/resources.ts +21 -9
- package/src/domains/extensions/state.ts +18 -5
- package/src/domains/extensions/types.ts +6 -1
- package/src/domains/lifecycle/doctor.ts +209 -2
- package/src/domains/memory/index.ts +14 -0
- package/src/domains/memory/task-bank-promotion.ts +64 -0
- package/src/domains/memory/task-memory-policy.ts +77 -8
- package/src/domains/memory/task-memory-spend.ts +131 -0
- package/src/domains/memory/task-memory-status.ts +7 -0
- package/src/domains/memory/task-memory-telemetry.ts +2 -0
- package/src/domains/middleware/index.ts +1 -0
- package/src/domains/middleware/memory-intervention.ts +69 -5
- package/src/domains/middleware/memory-step-endpoint.ts +71 -0
- package/src/domains/observability/background-memory-usage.ts +140 -0
- package/src/domains/observability/cost.ts +1 -1
- package/src/domains/observability/index.ts +7 -0
- package/src/domains/observability/out-of-turn-usage.ts +51 -2
- package/src/domains/observability/trace-store.ts +192 -2
- package/src/domains/prompts/compiler.ts +100 -13
- package/src/domains/prompts/contract.ts +3 -5
- package/src/domains/providers/endpoint-capacity.ts +96 -0
- package/src/domains/providers/extension.ts +30 -2
- package/src/domains/providers/index.ts +10 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
- package/src/domains/providers/runtime-resolution.ts +8 -1
- package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
- package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
- package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
- package/src/domains/providers/types/capability-flags.ts +2 -0
- package/src/domains/providers/types/target-descriptor.ts +2 -0
- package/src/domains/resources/common-loader.ts +3 -0
- package/src/domains/resources/prompts/loader.ts +184 -17
- package/src/domains/safety/call-target.ts +52 -0
- package/src/domains/safety/policy-engine.ts +5 -5
- package/src/domains/safety/run-effects.ts +96 -2
- package/src/domains/safety/scope.ts +7 -12
- package/src/domains/session/context-accounting.ts +52 -1
- package/src/domains/session/context-ledger.ts +37 -13
- package/src/domains/session/index.ts +6 -0
- package/src/domains/session/prompt-cache.ts +140 -0
- package/src/domains/session/prompt-manifest.ts +42 -0
- package/src/engine/acp/adapter.ts +18 -3
- package/src/engine/acp/server.ts +4 -1
- package/src/engine/ai.ts +35 -0
- package/src/engine/apis/llamacpp-residency.ts +55 -3
- package/src/engine/apis/lmstudio.ts +25 -5
- package/src/engine/apis/ollama-native.ts +2 -1
- package/src/engine/apis/openai-completions.ts +80 -17
- package/src/engine/apis/residency-lock.ts +3 -1
- package/src/engine/apis/residency.ts +34 -1
- package/src/engine/prompt-templates.ts +18 -1
- package/src/engine/provider-payload.ts +29 -1
- package/src/engine/worker-runtime.ts +6 -3
- package/src/entry/orchestrator.ts +176 -30
- package/src/interactive/chat-loop-messages.ts +26 -7
- package/src/interactive/chat-loop.ts +318 -41
- package/src/interactive/chat-panel.ts +62 -8
- package/src/interactive/clio-editor.ts +45 -8
- package/src/interactive/context-activity.ts +5 -1
- package/src/interactive/context-meter.ts +1 -1
- package/src/interactive/context-overlay.ts +40 -10
- package/src/interactive/cost-overlay.ts +64 -6
- package/src/interactive/dispatch-board.ts +127 -5
- package/src/interactive/fleet-run-preview.ts +41 -15
- package/src/interactive/handoff-round.ts +41 -2
- package/src/interactive/interactive-application.ts +24 -1
- package/src/interactive/interactive-event-projection.ts +14 -0
- package/src/interactive/interactive-input-runtime.ts +8 -0
- package/src/interactive/interactive-presentation.ts +4 -0
- package/src/interactive/interactive-shell.ts +20 -17
- package/src/interactive/interactive-slash-runtime.ts +27 -4
- package/src/interactive/memory-overlay.ts +8 -0
- package/src/interactive/mutation-preview.ts +295 -0
- package/src/interactive/overlay-general-openers.ts +16 -0
- package/src/interactive/overlay-key-routing.ts +38 -0
- package/src/interactive/overlay-lifecycle.ts +38 -5
- package/src/interactive/overlay-permission-lifecycle.ts +22 -2
- package/src/interactive/overlay-session-lifecycle.ts +73 -9
- package/src/interactive/overlays/ask-user.ts +91 -19
- package/src/interactive/overlays/help-reference.ts +4 -0
- package/src/interactive/overlays/prompts.ts +11 -1
- package/src/interactive/overlays/settings.ts +176 -48
- package/src/interactive/permission-hint.ts +34 -2
- package/src/interactive/permission-overlay.ts +159 -9
- package/src/interactive/prewarm.ts +197 -0
- package/src/interactive/render-trace.ts +162 -15
- package/src/interactive/renderers/tool-execution.ts +4 -0
- package/src/interactive/side-question.ts +58 -1
- package/src/interactive/slash-commands.ts +7 -2
- package/src/interactive/status/controller.ts +11 -0
- package/src/interactive/status/state-machine.ts +54 -2
- package/src/interactive/status/types.ts +7 -0
- package/src/interactive/terminal-lease.ts +2 -0
- package/src/interactive/turn-context.ts +299 -31
- package/src/interactive/turn-persistence.ts +14 -4
- package/src/interactive/turn-prewarm.ts +364 -0
- package/src/interactive/turn-queues.ts +7 -4
- package/src/interactive/turn-runtime.ts +8 -1
- package/src/interactive/turn-state.ts +23 -0
- package/src/interactive/view/artifacts.ts +42 -9
- package/src/interactive/view/view-overlay.ts +43 -6
- package/src/interactive/worker-receipts.ts +14 -2
- package/src/interactive/worker-stream.ts +8 -0
- package/src/tools/ask-user.ts +43 -2
- package/src/tools/dispatch-admission.ts +12 -13
- package/src/tools/dispatch-arguments.ts +27 -0
- package/src/tools/dispatch-plan.ts +46 -9
- package/src/tools/dispatch-runner.ts +48 -13
- package/src/tools/dispatch-scout.ts +1 -1
- package/src/tools/monitor.ts +13 -0
- package/src/tools/registry.ts +16 -0
- package/src/tools/worker-evidence.ts +19 -13
- package/src/worker/spec-contract.ts +2 -1
- package/dist/chunk-AOCYTWAV.js +0 -449
- package/dist/chunk-HWUFFB6L.js +0 -83
- package/dist/chunk-R346GLFC.js +0 -31
- package/dist/chunk-ZGH7FGS5.js +0 -1079
- package/dist/doctor-RN4YKO2X.js +0 -87
- package/dist/eval-RUBJVSNQ.js +0 -2557
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iowarp/clio-coder",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "Coding agent for HPC and scientific-software developers, part of IOWarp's CLIO ecosystem of agentic science.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
"//": "below here: a real model target, chosen with --target <id>; costs money and/or GPU time, never run in CI",
|
|
93
93
|
"live:smoke": "node --import tsx benchmarks/internal/live-smoke.ts",
|
|
94
94
|
"live:fleet-dispatch": "node --import tsx benchmarks/internal/live-fleet-dispatch.ts",
|
|
95
|
+
"live:release-residue": "node --import tsx tests/live/release-residue.ts",
|
|
95
96
|
"live:tui": "node --import tsx benchmarks/internal/pty-drive.ts",
|
|
96
97
|
"live:home": "node --import tsx benchmarks/internal/live-home.ts"
|
|
97
98
|
},
|
|
@@ -107,7 +108,6 @@
|
|
|
107
108
|
},
|
|
108
109
|
"overrides": {
|
|
109
110
|
"@anthropic-ai/sdk": "0.105.0",
|
|
110
|
-
"ip-address": "10.2.0",
|
|
111
111
|
"esbuild": "0.28.1"
|
|
112
112
|
},
|
|
113
113
|
"devDependencies": {
|
package/src/cli/agents.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { printError } from "./shared.js";
|
|
|
9
9
|
|
|
10
10
|
const HELP = `clio-coder agents [--json] [--all]
|
|
11
11
|
|
|
12
|
-
List user-facing agent specs from built-in, user, and project recipes.
|
|
12
|
+
List user-facing agent specs from built-in, extension, user, and project recipes.
|
|
13
13
|
|
|
14
14
|
Flags:
|
|
15
15
|
--json emit specs as JSON instead of the formatted table
|
package/src/cli/argv.ts
CHANGED
|
@@ -15,6 +15,11 @@ export function printError(message: string, detail?: string): void {
|
|
|
15
15
|
if (detail) process.stderr.write(` ${detail}\n`);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/** An expected condition worth a line on stderr that is neither an error nor a success. */
|
|
19
|
+
export function printNote(message: string): void {
|
|
20
|
+
process.stderr.write(`${chalk.yellow("note:")} ${message}\n`);
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
export function printOk(message: string): void {
|
|
19
24
|
process.stdout.write(`${chalk.green("ok:")} ${message}\n`);
|
|
20
25
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The effective-customization graph behind `clio-coder config inspect`. This is the
|
|
3
3
|
* "why is Clio behaving this way" surface: it answers what settings, context
|
|
4
|
-
* files, rules, skills, prompts, agents, extensions, safety, memory, hooks, and
|
|
4
|
+
* files, rules, skills, prompts, agents, fleets, extensions, safety, memory, hooks, and
|
|
5
5
|
* the operator profile loaded, from where, with what precedence, and what each
|
|
6
6
|
* costs in context.
|
|
7
7
|
*
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { existsSync, readFileSync } from "node:fs";
|
|
15
|
-
import { basename } from "node:path";
|
|
15
|
+
import { basename, join } from "node:path";
|
|
16
16
|
import type { ClioSettings } from "../core/config.js";
|
|
17
|
+
import { resolvePackageRoot } from "../core/package-root.js";
|
|
17
18
|
import { readLayeredSettings, type SettingsOrigin, settingsSourceFor } from "../core/settings-layers.js";
|
|
18
19
|
import { clioDataDir } from "../core/xdg.js";
|
|
19
20
|
import {
|
|
@@ -39,7 +40,8 @@ export type CustomizationCategory =
|
|
|
39
40
|
| "extension"
|
|
40
41
|
| "skill-root"
|
|
41
42
|
| "prompt-root"
|
|
42
|
-
| "
|
|
43
|
+
| "agent-root"
|
|
44
|
+
| "fleet-root"
|
|
43
45
|
| "safety"
|
|
44
46
|
| "memory";
|
|
45
47
|
|
|
@@ -265,18 +267,43 @@ function inspectResourceRoots(cwd: string, graph: CustomizationGraph): void {
|
|
|
265
267
|
for (const [kind, category] of [
|
|
266
268
|
["skills", "skill-root"],
|
|
267
269
|
["prompts", "prompt-root"],
|
|
270
|
+
["agents", "agent-root"],
|
|
271
|
+
["fleets", "fleet-root"],
|
|
268
272
|
] as const) {
|
|
269
273
|
try {
|
|
274
|
+
if (kind === "agents" || kind === "fleets") {
|
|
275
|
+
const builtinPath = join(
|
|
276
|
+
resolvePackageRoot(),
|
|
277
|
+
"src",
|
|
278
|
+
"domains",
|
|
279
|
+
"agents",
|
|
280
|
+
kind === "agents" ? "builtins" : "fleets",
|
|
281
|
+
);
|
|
282
|
+
graph.entries.push({
|
|
283
|
+
category,
|
|
284
|
+
id: `${kind}:builtin`,
|
|
285
|
+
scope: "builtin",
|
|
286
|
+
sourcePath: builtinPath,
|
|
287
|
+
trust: "trusted",
|
|
288
|
+
precedence: "layer",
|
|
289
|
+
reloadClass: "next-turn",
|
|
290
|
+
detail: { present: existsSync(builtinPath), source: "builtin", resourcePrecedence: 0 },
|
|
291
|
+
});
|
|
292
|
+
}
|
|
270
293
|
for (const root of defaultScopedResourceRoots(kind, cwd)) {
|
|
271
294
|
graph.entries.push({
|
|
272
295
|
category,
|
|
273
296
|
id: `${kind}:${root.scope}`,
|
|
274
|
-
scope: root.scope,
|
|
297
|
+
scope: root.scope === "package" ? "extension" : root.scope,
|
|
275
298
|
sourcePath: root.path,
|
|
276
299
|
trust: root.scope === "package" ? "untrusted" : "trusted",
|
|
277
|
-
precedence: "
|
|
300
|
+
precedence: "layer",
|
|
278
301
|
reloadClass: "next-turn",
|
|
279
|
-
detail: {
|
|
302
|
+
detail: {
|
|
303
|
+
present: existsSync(root.path),
|
|
304
|
+
source: root.source,
|
|
305
|
+
...(root.precedence === undefined ? {} : { resourcePrecedence: root.precedence }),
|
|
306
|
+
},
|
|
280
307
|
});
|
|
281
308
|
}
|
|
282
309
|
} catch (err) {
|
package/src/cli/config.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { printError } from "./shared.js";
|
|
|
4
4
|
const HELP = `clio-coder config inspect [--json]
|
|
5
5
|
|
|
6
6
|
Print the effective-customization graph: what settings, context files, rules,
|
|
7
|
-
skills, prompts, agents, extensions, safety, memory, hooks, and the operator
|
|
7
|
+
skills, prompts, agents, fleets, extensions, safety, memory, hooks, and the operator
|
|
8
8
|
profile loaded, from where, with what precedence, trust, reload class, and
|
|
9
9
|
context cost. Read-only; nothing is created.
|
|
10
10
|
|
package/src/cli/configure.ts
CHANGED
|
@@ -27,7 +27,12 @@ import { fingerprintNativeRuntime } from "../domains/providers/probe/fingerprint
|
|
|
27
27
|
import { getRuntimeRegistry } from "../domains/providers/registry.js";
|
|
28
28
|
import { registerBuiltinRuntimes } from "../domains/providers/runtimes/builtins.js";
|
|
29
29
|
import { greetLmStudio } from "../domains/providers/runtimes/common/lmstudio-http.js";
|
|
30
|
-
import type {
|
|
30
|
+
import type {
|
|
31
|
+
ProbeContext,
|
|
32
|
+
ProbeModelStatus,
|
|
33
|
+
ProbeResult,
|
|
34
|
+
RuntimeDescriptor,
|
|
35
|
+
} from "../domains/providers/types/runtime-descriptor.js";
|
|
31
36
|
import type { TargetDescriptor } from "../domains/providers/types/target-descriptor.js";
|
|
32
37
|
import { registerClioOAuthProviders } from "../engine/oauth.js";
|
|
33
38
|
import { ask, askYesNo } from "./ask.js";
|
|
@@ -44,7 +49,7 @@ import { createDelayedManualCodeInput } from "./oauth-manual-input.js";
|
|
|
44
49
|
import { promptOAuthSelection } from "./oauth-select.js";
|
|
45
50
|
import { credentialWriteFailed, printError, printOk, printPlaintextCredentialWarning } from "./shared.js";
|
|
46
51
|
import { terminalColumns, wrapPlain } from "./text-layout.js";
|
|
47
|
-
import { validateModelChoice } from "./validate-model.js";
|
|
52
|
+
import { type LiveModelInventory, validateModelChoice } from "./validate-model.js";
|
|
48
53
|
|
|
49
54
|
const HELP = `clio-coder configure
|
|
50
55
|
|
|
@@ -70,7 +75,8 @@ Non-interactive flags:
|
|
|
70
75
|
--agent-profile-model <id> model to use for --agent-profile
|
|
71
76
|
--api-key-env <VAR> read API key from this env var at call time
|
|
72
77
|
--api-key <literal> store API key in credentials.yaml
|
|
73
|
-
--force
|
|
78
|
+
--force save a model outside the runtime catalog, or one the
|
|
79
|
+
target does not advertise, without refusing
|
|
74
80
|
--gateway mark the target as a gateway
|
|
75
81
|
--lifecycle <user-managed|clio-managed>
|
|
76
82
|
resident model lifecycle policy
|
|
@@ -378,19 +384,35 @@ function catalogContextWindowFor(runtime: RuntimeDescriptor, modelId: string): n
|
|
|
378
384
|
return null;
|
|
379
385
|
}
|
|
380
386
|
|
|
381
|
-
|
|
387
|
+
/**
|
|
388
|
+
* Check the resolved model against the catalog where there is one and against
|
|
389
|
+
* the target's own list where there is not. A runtime with no catalog used to
|
|
390
|
+
* pass any string here while the same command wrote the live list that ruled
|
|
391
|
+
* it out into `wireModels`, so the target saved as `ok` and failed on its first
|
|
392
|
+
* turn. Without a catalog or a live list there is nothing to check against, and
|
|
393
|
+
* the note says so rather than implying the id was verified.
|
|
394
|
+
*/
|
|
395
|
+
function validateResolvedModel(
|
|
396
|
+
runtime: RuntimeDescriptor,
|
|
397
|
+
target: Pick<TargetDescriptor, "id" | "url">,
|
|
398
|
+
modelId: string | undefined,
|
|
399
|
+
force: boolean,
|
|
400
|
+
inventory: WireModelInventory,
|
|
401
|
+
): boolean {
|
|
382
402
|
if (!modelId) return true;
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
knownModels: runtimeKnownModelsFor(runtimeId),
|
|
387
|
-
force,
|
|
388
|
-
});
|
|
403
|
+
const knownModels = runtimeKnownModelsFor(runtime.id);
|
|
404
|
+
const live = inventory.source === "probe" ? liveInventoryFor(target, inventory) : undefined;
|
|
405
|
+
const validation = validateModelChoice({ runtimeId: runtime.id, modelId, knownModels, live, force });
|
|
389
406
|
if (!validation.ok) {
|
|
390
407
|
process.stderr.write(`error: ${validation.reason}\n`);
|
|
391
408
|
return false;
|
|
392
409
|
}
|
|
393
410
|
if (validation.warning) process.stderr.write(`warning: ${validation.warning}\n`);
|
|
411
|
+
if (knownModels.length === 0 && live === undefined && runtime.kind === "http") {
|
|
412
|
+
process.stderr.write(
|
|
413
|
+
`warning: could not verify model '${modelId}': ${target.url ?? `target '${target.id}'`} returned no model list; it is saved as written\n`,
|
|
414
|
+
);
|
|
415
|
+
}
|
|
394
416
|
return true;
|
|
395
417
|
}
|
|
396
418
|
|
|
@@ -412,10 +434,15 @@ function validateContextWindowOverride(
|
|
|
412
434
|
return true;
|
|
413
435
|
}
|
|
414
436
|
|
|
415
|
-
async function runtimeProbe(
|
|
437
|
+
async function runtimeProbe(
|
|
438
|
+
runtime: RuntimeDescriptor,
|
|
439
|
+
target: TargetDescriptor,
|
|
440
|
+
authToken?: string,
|
|
441
|
+
): Promise<ProbeResult | null> {
|
|
416
442
|
if (typeof runtime.probe !== "function") return null;
|
|
417
443
|
try {
|
|
418
|
-
|
|
444
|
+
const context = await buildProbeContext(runtime, target);
|
|
445
|
+
return await runtime.probe(target, authToken === undefined ? context : { ...context, authToken });
|
|
419
446
|
} catch (err) {
|
|
420
447
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
421
448
|
}
|
|
@@ -679,17 +706,69 @@ async function loginOAuthRuntime(rl: ReturnType<typeof createInterface>, runtime
|
|
|
679
706
|
}
|
|
680
707
|
}
|
|
681
708
|
|
|
709
|
+
/**
|
|
710
|
+
* The model ids a target can be configured with, and where they came from.
|
|
711
|
+
* `probe` is the only source that says anything about the server in front of
|
|
712
|
+
* us right now; `catalog` is static provider knowledge, and `existing` is the
|
|
713
|
+
* list a previous configure recorded, which the server may no longer match.
|
|
714
|
+
*/
|
|
715
|
+
interface WireModelInventory {
|
|
716
|
+
models: string[];
|
|
717
|
+
source: "catalog" | "probe" | "existing" | "none";
|
|
718
|
+
/** Per-model load state when the probe reported it. */
|
|
719
|
+
modelStates?: Readonly<Record<string, ProbeModelStatus>> | undefined;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Every id the runtime would resolve. LM Studio lists a loaded model under its
|
|
724
|
+
* instance id and keeps the model key only in the state map, and the request
|
|
725
|
+
* path accepts either, so both count as advertised.
|
|
726
|
+
*/
|
|
727
|
+
function advertisedModelIds(inventory: Pick<WireModelInventory, "models" | "modelStates">): string[] {
|
|
728
|
+
const ids = [...inventory.models];
|
|
729
|
+
for (const id of Object.keys(inventory.modelStates ?? {})) if (!ids.includes(id)) ids.push(id);
|
|
730
|
+
return ids;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
function residentModelIds(modelStates: WireModelInventory["modelStates"]): string[] {
|
|
734
|
+
return Object.entries(modelStates ?? {})
|
|
735
|
+
.filter(([, status]) => status.state === "loaded" || status.state === "loading")
|
|
736
|
+
.map(([id]) => id);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
function liveInventoryFor(
|
|
740
|
+
target: Pick<TargetDescriptor, "id" | "url">,
|
|
741
|
+
inventory: WireModelInventory,
|
|
742
|
+
): LiveModelInventory {
|
|
743
|
+
return {
|
|
744
|
+
targetId: target.id,
|
|
745
|
+
url: target.url,
|
|
746
|
+
models: advertisedModelIds(inventory),
|
|
747
|
+
resident: residentModelIds(inventory.modelStates),
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
|
|
682
751
|
async function resolveSupportedWireModels(
|
|
683
752
|
runtime: RuntimeDescriptor,
|
|
684
753
|
target: TargetDescriptor,
|
|
685
754
|
existing?: TargetDescriptor,
|
|
686
755
|
authToken?: string,
|
|
687
|
-
): Promise<
|
|
756
|
+
): Promise<WireModelInventory> {
|
|
688
757
|
const known = listKnownModelsForRuntime(runtime.id);
|
|
689
|
-
if (known.length > 0) return known;
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
758
|
+
if (known.length > 0) return { models: known, source: "catalog" };
|
|
759
|
+
if (runtime.kind === "http") {
|
|
760
|
+
// The full probe carries load state alongside the ids; a runtime that
|
|
761
|
+
// lists models only through probeModels still gets its ids checked.
|
|
762
|
+
const probe = await runtimeProbe(runtime, target, authToken);
|
|
763
|
+
if (probe?.ok && probe.models && probe.models.length > 0) {
|
|
764
|
+
return { models: [...probe.models], source: "probe", modelStates: probe.modelStates };
|
|
765
|
+
}
|
|
766
|
+
const discovered = await runtimeProbeModels(runtime, target, authToken);
|
|
767
|
+
if (discovered.length > 0) return { models: discovered, source: "probe" };
|
|
768
|
+
}
|
|
769
|
+
if (existing?.wireModels && existing.wireModels.length > 0)
|
|
770
|
+
return { models: [...existing.wireModels], source: "existing" };
|
|
771
|
+
return { models: [], source: "none" };
|
|
693
772
|
}
|
|
694
773
|
|
|
695
774
|
function resolveModelChoice(
|
|
@@ -810,7 +889,8 @@ async function runNonInteractive(runtime: RuntimeDescriptor, args: ParsedArgs):
|
|
|
810
889
|
...(args.reasoning !== undefined ? { reasoning: args.reasoning } : {}),
|
|
811
890
|
...(existing?.lmstudio ? { lmstudio: existing.lmstudio } : {}),
|
|
812
891
|
});
|
|
813
|
-
const
|
|
892
|
+
const inventory = await resolveSupportedWireModels(runtime, seed, existing, args.apiKey);
|
|
893
|
+
const wireModels = inventory.models;
|
|
814
894
|
const model =
|
|
815
895
|
args.model ??
|
|
816
896
|
existing?.defaultModel ??
|
|
@@ -820,7 +900,7 @@ async function runNonInteractive(runtime: RuntimeDescriptor, args: ParsedArgs):
|
|
|
820
900
|
refuseCatalogSeededModel(runtime, support);
|
|
821
901
|
return 2;
|
|
822
902
|
}
|
|
823
|
-
if (!validateResolvedModel(runtime
|
|
903
|
+
if (!validateResolvedModel(runtime, seed, model, args.force, inventory)) return 2;
|
|
824
904
|
if (!validateContextWindowOverride(runtime, model, args.contextWindow, args.force)) return 2;
|
|
825
905
|
const descriptor = buildDescriptor(runtime, args.id, {
|
|
826
906
|
...(url !== undefined ? { url } : {}),
|
|
@@ -1192,7 +1272,10 @@ async function runInteractive(
|
|
|
1192
1272
|
}
|
|
1193
1273
|
|
|
1194
1274
|
let model: string | undefined = defaults.model;
|
|
1195
|
-
let
|
|
1275
|
+
let inventory: WireModelInventory =
|
|
1276
|
+
existing?.wireModels && existing.wireModels.length > 0
|
|
1277
|
+
? { models: [...existing.wireModels], source: "existing" }
|
|
1278
|
+
: { models: [], source: "none" };
|
|
1196
1279
|
const tentative = buildDescriptor(runtime, targetId, {
|
|
1197
1280
|
...(url !== undefined ? { url } : {}),
|
|
1198
1281
|
...(apiKeyEnv !== undefined ? { apiKeyEnv } : {}),
|
|
@@ -1211,8 +1294,9 @@ async function runInteractive(
|
|
|
1211
1294
|
});
|
|
1212
1295
|
|
|
1213
1296
|
if (runtime.kind === "http") {
|
|
1214
|
-
|
|
1297
|
+
inventory = await resolveSupportedWireModels(runtime, tentative, existing ?? undefined);
|
|
1215
1298
|
}
|
|
1299
|
+
const wireModels = inventory.models;
|
|
1216
1300
|
// The wizard shows the whole list, so a catalog-ordered runtime does not need
|
|
1217
1301
|
// --model here the way the non-interactive path does. It does need to stop
|
|
1218
1302
|
// offering the alphabetically first id as though it were the recommended one.
|
|
@@ -1234,11 +1318,11 @@ async function runInteractive(
|
|
|
1234
1318
|
process.stdout.write(" a model is required: enter a number from the list or a model id.\n");
|
|
1235
1319
|
continue;
|
|
1236
1320
|
}
|
|
1237
|
-
if (validateResolvedModel(runtime
|
|
1321
|
+
if (validateResolvedModel(runtime, tentative, model, defaults.force, inventory)) break;
|
|
1238
1322
|
}
|
|
1239
1323
|
} else {
|
|
1240
1324
|
for (;;) {
|
|
1241
|
-
if (model && validateResolvedModel(runtime
|
|
1325
|
+
if (model && validateResolvedModel(runtime, tentative, model, defaults.force, inventory)) break;
|
|
1242
1326
|
const manual = await ask(rl, "Default model id (blank to leave empty)", model ?? "");
|
|
1243
1327
|
if (manual === null) return 0;
|
|
1244
1328
|
model = manual.length > 0 ? manual : undefined;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { lstatSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { resolveClioDirs } from "../core/xdg.js";
|
|
4
|
+
import type { DoctorFinding } from "../domains/lifecycle/doctor.js";
|
|
5
|
+
|
|
6
|
+
interface MeasuredEntry {
|
|
7
|
+
bytes: number;
|
|
8
|
+
error: string | null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Report aggregate state usage and the largest top-level contributor. */
|
|
12
|
+
export function stateStorageFinding(stateDir = resolveClioDirs().state): DoctorFinding {
|
|
13
|
+
let names: string[];
|
|
14
|
+
try {
|
|
15
|
+
names = readdirSync(stateDir);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
name: "state storage",
|
|
20
|
+
detail: `${stateDir} could not be measured: ${error instanceof Error ? error.message : String(error)}`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let total = 0;
|
|
25
|
+
let largest: { name: string; bytes: number } | null = null;
|
|
26
|
+
for (const name of names.sort()) {
|
|
27
|
+
const measured = measureEntry(join(stateDir, name));
|
|
28
|
+
if (measured.error !== null) {
|
|
29
|
+
return { ok: false, name: "state storage", detail: measured.error };
|
|
30
|
+
}
|
|
31
|
+
total += measured.bytes;
|
|
32
|
+
if (largest === null || measured.bytes > largest.bytes) largest = { name, bytes: measured.bytes };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
ok: true,
|
|
37
|
+
name: "state storage",
|
|
38
|
+
detail:
|
|
39
|
+
largest === null
|
|
40
|
+
? `${formatBytes(total)} (${total.toLocaleString("en-US")} bytes); largest contributor none`
|
|
41
|
+
: `${formatBytes(total)} (${total.toLocaleString("en-US")} bytes); largest contributor ${largest.name} at ${formatBytes(largest.bytes)} (${largest.bytes.toLocaleString("en-US")} bytes)`,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function measureEntry(path: string): MeasuredEntry {
|
|
46
|
+
let stats: ReturnType<typeof lstatSync>;
|
|
47
|
+
try {
|
|
48
|
+
stats = lstatSync(path);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
return {
|
|
51
|
+
bytes: 0,
|
|
52
|
+
error: `${path} could not be inspected: ${error instanceof Error ? error.message : String(error)}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) return { bytes: stats.size, error: null };
|
|
56
|
+
|
|
57
|
+
let names: string[];
|
|
58
|
+
try {
|
|
59
|
+
names = readdirSync(path);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
return { bytes: 0, error: `${path} could not be listed: ${error instanceof Error ? error.message : String(error)}` };
|
|
62
|
+
}
|
|
63
|
+
let bytes = 0;
|
|
64
|
+
for (const name of names) {
|
|
65
|
+
const child = measureEntry(join(path, name));
|
|
66
|
+
if (child.error !== null) return child;
|
|
67
|
+
bytes += child.bytes;
|
|
68
|
+
}
|
|
69
|
+
return { bytes, error: null };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function formatBytes(bytes: number): string {
|
|
73
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
74
|
+
const units = ["KiB", "MiB", "GiB", "TiB"];
|
|
75
|
+
let value = bytes;
|
|
76
|
+
let unit = -1;
|
|
77
|
+
do {
|
|
78
|
+
value /= 1024;
|
|
79
|
+
unit += 1;
|
|
80
|
+
} while (value >= 1024 && unit < units.length - 1);
|
|
81
|
+
return `${value.toFixed(value >= 10 ? 1 : 2)} ${units[unit]}`;
|
|
82
|
+
}
|
package/src/cli/doctor.ts
CHANGED
|
@@ -4,8 +4,10 @@ import {
|
|
|
4
4
|
runDoctor,
|
|
5
5
|
runDoctorFleetChecks,
|
|
6
6
|
runDoctorInteropChecks,
|
|
7
|
+
runDoctorModelChecks,
|
|
7
8
|
runDoctorRuntimeChecks,
|
|
8
9
|
} from "../domains/lifecycle/doctor.js";
|
|
10
|
+
import { stateStorageFinding } from "./doctor-state-size.js";
|
|
9
11
|
import { printError } from "./shared.js";
|
|
10
12
|
|
|
11
13
|
const HELP = `clio-coder doctor [--fix] [--json]
|
|
@@ -34,7 +36,11 @@ export async function runDoctorCommand(args: ReadonlyArray<string> = []): Promis
|
|
|
34
36
|
// gets every check on the home it just built.
|
|
35
37
|
const untouched = !fix && isUninitializedHome();
|
|
36
38
|
const findings = runDoctor({ fix });
|
|
39
|
+
const storageChecks = untouched ? [] : [stateStorageFinding()];
|
|
37
40
|
const runtimeChecks = await runDoctorRuntimeChecks();
|
|
41
|
+
// Every model pointer is checked against what its target advertises, so a
|
|
42
|
+
// placeholder id saved by configure is reported here and not on the first turn.
|
|
43
|
+
const modelChecks = await runDoctorModelChecks();
|
|
38
44
|
// The interop and fleet sweeps read the state and config roots through the
|
|
39
45
|
// ensuring accessors, which create them, and there is no fleet or interop
|
|
40
46
|
// state to inspect before Clio has ever written anything. On a home Clio has
|
|
@@ -43,7 +49,7 @@ export async function runDoctorCommand(args: ReadonlyArray<string> = []): Promis
|
|
|
43
49
|
// Fleet preflight probes each configured node over SSH and persists the
|
|
44
50
|
// per-node eligibility verdicts dispatch placement enforces.
|
|
45
51
|
const fleetChecks = untouched ? [] : await runDoctorFleetChecks();
|
|
46
|
-
const all = [...findings, ...runtimeChecks, ...interopChecks, ...fleetChecks];
|
|
52
|
+
const all = [...findings, ...storageChecks, ...runtimeChecks, ...modelChecks, ...interopChecks, ...fleetChecks];
|
|
47
53
|
const ok = all.every((f) => f.ok);
|
|
48
54
|
if (json) {
|
|
49
55
|
process.stdout.write(`${JSON.stringify({ ok, fix, findings: all }, null, 2)}\n`);
|
package/src/cli/eval.ts
CHANGED
|
@@ -2,10 +2,10 @@ import { resolve } from "node:path";
|
|
|
2
2
|
import { InvalidIdError } from "../core/safe-id.js";
|
|
3
3
|
import { clioDataDir } from "../core/xdg.js";
|
|
4
4
|
import { loadEvalArtifactV4, writeEvalArtifactV4 } from "../domains/eval/artifacts/store.js";
|
|
5
|
-
import { compareEvalArtifactsV4
|
|
6
|
-
import { evaluateGate, renderGateFailure } from "../domains/eval/compare/gates.js";
|
|
5
|
+
import { compareEvalArtifactsV4 } from "../domains/eval/compare/compare.js";
|
|
6
|
+
import { evaluateGate, renderGateFailure, renderInformationalBudget } from "../domains/eval/compare/gates.js";
|
|
7
7
|
import { loadThresholds } from "../domains/eval/compare/thresholds.js";
|
|
8
|
-
|
|
8
|
+
import { type EvalComparisonReportFormat, renderEvalComparisonReportV1 } from "../domains/eval/reports/comparison.js";
|
|
9
9
|
import { renderEvalJsonReportV4 } from "../domains/eval/reports/json.js";
|
|
10
10
|
import { renderEvalJunitReportV4 } from "../domains/eval/reports/junit.js";
|
|
11
11
|
import { renderEvalMarkdownReportV4 } from "../domains/eval/reports/markdown.js";
|
|
@@ -22,10 +22,10 @@ const HELP = `clio-coder eval <command>
|
|
|
22
22
|
|
|
23
23
|
Commands:
|
|
24
24
|
clio-coder eval validate --suite <suite.yaml>
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
clio-coder eval run --suite <suite.yaml> [--trials <n>] [--target <id>] [--model <id>] [--out <path>] [--clio-coder-entry <path>]
|
|
26
|
+
clio-coder eval run --task-file <tasks.yaml> [--repeat <n>] [--out <path>] [--clio-coder-entry <path>]
|
|
27
27
|
clio-coder eval report <evalId> --format text|json|md|swe-jsonl|junit
|
|
28
|
-
|
|
28
|
+
clio-coder eval compare <baselineEvalId> <candidateEvalId> [--metric <name>] [--format text|json|md|junit] [--allow-config-drift]
|
|
29
29
|
clio-coder eval gate <candidateEvalId> --baseline <baselineEvalId> [--thresholds <file>]
|
|
30
30
|
`;
|
|
31
31
|
|
|
@@ -37,6 +37,7 @@ interface ParsedEvalArgs {
|
|
|
37
37
|
suite?: string;
|
|
38
38
|
taskFile?: string;
|
|
39
39
|
repeat: number;
|
|
40
|
+
trials?: number;
|
|
40
41
|
target?: string;
|
|
41
42
|
model?: string;
|
|
42
43
|
out?: string;
|
|
@@ -44,13 +45,21 @@ interface ParsedEvalArgs {
|
|
|
44
45
|
evalId?: string;
|
|
45
46
|
format: EvalReportFormat;
|
|
46
47
|
compareIds: string[];
|
|
48
|
+
metric?: string;
|
|
49
|
+
allowConfigDrift: boolean;
|
|
47
50
|
baseline?: string;
|
|
48
51
|
thresholds?: string;
|
|
49
52
|
help: boolean;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
function parseEvalArgs(args: ReadonlyArray<string>): ParsedEvalArgs {
|
|
53
|
-
const parsed: ParsedEvalArgs = {
|
|
56
|
+
const parsed: ParsedEvalArgs = {
|
|
57
|
+
repeat: 1,
|
|
58
|
+
compareIds: [],
|
|
59
|
+
format: "text",
|
|
60
|
+
allowConfigDrift: false,
|
|
61
|
+
help: false,
|
|
62
|
+
};
|
|
54
63
|
for (let index = 0; index < args.length; index += 1) {
|
|
55
64
|
const arg = args[index];
|
|
56
65
|
if (arg === undefined) continue;
|
|
@@ -110,6 +119,11 @@ function parseEvalArgs(args: ReadonlyArray<string>): ParsedEvalArgs {
|
|
|
110
119
|
index += 1;
|
|
111
120
|
continue;
|
|
112
121
|
}
|
|
122
|
+
if (arg === "--trials") {
|
|
123
|
+
parsed.trials = positiveInteger(requiredValue(args, index, "--trials"), "--trials");
|
|
124
|
+
index += 1;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
113
127
|
throw new Error(`unknown eval run argument: ${arg}`);
|
|
114
128
|
}
|
|
115
129
|
if (parsed.command === "report") {
|
|
@@ -125,6 +139,20 @@ function parseEvalArgs(args: ReadonlyArray<string>): ParsedEvalArgs {
|
|
|
125
139
|
throw new Error(`unexpected eval report argument: ${arg}`);
|
|
126
140
|
}
|
|
127
141
|
if (parsed.command === "compare") {
|
|
142
|
+
if (arg === "--format") {
|
|
143
|
+
parsed.format = comparisonFormat(requiredValue(args, index, "--format"));
|
|
144
|
+
index += 1;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (arg === "--metric") {
|
|
148
|
+
parsed.metric = requiredValue(args, index, "--metric");
|
|
149
|
+
index += 1;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (arg === "--allow-config-drift") {
|
|
153
|
+
parsed.allowConfigDrift = true;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
128
156
|
if (!arg.startsWith("-")) {
|
|
129
157
|
parsed.compareIds.push(arg);
|
|
130
158
|
continue;
|
|
@@ -202,15 +230,21 @@ async function runEvalRun(parsed: ParsedEvalArgs): Promise<number> {
|
|
|
202
230
|
const loaded =
|
|
203
231
|
parsed.suite !== undefined
|
|
204
232
|
? await loadEvalSuiteFile(parsed.suite)
|
|
205
|
-
: await loadV1TaskFileAsSuite(parsed.taskFile ?? "", parsed.repeat);
|
|
233
|
+
: await loadV1TaskFileAsSuite(parsed.taskFile ?? "", parsed.trials ?? parsed.repeat);
|
|
206
234
|
const resolveOptions: { target?: string; model?: string } = {};
|
|
207
235
|
if (parsed.target !== undefined) resolveOptions.target = parsed.target;
|
|
208
236
|
if (parsed.model !== undefined) resolveOptions.model = parsed.model;
|
|
209
|
-
const suite = resolveSuiteForRun(loaded.suite,
|
|
237
|
+
const suite = resolveSuiteForRun(loaded.suite, {
|
|
238
|
+
...resolveOptions,
|
|
239
|
+
...(parsed.trials ? { trials: parsed.trials } : {}),
|
|
240
|
+
});
|
|
210
241
|
// Runner commands execute with cwd inside prepared eval workspaces, so a
|
|
211
242
|
// relative --clio-coder-entry must be pinned to the invoking directory here.
|
|
212
243
|
const clioEntry = resolve(parsed.clioEntry ?? process.argv[1] ?? "dist/cli/index.js");
|
|
213
|
-
const artifact = await runEvalSuiteV2(
|
|
244
|
+
const artifact = await runEvalSuiteV2(
|
|
245
|
+
{ ...loaded, suite },
|
|
246
|
+
{ clioEntry, freshWorkspaces: parsed.trials !== undefined },
|
|
247
|
+
);
|
|
214
248
|
const artifactPath = await writeEvalArtifactV4(clioDataDir(), artifact, parsed.out);
|
|
215
249
|
process.stdout.write(`${renderEvalTextReportV4(artifact)}artifact: ${artifactPath}\n`);
|
|
216
250
|
// A suite that declares thresholds is gated by them here, on the artifact
|
|
@@ -221,6 +255,10 @@ async function runEvalRun(parsed: ParsedEvalArgs): Promise<number> {
|
|
|
221
255
|
process.stdout.write(`gate: fail (${gate.failures.length} threshold failure)\n`);
|
|
222
256
|
for (const failure of gate.failures) process.stdout.write(renderGateFailure(failure));
|
|
223
257
|
}
|
|
258
|
+
if (gate !== null && gate.informational.length > 0) {
|
|
259
|
+
process.stdout.write(`informational budgets: ${gate.informational.length} notice\n`);
|
|
260
|
+
for (const finding of gate.informational) process.stdout.write(renderInformationalBudget(finding));
|
|
261
|
+
}
|
|
224
262
|
return artifact.summary.failed === 0 && (gate === null || gate.pass) ? 0 : 1;
|
|
225
263
|
} catch (error) {
|
|
226
264
|
return handleEvalLoadError(error, 1);
|
|
@@ -246,8 +284,12 @@ async function runEvalCompareCommand(parsed: ParsedEvalArgs): Promise<number> {
|
|
|
246
284
|
const dataDir = clioDataDir();
|
|
247
285
|
const baseline = await loadEvalArtifactV4(dataDir, baselineEvalId);
|
|
248
286
|
const candidate = await loadEvalArtifactV4(dataDir, candidateEvalId);
|
|
249
|
-
|
|
250
|
-
|
|
287
|
+
const summary = compareEvalArtifactsV4(baseline, candidate, {
|
|
288
|
+
allowConfigDrift: parsed.allowConfigDrift,
|
|
289
|
+
...(parsed.metric === undefined ? {} : { metric: parsed.metric }),
|
|
290
|
+
});
|
|
291
|
+
process.stdout.write(renderEvalComparisonReportV1(summary, parsed.format as EvalComparisonReportFormat));
|
|
292
|
+
return summary.hardGate.pass ? 0 : 1;
|
|
251
293
|
} catch (error) {
|
|
252
294
|
printError(error instanceof Error ? error.message : String(error));
|
|
253
295
|
return error instanceof InvalidIdError ? 2 : 1;
|
|
@@ -258,18 +300,35 @@ async function runEvalGateCommand(parsed: ParsedEvalArgs): Promise<number> {
|
|
|
258
300
|
try {
|
|
259
301
|
const dataDir = clioDataDir();
|
|
260
302
|
const candidate = await loadEvalArtifactV4(dataDir, parsed.evalId ?? "");
|
|
261
|
-
await loadEvalArtifactV4(dataDir, parsed.baseline ?? "");
|
|
303
|
+
const baseline = await loadEvalArtifactV4(dataDir, parsed.baseline ?? "");
|
|
262
304
|
const thresholds =
|
|
263
305
|
parsed.thresholds === undefined
|
|
264
|
-
? { fail: [{ metric: "result.pass", op: "eq" as const, value: false }] }
|
|
306
|
+
? { fail: [{ metric: "result.pass", op: "eq" as const, value: false }], informational: [] }
|
|
265
307
|
: loadThresholds(parsed.thresholds);
|
|
266
308
|
const gate = evaluateGate(candidate, thresholds);
|
|
267
|
-
|
|
309
|
+
const comparison = compareEvalArtifactsV4(baseline, candidate);
|
|
310
|
+
if (gate.informational.length > 0) {
|
|
311
|
+
process.stdout.write(`informational budgets: ${gate.informational.length} notice\n`);
|
|
312
|
+
for (const finding of gate.informational) process.stdout.write(renderInformationalBudget(finding));
|
|
313
|
+
}
|
|
314
|
+
if (gate.pass && comparison.hardGate.pass) {
|
|
268
315
|
process.stdout.write("gate: pass\n");
|
|
269
316
|
return 0;
|
|
270
317
|
}
|
|
271
|
-
|
|
318
|
+
const failureCount =
|
|
319
|
+
gate.failures.length + comparison.hardGate.failures.length + comparison.hardGate.envelopeFailures.length;
|
|
320
|
+
process.stdout.write(`gate: fail (${failureCount} hard failure)\n`);
|
|
272
321
|
for (const failure of gate.failures) process.stdout.write(renderGateFailure(failure));
|
|
322
|
+
for (const failure of comparison.hardGate.failures) {
|
|
323
|
+
process.stdout.write(
|
|
324
|
+
` ${failure.metric} [${failure.scenarioId}:${failure.role}:${failure.target.id}/${failure.target.model ?? "none"}]: ${failure.change} (hard behavioral gate)\n`,
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
for (const failure of comparison.hardGate.envelopeFailures) {
|
|
328
|
+
process.stdout.write(
|
|
329
|
+
` execution envelope [${failure.scenarioId}:${failure.role}:${failure.target.id}/${failure.target.model ?? "none"}]: incomparable fields ${failure.fields.join(", ")}\n`,
|
|
330
|
+
);
|
|
331
|
+
}
|
|
273
332
|
return 1;
|
|
274
333
|
} catch (error) {
|
|
275
334
|
printError(error instanceof Error ? error.message : String(error));
|
|
@@ -313,3 +372,8 @@ function reportFormat(value: string): EvalReportFormat {
|
|
|
313
372
|
if (value === "text" || value === "json" || value === "md" || value === "swe-jsonl" || value === "junit") return value;
|
|
314
373
|
throw new Error("--format must be text, json, md, swe-jsonl, or junit");
|
|
315
374
|
}
|
|
375
|
+
|
|
376
|
+
function comparisonFormat(value: string): EvalComparisonReportFormat {
|
|
377
|
+
if (value === "text" || value === "json" || value === "md" || value === "junit") return value;
|
|
378
|
+
throw new Error("eval compare --format must be text, json, md, or junit");
|
|
379
|
+
}
|