@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
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* proportional reconciliation the footer bar already performs.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import type { BackendCacheVerdict, BackendCompletionTimings } from "../../core/cache-telemetry.js";
|
|
19
20
|
import type { ContextWindowSlots, ContextWindowSource } from "../providers/index.js";
|
|
20
21
|
import { DEFAULT_COMPACTION_THRESHOLD } from "./compaction/auto.js";
|
|
21
22
|
|
|
@@ -100,6 +101,22 @@ export interface BuildContextLedgerInput {
|
|
|
100
101
|
} | null;
|
|
101
102
|
/** Prompt-cache honesty line; null until a turn has compiled and settled. */
|
|
102
103
|
promptCache?: PromptCacheStats | null;
|
|
104
|
+
/** Last pre-warm since the previous settled run; null when none has run. */
|
|
105
|
+
prewarm?: PrewarmStats | null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* One pre-warm's result. It is deliberately not a token category: the pre-warm
|
|
110
|
+
* spends no window space and adds no message, it only says the backend has
|
|
111
|
+
* already prefilled the prefix the next turn will send.
|
|
112
|
+
*/
|
|
113
|
+
export interface PrewarmStats {
|
|
114
|
+
/** Prompt tokens the backend processed; null when it reported no counts. */
|
|
115
|
+
tokens: number | null;
|
|
116
|
+
/** Wall clock the round took. */
|
|
117
|
+
ms: number;
|
|
118
|
+
/** True when the operator submitted before the round settled. */
|
|
119
|
+
aborted: boolean;
|
|
103
120
|
}
|
|
104
121
|
|
|
105
122
|
/**
|
|
@@ -117,13 +134,17 @@ export interface PromptCacheStats {
|
|
|
117
134
|
cacheWriteTokens: number | null;
|
|
118
135
|
/** Provider-reported uncached input tokens for the last run. */
|
|
119
136
|
uncachedInputTokens: number | null;
|
|
137
|
+
/** Serving-backend timings for the run's last API call; null when none were captured. */
|
|
138
|
+
backend: BackendCompletionTimings | null;
|
|
139
|
+
/** Backend prompt tokens not served from cache, derived only when cache reads were reported. */
|
|
140
|
+
uncachedPrefillTokens: number | null;
|
|
120
141
|
/**
|
|
121
|
-
* Cache verdict of the run's first API call, classified
|
|
122
|
-
* provider
|
|
123
|
-
* settled run. "Shell reused
|
|
124
|
-
* combination the overlay
|
|
142
|
+
* Cache verdict of the run's first API call, classified by
|
|
143
|
+
* `backendCacheVerdict` from normalized provider usage and captured serving
|
|
144
|
+
* backend timings when available. Null before any settled run. "Shell reused
|
|
145
|
+
* but backend cold" is the dishonest combination the overlay warns about.
|
|
125
146
|
*/
|
|
126
|
-
backendVerdict:
|
|
147
|
+
backendVerdict: BackendCacheVerdict | null;
|
|
127
148
|
/** Cache disturbances Clio expected before the last settled run. */
|
|
128
149
|
expectedColdReasons?: ReadonlyArray<string>;
|
|
129
150
|
}
|
|
@@ -185,6 +206,8 @@ export interface ContextLedger {
|
|
|
185
206
|
trigger: string;
|
|
186
207
|
} | null;
|
|
187
208
|
promptCache: PromptCacheStats | null;
|
|
209
|
+
/** Last pre-warm since the previous settled run; null when none has run. */
|
|
210
|
+
prewarm: PrewarmStats | null;
|
|
188
211
|
}
|
|
189
212
|
|
|
190
213
|
/** Maps a prompt segment id to the ledger bucket it belongs to. */
|
|
@@ -332,14 +355,6 @@ export function buildContextLedger(input: BuildContextLedgerInput): ContextLedge
|
|
|
332
355
|
}
|
|
333
356
|
|
|
334
357
|
const meter: ContextLedgerGroup[] = [...groups];
|
|
335
|
-
if (reserveTokens > 0) {
|
|
336
|
-
meter.push({
|
|
337
|
-
category: "reserve",
|
|
338
|
-
label: CONTEXT_CATEGORY_LABEL.reserve,
|
|
339
|
-
tokens: reserveTokens,
|
|
340
|
-
percent: percentOf(reserveTokens, window),
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
358
|
if (window > 0) {
|
|
344
359
|
meter.push({
|
|
345
360
|
category: "free",
|
|
@@ -348,6 +363,14 @@ export function buildContextLedger(input: BuildContextLedgerInput): ContextLedge
|
|
|
348
363
|
percent: percentOf(freeTokens, window),
|
|
349
364
|
});
|
|
350
365
|
}
|
|
366
|
+
if (reserveTokens > 0) {
|
|
367
|
+
meter.push({
|
|
368
|
+
category: "reserve",
|
|
369
|
+
label: CONTEXT_CATEGORY_LABEL.reserve,
|
|
370
|
+
tokens: reserveTokens,
|
|
371
|
+
percent: percentOf(reserveTokens, window),
|
|
372
|
+
});
|
|
373
|
+
}
|
|
351
374
|
|
|
352
375
|
return {
|
|
353
376
|
provider: input.provider ?? null,
|
|
@@ -369,5 +392,6 @@ export function buildContextLedger(input: BuildContextLedgerInput): ContextLedge
|
|
|
369
392
|
meter,
|
|
370
393
|
lastCompaction: input.lastCompaction ?? null,
|
|
371
394
|
promptCache: input.promptCache ?? null,
|
|
395
|
+
prewarm: input.prewarm ?? null,
|
|
372
396
|
};
|
|
373
397
|
}
|
|
@@ -61,6 +61,12 @@ export type {
|
|
|
61
61
|
export { isSessionEntry, isSessionHeader, SESSION_ENTRY_KINDS } from "./entries.js";
|
|
62
62
|
export { SessionManifest } from "./manifest.js";
|
|
63
63
|
export { CURRENT_SESSION_FORMAT_VERSION, runMigrations } from "./migrations/index.js";
|
|
64
|
+
export type { ExpectedColdReasonCount, PromptCacheTelemetry } from "./prompt-cache.js";
|
|
65
|
+
export {
|
|
66
|
+
foldPromptCacheTelemetry,
|
|
67
|
+
hasPromptCacheTelemetry,
|
|
68
|
+
topExpectedColdReason,
|
|
69
|
+
} from "./prompt-cache.js";
|
|
64
70
|
export {
|
|
65
71
|
protectedArtifactEntryFromArtifact,
|
|
66
72
|
protectedArtifactFromSessionEntry,
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type BackendCacheVerdict,
|
|
3
|
+
type BackendCompletionTimings,
|
|
4
|
+
type CacheVerdictCounts,
|
|
5
|
+
emptyCacheVerdictCounts,
|
|
6
|
+
uncachedPrefillTokens,
|
|
7
|
+
} from "../../core/cache-telemetry.js";
|
|
8
|
+
import type { SessionEntry } from "./entries.js";
|
|
9
|
+
|
|
10
|
+
/** Durable prompt-cache facts folded across assistant calls in one ledger slice. */
|
|
11
|
+
export interface PromptCacheTelemetry {
|
|
12
|
+
/** Sum of authoritative backend prefill work, or null when no call reported cache reads. */
|
|
13
|
+
uncachedPrefillTokens: number | null;
|
|
14
|
+
/** Calls contributing to `uncachedPrefillTokens`; distinguishes no evidence from a measured zero. */
|
|
15
|
+
uncachedPrefillCalls: number;
|
|
16
|
+
/** Counts of the verdict persisted on each assistant call. */
|
|
17
|
+
verdictCounts: CacheVerdictCounts;
|
|
18
|
+
/** Number of assistant calls carrying a recognized persisted verdict. */
|
|
19
|
+
verdictCalls: number;
|
|
20
|
+
/** How often each expected cache disturbance was stamped. */
|
|
21
|
+
expectedColdReasonCounts: Readonly<Record<string, number>>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ExpectedColdReasonCount {
|
|
25
|
+
reason: string;
|
|
26
|
+
count: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
30
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function finiteNonNegative(value: unknown): value is number {
|
|
34
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function backendTimings(value: unknown): BackendCompletionTimings | null {
|
|
38
|
+
if (!isRecord(value)) return null;
|
|
39
|
+
if (
|
|
40
|
+
!finiteNonNegative(value.promptTokens) ||
|
|
41
|
+
!finiteNonNegative(value.predictedTokens) ||
|
|
42
|
+
!finiteNonNegative(value.promptMs) ||
|
|
43
|
+
!finiteNonNegative(value.predictedMs) ||
|
|
44
|
+
(value.source !== "llamacpp-timings" && value.source !== "lmstudio-timings")
|
|
45
|
+
) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const cachedTokens = value.cachedTokens;
|
|
49
|
+
if (cachedTokens !== null && !finiteNonNegative(cachedTokens)) return null;
|
|
50
|
+
if (typeof cachedTokens === "number" && cachedTokens > value.promptTokens) return null;
|
|
51
|
+
return {
|
|
52
|
+
promptTokens: value.promptTokens,
|
|
53
|
+
cachedTokens,
|
|
54
|
+
predictedTokens: value.predictedTokens,
|
|
55
|
+
promptMs: value.promptMs,
|
|
56
|
+
predictedMs: value.predictedMs,
|
|
57
|
+
source: value.source,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function cacheVerdict(value: unknown): BackendCacheVerdict | null {
|
|
62
|
+
switch (value) {
|
|
63
|
+
case "hot":
|
|
64
|
+
case "partial":
|
|
65
|
+
case "cold":
|
|
66
|
+
case "small":
|
|
67
|
+
return value;
|
|
68
|
+
default:
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** True when the fold contains at least one durable cache fact. */
|
|
74
|
+
export function hasPromptCacheTelemetry(telemetry: PromptCacheTelemetry): boolean {
|
|
75
|
+
return (
|
|
76
|
+
telemetry.verdictCalls > 0 ||
|
|
77
|
+
telemetry.uncachedPrefillCalls > 0 ||
|
|
78
|
+
Object.keys(telemetry.expectedColdReasonCounts).length > 0
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Most frequent expected disturbance, with deterministic lexical tie-breaking. */
|
|
83
|
+
export function topExpectedColdReason(telemetry: PromptCacheTelemetry): ExpectedColdReasonCount | null {
|
|
84
|
+
const ranked = Object.entries(telemetry.expectedColdReasonCounts).sort(
|
|
85
|
+
([leftReason, leftCount], [rightReason, rightCount]) =>
|
|
86
|
+
rightCount - leftCount || leftReason.localeCompare(rightReason),
|
|
87
|
+
);
|
|
88
|
+
const first = ranked[0];
|
|
89
|
+
return first === undefined ? null : { reason: first[0], count: first[1] };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Fold persisted assistant `promptCache` payloads without reclassifying them.
|
|
94
|
+
* Callers provide the ledger slice they mean, such as one active branch or one
|
|
95
|
+
* report window, so every surface shares parsing while retaining its own scope.
|
|
96
|
+
*/
|
|
97
|
+
export function foldPromptCacheTelemetry(entries: ReadonlyArray<SessionEntry>): PromptCacheTelemetry {
|
|
98
|
+
const verdictCounts = emptyCacheVerdictCounts();
|
|
99
|
+
const expectedColdReasonCounts: Record<string, number> = {};
|
|
100
|
+
let verdictCalls = 0;
|
|
101
|
+
let uncachedTotal = 0;
|
|
102
|
+
let uncachedPrefillCalls = 0;
|
|
103
|
+
|
|
104
|
+
for (const entry of entries) {
|
|
105
|
+
if (entry.kind !== "message" || entry.role !== "assistant" || !isRecord(entry.payload)) continue;
|
|
106
|
+
const promptCache = entry.payload.promptCache;
|
|
107
|
+
if (!isRecord(promptCache)) continue;
|
|
108
|
+
|
|
109
|
+
const verdict = cacheVerdict(promptCache.backendVerdict);
|
|
110
|
+
if (verdict !== null) {
|
|
111
|
+
verdictCounts[verdict] += 1;
|
|
112
|
+
verdictCalls += 1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const backend = backendTimings(promptCache.backend);
|
|
116
|
+
const uncached = uncachedPrefillTokens(backend);
|
|
117
|
+
if (uncached !== null) {
|
|
118
|
+
uncachedTotal += uncached;
|
|
119
|
+
uncachedPrefillCalls += 1;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!Array.isArray(promptCache.expectedColdReasons)) continue;
|
|
123
|
+
const reasons = new Set(
|
|
124
|
+
promptCache.expectedColdReasons.filter(
|
|
125
|
+
(reason): reason is string => typeof reason === "string" && reason.trim().length > 0,
|
|
126
|
+
),
|
|
127
|
+
);
|
|
128
|
+
for (const reason of reasons) {
|
|
129
|
+
expectedColdReasonCounts[reason] = (expectedColdReasonCounts[reason] ?? 0) + 1;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
uncachedPrefillTokens: uncachedPrefillCalls > 0 ? uncachedTotal : null,
|
|
135
|
+
uncachedPrefillCalls,
|
|
136
|
+
verdictCounts,
|
|
137
|
+
verdictCalls,
|
|
138
|
+
expectedColdReasonCounts,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
@@ -14,6 +14,21 @@ import type { SessionMeta } from "./contract.js";
|
|
|
14
14
|
* stay diffable without recompiling anything.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Layout version of the compiled prompt these records describe.
|
|
19
|
+
*
|
|
20
|
+
* 1: the order shipped through 0.3.8.
|
|
21
|
+
* 2: stable-prefix-first ordering with one `# Memory` header, and
|
|
22
|
+
* `contextWindowSource` recorded alongside the window the prompt states
|
|
23
|
+
* (issue #249).
|
|
24
|
+
*
|
|
25
|
+
* A record without a `version` field predates the field and is read as 1, so a
|
|
26
|
+
* 0.3.8 manifest still parses. Bump this whenever the compiled text moves for a
|
|
27
|
+
* reason other than its inputs: a resumed session then has the version in hand
|
|
28
|
+
* to explain the one `promptRecompiled` entry its first compile writes.
|
|
29
|
+
*/
|
|
30
|
+
export const PROMPT_MANIFEST_VERSION = 2;
|
|
31
|
+
|
|
17
32
|
export interface PromptManifestSection {
|
|
18
33
|
id: string;
|
|
19
34
|
tokenEstimate: number;
|
|
@@ -27,6 +42,8 @@ export interface PromptManifestFragment {
|
|
|
27
42
|
}
|
|
28
43
|
|
|
29
44
|
export interface SessionPromptCompileRecord {
|
|
45
|
+
/** Prompt layout version; see `PROMPT_MANIFEST_VERSION`. Absent on pre-0.3.9 records. */
|
|
46
|
+
version?: number;
|
|
30
47
|
/** ISO timestamp of the compile. */
|
|
31
48
|
at: string;
|
|
32
49
|
/** Hash of the previously served prompt, null on the first compile. */
|
|
@@ -35,6 +52,14 @@ export interface SessionPromptCompileRecord {
|
|
|
35
52
|
tokenEstimate: number;
|
|
36
53
|
/** Thinking dial applied to the live agent when this prompt was compiled. */
|
|
37
54
|
thinkingLevel: string | null;
|
|
55
|
+
/**
|
|
56
|
+
* The window the prompt's `Context window: N` states, and the layer that
|
|
57
|
+
* answered it. `loaded` is what the backend has this model open at; anything
|
|
58
|
+
* else means the figure can still move once a loaded window is observed, and
|
|
59
|
+
* a later recompile is then explained rather than mysterious.
|
|
60
|
+
*/
|
|
61
|
+
contextWindow?: number | null;
|
|
62
|
+
contextWindowSource?: string | null;
|
|
38
63
|
projectPreload: ProjectPreloadClass | null;
|
|
39
64
|
sections: PromptManifestSection[];
|
|
40
65
|
fragments: PromptManifestFragment[];
|
|
@@ -102,9 +127,21 @@ function isProjectPreloadClass(value: unknown): value is ProjectPreloadClass {
|
|
|
102
127
|
);
|
|
103
128
|
}
|
|
104
129
|
|
|
130
|
+
/** Optional fields added after 0.3.8: absent is valid, present must be well-typed. */
|
|
131
|
+
function isOptional<T>(value: unknown, guard: (candidate: unknown) => candidate is T): boolean {
|
|
132
|
+
return value === undefined || guard(value);
|
|
133
|
+
}
|
|
134
|
+
|
|
105
135
|
function isSessionPromptCompileRecord(value: unknown): value is SessionPromptCompileRecord {
|
|
106
136
|
if (!isRecord(value)) return false;
|
|
107
137
|
return (
|
|
138
|
+
isOptional(value.version, isNonNegativeInteger) &&
|
|
139
|
+
isOptional(value.contextWindow, (candidate): candidate is number | null =>
|
|
140
|
+
candidate === null ? true : isNonNegativeInteger(candidate),
|
|
141
|
+
) &&
|
|
142
|
+
isOptional(value.contextWindowSource, (candidate): candidate is string | null =>
|
|
143
|
+
candidate === null ? true : typeof candidate === "string",
|
|
144
|
+
) &&
|
|
108
145
|
isCanonicalUtcTimestamp(value.at) &&
|
|
109
146
|
(value.previousHash === null || isSha256(value.previousHash)) &&
|
|
110
147
|
isSha256(value.systemPromptHash) &&
|
|
@@ -118,6 +155,11 @@ function isSessionPromptCompileRecord(value: unknown): value is SessionPromptCom
|
|
|
118
155
|
);
|
|
119
156
|
}
|
|
120
157
|
|
|
158
|
+
/** A record written before the field existed describes the 0.3.8 layout. */
|
|
159
|
+
export function promptManifestVersion(record: SessionPromptCompileRecord): number {
|
|
160
|
+
return record.version ?? 1;
|
|
161
|
+
}
|
|
162
|
+
|
|
121
163
|
export function getPromptManifestFilePath(meta: SessionMeta, stateDir?: string): string {
|
|
122
164
|
const safeMeta = {
|
|
123
165
|
...meta,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
1
2
|
import {
|
|
2
3
|
DEFAULT_DELEGATION_CONNECT_TIMEOUT_MS,
|
|
3
4
|
DEFAULT_DELEGATION_TURN_TIMEOUT_MS,
|
|
4
5
|
type DelegationAgentConfig,
|
|
5
6
|
} from "../../core/defaults.js";
|
|
7
|
+
import type { HeartbeatStamp } from "../../domains/dispatch/heartbeat.js";
|
|
6
8
|
import type { AutonomyLevel } from "../../domains/safety/autonomy.js";
|
|
7
9
|
import type { SafetyContract } from "../../domains/safety/contract.js";
|
|
8
10
|
import type { AgentEvent } from "../types.js";
|
|
@@ -40,6 +42,10 @@ export interface AcpDelegationRunInput {
|
|
|
40
42
|
terminationWaitMs?: number;
|
|
41
43
|
/** Grace for session/cancel before abort escalates into hard termination. */
|
|
42
44
|
cancelGraceMs?: number;
|
|
45
|
+
/** Wall clock for the persisted heartbeat anchor. */
|
|
46
|
+
now?: () => number;
|
|
47
|
+
/** Monotonic clock for event-inactivity spans. */
|
|
48
|
+
monotonicNow?: () => number;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
export interface AcpDelegationRunHandle {
|
|
@@ -54,7 +60,7 @@ export interface AcpDelegationRunHandle {
|
|
|
54
60
|
* final observation bound expires.
|
|
55
61
|
*/
|
|
56
62
|
kill(): void;
|
|
57
|
-
heartbeatAt:
|
|
63
|
+
heartbeatAt: HeartbeatStamp;
|
|
58
64
|
toolCallLog(): ReturnType<AcpToolMediator["snapshot"]>["toolCallLog"];
|
|
59
65
|
}
|
|
60
66
|
|
|
@@ -176,7 +182,14 @@ export function startAcpDelegationRun(input: AcpDelegationRunInput): AcpDelegati
|
|
|
176
182
|
// peer into an unbounded request.
|
|
177
183
|
const connectTimeoutMs = input.agent.connectTimeoutMs ?? DEFAULT_DELEGATION_CONNECT_TIMEOUT_MS;
|
|
178
184
|
const turnTimeoutMs = input.agent.turnTimeoutMs ?? DEFAULT_DELEGATION_TURN_TIMEOUT_MS;
|
|
179
|
-
const
|
|
185
|
+
const now = input.now ?? Date.now;
|
|
186
|
+
const monotonicNow = input.monotonicNow ?? (() => performance.now());
|
|
187
|
+
const heartbeatWallAnchor = now();
|
|
188
|
+
const heartbeatMonotonicAnchor = monotonicNow();
|
|
189
|
+
const heartbeatAt: HeartbeatStamp = {
|
|
190
|
+
current: heartbeatWallAnchor,
|
|
191
|
+
monotonic: heartbeatMonotonicAnchor,
|
|
192
|
+
};
|
|
180
193
|
const queue = new AsyncEventQueue<AcpRunEvent>();
|
|
181
194
|
const usage = emptyUsage();
|
|
182
195
|
const mapper = new AcpEventMapper();
|
|
@@ -202,7 +215,9 @@ export function startAcpDelegationRun(input: AcpDelegationRunInput): AcpDelegati
|
|
|
202
215
|
cancelTimer = null;
|
|
203
216
|
};
|
|
204
217
|
const emit = (event: AcpRunEvent): void => {
|
|
205
|
-
|
|
218
|
+
const stamp = monotonicNow();
|
|
219
|
+
heartbeatAt.monotonic = stamp;
|
|
220
|
+
heartbeatAt.current = heartbeatWallAnchor + (stamp - heartbeatMonotonicAnchor);
|
|
206
221
|
queue.push(event);
|
|
207
222
|
};
|
|
208
223
|
const mediator = new AcpToolMediator({
|
package/src/engine/acp/server.ts
CHANGED
|
@@ -1233,7 +1233,10 @@ function safeProbeReason(
|
|
|
1233
1233
|
} catch {
|
|
1234
1234
|
return "not-configured";
|
|
1235
1235
|
}
|
|
1236
|
-
|
|
1236
|
+
// Degraded is reachable with a default the server does not serve; a client
|
|
1237
|
+
// that names its own model can still use the target.
|
|
1238
|
+
const reachable = status.health.status === "healthy" || status.health.status === "degraded";
|
|
1239
|
+
return status.available && reachable ? null : "unreachable";
|
|
1237
1240
|
}
|
|
1238
1241
|
|
|
1239
1242
|
interface AcpPermissionBridge {
|
package/src/engine/ai.ts
CHANGED
|
@@ -27,9 +27,11 @@ import {
|
|
|
27
27
|
type ToolCall,
|
|
28
28
|
type Usage,
|
|
29
29
|
} from "@earendil-works/pi-ai";
|
|
30
|
+
import type { BackendCompletionTimings } from "../core/cache-telemetry.js";
|
|
30
31
|
import {
|
|
31
32
|
completeEngineSimple,
|
|
32
33
|
engineStream,
|
|
34
|
+
engineStreamSimple,
|
|
33
35
|
registerEngineBuiltins,
|
|
34
36
|
registerEngineFauxProvider,
|
|
35
37
|
} from "./api-registry.js";
|
|
@@ -40,6 +42,14 @@ export { StringEnum };
|
|
|
40
42
|
|
|
41
43
|
export const stream = engineStream;
|
|
42
44
|
|
|
45
|
+
/**
|
|
46
|
+
* The dispatcher a turn runs on. `createEngineAgent` hands this to pi-agent-core
|
|
47
|
+
* as its `streamFn`, so a caller that needs a request byte-identical to the one
|
|
48
|
+
* the next turn would send (the session pre-warm) sends it through here rather
|
|
49
|
+
* than through `stream`, whose bare-call path has to guess a thinking level.
|
|
50
|
+
*/
|
|
51
|
+
export const streamSimple = engineStreamSimple;
|
|
52
|
+
|
|
43
53
|
export interface EngineTextCompletionInput {
|
|
44
54
|
model: EngineModel;
|
|
45
55
|
systemPrompt: string;
|
|
@@ -55,6 +65,21 @@ export interface EngineTextCompletionResult {
|
|
|
55
65
|
text: string;
|
|
56
66
|
inputTokens: number;
|
|
57
67
|
outputTokens: number;
|
|
68
|
+
/**
|
|
69
|
+
* The provider's full usage record for the call, so a caller that has to
|
|
70
|
+
* account for the spend does not have to re-derive it from two token counts.
|
|
71
|
+
*/
|
|
72
|
+
usage: {
|
|
73
|
+
input: number;
|
|
74
|
+
output: number;
|
|
75
|
+
cacheRead: number;
|
|
76
|
+
cacheWrite: number;
|
|
77
|
+
reasoning: number;
|
|
78
|
+
totalTokens: number;
|
|
79
|
+
costUsd: number;
|
|
80
|
+
};
|
|
81
|
+
/** Backend prefill and prediction facts when the serving runtime reported them. */
|
|
82
|
+
backend: BackendCompletionTimings | null;
|
|
58
83
|
}
|
|
59
84
|
|
|
60
85
|
/** Run one tool-free completion while keeping pi message types at the engine boundary. */
|
|
@@ -83,6 +108,16 @@ export async function completeEngineText(input: EngineTextCompletionInput): Prom
|
|
|
83
108
|
.join(""),
|
|
84
109
|
inputTokens: response.usage.input,
|
|
85
110
|
outputTokens: response.usage.output,
|
|
111
|
+
usage: {
|
|
112
|
+
input: response.usage.input,
|
|
113
|
+
output: response.usage.output,
|
|
114
|
+
cacheRead: response.usage.cacheRead,
|
|
115
|
+
cacheWrite: response.usage.cacheWrite,
|
|
116
|
+
reasoning: response.usage.reasoning ?? 0,
|
|
117
|
+
totalTokens: response.usage.totalTokens,
|
|
118
|
+
costUsd: response.usage.cost.total,
|
|
119
|
+
},
|
|
120
|
+
backend: response.backendTimings ?? null,
|
|
86
121
|
};
|
|
87
122
|
}
|
|
88
123
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { performance } from "node:perf_hooks";
|
|
2
|
+
import { residencyTargetKey } from "../../core/residency-target-key.js";
|
|
2
3
|
import { sleep } from "../../core/timers.js";
|
|
3
4
|
import {
|
|
4
5
|
type ResidencyAdapter,
|
|
@@ -169,6 +170,26 @@ async function fetchRouterModels(
|
|
|
169
170
|
return parseRouterModels(await response.json());
|
|
170
171
|
}
|
|
171
172
|
|
|
173
|
+
class RouterModelPostError extends Error {
|
|
174
|
+
constructor(
|
|
175
|
+
readonly url: string,
|
|
176
|
+
readonly status: number,
|
|
177
|
+
readonly responseBody: string,
|
|
178
|
+
) {
|
|
179
|
+
super(`llama.cpp router rejected ${url}: HTTP ${status}; response: ${responseBody}`);
|
|
180
|
+
this.name = "RouterModelPostError";
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function routerErrorBody(response: Response): Promise<string> {
|
|
185
|
+
try {
|
|
186
|
+
const body = (await response.text()).trim();
|
|
187
|
+
return body.length > 0 ? body : "<empty body>";
|
|
188
|
+
} catch (error) {
|
|
189
|
+
return `<unreadable body: ${error instanceof Error ? error.message : String(error)}>`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
172
193
|
async function postRouterModel(fetchImpl: typeof fetch, url: string, modelId: string): Promise<void> {
|
|
173
194
|
const response = await fetchImpl(url, {
|
|
174
195
|
method: "POST",
|
|
@@ -177,7 +198,38 @@ async function postRouterModel(fetchImpl: typeof fetch, url: string, modelId: st
|
|
|
177
198
|
signal: AbortSignal.timeout(LOAD_TIMEOUT_MS),
|
|
178
199
|
});
|
|
179
200
|
if (response.ok) return;
|
|
180
|
-
throw new
|
|
201
|
+
throw new RouterModelPostError(url, response.status, await routerErrorBody(response));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function alreadyRunningResponse(body: string): boolean {
|
|
205
|
+
return body.toLowerCase().includes("already running");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* A router wake and Clio's explicit load can cross between the listing and the
|
|
210
|
+
* POST. In that race the router rejects the duplicate request even though the
|
|
211
|
+
* requested model now owns a resident slot. Re-read the authoritative listing
|
|
212
|
+
* before treating a non-2xx as a load failure; only a definitively absent,
|
|
213
|
+
* unloaded, or failed model preserves the rejection.
|
|
214
|
+
*/
|
|
215
|
+
async function postRouterLoad(input: LlamaCppResidencyInput, fetchImpl: typeof fetch, modelId: string): Promise<void> {
|
|
216
|
+
try {
|
|
217
|
+
await postRouterModel(fetchImpl, loadUrl(input.baseUrl), modelId);
|
|
218
|
+
} catch (error) {
|
|
219
|
+
if (!(error instanceof RouterModelPostError)) throw error;
|
|
220
|
+
let model: LlamaCppRouterModel | undefined;
|
|
221
|
+
try {
|
|
222
|
+
model = (await fetchRouterModels(input, fetchImpl)).find((entry) => entry.id === modelId);
|
|
223
|
+
} catch {
|
|
224
|
+
// The router's explicit "already running" answer is sufficient even if
|
|
225
|
+
// the confirming snapshot itself races or is temporarily unavailable.
|
|
226
|
+
if (alreadyRunningResponse(error.responseBody)) return;
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
if (alreadyRunningResponse(error.responseBody)) return;
|
|
230
|
+
if (model !== undefined && model.state !== "unloaded" && model.state !== "failed") return;
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
181
233
|
}
|
|
182
234
|
|
|
183
235
|
async function waitForLoaded(input: LlamaCppResidencyInput, fetchImpl: typeof fetch, modelId: string): Promise<void> {
|
|
@@ -206,7 +258,7 @@ async function ensureModelLoaded(
|
|
|
206
258
|
// router answers `400 model is already running`, which fails the turn before
|
|
207
259
|
// it reaches the model.
|
|
208
260
|
if (knownState === "loaded" || knownState === "sleeping") return;
|
|
209
|
-
if (knownState !== "loading") await
|
|
261
|
+
if (knownState !== "loading") await postRouterLoad(input, fetchImpl, modelId);
|
|
210
262
|
await waitForLoaded(input, fetchImpl, modelId);
|
|
211
263
|
}
|
|
212
264
|
|
|
@@ -246,7 +298,7 @@ export async function ensureLlamaCppResidency(input: LlamaCppResidencyInput): Pr
|
|
|
246
298
|
const fetchImpl = input.fetchImpl ?? fetch;
|
|
247
299
|
let snapshot: LlamaCppRouterModel[] = [];
|
|
248
300
|
const adapter: ResidencyAdapter = {
|
|
249
|
-
targetKey:
|
|
301
|
+
targetKey: residencyTargetKey("llamacpp", input.baseUrl),
|
|
250
302
|
targetId: input.targetId,
|
|
251
303
|
runtimeId: input.runtimeId,
|
|
252
304
|
keepModelId: input.keepModelId,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
2
2
|
|
|
3
|
+
import { residencyTargetKey } from "../../core/residency-target-key.js";
|
|
3
4
|
import {
|
|
4
5
|
type LmStudioCatalog,
|
|
5
6
|
type LmStudioLoadedInstance,
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
} from "../../domains/providers/runtimes/common/lmstudio-http.js";
|
|
12
13
|
import type { TargetDescriptor } from "../../domains/providers/types/target-descriptor.js";
|
|
13
14
|
import { coResidentContextCeiling, fitLoadContextLength } from "./lmstudio-residency.js";
|
|
14
|
-
import { emitResidencyNotice, reconcileResidency, residencyManagedFor } from "./residency.js";
|
|
15
|
+
import { emitResidencyMutation, emitResidencyNotice, reconcileResidency, residencyManagedFor } from "./residency.js";
|
|
15
16
|
import { withResidencyLock } from "./residency-lock.js";
|
|
16
17
|
|
|
17
18
|
interface LmStudioModelMetadata {
|
|
@@ -205,7 +206,7 @@ export async function ensureLmStudioResidency(
|
|
|
205
206
|
entry.loadedInstances.map((instance) => ({ modelKey: entry.key, identifier: instance.id, instance })),
|
|
206
207
|
);
|
|
207
208
|
const managed = residencyManagedFor(info.lifecycle);
|
|
208
|
-
const targetKey =
|
|
209
|
+
const targetKey = residencyTargetKey("lmstudio", target.url ?? model.baseUrl);
|
|
209
210
|
const contextLength = target.lmstudio?.load?.contextLength;
|
|
210
211
|
const plan = await reconcileResidency({
|
|
211
212
|
targetKey,
|
|
@@ -248,17 +249,36 @@ export async function ensureLmStudioResidency(
|
|
|
248
249
|
});
|
|
249
250
|
}
|
|
250
251
|
}
|
|
252
|
+
const loadAndReport = async (): Promise<string> => {
|
|
253
|
+
const instanceId = await loadOwnedInstance(target, targetKey, body, options.apiKey, options.signal);
|
|
254
|
+
emitResidencyMutation({
|
|
255
|
+
targetKey,
|
|
256
|
+
targetId: info.targetId,
|
|
257
|
+
runtimeId: "lmstudio",
|
|
258
|
+
model: modelKey,
|
|
259
|
+
operation: "load",
|
|
260
|
+
});
|
|
261
|
+
return instanceId ?? model.id;
|
|
262
|
+
};
|
|
251
263
|
try {
|
|
252
|
-
return
|
|
264
|
+
return await loadAndReport();
|
|
253
265
|
} catch (error) {
|
|
254
266
|
if (plan.decision === "observe" || plan.fallbackEvict.length === 0) throw error;
|
|
255
267
|
return withResidencyLock(targetKey, async () => {
|
|
256
268
|
for (const candidate of plan.fallbackEvict) {
|
|
257
269
|
for (const entry of instances.filter((resident) => resident.modelKey === candidate.modelId)) {
|
|
258
|
-
await unloadOwnedInstance(target, targetKey, entry.identifier, options.apiKey, options.signal)
|
|
270
|
+
if (await unloadOwnedInstance(target, targetKey, entry.identifier, options.apiKey, options.signal)) {
|
|
271
|
+
emitResidencyMutation({
|
|
272
|
+
targetKey,
|
|
273
|
+
targetId: info.targetId,
|
|
274
|
+
runtimeId: "lmstudio",
|
|
275
|
+
model: candidate.modelId,
|
|
276
|
+
operation: "evict",
|
|
277
|
+
});
|
|
278
|
+
}
|
|
259
279
|
}
|
|
260
280
|
}
|
|
261
|
-
return (
|
|
281
|
+
return loadAndReport();
|
|
262
282
|
});
|
|
263
283
|
}
|
|
264
284
|
}
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type Tool as OllamaTool,
|
|
25
25
|
type ToolCall as OllamaToolCall,
|
|
26
26
|
} from "ollama";
|
|
27
|
+
import { residencyTargetKey } from "../../core/residency-target-key.js";
|
|
27
28
|
import {
|
|
28
29
|
type AppliedThinking,
|
|
29
30
|
resolveModelRuntimeCapabilitiesForModel,
|
|
@@ -75,7 +76,7 @@ async function reconcileOllamaResidency(model: Model<"ollama-native">, headers:
|
|
|
75
76
|
if (!baseUrl) return;
|
|
76
77
|
const metadata = (model as Model<"ollama-native"> & ClioRuntimeMetadata).clio;
|
|
77
78
|
const adapter: ResidencyAdapter = {
|
|
78
|
-
targetKey:
|
|
79
|
+
targetKey: residencyTargetKey("ollama-native", baseUrl),
|
|
79
80
|
targetId: ollamaTargetId(model),
|
|
80
81
|
runtimeId: "ollama-native",
|
|
81
82
|
keepModelId: model.id,
|