@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
|
@@ -12,9 +12,17 @@ import {
|
|
|
12
12
|
type ContextPrunedPayload,
|
|
13
13
|
type ContextRecalledPayload,
|
|
14
14
|
type ContextWarningPayload,
|
|
15
|
+
type MemoryStepCompletedPayload,
|
|
16
|
+
type ResidencyMutationPayload,
|
|
15
17
|
} from "../core/bus-events.js";
|
|
18
|
+
import {
|
|
19
|
+
type BackendCacheVerdict,
|
|
20
|
+
type BackendCompletionTimings,
|
|
21
|
+
uncachedPrefillTokens,
|
|
22
|
+
} from "../core/cache-telemetry.js";
|
|
16
23
|
import type { ClioSettings } from "../core/config.js";
|
|
17
24
|
import type { SafeEventBus } from "../core/event-bus.js";
|
|
25
|
+
import { residencyTargetKey } from "../core/residency-target-key.js";
|
|
18
26
|
import type { ToolName } from "../core/tool-names.js";
|
|
19
27
|
import { buildEvictionFields, planEviction } from "../domains/context/working-set/engine.js";
|
|
20
28
|
import { foldWorkingSet } from "../domains/context/working-set/fold.js";
|
|
@@ -26,6 +34,7 @@ import type { PromptsContract } from "../domains/prompts/contract.js";
|
|
|
26
34
|
import {
|
|
27
35
|
type ContextWindowDetails,
|
|
28
36
|
type ContextWindowSource,
|
|
37
|
+
canonicalEndpointKey,
|
|
29
38
|
type ProvidersContract,
|
|
30
39
|
resolveRuntimeTarget,
|
|
31
40
|
} from "../domains/providers/index.js";
|
|
@@ -50,18 +59,29 @@ import {
|
|
|
50
59
|
contextUsageSnapshot,
|
|
51
60
|
estimateAgentContextBreakdown,
|
|
52
61
|
estimateAgentContextTokens,
|
|
62
|
+
estimateAgentMessageTokens,
|
|
53
63
|
getLatestContextSnapshot,
|
|
64
|
+
lastLoadedContextWindow,
|
|
54
65
|
reconcileSnapshot,
|
|
55
66
|
snapshotInputTokens,
|
|
56
67
|
} from "../domains/session/context-accounting.js";
|
|
57
|
-
import {
|
|
68
|
+
import {
|
|
69
|
+
buildContextLedger,
|
|
70
|
+
type ContextLedger,
|
|
71
|
+
type PrewarmStats,
|
|
72
|
+
type PromptCacheStats,
|
|
73
|
+
} from "../domains/session/context-ledger.js";
|
|
58
74
|
import type { SessionContract } from "../domains/session/contract.js";
|
|
59
75
|
import type { CompactionTrigger, SessionEntry } from "../domains/session/entries.js";
|
|
60
|
-
import {
|
|
76
|
+
import {
|
|
77
|
+
appendPromptCompileRecord,
|
|
78
|
+
PROMPT_MANIFEST_VERSION,
|
|
79
|
+
readPromptCompileRecords,
|
|
80
|
+
type SessionPromptCompileRecord,
|
|
81
|
+
} from "../domains/session/prompt-manifest.js";
|
|
61
82
|
import type { AgentMessage, Usage } from "../engine/types.js";
|
|
62
83
|
import type { ToolRegistry } from "../tools/registry.js";
|
|
63
84
|
import {
|
|
64
|
-
type BackendCacheVerdict,
|
|
65
85
|
backendCacheVerdict,
|
|
66
86
|
extractUserText,
|
|
67
87
|
runtimeSupportsTools,
|
|
@@ -92,11 +112,43 @@ export interface TurnContextDeps {
|
|
|
92
112
|
}
|
|
93
113
|
|
|
94
114
|
export interface LiveContextEstimate {
|
|
115
|
+
/**
|
|
116
|
+
* The figure to budget against: the reconciled total when the provider has
|
|
117
|
+
* attested one for this conversation, otherwise the estimate. Never below
|
|
118
|
+
* the estimate, because the estimate covers material the last provider call
|
|
119
|
+
* did not see.
|
|
120
|
+
*/
|
|
95
121
|
tokens: number;
|
|
122
|
+
/** Pure chars/4 projection, with the pre-existing provider-usage anchor. */
|
|
123
|
+
estimatedTokens: number;
|
|
124
|
+
/**
|
|
125
|
+
* Provider-attested prompt tokens for the messages up to the last reconciled
|
|
126
|
+
* call, plus a chars/4 estimate of everything appended since. Null before the
|
|
127
|
+
* first reconcile of a session and after a summary compaction rewrites the
|
|
128
|
+
* history the attestation described.
|
|
129
|
+
*/
|
|
130
|
+
reconciledTokens: number | null;
|
|
96
131
|
contextWindow: number;
|
|
97
132
|
breakdown: ReturnType<typeof estimateAgentContextBreakdown>;
|
|
98
133
|
}
|
|
99
134
|
|
|
135
|
+
/** Known causes that make the next provider prefix cache miss expected. */
|
|
136
|
+
export type ExpectedColdReason =
|
|
137
|
+
| "dispatch"
|
|
138
|
+
| "compaction"
|
|
139
|
+
| "working_set_evict"
|
|
140
|
+
| "residency"
|
|
141
|
+
| "thinking_change"
|
|
142
|
+
| "tool_surface_change"
|
|
143
|
+
| "prompt_recompiled"
|
|
144
|
+
/**
|
|
145
|
+
* A proactive-memory step ran between turns on the endpoint this session
|
|
146
|
+
* streams against. Its prompt is a trajectory rather than the chat prefix, so
|
|
147
|
+
* on a local server that keeps one prefix cache the next turn re-prefills
|
|
148
|
+
* (#229).
|
|
149
|
+
*/
|
|
150
|
+
| "background_memory";
|
|
151
|
+
|
|
100
152
|
export interface TurnContext {
|
|
101
153
|
ensureSessionPrompt(agentRuntime: AgentRuntime): Promise<CompiledSessionPrompt | null>;
|
|
102
154
|
logPromptCompileIfPending(): void;
|
|
@@ -120,6 +172,12 @@ export interface TurnContext {
|
|
|
120
172
|
*/
|
|
121
173
|
promptSideTokens(): number;
|
|
122
174
|
liveContextEstimate(agentRuntime: AgentRuntime, pendingUserText?: string): LiveContextEstimate;
|
|
175
|
+
/**
|
|
176
|
+
* The loaded context window this session already recorded for a target and
|
|
177
|
+
* model, so a resume budgets against it instead of re-probing. Null when the
|
|
178
|
+
* ledger has no such measurement.
|
|
179
|
+
*/
|
|
180
|
+
rememberedLoadedContextWindow(targetId: string, modelId: string): number | null;
|
|
123
181
|
refreshAgentMessagesFromSession(agentRuntime: AgentRuntime): ReadonlyArray<SessionEntry>;
|
|
124
182
|
runAutoCompact(
|
|
125
183
|
agentRuntime: AgentRuntime,
|
|
@@ -142,12 +200,20 @@ export interface TurnContext {
|
|
|
142
200
|
contextUsage(): ContextUsageSnapshot;
|
|
143
201
|
contextLedger(): ContextLedger;
|
|
144
202
|
emitContextWindowWarningTransition(warning: string | null): void;
|
|
203
|
+
/** Record one known cache disturbance for the current or next call. */
|
|
204
|
+
noteColdReason(reason: ExpectedColdReason): void;
|
|
145
205
|
/** Consume disturbances since the last settled run (T3.3 honesty). */
|
|
146
206
|
consumeExpectedColdReasons(runtimeId: string): void;
|
|
147
207
|
/** Prompt-cache record for one persisted assistant call, with cold-reason stamp. */
|
|
148
|
-
promptCachePayloadForAssistant(usage: Usage): Record<string, unknown>;
|
|
208
|
+
promptCachePayloadForAssistant(usage: Usage, backend?: BackendCompletionTimings): Record<string, unknown>;
|
|
149
209
|
/** Record the settled run's cache summary for /context. */
|
|
150
210
|
noteRunCacheSummary(messages: ReadonlyArray<AgentMessage>, runFirstCallVerdict: BackendCacheVerdict | null): void;
|
|
211
|
+
/**
|
|
212
|
+
* Record one pre-warm for `/context`. It contributes no tokens to the context
|
|
213
|
+
* estimate and is never an expected-cold reason: a pre-warm is the opposite
|
|
214
|
+
* of a disturbance, it is the prefix the next turn wants already resident.
|
|
215
|
+
*/
|
|
216
|
+
notePrewarm(prewarm: PrewarmStats): void;
|
|
151
217
|
resetForSession(): void;
|
|
152
218
|
dispose(): void;
|
|
153
219
|
}
|
|
@@ -157,12 +223,30 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
157
223
|
const compactionTrigger = new AutoCompactionTrigger<CompactResult | null>();
|
|
158
224
|
|
|
159
225
|
let currentContextSnapshot: ContextSnapshot | null = null;
|
|
226
|
+
/**
|
|
227
|
+
* The last provider-attested prompt size, and how many agent messages it
|
|
228
|
+
* covered (issue #227).
|
|
229
|
+
*
|
|
230
|
+
* `tokens` is the provider's own prompt count for that call plus the output
|
|
231
|
+
* it produced, which together are what the next call's prompt carries for
|
|
232
|
+
* the same messages. `anchoredMessageCount` is the length of the live
|
|
233
|
+
* message list at that moment, so anything appended since is priced by
|
|
234
|
+
* estimate and added on top. Unlike the per-message usage anchor inside
|
|
235
|
+
* `estimateAgentContextTokens`, this survives `contextUsageInvalidated`:
|
|
236
|
+
* a working-set projection subtracts the tokens it removed rather than
|
|
237
|
+
* throwing the attestation away.
|
|
238
|
+
*/
|
|
239
|
+
let reconciledAnchor: { tokens: number; anchoredMessageCount: number } | null = null;
|
|
160
240
|
let lastCompactionEvent: { stage: string; tokensBefore: number; tokensAfter: number; trigger: string } | null = null;
|
|
161
241
|
// Last settled run's provider cache usage plus whether the compiled system
|
|
162
242
|
// prompt was reused. Shown together in /context so "prompt reused" can
|
|
163
243
|
// never imply provider cache reuse the backend did not report.
|
|
164
244
|
let lastPromptCache: PromptCacheStats | null = null;
|
|
165
245
|
let lastSystemPromptReused = false;
|
|
246
|
+
// The last pre-warm, shown by /context until the next settled run answers the
|
|
247
|
+
// question it was asked about: did the prefix the next turn needs get there
|
|
248
|
+
// before the operator did.
|
|
249
|
+
let lastPrewarm: PrewarmStats | null = null;
|
|
166
250
|
// The session system prompt, compiled once per session. Recompiles happen
|
|
167
251
|
// only on explicit events: the compile key (target, model, safety level,
|
|
168
252
|
// session id) changes, or a config hot-reload invalidates the cache. A
|
|
@@ -170,6 +254,19 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
170
254
|
// ledger entry so a cold provider cache is always explainable.
|
|
171
255
|
let sessionPrompt: CompiledSessionPrompt | null = null;
|
|
172
256
|
let sessionPromptKey: string | null = null;
|
|
257
|
+
// The hash this process compiled *for the session that is current now*, and
|
|
258
|
+
// the manifest's `previousHash` whenever it is set. It is not read off
|
|
259
|
+
// `sessionPrompt`: an in-process `/resume` leaves that compile in place so
|
|
260
|
+
// the ledger keeps its project-preload labels until the next compile, but
|
|
261
|
+
// manifest provenance follows the session, so a switch drops the hash here
|
|
262
|
+
// and the next compile falls through to the incoming session's own manifest
|
|
263
|
+
// exactly as a cold-start resume does (#249).
|
|
264
|
+
let sessionPromptHash: string | null = null;
|
|
265
|
+
// Whether this process has already looked up the resumed session's last
|
|
266
|
+
// recorded prompt hash. The lookup reads the manifest file, so it happens
|
|
267
|
+
// once, on the first compile, and never on the reuse path.
|
|
268
|
+
let resumedPromptHashRead = false;
|
|
269
|
+
let resumedPromptHash: string | null = null;
|
|
173
270
|
const sessionWorkingContextPaths = new Set<string>();
|
|
174
271
|
let pendingPromptLogEntry: SessionPromptCompileRecord | null = null;
|
|
175
272
|
// A post-tool guard can run after every tool result in one model turn. Once
|
|
@@ -178,22 +275,25 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
178
275
|
// and summary probes. A new submitted user turn gets a new id naturally.
|
|
179
276
|
let emptyAutoCompactTurnId: string | null = null;
|
|
180
277
|
|
|
181
|
-
// Cache-disturbance honesty (T3.3).
|
|
182
|
-
//
|
|
183
|
-
//
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
let
|
|
188
|
-
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
278
|
+
// Cache-disturbance honesty (T3.3). Accumulate every known local-runtime
|
|
279
|
+
// disturbance and prefix-byte change since the last settled run. The next
|
|
280
|
+
// submit consumes the set, stamps `promptCache.expectedColdReasons` on its
|
|
281
|
+
// first assistant entry, and shows one dim notice.
|
|
282
|
+
const pendingColdReasons = new Set<ExpectedColdReason>();
|
|
283
|
+
let runExpectedColdReasons: ExpectedColdReason[] = [];
|
|
284
|
+
let nextAssistantColdReasons: ExpectedColdReason[] = [];
|
|
285
|
+
// Prefix-byte changes cool every tier. Residency, thinking changes, dispatch
|
|
286
|
+
// traffic, and compaction keep the local-native gate because they disturb a
|
|
287
|
+
// local server or its rendered template.
|
|
288
|
+
const TIER_INDEPENDENT_COLD_REASONS: ReadonlySet<ExpectedColdReason> = new Set([
|
|
289
|
+
"working_set_evict",
|
|
290
|
+
"tool_surface_change",
|
|
291
|
+
"prompt_recompiled",
|
|
292
|
+
]);
|
|
293
|
+
const stampsOnTier = (reason: ExpectedColdReason, runtimeId: string | undefined): boolean =>
|
|
194
294
|
TIER_INDEPENDENT_COLD_REASONS.has(reason) ||
|
|
195
295
|
(runtimeId !== undefined && deps.providers.getRuntime(runtimeId)?.tier === "local-native");
|
|
196
|
-
const noteColdReason = (reason:
|
|
296
|
+
const noteColdReason = (reason: ExpectedColdReason): void => {
|
|
197
297
|
if (!state.streaming) {
|
|
198
298
|
pendingColdReasons.add(reason);
|
|
199
299
|
return;
|
|
@@ -217,6 +317,21 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
217
317
|
noteColdReason("compaction");
|
|
218
318
|
}) ?? null,
|
|
219
319
|
),
|
|
320
|
+
deps.bus?.on(BusChannels.ResidencyMutation, (payload: ResidencyMutationPayload) => {
|
|
321
|
+
const runtime = state.runtime;
|
|
322
|
+
const model = runtime?.agent.state.model as { baseUrl?: unknown } | undefined;
|
|
323
|
+
const baseUrl = typeof model?.baseUrl === "string" ? model.baseUrl : null;
|
|
324
|
+
if (payload.targetKey !== residencyTargetKey(runtime?.runtimeId ?? "", baseUrl)) return;
|
|
325
|
+
noteColdReason("residency");
|
|
326
|
+
}) ?? null,
|
|
327
|
+
// A memory step on another endpoint disturbs nothing here, so the stamp is
|
|
328
|
+
// gated on the step having called the very server this session streams to.
|
|
329
|
+
deps.bus?.on(BusChannels.MemoryStepCompleted, (payload: MemoryStepCompletedPayload) => {
|
|
330
|
+
const target = state.runtime?.runtimeResolution.target;
|
|
331
|
+
if (target === undefined) return;
|
|
332
|
+
if (canonicalEndpointKey(target) !== payload.endpointKey) return;
|
|
333
|
+
noteColdReason("background_memory");
|
|
334
|
+
}) ?? null,
|
|
220
335
|
deps.bus?.on(BusChannels.ContextRecalled, (payload: ContextRecalledPayload) => {
|
|
221
336
|
middleware.fireCompactionHook("working_set_recall", payload.trigger);
|
|
222
337
|
}) ?? null,
|
|
@@ -322,6 +437,33 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
322
437
|
* (issue #189). Null when no target is configured or it does not resolve,
|
|
323
438
|
* and the overlay's "unknown" is then true.
|
|
324
439
|
*/
|
|
440
|
+
const rememberedLoadedContextWindow = (targetId: string, modelId: string): number | null => {
|
|
441
|
+
const session = deps.session?.current();
|
|
442
|
+
if (!session) return null;
|
|
443
|
+
return lastLoadedContextWindow(session, targetId, modelId);
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* The prompt hash this session last recorded, for the first compile of a
|
|
448
|
+
* resumed process. Without it a resume reports `previousHash: null`, which
|
|
449
|
+
* reads as "there was no prompt before" when in fact there was one and it
|
|
450
|
+
* is exactly what a reader needs to attribute the cold cache to: a layout
|
|
451
|
+
* bump, a fragment edit, or a moved context window (issue #249).
|
|
452
|
+
*/
|
|
453
|
+
const lastRecordedPromptHash = (): string | null => {
|
|
454
|
+
if (resumedPromptHashRead) return resumedPromptHash;
|
|
455
|
+
resumedPromptHashRead = true;
|
|
456
|
+
const currentSession = deps.session?.current();
|
|
457
|
+
if (!currentSession) {
|
|
458
|
+
// No session to read; leave the lookup open for the next compile.
|
|
459
|
+
resumedPromptHashRead = false;
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
const records = readPromptCompileRecords(currentSession);
|
|
463
|
+
resumedPromptHash = records[records.length - 1]?.systemPromptHash ?? null;
|
|
464
|
+
return resumedPromptHash;
|
|
465
|
+
};
|
|
466
|
+
|
|
325
467
|
const resolveWindowWithoutRuntime = (): ContextWindowDetails | null => {
|
|
326
468
|
const settings = deps.getSettings();
|
|
327
469
|
const targetId = settings.orchestrator?.target?.trim();
|
|
@@ -334,6 +476,7 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
334
476
|
use: "orchestrator",
|
|
335
477
|
requireTools: false,
|
|
336
478
|
requireOutputBudget: true,
|
|
479
|
+
knownLoadedContextWindow: rememberedLoadedContextWindow(targetId, wireModelId),
|
|
337
480
|
});
|
|
338
481
|
return resolved.ok ? resolved.target.contextWindowDetails : null;
|
|
339
482
|
};
|
|
@@ -383,6 +526,29 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
383
526
|
return { contextWindow: 0, contextWindowSource: null, contextWindowSlots: null };
|
|
384
527
|
};
|
|
385
528
|
|
|
529
|
+
/**
|
|
530
|
+
* Carry the reconciled anchor onto the current message list: the attested
|
|
531
|
+
* prompt for the messages it covered, plus a chars/4 estimate of everything
|
|
532
|
+
* appended since, plus text that has not been submitted yet. The tool
|
|
533
|
+
* schemas and the system prompt are inside the attested figure already, so
|
|
534
|
+
* they are not added again. Null when there is no attestation, or when the
|
|
535
|
+
* list is shorter than the anchor covered, which means the history it
|
|
536
|
+
* described was rewritten beneath it.
|
|
537
|
+
*/
|
|
538
|
+
const reconciledAnchoredTokens = (agentRuntime: AgentRuntime, pendingUserTokens: number): number | null => {
|
|
539
|
+
const anchor = reconciledAnchor;
|
|
540
|
+
if (!anchor) return null;
|
|
541
|
+
const messages = agentRuntime.agent.state.messages;
|
|
542
|
+
if (anchor.anchoredMessageCount > messages.length) return null;
|
|
543
|
+
let tail = 0;
|
|
544
|
+
for (let i = anchor.anchoredMessageCount; i < messages.length; i += 1) {
|
|
545
|
+
const message = messages[i];
|
|
546
|
+
if (message === undefined) continue;
|
|
547
|
+
tail += estimateAgentMessageTokens(message);
|
|
548
|
+
}
|
|
549
|
+
return anchor.tokens + tail + pendingUserTokens;
|
|
550
|
+
};
|
|
551
|
+
|
|
386
552
|
const liveContextEstimate = (agentRuntime: AgentRuntime, pendingUserText?: string): LiveContextEstimate => {
|
|
387
553
|
const contextWindow = agentRuntime.runtimeResolution.contextWindowDetails.effectiveContextWindow;
|
|
388
554
|
const estimateInput = {
|
|
@@ -391,10 +557,34 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
391
557
|
tools: agentRuntime.agent.state.tools,
|
|
392
558
|
...(pendingUserText !== undefined ? { pendingUserText } : {}),
|
|
393
559
|
};
|
|
560
|
+
const breakdown = estimateAgentContextBreakdown(estimateInput);
|
|
561
|
+
const estimatedTokens = estimateAgentContextTokens(estimateInput);
|
|
562
|
+
const reconciledTokens = reconciledAnchoredTokens(agentRuntime, breakdown.pendingUserTokens);
|
|
394
563
|
return {
|
|
395
|
-
|
|
564
|
+
// The estimate is a floor, not a competing verdict: it prices material
|
|
565
|
+
// the attested call never saw, so a provider count below it would be
|
|
566
|
+
// answering about a smaller conversation.
|
|
567
|
+
tokens: Math.max(estimatedTokens, reconciledTokens ?? 0),
|
|
568
|
+
estimatedTokens,
|
|
569
|
+
reconciledTokens,
|
|
396
570
|
contextWindow,
|
|
397
|
-
breakdown
|
|
571
|
+
breakdown,
|
|
572
|
+
};
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* A working-set projection removes tokens from messages the attestation
|
|
577
|
+
* covered; it does not make the attestation wrong about the rest. Subtract
|
|
578
|
+
* what the planner priced out against the same projection and re-anchor on
|
|
579
|
+
* the refreshed list, instead of discarding the figure and falling back to
|
|
580
|
+
* pure chars/4 exactly when the accounting matters most (issue #227).
|
|
581
|
+
* Call after the message list has been rebuilt.
|
|
582
|
+
*/
|
|
583
|
+
const carryReconciledAnchorThroughProjection = (agentRuntime: AgentRuntime, tokensRemoved: number): void => {
|
|
584
|
+
if (!reconciledAnchor) return;
|
|
585
|
+
reconciledAnchor = {
|
|
586
|
+
tokens: Math.max(0, reconciledAnchor.tokens - Math.max(0, tokensRemoved)),
|
|
587
|
+
anchoredMessageCount: agentRuntime.agent.state.messages.length,
|
|
398
588
|
};
|
|
399
589
|
};
|
|
400
590
|
|
|
@@ -414,7 +604,7 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
414
604
|
const emitCompactionActivity = (status: ContextActivityStatus, message: string): void => {
|
|
415
605
|
deps.bus?.emit(BusChannels.ContextActivity, {
|
|
416
606
|
kind: "compaction",
|
|
417
|
-
phase: "done",
|
|
607
|
+
phase: status === "completed" ? "done" : "compact",
|
|
418
608
|
status,
|
|
419
609
|
message,
|
|
420
610
|
at: Date.now(),
|
|
@@ -507,6 +697,8 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
507
697
|
emitCompactionActivity("started", "compacting context (mask stage)");
|
|
508
698
|
deps.session.replaceEntries(masked.entries);
|
|
509
699
|
refreshAgentMessagesFromSession(agentRuntime);
|
|
700
|
+
// The masked history is not the one the provider counted.
|
|
701
|
+
reconciledAnchor = null;
|
|
510
702
|
deps.bus?.emit(BusChannels.CompactionEnd, { trigger, at: Date.now() });
|
|
511
703
|
|
|
512
704
|
const postMaskSnapshot = captureRuntimeContextSnapshot(
|
|
@@ -591,6 +783,7 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
591
783
|
});
|
|
592
784
|
noteColdReason("working_set_evict");
|
|
593
785
|
refreshAgentMessagesFromSession(agentRuntime);
|
|
786
|
+
carryReconciledAnchorThroughProjection(agentRuntime, planned.tokensBefore - planned.tokensAfter);
|
|
594
787
|
|
|
595
788
|
const postEvictionSnapshot = captureRuntimeContextSnapshot(
|
|
596
789
|
agentRuntime,
|
|
@@ -683,6 +876,9 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
683
876
|
recordCompactionUsage(agentRuntime, result);
|
|
684
877
|
|
|
685
878
|
refreshAgentMessagesFromSession(agentRuntime);
|
|
879
|
+
// A summary replaces the conversation the attestation described, so no
|
|
880
|
+
// arithmetic carries it forward; the next call re-anchors it.
|
|
881
|
+
reconciledAnchor = null;
|
|
686
882
|
|
|
687
883
|
const postCompactSnapshot = captureRuntimeContextSnapshot(
|
|
688
884
|
agentRuntime,
|
|
@@ -741,6 +937,7 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
741
937
|
captureRuntimeContextSnapshot,
|
|
742
938
|
persistContextSnapshot,
|
|
743
939
|
liveContextEstimate,
|
|
940
|
+
rememberedLoadedContextWindow,
|
|
744
941
|
refreshAgentMessagesFromSession,
|
|
745
942
|
runAutoCompact,
|
|
746
943
|
|
|
@@ -754,6 +951,18 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
754
951
|
},
|
|
755
952
|
|
|
756
953
|
reconcileUsage(usage: Usage): void {
|
|
954
|
+
// Cached prompt tokens still occupy the window; providers report them
|
|
955
|
+
// outside `input`, so the attested prompt is the three summed.
|
|
956
|
+
const promptTokens = (usage.input || 0) + (usage.cacheRead || 0) + (usage.cacheWrite || 0);
|
|
957
|
+
const messages = state.runtime?.agent.state.messages;
|
|
958
|
+
if (promptTokens > 0 && messages) {
|
|
959
|
+
// The output of this call is part of the next call's prompt for the
|
|
960
|
+
// same messages, which is why it is folded in here.
|
|
961
|
+
reconciledAnchor = {
|
|
962
|
+
tokens: promptTokens + (usage.output || 0),
|
|
963
|
+
anchoredMessageCount: messages.length,
|
|
964
|
+
};
|
|
965
|
+
}
|
|
757
966
|
if (!currentContextSnapshot) return;
|
|
758
967
|
// Reconcile in memory on every API call so the live meters
|
|
759
968
|
// track usage; persistence waits for the run to settle.
|
|
@@ -787,7 +996,22 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
787
996
|
const modelState = agentRuntime.agent.state.model as
|
|
788
997
|
| (typeof agentRuntime.agent.state.model & { clio?: { quirks?: LocalModelQuirks } })
|
|
789
998
|
| undefined;
|
|
790
|
-
|
|
999
|
+
// `Context window: N` is the window the backend will actually serve
|
|
1000
|
+
// this session, taken from the resolution the turn already ran rather
|
|
1001
|
+
// than from the model descriptor's copy of it (issue #249). The
|
|
1002
|
+
// ranking that puts a loaded figure ahead of a probed one lives in
|
|
1003
|
+
// `resolveContextWindowDetails`, which tests `loadedContextWindow`
|
|
1004
|
+
// first and only then `probedContextWindow`, so `effectiveContextWindow`
|
|
1005
|
+
// already is the loaded window whenever one is known and the source
|
|
1006
|
+
// already reads "loaded"; brief #227's carry-forward is what puts that
|
|
1007
|
+
// figure in reach on a resume. The source rides into the prompt
|
|
1008
|
+
// manifest, so a recompile after the loaded window is first observed
|
|
1009
|
+
// is explained by the record.
|
|
1010
|
+
const windowDetails = agentRuntime.runtimeResolution.contextWindowDetails;
|
|
1011
|
+
const resolvedWindow = windowDetails.effectiveContextWindow;
|
|
1012
|
+
const contextWindow = typeof resolvedWindow === "number" && resolvedWindow > 0 ? resolvedWindow : null;
|
|
1013
|
+
const contextWindowSource: ContextWindowSource | null =
|
|
1014
|
+
contextWindow === null ? null : windowDetails.contextWindowSource;
|
|
791
1015
|
const guidance = modelState?.clio?.quirks?.thinking?.guidance;
|
|
792
1016
|
// Per-tool prompt hints come from registry metadata, derived once from
|
|
793
1017
|
// the frozen surface per compile. The compiler renders them sorted by
|
|
@@ -823,16 +1047,19 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
823
1047
|
cwd: process.cwd(),
|
|
824
1048
|
workingContextPaths: [...sessionWorkingContextPaths],
|
|
825
1049
|
});
|
|
826
|
-
const previousHash =
|
|
1050
|
+
const previousHash = sessionPromptHash ?? lastRecordedPromptHash();
|
|
827
1051
|
const changed = agentRuntime.agent.state.systemPrompt !== result.systemPrompt;
|
|
828
1052
|
if (changed) {
|
|
829
1053
|
agentRuntime.agent.state.systemPrompt = result.systemPrompt;
|
|
830
1054
|
pendingPromptLogEntry = {
|
|
1055
|
+
version: PROMPT_MANIFEST_VERSION,
|
|
831
1056
|
at: new Date().toISOString(),
|
|
832
1057
|
previousHash,
|
|
833
1058
|
systemPromptHash: result.systemPromptHash,
|
|
834
1059
|
tokenEstimate: result.tokenEstimate,
|
|
835
1060
|
thinkingLevel: agentRuntime.agent.state.thinkingLevel ?? null,
|
|
1061
|
+
contextWindow,
|
|
1062
|
+
contextWindowSource,
|
|
836
1063
|
projectPreload: result.projectPreload ?? null,
|
|
837
1064
|
sections: result.sections.map((s) => ({ id: s.id, tokenEstimate: s.tokenEstimate })),
|
|
838
1065
|
fragments: result.fragmentManifest.map((f) => ({
|
|
@@ -845,6 +1072,7 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
845
1072
|
}
|
|
846
1073
|
lastSystemPromptReused = !changed;
|
|
847
1074
|
sessionPrompt = result;
|
|
1075
|
+
sessionPromptHash = result.systemPromptHash;
|
|
848
1076
|
sessionPromptKey = key;
|
|
849
1077
|
return result;
|
|
850
1078
|
} catch (err) {
|
|
@@ -877,6 +1105,11 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
877
1105
|
tokenEstimate: entry.tokenEstimate,
|
|
878
1106
|
},
|
|
879
1107
|
});
|
|
1108
|
+
// A resumed process names the session's last recorded hash as previousHash (#249), so
|
|
1109
|
+
// the stamp requires the hash to have moved, not merely to have a predecessor.
|
|
1110
|
+
if (entry.previousHash !== null && entry.previousHash !== entry.systemPromptHash) {
|
|
1111
|
+
noteColdReason("prompt_recompiled");
|
|
1112
|
+
}
|
|
880
1113
|
} catch {
|
|
881
1114
|
// Ledger logging is diagnostics, not control flow; never abort a turn.
|
|
882
1115
|
}
|
|
@@ -966,6 +1199,7 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
966
1199
|
compactionThreshold,
|
|
967
1200
|
compactionAuto,
|
|
968
1201
|
promptCache: lastPromptCache,
|
|
1202
|
+
prewarm: lastPrewarm,
|
|
969
1203
|
});
|
|
970
1204
|
}
|
|
971
1205
|
|
|
@@ -998,6 +1232,7 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
998
1232
|
measured,
|
|
999
1233
|
lastCompaction: lastCompactionEvent,
|
|
1000
1234
|
promptCache: lastPromptCache,
|
|
1235
|
+
prewarm: lastPrewarm,
|
|
1001
1236
|
});
|
|
1002
1237
|
},
|
|
1003
1238
|
|
|
@@ -1007,12 +1242,14 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
1007
1242
|
deps.bus?.emit(BusChannels.ContextWarning, { warning } satisfies ContextWarningPayload);
|
|
1008
1243
|
},
|
|
1009
1244
|
|
|
1245
|
+
noteColdReason,
|
|
1246
|
+
|
|
1010
1247
|
consumeExpectedColdReasons(runtimeId: string): void {
|
|
1011
1248
|
// Cache-disturbance honesty (T3.3): consume disturbances since
|
|
1012
1249
|
// the last settled run. Only single-slot local backends lose their
|
|
1013
|
-
// prefix cache to interleaved work, so
|
|
1014
|
-
// stamp only on local-native targets
|
|
1015
|
-
// the prefix
|
|
1250
|
+
// prefix cache to interleaved work, so residency, thinking changes,
|
|
1251
|
+
// dispatch, and compaction stamp only on local-native targets. Reasons
|
|
1252
|
+
// that change the prefix bytes stamp every tier (see stampsOnTier).
|
|
1016
1253
|
runExpectedColdReasons = [];
|
|
1017
1254
|
nextAssistantColdReasons = [];
|
|
1018
1255
|
if (pendingColdReasons.size > 0) {
|
|
@@ -1026,10 +1263,10 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
1026
1263
|
}
|
|
1027
1264
|
},
|
|
1028
1265
|
|
|
1029
|
-
promptCachePayloadForAssistant(usage: Usage): Record<string, unknown> {
|
|
1030
|
-
// Per-call prompt-cache record (T3.2)
|
|
1031
|
-
//
|
|
1032
|
-
//
|
|
1266
|
+
promptCachePayloadForAssistant(usage: Usage, backend?: BackendCompletionTimings): Record<string, unknown> {
|
|
1267
|
+
// Per-call prompt-cache record (T3.2) keeps normalized provider usage
|
|
1268
|
+
// beside any timings captured from the server response. The run's first
|
|
1269
|
+
// persisted call also carries any expected-cold reasons.
|
|
1033
1270
|
const input = typeof usage.input === "number" ? usage.input : 0;
|
|
1034
1271
|
const cacheRead = typeof usage.cacheRead === "number" ? usage.cacheRead : 0;
|
|
1035
1272
|
const cacheWrite = typeof usage.cacheWrite === "number" ? usage.cacheWrite : 0;
|
|
@@ -1037,8 +1274,9 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
1037
1274
|
input,
|
|
1038
1275
|
cacheRead,
|
|
1039
1276
|
cacheWrite,
|
|
1040
|
-
backendVerdict: backendCacheVerdict(input, cacheRead),
|
|
1277
|
+
backendVerdict: backendCacheVerdict(input, cacheRead, backend),
|
|
1041
1278
|
};
|
|
1279
|
+
if (backend !== undefined) promptCache.backend = { ...backend };
|
|
1042
1280
|
if (nextAssistantColdReasons.length > 0) {
|
|
1043
1281
|
promptCache.expectedColdReasons = [...nextAssistantColdReasons];
|
|
1044
1282
|
nextAssistantColdReasons = [];
|
|
@@ -1046,14 +1284,30 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
1046
1284
|
return promptCache;
|
|
1047
1285
|
},
|
|
1048
1286
|
|
|
1287
|
+
notePrewarm(prewarm: PrewarmStats): void {
|
|
1288
|
+
lastPrewarm = prewarm;
|
|
1289
|
+
},
|
|
1290
|
+
|
|
1049
1291
|
noteRunCacheSummary(messages, runFirstCallVerdict): void {
|
|
1292
|
+
// The settled run is the answer to the pre-warm's question, so the
|
|
1293
|
+
// pre-warm line stops being the newest fact about the prefix here.
|
|
1294
|
+
lastPrewarm = null;
|
|
1050
1295
|
const cacheSummary = sumRunUsage(messages);
|
|
1051
1296
|
if (cacheSummary.hadUsage) {
|
|
1297
|
+
let lastBackend: BackendCompletionTimings | null = null;
|
|
1298
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
1299
|
+
const message = messages[index];
|
|
1300
|
+
if (message?.role !== "assistant") continue;
|
|
1301
|
+
lastBackend = (message as { backendTimings?: BackendCompletionTimings }).backendTimings ?? null;
|
|
1302
|
+
break;
|
|
1303
|
+
}
|
|
1052
1304
|
lastPromptCache = {
|
|
1053
1305
|
shellReused: lastSystemPromptReused,
|
|
1054
1306
|
cacheReadTokens: cacheSummary.cacheRead > 0 || cacheSummary.cacheWrite > 0 ? cacheSummary.cacheRead : null,
|
|
1055
1307
|
cacheWriteTokens: cacheSummary.cacheRead > 0 || cacheSummary.cacheWrite > 0 ? cacheSummary.cacheWrite : null,
|
|
1056
1308
|
uncachedInputTokens: cacheSummary.input,
|
|
1309
|
+
backend: lastBackend,
|
|
1310
|
+
uncachedPrefillTokens: uncachedPrefillTokens(lastBackend),
|
|
1057
1311
|
backendVerdict: runFirstCallVerdict,
|
|
1058
1312
|
...(runExpectedColdReasons.length > 0 ? { expectedColdReasons: [...runExpectedColdReasons] } : {}),
|
|
1059
1313
|
};
|
|
@@ -1061,12 +1315,26 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
1061
1315
|
},
|
|
1062
1316
|
|
|
1063
1317
|
resetForSession(): void {
|
|
1318
|
+
// An in-process switch replaces the whole prefix: the backend's slot
|
|
1319
|
+
// still holds the outgoing session's prompt and history, so the first
|
|
1320
|
+
// turn on the incoming one is expected-cold on every tier, exactly as
|
|
1321
|
+
// a recompile is. The manifest can no longer say so on its own once
|
|
1322
|
+
// provenance follows the session, because the incoming session's last
|
|
1323
|
+
// recorded hash usually equals its fresh compile, so the stamp comes
|
|
1324
|
+
// from here. Only when this process had actually applied a prompt:
|
|
1325
|
+
// before the first compile there is nothing in the slot to have lost.
|
|
1326
|
+
if (sessionPromptHash !== null) noteColdReason("prompt_recompiled");
|
|
1064
1327
|
lastPromptCache = null;
|
|
1328
|
+
lastPrewarm = null;
|
|
1065
1329
|
lastSystemPromptReused = false;
|
|
1330
|
+
sessionPromptHash = null;
|
|
1066
1331
|
sessionPromptKey = null;
|
|
1332
|
+
resumedPromptHashRead = false;
|
|
1333
|
+
resumedPromptHash = null;
|
|
1067
1334
|
sessionWorkingContextPaths.clear();
|
|
1068
1335
|
pendingPromptLogEntry = null;
|
|
1069
1336
|
emptyAutoCompactTurnId = null;
|
|
1337
|
+
reconciledAnchor = null;
|
|
1070
1338
|
const session = deps.session?.current();
|
|
1071
1339
|
currentContextSnapshot = session ? getLatestContextSnapshot(session) : null;
|
|
1072
1340
|
},
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* append advances `state.lastTurnId`.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { BackendCompletionTimings } from "../core/cache-telemetry.js";
|
|
8
9
|
import type { ClioSettings } from "../core/config.js";
|
|
9
10
|
import type { MiddlewareToolChoiceControl } from "../domains/middleware/index.js";
|
|
10
11
|
import type { ObservabilityContract } from "../domains/observability/contract.js";
|
|
@@ -39,7 +40,7 @@ export interface TurnPersistenceDeps {
|
|
|
39
40
|
/** Remove a queued-mirror entry once the engine injects it. */
|
|
40
41
|
removeQueuedMirrorEntry: (text: string) => void;
|
|
41
42
|
/** Prompt-cache record for a persisted assistant call (T3.2 + cold stamp). */
|
|
42
|
-
promptCachePayloadForAssistant: (usage: Usage) => Record<string, unknown>;
|
|
43
|
+
promptCachePayloadForAssistant: (usage: Usage, backend?: BackendCompletionTimings) => Record<string, unknown>;
|
|
43
44
|
/**
|
|
44
45
|
* Prompt-side tokens the live context accounting holds for the turn in
|
|
45
46
|
* flight. Used only to record what an interrupted call is known to have
|
|
@@ -228,7 +229,8 @@ export function createTurnPersistence(deps: TurnPersistenceDeps): TurnPersistenc
|
|
|
228
229
|
if (timing) payload.timing = timing;
|
|
229
230
|
const usage = (message as { usage?: Usage }).usage;
|
|
230
231
|
if (usage && typeof usage === "object") {
|
|
231
|
-
|
|
232
|
+
const backendTimings = (message as { backendTimings?: BackendCompletionTimings }).backendTimings;
|
|
233
|
+
payload.promptCache = deps.promptCachePayloadForAssistant(usage, backendTimings);
|
|
232
234
|
}
|
|
233
235
|
// A cancelled turn's provider usage is the object the stream started with
|
|
234
236
|
// and never updated. Record what the call is known to have spent instead of
|
|
@@ -278,8 +280,16 @@ export function createTurnPersistence(deps: TurnPersistenceDeps): TurnPersistenc
|
|
|
278
280
|
|
|
279
281
|
appendQueuedUserTurn(message: AgentMessage): void {
|
|
280
282
|
if (message?.role !== "user") return;
|
|
281
|
-
|
|
282
|
-
|
|
283
|
+
// Byte-exact. Trimming here wrote a second, shortened row that the
|
|
284
|
+
// assistant then parented to, so the model's parent turn disagreed with
|
|
285
|
+
// the expansion the operator actually submitted: `/raw bar` produced a
|
|
286
|
+
// correct 5-byte row and a 3-byte one, and the 3-byte one won (issue
|
|
287
|
+
// #244). Only the emptiness test reads the trimmed form, and the
|
|
288
|
+
// echo/mirror lookups match on the same bytes the engine was given, so a
|
|
289
|
+
// payload with edge whitespace is recognized as the echo it is instead
|
|
290
|
+
// of being persisted a second time.
|
|
291
|
+
const text = extractUserText(message);
|
|
292
|
+
if (text.trim().length === 0) return;
|
|
283
293
|
if (deps.consumePersistedEcho(text)) return;
|
|
284
294
|
deps.removeQueuedMirrorEntry(text);
|
|
285
295
|
if (!deps.session) return;
|