@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
|
@@ -1,7 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a target advertised when it was asked, for runtimes with no static
|
|
3
|
+
* catalog. `models` is the id list the probe returned and `resident` the
|
|
4
|
+
* subset the server reports as loaded, when it reports load state at all.
|
|
5
|
+
*/
|
|
6
|
+
export interface LiveModelInventory {
|
|
7
|
+
targetId: string;
|
|
8
|
+
url?: string | undefined;
|
|
9
|
+
models: ReadonlyArray<string>;
|
|
10
|
+
resident: ReadonlyArray<string>;
|
|
11
|
+
}
|
|
12
|
+
|
|
1
13
|
export interface ValidateModelInput {
|
|
2
14
|
runtimeId: string;
|
|
3
15
|
modelId: string;
|
|
4
16
|
knownModels: ReadonlyArray<string>;
|
|
17
|
+
/**
|
|
18
|
+
* The live list, when one was fetched. It is consulted only when the static
|
|
19
|
+
* catalog is empty, so the catalog stays the authority for cloud runtimes
|
|
20
|
+
* and the probe becomes the authority where there is nothing else.
|
|
21
|
+
*/
|
|
22
|
+
live?: LiveModelInventory | undefined;
|
|
5
23
|
force: boolean;
|
|
6
24
|
}
|
|
7
25
|
|
|
@@ -9,9 +27,30 @@ export type ValidateModelResult =
|
|
|
9
27
|
| { ok: true; warning?: string }
|
|
10
28
|
| { ok: false; reason: string; knownModels: ReadonlyArray<string> };
|
|
11
29
|
|
|
30
|
+
const SAMPLE_SIZE = 10;
|
|
31
|
+
|
|
32
|
+
function sample(models: ReadonlyArray<string>): string {
|
|
33
|
+
const shown = models.slice(0, SAMPLE_SIZE).join(", ");
|
|
34
|
+
return models.length > SAMPLE_SIZE ? `${shown}, …` : shown;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function describeLiveTarget(live: LiveModelInventory): string {
|
|
38
|
+
return live.url ? `target '${live.targetId}' at ${live.url}` : `target '${live.targetId}'`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The refusal `configure` prints for a model the live target does not advertise. */
|
|
42
|
+
export function formatUnadvertisedModelReason(modelId: string, live: LiveModelInventory): string {
|
|
43
|
+
const resident = live.resident.length > 0 ? live.resident.join(", ") : "none";
|
|
44
|
+
return (
|
|
45
|
+
`${describeLiveTarget(live)} does not advertise model '${modelId}'. ` +
|
|
46
|
+
`Advertised (${live.models.length}): ${sample(live.models)}. Resident instances: ${resident}. ` +
|
|
47
|
+
"Pass one of the advertised ids with --model, or --force to save a model the target cannot serve."
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
12
51
|
export function validateModelChoice(input: ValidateModelInput): ValidateModelResult {
|
|
13
|
-
const { runtimeId, modelId, knownModels, force } = input;
|
|
14
|
-
if (knownModels.length === 0) return
|
|
52
|
+
const { runtimeId, modelId, knownModels, live, force } = input;
|
|
53
|
+
if (knownModels.length === 0) return validateAgainstLive(modelId, live, force);
|
|
15
54
|
if (knownModels.includes(modelId)) return { ok: true };
|
|
16
55
|
if (force) {
|
|
17
56
|
return {
|
|
@@ -19,10 +58,26 @@ export function validateModelChoice(input: ValidateModelInput): ValidateModelRes
|
|
|
19
58
|
warning: `model '${modelId}' not in ${runtimeId} catalog (use without --force to reject)`,
|
|
20
59
|
};
|
|
21
60
|
}
|
|
22
|
-
const sample = knownModels.slice(0, 10).join(", ");
|
|
23
61
|
return {
|
|
24
62
|
ok: false,
|
|
25
|
-
reason: `model '${modelId}' not in ${runtimeId} catalog. Known: ${sample}. Use --force to skip validation.`,
|
|
26
|
-
knownModels: knownModels.slice(0,
|
|
63
|
+
reason: `model '${modelId}' not in ${runtimeId} catalog. Known: ${sample(knownModels)}. Use --force to skip validation.`,
|
|
64
|
+
knownModels: knownModels.slice(0, SAMPLE_SIZE),
|
|
27
65
|
};
|
|
28
66
|
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* With no catalog, the live list is the only evidence there is. An empty
|
|
70
|
+
* catalog used to be an early `ok` on its own, which is how a placeholder id
|
|
71
|
+
* was written next to the very list that ruled it out.
|
|
72
|
+
*/
|
|
73
|
+
function validateAgainstLive(
|
|
74
|
+
modelId: string,
|
|
75
|
+
live: LiveModelInventory | undefined,
|
|
76
|
+
force: boolean,
|
|
77
|
+
): ValidateModelResult {
|
|
78
|
+
if (!live || live.models.length === 0) return { ok: true };
|
|
79
|
+
if (live.models.includes(modelId)) return { ok: true };
|
|
80
|
+
const reason = formatUnadvertisedModelReason(modelId, live);
|
|
81
|
+
if (force) return { ok: true, warning: `${reason.replace(/ Pass one of.*$/u, "")} Saved anyway because of --force.` };
|
|
82
|
+
return { ok: false, reason, knownModels: live.models.slice(0, SAMPLE_SIZE) };
|
|
83
|
+
}
|
package/src/core/bus-events.ts
CHANGED
|
@@ -51,6 +51,8 @@ export const BusChannels = {
|
|
|
51
51
|
ToolBudgetExceeded: "safety.toolBudgetExceeded",
|
|
52
52
|
ProviderHealth: "provider.health",
|
|
53
53
|
RuntimeNotice: "runtime.notice",
|
|
54
|
+
ResidencyMutation: "residency.mutation",
|
|
55
|
+
DispatchScopeNotice: "dispatch.scopeNotice",
|
|
54
56
|
DispatchEnqueued: "dispatch.enqueued",
|
|
55
57
|
DispatchStarted: "dispatch.started",
|
|
56
58
|
DispatchProgress: "dispatch.progress",
|
|
@@ -63,6 +65,7 @@ export const BusChannels = {
|
|
|
63
65
|
ContextWarning: "context.warning",
|
|
64
66
|
ContextPruned: "context.pruned",
|
|
65
67
|
ContextRecalled: "context.recalled",
|
|
68
|
+
MemoryStepCompleted: "memory.stepCompleted",
|
|
66
69
|
AgentStatusChanged: "agent.status.changed",
|
|
67
70
|
RunAborted: "run.aborted",
|
|
68
71
|
BudgetAlert: "budget.alert",
|
|
@@ -99,6 +102,28 @@ export interface RuntimeNoticePayload {
|
|
|
99
102
|
detail?: Record<string, number | string | boolean>;
|
|
100
103
|
}
|
|
101
104
|
|
|
105
|
+
/**
|
|
106
|
+
* One completed proactive-memory model step, published on
|
|
107
|
+
* {@link BusChannels.MemoryStepCompleted}. It carries the endpoint the step
|
|
108
|
+
* called and nothing about what the step decided: the only consumer is the
|
|
109
|
+
* turn context, which stamps an expected-cold reason when a step ran between
|
|
110
|
+
* turns on the endpoint the chat target streams against.
|
|
111
|
+
*/
|
|
112
|
+
export interface MemoryStepCompletedPayload {
|
|
113
|
+
endpointKey: string;
|
|
114
|
+
targetId: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** A successful model load or eviction on one residency-managed endpoint. */
|
|
118
|
+
export interface ResidencyMutationPayload {
|
|
119
|
+
targetKey: string;
|
|
120
|
+
targetId: string;
|
|
121
|
+
runtimeId: string;
|
|
122
|
+
model: string;
|
|
123
|
+
operation: "load" | "evict";
|
|
124
|
+
at: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
102
127
|
/**
|
|
103
128
|
* Window-resolution warning published on {@link BusChannels.ContextWarning}.
|
|
104
129
|
* Emitted on transitions only: `warning` carries the text when a warning
|
|
@@ -108,8 +133,31 @@ export interface ContextWarningPayload {
|
|
|
108
133
|
warning: string | null;
|
|
109
134
|
}
|
|
110
135
|
|
|
136
|
+
/** A dispatch path-scope decision that must remain visible in the operator transcript. */
|
|
137
|
+
export type DispatchScopeNoticePayload =
|
|
138
|
+
| {
|
|
139
|
+
code: "typed_scope_replaced_inferred_paths";
|
|
140
|
+
level: "warning";
|
|
141
|
+
agentId: string;
|
|
142
|
+
omittedPaths: ReadonlyArray<string>;
|
|
143
|
+
message: string;
|
|
144
|
+
}
|
|
145
|
+
| {
|
|
146
|
+
code: "legacy_scope_inferred" | "legacy_scope_empty";
|
|
147
|
+
level: "warning";
|
|
148
|
+
agentId: string;
|
|
149
|
+
paths: ReadonlyArray<{
|
|
150
|
+
path: string;
|
|
151
|
+
policy: "working-context" | "write-boundary";
|
|
152
|
+
provenance: "declared" | "derived" | "inferred";
|
|
153
|
+
source: "intent.read_roots" | "intent.write_roots" | "intent.relevant_paths" | "writeRoots" | "task" | "briefing";
|
|
154
|
+
confidence: "certain" | "high" | "medium" | "low";
|
|
155
|
+
}>;
|
|
156
|
+
message: string;
|
|
157
|
+
};
|
|
158
|
+
|
|
111
159
|
export type ContextActivityKind = "context-init" | "context-clear" | "context-refresh" | "context-wiki" | "compaction";
|
|
112
|
-
export type ContextActivityPhase = "scan" | "codewiki" | "generate" | "clio-md" | "state" | "done";
|
|
160
|
+
export type ContextActivityPhase = "scan" | "codewiki" | "generate" | "clio-md" | "state" | "compact" | "done";
|
|
113
161
|
export type ContextActivityStatus = "started" | "running" | "completed" | "failed";
|
|
114
162
|
|
|
115
163
|
/** Structured progress for context operations. Interactive renders this as a live context island. */
|
|
@@ -481,6 +529,8 @@ export interface DispatchRunIdentity {
|
|
|
481
529
|
wireModelId: string;
|
|
482
530
|
runtimeId: string;
|
|
483
531
|
runtimeKind: RunKind;
|
|
532
|
+
/** Canonical inference scheduler and its resolved request-slot bound. */
|
|
533
|
+
endpoint?: { key: string; label: string; limit: number } | undefined;
|
|
484
534
|
/** Admitted invocation budget provenance for native workers. */
|
|
485
535
|
budget?: RunToolBudgetEnvelope | undefined;
|
|
486
536
|
/** Fleet node id the run was placed on; absent renders as the local node. */
|
|
@@ -737,6 +787,8 @@ export type BusPayloadMap = {
|
|
|
737
787
|
[BusChannels.ToolBudgetExceeded]: ToolBudgetExceededPayload;
|
|
738
788
|
[BusChannels.ProviderHealth]: ProviderHealthPayload;
|
|
739
789
|
[BusChannels.RuntimeNotice]: RuntimeNoticePayload;
|
|
790
|
+
[BusChannels.ResidencyMutation]: ResidencyMutationPayload;
|
|
791
|
+
[BusChannels.DispatchScopeNotice]: DispatchScopeNoticePayload;
|
|
740
792
|
[BusChannels.DispatchEnqueued]: DispatchEnqueuedPayload;
|
|
741
793
|
[BusChannels.DispatchStarted]: DispatchStartedPayload;
|
|
742
794
|
[BusChannels.DispatchProgress]: DispatchProgressPayload;
|
|
@@ -749,6 +801,7 @@ export type BusPayloadMap = {
|
|
|
749
801
|
[BusChannels.ContextWarning]: ContextWarningPayload;
|
|
750
802
|
[BusChannels.ContextPruned]: ContextPrunedPayload;
|
|
751
803
|
[BusChannels.ContextRecalled]: ContextRecalledPayload;
|
|
804
|
+
[BusChannels.MemoryStepCompleted]: MemoryStepCompletedPayload;
|
|
752
805
|
[BusChannels.AgentStatusChanged]: AgentStatusChangedPayload;
|
|
753
806
|
[BusChannels.RunAborted]: RunAbortedPayload;
|
|
754
807
|
[BusChannels.BudgetAlert]: BudgetAlertPayload;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Cache classification for one backend completion call. */
|
|
2
|
+
export type BackendCacheVerdict = "hot" | "partial" | "cold" | "small";
|
|
3
|
+
|
|
4
|
+
/** Backend timing source that directly reports local prefill work. */
|
|
5
|
+
export type BackendTimingsSource = "llamacpp-timings" | "lmstudio-timings";
|
|
6
|
+
|
|
7
|
+
/** Normalized prefill and prediction timings reported by the serving backend. */
|
|
8
|
+
export interface BackendCompletionTimings {
|
|
9
|
+
promptTokens: number;
|
|
10
|
+
cachedTokens: number | null;
|
|
11
|
+
predictedTokens: number;
|
|
12
|
+
promptMs: number;
|
|
13
|
+
predictedMs: number;
|
|
14
|
+
source: BackendTimingsSource;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Per-session call counts grouped by backend cache verdict. */
|
|
18
|
+
export interface CacheVerdictCounts {
|
|
19
|
+
hot: number;
|
|
20
|
+
partial: number;
|
|
21
|
+
cold: number;
|
|
22
|
+
small: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function emptyCacheVerdictCounts(): CacheVerdictCounts {
|
|
26
|
+
return { hot: 0, partial: 0, cold: 0, small: 0 };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Return newly evaluated prefill tokens when the backend reports cache reads. */
|
|
30
|
+
export function uncachedPrefillTokens(backend: BackendCompletionTimings | null | undefined): number | null {
|
|
31
|
+
if (backend === null || backend === undefined || backend.cachedTokens === null) return null;
|
|
32
|
+
if (
|
|
33
|
+
!Number.isFinite(backend.promptTokens) ||
|
|
34
|
+
backend.promptTokens < 0 ||
|
|
35
|
+
!Number.isFinite(backend.cachedTokens) ||
|
|
36
|
+
backend.cachedTokens < 0 ||
|
|
37
|
+
backend.cachedTokens > backend.promptTokens
|
|
38
|
+
) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return backend.promptTokens - backend.cachedTokens;
|
|
42
|
+
}
|
|
@@ -16,7 +16,7 @@ export const CLIO_COMMIT_TRAILERS = {
|
|
|
16
16
|
} as const;
|
|
17
17
|
|
|
18
18
|
export interface CommitReceiptEvidence {
|
|
19
|
-
version:
|
|
19
|
+
version: 20;
|
|
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-v20/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 !== 20 ||
|
|
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-v20/sha256:${receipt.digest}`;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
/**
|
package/src/core/config.ts
CHANGED
|
@@ -521,6 +521,7 @@ function validateTarget(issues: Issues, path: string, value: unknown): ClioSetti
|
|
|
521
521
|
"gateway",
|
|
522
522
|
"pricing",
|
|
523
523
|
"lmstudio",
|
|
524
|
+
"maxConcurrentRequests",
|
|
524
525
|
]);
|
|
525
526
|
const id = "id" in value ? expectString(issues, `${path}.id`, value.id) : undefined;
|
|
526
527
|
const runtime = "runtime" in value ? expectString(issues, `${path}.runtime`, value.runtime) : undefined;
|
|
@@ -566,6 +567,10 @@ function validateTarget(issues: Issues, path: string, value: unknown): ClioSetti
|
|
|
566
567
|
const v = validateLmStudioSettings(issues, `${path}.lmstudio`, value.lmstudio);
|
|
567
568
|
if (v !== undefined) target.lmstudio = v;
|
|
568
569
|
}
|
|
570
|
+
if ("maxConcurrentRequests" in value) {
|
|
571
|
+
const v = expectInteger(issues, `${path}.maxConcurrentRequests`, value.maxConcurrentRequests, { min: 1 });
|
|
572
|
+
if (v !== undefined) target.maxConcurrentRequests = v;
|
|
573
|
+
}
|
|
569
574
|
return target;
|
|
570
575
|
}
|
|
571
576
|
|
|
@@ -1004,6 +1009,7 @@ const TOP_LEVEL_KEYS = [
|
|
|
1004
1009
|
"keybindings",
|
|
1005
1010
|
"compaction",
|
|
1006
1011
|
"context",
|
|
1012
|
+
"prewarm",
|
|
1007
1013
|
"retry",
|
|
1008
1014
|
"guardrails",
|
|
1009
1015
|
] as const;
|
|
@@ -1589,6 +1595,18 @@ export function validateSettings(raw: unknown): SettingsValidationResult {
|
|
|
1589
1595
|
}
|
|
1590
1596
|
}
|
|
1591
1597
|
|
|
1598
|
+
if ("prewarm" in raw) {
|
|
1599
|
+
if (!isPlainObject(raw.prewarm)) {
|
|
1600
|
+
issues.add("prewarm", `expected a map, got ${describe(raw.prewarm)}`);
|
|
1601
|
+
} else {
|
|
1602
|
+
issues.unknownKeys("prewarm", raw.prewarm, ["enabled"]);
|
|
1603
|
+
if ("enabled" in raw.prewarm) {
|
|
1604
|
+
const v = expectBoolean(issues, "prewarm.enabled", raw.prewarm.enabled);
|
|
1605
|
+
if (v !== undefined) settings.prewarm.enabled = v;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1592
1610
|
if ("retry" in raw) {
|
|
1593
1611
|
if (!isPlainObject(raw.retry)) {
|
|
1594
1612
|
issues.add("retry", `expected a map, got ${describe(raw.retry)}`);
|
package/src/core/defaults.ts
CHANGED
|
@@ -151,6 +151,21 @@ export interface WorkingSetSettings {
|
|
|
151
151
|
minEvictableTokens: number;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Prompt pre-warm settings (`prewarm`). On a local server prefill is the cost,
|
|
156
|
+
* and the prefix the next turn will send is fully known before the operator
|
|
157
|
+
* types anything: at session start, after a resume rebuilds the message array,
|
|
158
|
+
* and after a compaction settles. Clio sends that prefix to the backend right
|
|
159
|
+
* then so the slot's prefix cache already holds it when the real turn arrives.
|
|
160
|
+
*
|
|
161
|
+
* - enabled: master switch. The feature is off on every tier but
|
|
162
|
+
* `local-native` whatever this says, and off for workers and headless runs,
|
|
163
|
+
* because it buys latency for an operator watching a local server.
|
|
164
|
+
*/
|
|
165
|
+
export interface PrewarmSettings {
|
|
166
|
+
enabled: boolean;
|
|
167
|
+
}
|
|
168
|
+
|
|
154
169
|
/**
|
|
155
170
|
* Transient provider retry controls for the interactive chat loop. These are
|
|
156
171
|
* intentionally small and mirror the session retry helper defaults. Dispatched
|
|
@@ -354,11 +369,15 @@ export const DEFAULT_SETTINGS = {
|
|
|
354
369
|
everyNTools: 10,
|
|
355
370
|
windowSteps: 8,
|
|
356
371
|
maxTokens: 400,
|
|
357
|
-
// A memory step runs detached from the turn that triggered it,
|
|
358
|
-
//
|
|
359
|
-
//
|
|
360
|
-
//
|
|
361
|
-
|
|
372
|
+
// A memory step runs detached from the turn that triggered it, but it
|
|
373
|
+
// runs on a real inference endpoint that the operator's own turns and
|
|
374
|
+
// dispatched workers also queue against. The operator's ledger over 14
|
|
375
|
+
// days recorded 60 llm-tier steps spending 1,666 seconds of model time
|
|
376
|
+
// for 6 injections, with one step holding a local server for 102.5
|
|
377
|
+
// seconds to answer nothing. The deadline is what a turn boundary can
|
|
378
|
+
// actually wait for; a step that runs past it is recorded as timed out
|
|
379
|
+
// rather than spending the remaining minutes unobserved.
|
|
380
|
+
timeoutMs: 30_000,
|
|
362
381
|
},
|
|
363
382
|
},
|
|
364
383
|
watchdog: { enabled: false } as WatchdogSettings,
|
|
@@ -444,6 +463,9 @@ export const DEFAULT_SETTINGS = {
|
|
|
444
463
|
context: {
|
|
445
464
|
workingSet: DEFAULT_WORKING_SET_SETTINGS,
|
|
446
465
|
},
|
|
466
|
+
prewarm: {
|
|
467
|
+
enabled: true,
|
|
468
|
+
} as PrewarmSettings,
|
|
447
469
|
retry: {
|
|
448
470
|
enabled: true,
|
|
449
471
|
maxRetries: 3,
|
|
@@ -539,7 +561,7 @@ memory:
|
|
|
539
561
|
everyNTools: 10
|
|
540
562
|
windowSteps: 8
|
|
541
563
|
maxTokens: 400
|
|
542
|
-
timeoutMs:
|
|
564
|
+
timeoutMs: 30000
|
|
543
565
|
|
|
544
566
|
# Opt-in turn-end watchdog. When enabled, a turn that changed the tree is
|
|
545
567
|
# reviewed by one read-only verifier run briefed with the turn's coalesced diff
|
|
@@ -751,6 +773,14 @@ context:
|
|
|
751
773
|
protectLastTurns: 6
|
|
752
774
|
minEvictableTokens: 200
|
|
753
775
|
|
|
776
|
+
# Prompt pre-warm. At session start, after a resume rebuilds the message array,
|
|
777
|
+
# and after a compaction settles, Clio sends the prefix the next turn would send
|
|
778
|
+
# (minus your text) so a local server has already prefilled it when you press
|
|
779
|
+
# Enter. Local-native targets only, interactive sessions only, and never while a
|
|
780
|
+
# turn or a dispatch is running.
|
|
781
|
+
prewarm:
|
|
782
|
+
enabled: true
|
|
783
|
+
|
|
754
784
|
# Transient provider/stream retry controls for interactive chat.
|
|
755
785
|
# Retryable errors include overloads, rate limits, 5xx responses, network
|
|
756
786
|
# resets, and timeouts. Context overflow uses compaction recovery instead.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical identity of an OpenAI-compatible inference endpoint: normalized
|
|
3
|
+
* HTTP scheme, lower-cased host, normalized port, and normalized base path with
|
|
4
|
+
* a conventional terminal `/v1` mount stripped. Credentials, query, and
|
|
5
|
+
* fragment do not participate. Host aliases are not resolved, so
|
|
6
|
+
* `localhost` and `127.0.0.1` stay distinct. Shared by dispatch capacity and
|
|
7
|
+
* residency locking so both speak the same key for one server.
|
|
8
|
+
*/
|
|
9
|
+
export function canonicalEndpointUrl(raw: string | null | undefined): string | null {
|
|
10
|
+
if (!raw?.trim()) return null;
|
|
11
|
+
try {
|
|
12
|
+
const url = new URL(raw.trim().replace(/^ws:/u, "http:").replace(/^wss:/u, "https:"));
|
|
13
|
+
url.protocol = url.protocol.toLowerCase();
|
|
14
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
|
|
15
|
+
url.hostname = url.hostname.toLowerCase();
|
|
16
|
+
url.username = "";
|
|
17
|
+
url.password = "";
|
|
18
|
+
url.hash = "";
|
|
19
|
+
url.search = "";
|
|
20
|
+
let path = url.pathname.replace(/\/{2,}/gu, "/").replace(/\/$/u, "");
|
|
21
|
+
if (path.endsWith("/v1")) path = path.slice(0, -3);
|
|
22
|
+
url.pathname = path || "/";
|
|
23
|
+
return url.toString().replace(/\/$/u, "");
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
export const PATH_BOUNDARY_MAX_ENTRIES = 32;
|
|
4
|
+
|
|
5
|
+
export type PathBoundary = ReadonlyArray<string>;
|
|
6
|
+
|
|
7
|
+
type PathBoundaryErrorCode = "empty" | "separator" | "glob" | "absolute" | "parent" | "dot";
|
|
8
|
+
|
|
9
|
+
export class PathBoundaryError extends Error {
|
|
10
|
+
readonly code: PathBoundaryErrorCode;
|
|
11
|
+
|
|
12
|
+
constructor(code: PathBoundaryErrorCode, message: string) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "PathBoundaryError";
|
|
15
|
+
this.code = code;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const GLOB_CHARACTERS = /[*?[\]{}]/u;
|
|
20
|
+
|
|
21
|
+
/** Normalize one repository-relative boundary entry. */
|
|
22
|
+
export function normalizePathBoundaryEntry(entry: string): string {
|
|
23
|
+
const raw = entry.trim();
|
|
24
|
+
if (raw.length === 0) throw new PathBoundaryError("empty", "write boundary: entry must be a non-empty path");
|
|
25
|
+
if (raw.includes("\\")) {
|
|
26
|
+
throw new PathBoundaryError("separator", `write boundary: entry '${entry}' must use '/' separators`);
|
|
27
|
+
}
|
|
28
|
+
if (GLOB_CHARACTERS.test(raw)) {
|
|
29
|
+
throw new PathBoundaryError("glob", `write boundary: entry '${entry}' looks like a glob, which v1 does not support`);
|
|
30
|
+
}
|
|
31
|
+
if (raw.startsWith("/") || /^[A-Za-z]:/u.test(raw)) {
|
|
32
|
+
throw new PathBoundaryError("absolute", `write boundary: entry '${entry}' must be repository-relative, not absolute`);
|
|
33
|
+
}
|
|
34
|
+
const subtree = raw.endsWith("/");
|
|
35
|
+
const segments = raw.split("/").filter((segment) => segment.length > 0);
|
|
36
|
+
if (segments.length === 0) {
|
|
37
|
+
throw new PathBoundaryError("empty", `write boundary: entry '${entry}' must name a path inside the repository`);
|
|
38
|
+
}
|
|
39
|
+
for (const segment of segments) {
|
|
40
|
+
if (segment === "..") {
|
|
41
|
+
throw new PathBoundaryError("parent", `write boundary: entry '${entry}' must not contain '..'`);
|
|
42
|
+
}
|
|
43
|
+
if (segment === ".") {
|
|
44
|
+
throw new PathBoundaryError("dot", `write boundary: entry '${entry}' must not contain '.' segments`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const joined = segments.join("/");
|
|
48
|
+
return subtree ? `${joined}/` : joined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Normalize, deduplicate, and sort a boundary declaration. */
|
|
52
|
+
export function normalizePathBoundary(entries: ReadonlyArray<string>): string[] {
|
|
53
|
+
if (entries.length > PATH_BOUNDARY_MAX_ENTRIES) {
|
|
54
|
+
throw new Error(`write boundary: at most ${PATH_BOUNDARY_MAX_ENTRIES} entries may be declared`);
|
|
55
|
+
}
|
|
56
|
+
return [...new Set(entries.map(normalizePathBoundaryEntry))].sort();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function toPosixBoundaryPath(value: string): string {
|
|
60
|
+
return value.split("\\").join("/");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function isDirectoryPathBoundary(entry: string): boolean {
|
|
64
|
+
return toPosixBoundaryPath(entry).endsWith("/");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Convert a path to the subtree form spoken by the boundary grammar. */
|
|
68
|
+
export function asDirectoryPathBoundary(entry: string): string {
|
|
69
|
+
const normalized = toPosixBoundaryPath(entry);
|
|
70
|
+
return normalized.endsWith("/") ? normalized : `${normalized}/`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Resolve a repository-relative boundary while retaining exact or subtree meaning. */
|
|
74
|
+
export function resolvePathBoundary(cwd: string, entry: string): string {
|
|
75
|
+
const directory = isDirectoryPathBoundary(entry);
|
|
76
|
+
const withoutMarker = directory ? entry.slice(0, -1) : entry;
|
|
77
|
+
const resolved = toPosixBoundaryPath(path.resolve(cwd, withoutMarker));
|
|
78
|
+
return directory ? asDirectoryPathBoundary(resolved) : resolved;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Whether one boundary entry contains another exact path or subtree. */
|
|
82
|
+
export function pathBoundaryEntryCovers(outer: string, inner: string): boolean {
|
|
83
|
+
const normalizedOuter = toPosixBoundaryPath(outer);
|
|
84
|
+
const normalizedInner = toPosixBoundaryPath(inner);
|
|
85
|
+
return normalizedOuter.endsWith("/")
|
|
86
|
+
? normalizedInner.startsWith(normalizedOuter)
|
|
87
|
+
: !normalizedInner.endsWith("/") && normalizedInner === normalizedOuter;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Whether any entry in a boundary contains the candidate. */
|
|
91
|
+
export function pathBoundaryCovers(boundary: PathBoundary, candidate: string): boolean {
|
|
92
|
+
return boundary.some((entry) => pathBoundaryEntryCovers(entry, candidate));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Whether two boundary declarations share any possible path. */
|
|
96
|
+
export function pathBoundariesOverlap(left: PathBoundary, right: PathBoundary): boolean {
|
|
97
|
+
return left.some((entry) =>
|
|
98
|
+
right.some((other) => pathBoundaryEntryCovers(entry, other) || pathBoundaryEntryCovers(other, entry)),
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { canonicalEndpointUrl } from "./endpoint-key.js";
|
|
2
|
+
|
|
3
|
+
/** Runtime families whose model residency Clio can actively mutate. */
|
|
4
|
+
export type ResidencyRuntimeId = "llamacpp" | "lmstudio" | "ollama-native";
|
|
5
|
+
|
|
6
|
+
const RESIDENCY_RUNTIME_IDS: ReadonlySet<string> = new Set<ResidencyRuntimeId>([
|
|
7
|
+
"llamacpp",
|
|
8
|
+
"lmstudio",
|
|
9
|
+
"ollama-native",
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
export function residencyTargetKey(runtimeId: ResidencyRuntimeId, baseUrl: string): string;
|
|
13
|
+
export function residencyTargetKey(runtimeId: string, baseUrl: string | null | undefined): string | null;
|
|
14
|
+
/** Stable key for one residency-managed server endpoint: its canonical URL. */
|
|
15
|
+
export function residencyTargetKey(runtimeId: string, baseUrl: string | null | undefined): string | null {
|
|
16
|
+
if (!RESIDENCY_RUNTIME_IDS.has(runtimeId) || typeof baseUrl !== "string") return null;
|
|
17
|
+
// The key is the canonical endpoint itself, without a runtime prefix, so the
|
|
18
|
+
// residency lock and dispatch capacity name one server the same way (#250).
|
|
19
|
+
// A base url the canonical form refuses, such as one written without a
|
|
20
|
+
// scheme, still gets a key: callers store this in `ResidencyAdapter.targetKey`,
|
|
21
|
+
// which is a `string`, and dispatch capacity has no key for that target
|
|
22
|
+
// either, so there is nothing to agree with and nothing to gain by dropping
|
|
23
|
+
// the lock the reconciler serializes on.
|
|
24
|
+
return canonicalEndpointUrl(baseUrl) ?? baseUrl;
|
|
25
|
+
}
|
|
@@ -11,11 +11,45 @@ export const RESPONSE_SCHEMA_MAX_SERIALIZED_BYTES = 64 * 1024;
|
|
|
11
11
|
* `schema` key, and returns HTTP 200 with unconstrained JSON, so widening this
|
|
12
12
|
* to the api family would convert a clean refusal into a silent
|
|
13
13
|
* non-enforcement. lmstudio declares `structuredOutputs: "json-schema"`
|
|
14
|
-
* truthfully and is still excluded here, because
|
|
15
|
-
* transport. Widen this only together with a dialect for the
|
|
14
|
+
* truthfully and is still excluded here, because the worker seam has no
|
|
15
|
+
* dialect for its transport. Widen this only together with a dialect for the
|
|
16
|
+
* runtime added; {@link responseSchemaDialectFor} is where the out-of-turn
|
|
17
|
+
* seam did exactly that (issue #223).
|
|
16
18
|
*/
|
|
17
19
|
export const RESPONSE_SCHEMA_RUNTIME_ID = "llamacpp";
|
|
18
20
|
|
|
21
|
+
/** The runtime that takes the standard OpenAI `json_schema` response format. */
|
|
22
|
+
export const OPENAI_SCHEMA_RUNTIME_ID = "lmstudio";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* How a runtime spells a JSON-schema response constraint on the wire.
|
|
26
|
+
*
|
|
27
|
+
* `llamacpp-json-object` is llama-server's own `response_format: { type:
|
|
28
|
+
* "json_object", schema }`, which it compiles into a sampler grammar.
|
|
29
|
+
* `openai-json-schema` is the standard `response_format: { type:
|
|
30
|
+
* "json_schema", json_schema: { name, strict, schema } }` that LM Studio
|
|
31
|
+
* implements.
|
|
32
|
+
*/
|
|
33
|
+
export type ResponseSchemaDialect = "llamacpp-json-object" | "openai-json-schema";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The dialect this runtime takes, or null when Clio has none for it and the
|
|
37
|
+
* request has to go unconstrained.
|
|
38
|
+
*
|
|
39
|
+
* Deliberately a name check, for the reason {@link RESPONSE_SCHEMA_RUNTIME_ID}
|
|
40
|
+
* gives: a generic OpenAI-compatible gateway answers HTTP 200 to a spelling it
|
|
41
|
+
* does not implement and returns unconstrained JSON, so a capability flag would
|
|
42
|
+
* turn a known non-enforcement into a silent one. This is the out-of-turn
|
|
43
|
+
* seam's table; the worker seam keeps the narrower
|
|
44
|
+
* {@link runtimeSpeaksResponseSchemaDialect} check, because a worker that
|
|
45
|
+
* cannot enforce a contract must refuse admission rather than degrade.
|
|
46
|
+
*/
|
|
47
|
+
export function responseSchemaDialectFor(runtimeId: string): ResponseSchemaDialect | null {
|
|
48
|
+
if (runtimeId === RESPONSE_SCHEMA_RUNTIME_ID) return "llamacpp-json-object";
|
|
49
|
+
if (runtimeId === OPENAI_SCHEMA_RUNTIME_ID) return "openai-json-schema";
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
19
53
|
/** Whether this runtime speaks the dialect above. Transport shape, not capability. */
|
|
20
54
|
export function runtimeSpeaksResponseSchemaDialect(runtime: { id: string; kind: string; apiFamily: string }): boolean {
|
|
21
55
|
return (
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
1
|
import type { DomainBundle, DomainContext, DomainExtension } from "../../core/domain-loader.js";
|
|
3
|
-
import { resolvePackageRoot } from "../../core/package-root.js";
|
|
4
|
-
import { clioConfigDir } from "../../core/xdg.js";
|
|
5
2
|
import { assertAgentIdNamespace } from "../config/agent-namespace.js";
|
|
6
3
|
import type { ConfigContract } from "../config/contract.js";
|
|
7
4
|
import type { AgentsContract } from "./contract.js";
|
|
8
5
|
import type { AgentRecipe } from "./recipe.js";
|
|
9
|
-
import { type AgentRecipeDiagnostic,
|
|
6
|
+
import { type AgentRecipeDiagnostic, discoverAgentRecipes } from "./registry.js";
|
|
10
7
|
import { type AgentSpec, normalizeAgentSpec } from "./spec.js";
|
|
11
8
|
|
|
12
9
|
export function createAgentsBundle(_context: DomainContext): DomainBundle<AgentsContract> {
|
|
@@ -15,14 +12,8 @@ export function createAgentsBundle(_context: DomainContext): DomainBundle<Agents
|
|
|
15
12
|
let diagnostics: ReadonlyArray<AgentRecipeDiagnostic> = [];
|
|
16
13
|
|
|
17
14
|
function discover(): void {
|
|
18
|
-
const builtinDir = path.join(resolvePackageRoot(), "src", "domains", "agents", "builtins");
|
|
19
|
-
const userDir = path.join(clioConfigDir(), "agents");
|
|
20
|
-
const projectDir = path.join(process.cwd(), ".clio-coder", "agents");
|
|
21
15
|
const nextDiagnostics: AgentRecipeDiagnostic[] = [];
|
|
22
|
-
const
|
|
23
|
-
const user = loadRecipesFromDir({ dir: userDir, source: "user" }, nextDiagnostics);
|
|
24
|
-
const project = loadRecipesFromDir({ dir: projectDir, source: "project" }, nextDiagnostics);
|
|
25
|
-
const merged = mergeRecipes(builtin, user, project);
|
|
16
|
+
const merged = discoverAgentRecipes(process.cwd(), nextDiagnostics);
|
|
26
17
|
const config = _context.getContract<ConfigContract>("config");
|
|
27
18
|
assertAgentIdNamespace(merged, config?.get()?.delegation?.agents ?? []);
|
|
28
19
|
recipes = merged;
|