@iowarp/clio-coder 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +80 -0
- package/README.md +13 -4
- package/dist/{acp-SK4MD6MM.js → acp-7LOELQFP.js} +13 -13
- package/dist/{agents-2FN2K6ME.js → agents-FIBG2SHA.js} +41 -37
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-QIYZWM5I.js → auth-OI4LIH2I.js} +31 -24
- package/dist/builtins-AD25UL3C.js +17 -0
- package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
- package/dist/chunk-3DPEIQKN.js +113 -0
- package/dist/{chunk-EOOQZZDE.js → chunk-3DUR4WUA.js} +19 -19
- package/dist/{chunk-WHJYKASB.js → chunk-3MRC2YSQ.js} +2 -2
- package/dist/{chunk-EBEFWSGL.js → chunk-3UUY7R3Z.js} +14 -10
- package/dist/{chunk-LADCF22A.js → chunk-3V5AYSEQ.js} +113 -54
- package/dist/{chunk-BMWK7ZIZ.js → chunk-465CC7FK.js} +16 -13
- package/dist/{chunk-5WIGXA4T.js → chunk-47CMYGET.js} +111 -4
- package/dist/{chunk-CEYBNUGC.js → chunk-4H6ULJ3H.js} +378 -36
- package/dist/{chunk-YTYFXUI3.js → chunk-4LJX2PUC.js} +9 -9
- package/dist/{chunk-DOOEX22V.js → chunk-56KB5IJP.js} +5 -5
- package/dist/{chunk-SPULKLCF.js → chunk-5DQRIYDZ.js} +2 -2
- package/dist/{chunk-TSHXZTOQ.js → chunk-5HFBWUMU.js} +23 -11
- package/dist/{chunk-5UJ6ECTS.js → chunk-5PVQ4SRS.js} +80 -8
- package/dist/{chunk-ZWLZP4ZT.js → chunk-5QKCQQ3E.js} +359 -17
- package/dist/{chunk-6M7VS3J3.js → chunk-5T7RBWN2.js} +111 -5
- package/dist/chunk-774ILSRL.js +172 -0
- package/dist/chunk-7C6RYZGQ.js +391 -0
- package/dist/{chunk-GH5622CP.js → chunk-A2NJGIB3.js} +2 -2
- package/dist/{chunk-C4JBQ5SR.js → chunk-AD7Y7STJ.js} +6 -6
- package/dist/{chunk-GEYXPTRF.js → chunk-AEYBF3TB.js} +33 -12
- package/dist/{chunk-2SFS6XQE.js → chunk-AMKHQW3C.js} +3 -2
- package/dist/{chunk-D4MDIG46.js → chunk-B5CSFE7B.js} +7 -7
- package/dist/{chunk-MXI6J5JF.js → chunk-B5XRQOLB.js} +10 -10
- package/dist/{chunk-X2KV5FXT.js → chunk-BVDVID7E.js} +2 -2
- package/dist/{chunk-JNXPYBB4.js → chunk-CA42X6KT.js} +3 -3
- package/dist/{chunk-VREKEFLL.js → chunk-D73KXYPF.js} +3 -3
- package/dist/{chunk-JTSEDYVQ.js → chunk-DG4M6ZUE.js} +7 -7
- package/dist/{chunk-DQA7QLMD.js → chunk-EBOC7MT3.js} +10 -25
- package/dist/{chunk-KZ2H5X4G.js → chunk-ECUO3KDP.js} +129 -14
- package/dist/{chunk-JRIO5UD2.js → chunk-EQ63NRB7.js} +5 -5
- package/dist/{chunk-YD734TPH.js → chunk-FALJGAWU.js} +2 -2
- package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
- package/dist/{chunk-XEGB6BCN.js → chunk-GAYUJ7LE.js} +68 -14
- package/dist/{chunk-UND3GU2L.js → chunk-H7IXIC72.js} +2 -2
- package/dist/{chunk-IR4CFBFN.js → chunk-HAY4ZE2P.js} +12 -12
- package/dist/{chunk-UVDSQ6LW.js → chunk-HCBCAYZU.js} +74 -147
- package/dist/{chunk-4DWFMQDR.js → chunk-HJB5IUKP.js} +89 -145
- package/dist/{chunk-M4AKACEO.js → chunk-HKO36JWF.js} +33 -5
- package/dist/{chunk-KCMKRQX4.js → chunk-HPCTNZM2.js} +45 -82
- package/dist/{chunk-465YSENW.js → chunk-IFBNV6H6.js} +3 -3
- package/dist/{chunk-FJ3H4MN5.js → chunk-IHKBWSXF.js} +2 -2
- package/dist/chunk-JEQQR47K.js +3025 -0
- package/dist/{chunk-FO5ZOVUY.js → chunk-KV2AOLDF.js} +27 -7
- package/dist/chunk-LU7P4LHA.js +33 -0
- package/dist/{chunk-6TUKSZVF.js → chunk-LXPJXFM5.js} +11 -11
- package/dist/{chunk-VQNODYQ4.js → chunk-MIX5N5AC.js} +488 -3668
- package/dist/chunk-MLOK6ZOS.js +2888 -0
- package/dist/{chunk-ZZMN5OM4.js → chunk-MV2VUEJC.js} +2 -2
- package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
- package/dist/{chunk-OBMAI2DP.js → chunk-N3PBVRTZ.js} +12 -388
- package/dist/{chunk-WJHBC77E.js → chunk-N5XKWMDW.js} +17 -7
- package/dist/{chunk-5C3AQNDW.js → chunk-NNNWO6F2.js} +124 -36
- package/dist/{chunk-UFQ3F4FW.js → chunk-NQ6UCCOD.js} +4 -4
- package/dist/chunk-NUGM5KR6.js +165 -0
- package/dist/{chunk-DMD2AGVS.js → chunk-NZU6YDNV.js} +20 -18
- package/dist/{chunk-WHGPSPT5.js → chunk-O6I4CIEU.js} +151 -13
- package/dist/{chunk-XN3L4EYL.js → chunk-OEDBCISO.js} +2 -2
- package/dist/{chunk-PD3MESLB.js → chunk-P3JGPQFL.js} +4 -4
- package/dist/{chunk-UHXRNZ2J.js → chunk-PNY46YEY.js} +23 -6
- package/dist/{chunk-THKY7CD7.js → chunk-PZ4I4JE2.js} +134 -29
- package/dist/{chunk-SROCI7ZU.js → chunk-QQ7EKM72.js} +5 -5
- package/dist/{chunk-QCTRSGHQ.js → chunk-R7LNVMCS.js} +91 -53
- package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
- package/dist/chunk-RKKLTLYB.js +45 -0
- package/dist/{chunk-OB5HIGJY.js → chunk-RKRLDWD3.js} +4 -1
- package/dist/{chunk-DJNLUABN.js → chunk-S4COXYBG.js} +588 -32
- package/dist/{chunk-3HAPLH5M.js → chunk-T3Z6VAAF.js} +172 -11
- package/dist/{chunk-FOT2FX5J.js → chunk-TD7UE2L5.js} +12 -10
- package/dist/{chunk-UUANF5CR.js → chunk-TEO2TLVN.js} +856 -967
- package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
- package/dist/{chunk-EELBMBT6.js → chunk-VKBMFOYV.js} +74 -15
- package/dist/chunk-VO2LKSTM.js +165 -0
- package/dist/{chunk-5C77SEEY.js → chunk-VPTUJU4P.js} +3 -3
- package/dist/{chunk-WEH5XRJQ.js → chunk-WIE7ZOSW.js} +2 -2
- package/dist/{chunk-J7PIKKWC.js → chunk-WXCJ7VME.js} +8 -8
- package/dist/{chunk-4DGYLA73.js → chunk-XDOQXGFO.js} +22 -7
- package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
- package/dist/{chunk-AB4XIIVB.js → chunk-YKOFT37S.js} +6 -6
- package/dist/chunk-YSEHGPCT.js +127 -0
- package/dist/{chunk-HFSBBKSQ.js → chunk-YW7UVM5V.js} +138 -3
- package/dist/cli/index.js +32 -32
- package/dist/{clio-WBVQEBKO.js → clio-LT5V7SSZ.js} +9 -9
- package/dist/{code-nav-FGGFIE7L.js → code-nav-LMW275PA.js} +5 -5
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-F7OEATSO.js → components-ZFA3SAER.js} +8 -8
- package/dist/{config-TRBL3RCF.js → config-RXS5T3JT.js} +98 -65
- package/dist/{configure-OLCVPHNM.js → configure-2WYWSCSD.js} +26 -22
- package/dist/{context-MJIJ6GOX.js → context-I3BTOTCS.js} +12 -12
- package/dist/{context-XEWE3MOJ.js → context-MVOORGMF.js} +54 -47
- package/dist/{context-WFPKQSM6.js → context-PALKKQYL.js} +28 -28
- package/dist/{context-clear-KNOS2JPB.js → context-clear-N2WOYZ2K.js} +53 -46
- package/dist/{context-index-SSR5ECNE.js → context-index-HNG3MOME.js} +6 -6
- package/dist/{context-working-set-EUXAZI6N.js → context-working-set-MIEVECVZ.js} +17 -18
- package/dist/{dispatch-runner-B7MTOVKL.js → dispatch-runner-VVA4SRRH.js} +90 -61
- package/dist/{docs-FLJTIDSE.js → docs-7LQ23DLM.js} +8 -8
- package/dist/doctor-TWBWFK5V.js +165 -0
- package/dist/eval-IJ5VEZDJ.js +4483 -0
- package/dist/{evidence-JZNBUOQZ.js → evidence-L5APPXNV.js} +68 -61
- package/dist/{evolve-FJVC4KKI.js → evolve-RGNKFJ52.js} +47 -40
- package/dist/{extensions-IQL36S7K.js → extensions-7WYWUX5A.js} +13 -7
- package/dist/{fleet-BDKYJFCP.js → fleet-6CNVBZZP.js} +113 -76
- package/dist/{fleet-commands-ZFIWZSB3.js → fleet-commands-L2SXSYEI.js} +10 -10
- package/dist/{fleet-graph-Y6HPXIVF.js → fleet-graph-2J3OOIPO.js} +17 -15
- package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-CZRJ4JP5.js} +5 -6
- package/dist/{fleet-validate-BIYREGIK.js → fleet-validate-C5RI6DP7.js} +20 -19
- package/dist/{init-LQUB5COQ.js → init-VBN2ACVA.js} +70 -63
- package/dist/{library-NJAHIGG4.js → library-JHGUMLY2.js} +22 -20
- package/dist/{memory-OG6HOYKM.js → memory-K4OQIYWG.js} +49 -42
- package/dist/{models-5ZG5XY7J.js → models-2NCZUWDD.js} +35 -29
- package/dist/{monitor-TJ7AMTGB.js → monitor-MMVTJABD.js} +64 -45
- package/dist/{orchestrator-WZYB54DM.js → orchestrator-ZKBPCHW6.js} +1971 -520
- package/dist/{paths-XUC7GS6E.js → paths-DBXMZMDU.js} +5 -5
- package/dist/registry-LG64LTF4.js +11 -0
- package/dist/{reset-PXQT45IY.js → reset-DD5JGOY3.js} +11 -11
- package/dist/{run-FQ74YF62.js → run-QEGNX7FL.js} +89 -83
- package/dist/{share-FW7SVCL3.js → share-JKD3BQMW.js} +20 -18
- package/dist/{skills-7E7IRB3R.js → skills-LMQIKDOZ.js} +23 -21
- package/dist/{skills-eval-LI75W6OK.js → skills-eval-I7X2774U.js} +59 -52
- package/dist/{steer-GGWFUJUD.js → steer-CF5TDANS.js} +3 -3
- package/dist/support-I7LOJLIF.js +38 -0
- package/dist/{targets-4CIFKCTW.js → targets-RUSR6B5Z.js} +77 -42
- package/dist/{terminal-lease-WUZY7ZV5.js → terminal-lease-QYVORFR4.js} +6 -4
- package/dist/{trace-PNCASAXC.js → trace-ODOQIVIW.js} +61 -6
- package/dist/{uninstall-7FV7IP4E.js → uninstall-ZJF5H5ZN.js} +8 -8
- package/dist/{upgrade-K2HVIVMQ.js → upgrade-XANW3FXB.js} +29 -26
- package/dist/{usage-GTZELZQX.js → usage-4H7ZRXQT.js} +110 -61
- package/dist/{verifiers-RLAHT27O.js → verifiers-UZXNBZEB.js} +13 -13
- package/dist/{verify-BX3BRKH5.js → verify-BVKWTNDL.js} +9 -9
- package/dist/{wiki-generate-ASIFASCN.js → wiki-generate-MY7WV2QI.js} +76 -69
- package/dist/worker/entry.js +69 -66
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +1 -1
- package/docs/artifact-versions.md +11 -5
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +23 -2
- package/docs/commands-and-modes.md +2 -2
- package/docs/configuration-and-targets.md +37 -5
- package/docs/context-engine.md +63 -4
- package/docs/documentation-coverage.md +3 -3
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +2 -0
- package/docs/eval-runner.md +262 -11
- package/docs/evals-internal.md +72 -2
- package/docs/evidence-and-memory.md +77 -12
- package/docs/evolution.md +1 -1
- package/docs/extensions-and-sharing.md +3 -1
- package/docs/fleet-dispatch.md +34 -9
- package/docs/glossary.md +21 -1
- package/docs/installation-and-lifecycle.md +1 -1
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +1 -1
- package/docs/observability.md +54 -3
- package/docs/proactive-memory.md +127 -14
- package/docs/prompt-envelope-and-tools.md +22 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +60 -41
- package/docs/safety-model.md +1 -1
- package/docs/scientific-validation.md +1 -1
- package/docs/skills-marketplace.md +1 -1
- package/docs/tool-usage.md +1 -1
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +87 -0
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +2 -2
- package/src/cli/agents.ts +1 -1
- package/src/cli/argv.ts +5 -0
- package/src/cli/config-inspect.ts +33 -6
- package/src/cli/config.ts +1 -1
- package/src/cli/configure.ts +107 -23
- package/src/cli/doctor-state-size.ts +82 -0
- package/src/cli/doctor.ts +7 -1
- package/src/cli/eval.ts +80 -16
- package/src/cli/evidence.ts +30 -25
- package/src/cli/extensions.ts +5 -1
- package/src/cli/fleet-preflight.ts +2 -12
- package/src/cli/fleet.ts +32 -3
- package/src/cli/shared.ts +1 -0
- package/src/cli/targets.ts +45 -11
- package/src/cli/trace.ts +63 -4
- package/src/cli/usage.ts +63 -14
- package/src/cli/validate-model.ts +60 -5
- package/src/core/bus-events.ts +54 -1
- package/src/core/cache-telemetry.ts +42 -0
- package/src/core/commit-attribution.ts +4 -4
- package/src/core/config.ts +18 -0
- package/src/core/defaults.ts +36 -6
- package/src/core/endpoint-key.ts +27 -0
- package/src/core/path-boundary.ts +100 -0
- package/src/core/residency-target-key.ts +25 -0
- package/src/core/response-schema.ts +36 -2
- package/src/domains/agents/extension.ts +2 -11
- package/src/domains/agents/fleet-contract.ts +30 -12
- package/src/domains/agents/recipe.ts +7 -1
- package/src/domains/agents/registry.ts +73 -5
- package/src/domains/agents/result-contract.ts +128 -17
- package/src/domains/agents/write-boundary.ts +15 -50
- package/src/domains/config/classify.ts +3 -0
- package/src/domains/context/codewiki/coordinator.ts +12 -4
- package/src/domains/context/project-rules.ts +51 -1
- package/src/domains/dispatch/admission.ts +40 -3
- package/src/domains/dispatch/assignment-reconcile.ts +22 -5
- package/src/domains/dispatch/assignment-store.ts +151 -14
- package/src/domains/dispatch/capacity-lease.ts +98 -9
- package/src/domains/dispatch/contract.ts +26 -1
- package/src/domains/dispatch/delegation-plan.ts +2 -5
- package/src/domains/dispatch/execution-plan.ts +44 -4
- package/src/domains/dispatch/execution-role.ts +9 -1
- package/src/domains/dispatch/extension.ts +309 -96
- package/src/domains/dispatch/fleet-run.ts +78 -4
- package/src/domains/dispatch/gate-role-prompts.ts +38 -0
- package/src/domains/dispatch/heartbeat.ts +32 -8
- package/src/domains/dispatch/index.ts +6 -1
- package/src/domains/dispatch/intent-requirements.ts +40 -0
- package/src/domains/dispatch/intent.ts +84 -8
- package/src/domains/dispatch/orphan-recovery.ts +5 -0
- package/src/domains/dispatch/path-scope.ts +370 -0
- package/src/domains/dispatch/receipt-integrity.ts +2 -1
- package/src/domains/dispatch/reservation-store.ts +116 -8
- package/src/domains/dispatch/state.ts +4 -0
- package/src/domains/dispatch/types.ts +14 -7
- package/src/domains/dispatch/validation.ts +6 -3
- package/src/domains/dispatch/worker-spawn.ts +25 -11
- package/src/domains/dispatch/write-boundary-enforcer.ts +62 -0
- package/src/domains/dispatch/write-boundary.ts +262 -22
- package/src/domains/eval/artifacts/store.ts +62 -0
- package/src/domains/eval/compare/behavioral.ts +224 -0
- package/src/domains/eval/compare/compare.ts +355 -2
- package/src/domains/eval/compare/envelope.ts +128 -0
- package/src/domains/eval/compare/gates.ts +24 -6
- package/src/domains/eval/compare/thresholds.ts +30 -3
- package/src/domains/eval/execution-provenance.ts +240 -0
- package/src/domains/eval/metrics/aggregate.ts +136 -0
- package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
- package/src/domains/eval/metrics/evidence.ts +79 -2
- package/src/domains/eval/metrics/tracked.ts +413 -0
- package/src/domains/eval/provenance.ts +117 -0
- package/src/domains/eval/reports/comparison.ts +128 -0
- package/src/domains/eval/reports/junit.ts +17 -3
- package/src/domains/eval/reports/markdown.ts +3 -3
- package/src/domains/eval/reports/text.ts +14 -0
- package/src/domains/eval/run-compare.ts +20 -0
- package/src/domains/eval/runners/clio-run.ts +139 -2
- package/src/domains/eval/runners/external-command.ts +28 -3
- package/src/domains/eval/schema/adapter.ts +111 -0
- package/src/domains/eval/schema/artifact.ts +20 -0
- package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
- package/src/domains/eval/schema/behavioral.ts +520 -0
- package/src/domains/eval/schema/execution-envelope.ts +194 -0
- package/src/domains/eval/schema/serving.ts +74 -0
- package/src/domains/eval/schema/suite.ts +38 -8
- package/src/domains/eval/schema/validate.ts +58 -3
- package/src/domains/eval/schema/verdict.ts +237 -0
- package/src/domains/eval/suites/resolve.ts +2 -0
- package/src/domains/eval/suites/run.ts +264 -33
- package/src/domains/eval/verifiers/command.ts +2 -1
- package/src/domains/eval/workspaces/temp-copy.ts +145 -13
- package/src/domains/evidence/build.ts +68 -21
- package/src/domains/evidence/eval.ts +2 -12
- package/src/domains/evidence/findings-markdown.ts +33 -0
- package/src/domains/evidence/index.ts +21 -0
- package/src/domains/evidence/provenance.ts +46 -11
- package/src/domains/evidence/run-trust.ts +7 -113
- package/src/domains/evidence/trust-projection.ts +274 -0
- package/src/domains/evidence/trust-status.ts +145 -17
- package/src/domains/evidence/types.ts +4 -0
- package/src/domains/extensions/compatibility.ts +285 -0
- package/src/domains/extensions/discovery.ts +126 -4
- package/src/domains/extensions/resources.ts +21 -9
- package/src/domains/extensions/state.ts +18 -5
- package/src/domains/extensions/types.ts +6 -1
- package/src/domains/lifecycle/doctor.ts +209 -2
- package/src/domains/memory/index.ts +14 -0
- package/src/domains/memory/task-bank-promotion.ts +64 -0
- package/src/domains/memory/task-memory-policy.ts +77 -8
- package/src/domains/memory/task-memory-spend.ts +131 -0
- package/src/domains/memory/task-memory-status.ts +7 -0
- package/src/domains/memory/task-memory-telemetry.ts +2 -0
- package/src/domains/middleware/index.ts +1 -0
- package/src/domains/middleware/memory-intervention.ts +69 -5
- package/src/domains/middleware/memory-step-endpoint.ts +71 -0
- package/src/domains/observability/background-memory-usage.ts +140 -0
- package/src/domains/observability/cost.ts +1 -1
- package/src/domains/observability/index.ts +7 -0
- package/src/domains/observability/out-of-turn-usage.ts +51 -2
- package/src/domains/observability/trace-store.ts +192 -2
- package/src/domains/prompts/compiler.ts +100 -13
- package/src/domains/prompts/contract.ts +3 -5
- package/src/domains/providers/endpoint-capacity.ts +96 -0
- package/src/domains/providers/extension.ts +30 -2
- package/src/domains/providers/index.ts +10 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
- package/src/domains/providers/runtime-resolution.ts +8 -1
- package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
- package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
- package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
- package/src/domains/providers/types/capability-flags.ts +2 -0
- package/src/domains/providers/types/target-descriptor.ts +2 -0
- package/src/domains/resources/common-loader.ts +3 -0
- package/src/domains/resources/prompts/loader.ts +184 -17
- package/src/domains/safety/call-target.ts +52 -0
- package/src/domains/safety/policy-engine.ts +5 -5
- package/src/domains/safety/run-effects.ts +96 -2
- package/src/domains/safety/scope.ts +7 -12
- package/src/domains/session/context-accounting.ts +52 -1
- package/src/domains/session/context-ledger.ts +37 -13
- package/src/domains/session/index.ts +6 -0
- package/src/domains/session/prompt-cache.ts +140 -0
- package/src/domains/session/prompt-manifest.ts +42 -0
- package/src/engine/acp/adapter.ts +18 -3
- package/src/engine/acp/server.ts +4 -1
- package/src/engine/ai.ts +35 -0
- package/src/engine/apis/llamacpp-residency.ts +55 -3
- package/src/engine/apis/lmstudio.ts +25 -5
- package/src/engine/apis/ollama-native.ts +2 -1
- package/src/engine/apis/openai-completions.ts +80 -17
- package/src/engine/apis/residency-lock.ts +3 -1
- package/src/engine/apis/residency.ts +34 -1
- package/src/engine/prompt-templates.ts +18 -1
- package/src/engine/provider-payload.ts +29 -1
- package/src/engine/worker-runtime.ts +6 -3
- package/src/entry/orchestrator.ts +176 -30
- package/src/interactive/chat-loop-messages.ts +26 -7
- package/src/interactive/chat-loop.ts +318 -41
- package/src/interactive/chat-panel.ts +62 -8
- package/src/interactive/clio-editor.ts +45 -8
- package/src/interactive/context-activity.ts +5 -1
- package/src/interactive/context-meter.ts +1 -1
- package/src/interactive/context-overlay.ts +40 -10
- package/src/interactive/cost-overlay.ts +64 -6
- package/src/interactive/dispatch-board.ts +127 -5
- package/src/interactive/fleet-run-preview.ts +41 -15
- package/src/interactive/handoff-round.ts +41 -2
- package/src/interactive/interactive-application.ts +24 -1
- package/src/interactive/interactive-event-projection.ts +14 -0
- package/src/interactive/interactive-input-runtime.ts +8 -0
- package/src/interactive/interactive-presentation.ts +4 -0
- package/src/interactive/interactive-shell.ts +20 -17
- package/src/interactive/interactive-slash-runtime.ts +27 -4
- package/src/interactive/memory-overlay.ts +8 -0
- package/src/interactive/mutation-preview.ts +295 -0
- package/src/interactive/overlay-general-openers.ts +16 -0
- package/src/interactive/overlay-key-routing.ts +38 -0
- package/src/interactive/overlay-lifecycle.ts +38 -5
- package/src/interactive/overlay-permission-lifecycle.ts +22 -2
- package/src/interactive/overlay-session-lifecycle.ts +73 -9
- package/src/interactive/overlays/ask-user.ts +91 -19
- package/src/interactive/overlays/help-reference.ts +4 -0
- package/src/interactive/overlays/prompts.ts +11 -1
- package/src/interactive/overlays/settings.ts +176 -48
- package/src/interactive/permission-hint.ts +34 -2
- package/src/interactive/permission-overlay.ts +159 -9
- package/src/interactive/prewarm.ts +197 -0
- package/src/interactive/render-trace.ts +162 -15
- package/src/interactive/renderers/tool-execution.ts +4 -0
- package/src/interactive/side-question.ts +58 -1
- package/src/interactive/slash-commands.ts +7 -2
- package/src/interactive/status/controller.ts +11 -0
- package/src/interactive/status/state-machine.ts +54 -2
- package/src/interactive/status/types.ts +7 -0
- package/src/interactive/terminal-lease.ts +2 -0
- package/src/interactive/turn-context.ts +299 -31
- package/src/interactive/turn-persistence.ts +14 -4
- package/src/interactive/turn-prewarm.ts +364 -0
- package/src/interactive/turn-queues.ts +7 -4
- package/src/interactive/turn-runtime.ts +8 -1
- package/src/interactive/turn-state.ts +23 -0
- package/src/interactive/view/artifacts.ts +42 -9
- package/src/interactive/view/view-overlay.ts +43 -6
- package/src/interactive/worker-receipts.ts +14 -2
- package/src/interactive/worker-stream.ts +8 -0
- package/src/tools/ask-user.ts +43 -2
- package/src/tools/dispatch-admission.ts +12 -13
- package/src/tools/dispatch-arguments.ts +27 -0
- package/src/tools/dispatch-plan.ts +46 -9
- package/src/tools/dispatch-runner.ts +48 -13
- package/src/tools/dispatch-scout.ts +1 -1
- package/src/tools/monitor.ts +13 -0
- package/src/tools/registry.ts +16 -0
- package/src/tools/worker-evidence.ts +19 -13
- package/src/worker/spec-contract.ts +2 -1
- package/dist/chunk-AOCYTWAV.js +0 -449
- package/dist/chunk-HWUFFB6L.js +0 -83
- package/dist/chunk-R346GLFC.js +0 -31
- package/dist/chunk-ZGH7FGS5.js +0 -1079
- package/dist/doctor-RN4YKO2X.js +0 -87
- package/dist/eval-RUBJVSNQ.js +0 -2557
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { appendFile } from "node:fs/promises";
|
|
3
|
-
import { dirname } from "node:path";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
4
|
import type { TuiRenderObserver, TuiRenderPhase } from "../engine/tui.js";
|
|
5
5
|
|
|
6
6
|
/** The trace format is append-only JSONL so partial sessions remain readable. */
|
|
@@ -106,6 +106,106 @@ export type RenderTraceRecord =
|
|
|
106
106
|
}
|
|
107
107
|
| { type: "trace_drop"; version: typeof RENDER_TRACE_VERSION; at: number; records: number };
|
|
108
108
|
|
|
109
|
+
/** One byte-level delivery from the stdin reader to the application listener. */
|
|
110
|
+
export type RenderTraceInputIngressRecord = Extract<RenderTraceRecord, { type: "input_ingress" }>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* How many `input_ingress` records and how many committed frame records the
|
|
114
|
+
* always-on ring keeps, each. 256 keystrokes and 256 committed frames cover the
|
|
115
|
+
* last stretch of interaction an operator would still be describing when they
|
|
116
|
+
* kill a wedged pane, and cost about 200 KB of process memory in the worst case
|
|
117
|
+
* (a frame record carries its terminal-write commits).
|
|
118
|
+
*/
|
|
119
|
+
export const INPUT_WEDGE_RING_CAPACITY = 256;
|
|
120
|
+
|
|
121
|
+
/** Subdirectory of the state directory that holds SIGTERM wedge dumps. */
|
|
122
|
+
export const INPUT_WEDGE_DUMP_DIRNAME = "input-wedge";
|
|
123
|
+
|
|
124
|
+
/** Dumps kept in that directory; older ones are removed as new ones land. */
|
|
125
|
+
export const INPUT_WEDGE_DUMP_RETAINED = 5;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Which half of the input pipeline was still moving when the dump was taken.
|
|
129
|
+
*
|
|
130
|
+
* `input-not-committed` is the consumer's failure: bytes reached the
|
|
131
|
+
* application listener and no frame that carries them ever reached stdout.
|
|
132
|
+
* `no-input-recorded` is the reader's: nothing was delivered at all, so an
|
|
133
|
+
* operator who was typing was typing into a reader that had stopped.
|
|
134
|
+
* `input-committed` says neither half of this pipeline was stuck.
|
|
135
|
+
*/
|
|
136
|
+
export type InputWedgeClassification = "no-input-recorded" | "input-not-committed" | "input-committed";
|
|
137
|
+
|
|
138
|
+
export interface InputWedgeSnapshot {
|
|
139
|
+
version: typeof RENDER_TRACE_VERSION;
|
|
140
|
+
capacity: number;
|
|
141
|
+
pid: number;
|
|
142
|
+
/** Wall clock at trace open, so a record's relative `at` maps onto real time. */
|
|
143
|
+
openedAtEpochMs: number;
|
|
144
|
+
atEpochMs: number;
|
|
145
|
+
/** Milliseconds since trace open, the same clock every record's `at` uses. */
|
|
146
|
+
at: number;
|
|
147
|
+
classification: InputWedgeClassification;
|
|
148
|
+
msSinceLastInputIngress: number | null;
|
|
149
|
+
msSinceLastCommittedFrame: number | null;
|
|
150
|
+
inputIngress: RenderTraceInputIngressRecord[];
|
|
151
|
+
frames: RenderTraceFrameRecord[];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Bounded FIFO that overwrites its oldest entry rather than growing. */
|
|
155
|
+
function createRing<T>(capacity: number): { push(value: T): void; toArray(): T[] } {
|
|
156
|
+
const slots: T[] = [];
|
|
157
|
+
let next = 0;
|
|
158
|
+
return {
|
|
159
|
+
push(value): void {
|
|
160
|
+
if (slots.length < capacity) slots.push(value);
|
|
161
|
+
else slots[next] = value;
|
|
162
|
+
next = (next + 1) % capacity;
|
|
163
|
+
},
|
|
164
|
+
toArray(): T[] {
|
|
165
|
+
if (slots.length < capacity) return [...slots];
|
|
166
|
+
return [...slots.slice(next), ...slots.slice(0, next)];
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Read the two rings the way the ticket asks the wedge to be read: the newest
|
|
173
|
+
* input the operator should have seen, against the newest frame that reached
|
|
174
|
+
* stdout carrying it.
|
|
175
|
+
*/
|
|
176
|
+
function classifyInputWedge(
|
|
177
|
+
inputIngress: ReadonlyArray<RenderTraceInputIngressRecord>,
|
|
178
|
+
frames: ReadonlyArray<RenderTraceFrameRecord>,
|
|
179
|
+
): InputWedgeClassification {
|
|
180
|
+
const newest = [...inputIngress].reverse().find((record) => record.visualExpected) ?? inputIngress.at(-1);
|
|
181
|
+
if (newest === undefined) return "no-input-recorded";
|
|
182
|
+
return frames.some((frame) => frame.inputHighWater >= newest.inputSeq) ? "input-committed" : "input-not-committed";
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Write one snapshot under `<stateDir>/input-wedge/`, newest-first by name, and
|
|
187
|
+
* drop everything past the retention bound. Synchronous on purpose: the caller
|
|
188
|
+
* is a signal handler on a process that is about to end.
|
|
189
|
+
*/
|
|
190
|
+
export function writeInputWedgeDump(stateDir: string, snapshot: InputWedgeSnapshot): string {
|
|
191
|
+
const directory = join(stateDir, INPUT_WEDGE_DUMP_DIRNAME);
|
|
192
|
+
mkdirSync(directory, { recursive: true });
|
|
193
|
+
const stamp = new Date(snapshot.atEpochMs).toISOString().replace(/[:.]/gu, "-");
|
|
194
|
+
const path = join(directory, `${stamp}-${snapshot.pid}.json`);
|
|
195
|
+
writeFileSync(path, `${JSON.stringify(snapshot, null, 2)}\n`, "utf8");
|
|
196
|
+
try {
|
|
197
|
+
const existing = readdirSync(directory)
|
|
198
|
+
.filter((name) => name.endsWith(".json"))
|
|
199
|
+
.sort();
|
|
200
|
+
for (const name of existing.slice(0, Math.max(0, existing.length - INPUT_WEDGE_DUMP_RETAINED))) {
|
|
201
|
+
rmSync(join(directory, name), { force: true });
|
|
202
|
+
}
|
|
203
|
+
} catch {
|
|
204
|
+
// Retention is housekeeping; a dump that landed is worth more than a tidy directory.
|
|
205
|
+
}
|
|
206
|
+
return path;
|
|
207
|
+
}
|
|
208
|
+
|
|
109
209
|
interface TraceWriter {
|
|
110
210
|
enqueue(record: RenderTraceRecord): void;
|
|
111
211
|
close(): Promise<void>;
|
|
@@ -236,6 +336,8 @@ export interface RenderTrace extends TuiRenderObserver {
|
|
|
236
336
|
recordTerminalDrain(writeId: number): void;
|
|
237
337
|
currentFrameId(): number | null;
|
|
238
338
|
onFirstFrameCommit(listener: (frameId: number) => void): void;
|
|
339
|
+
/** The always-on ring as it stands, classified. Allocates; call it once, on the way out. */
|
|
340
|
+
snapshotInputWedge(): InputWedgeSnapshot;
|
|
239
341
|
close(): Promise<void>;
|
|
240
342
|
}
|
|
241
343
|
|
|
@@ -255,17 +357,32 @@ export function renderTracePath(env: NodeJS.ProcessEnv = process.env): string |
|
|
|
255
357
|
return raw && raw.length > 0 ? raw : null;
|
|
256
358
|
}
|
|
257
359
|
|
|
360
|
+
/**
|
|
361
|
+
* One tracer, two sinks. The JSONL file is the armed sink: it exists only when
|
|
362
|
+
* `CLIO_CODER_RENDER_TRACE` named a path, and it keeps every record. The
|
|
363
|
+
* bounded in-memory ring is the always-on sink: it keeps the last
|
|
364
|
+
* {@link INPUT_WEDGE_RING_CAPACITY} `input_ingress` records and the same number
|
|
365
|
+
* of committed frames, so the SIGTERM that recovers a wedged pane can still say
|
|
366
|
+
* which half of the input pipeline stopped (#224). A null `path` is the
|
|
367
|
+
* ring-only mode, and there the recorders that only ever fed the file keep
|
|
368
|
+
* their counters and skip building a record nothing would read.
|
|
369
|
+
*/
|
|
258
370
|
export function createRenderTrace(
|
|
259
|
-
path: string,
|
|
371
|
+
path: string | null,
|
|
260
372
|
now: () => number = () => performance.now(),
|
|
261
373
|
writerOptions: AsyncTraceWriterOptions = {},
|
|
262
374
|
): RenderTrace {
|
|
263
375
|
// Initialization happens before the terminal/TUI starts, never in a frame.
|
|
264
|
-
|
|
265
|
-
|
|
376
|
+
if (path !== null) {
|
|
377
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
378
|
+
writeFileSync(path, "", "utf8");
|
|
379
|
+
}
|
|
266
380
|
const openedAt = now();
|
|
381
|
+
const openedAtEpochMs = Date.now();
|
|
267
382
|
const at = (): number => rounded(now() - openedAt);
|
|
268
|
-
const writer = createAsyncTraceWriter(path, { ...writerOptions, recordTime: at });
|
|
383
|
+
const writer = path === null ? null : createAsyncTraceWriter(path, { ...writerOptions, recordTime: at });
|
|
384
|
+
const inputRing = createRing<RenderTraceInputIngressRecord>(INPUT_WEDGE_RING_CAPACITY);
|
|
385
|
+
const frameRing = createRing<RenderTraceFrameRecord>(INPUT_WEDGE_RING_CAPACITY);
|
|
269
386
|
let frameSeq = 0;
|
|
270
387
|
let writeSeq = 0;
|
|
271
388
|
let eventSeq = 0;
|
|
@@ -282,7 +399,7 @@ export function createRenderTrace(
|
|
|
282
399
|
const ranges = new Map<string, { codeUnits: number; graphemes: number }>();
|
|
283
400
|
const pendingDrains = new Map<number, { frameId: number | null; at: number }>();
|
|
284
401
|
|
|
285
|
-
writer
|
|
402
|
+
writer?.enqueue({ type: "trace_start", version: RENDER_TRACE_VERSION, at: 0 });
|
|
286
403
|
|
|
287
404
|
const trace: RenderTrace = {
|
|
288
405
|
recordPanelRender(metrics): void {
|
|
@@ -294,12 +411,15 @@ export function createRenderTrace(
|
|
|
294
411
|
},
|
|
295
412
|
recordVisibleEvent(fields): number {
|
|
296
413
|
eventSeq += 1;
|
|
414
|
+
// The ring keeps no provider deltas, so ring-only mode does not pay for
|
|
415
|
+
// grapheme segmentation on every token of every stream.
|
|
416
|
+
if (writer === null) return eventSeq;
|
|
297
417
|
const key = `${generation}:${fields.kind}:${fields.contentIndex}`;
|
|
298
418
|
const previous = ranges.get(key) ?? { codeUnits: 0, graphemes: 0 };
|
|
299
419
|
const graphemes = graphemeCount(fields.delta);
|
|
300
420
|
const next = { codeUnits: previous.codeUnits + fields.delta.length, graphemes: previous.graphemes + graphemes };
|
|
301
421
|
ranges.set(key, next);
|
|
302
|
-
writer
|
|
422
|
+
writer?.enqueue({
|
|
303
423
|
type: "event_ingress",
|
|
304
424
|
version: RENDER_TRACE_VERSION,
|
|
305
425
|
eventSeq,
|
|
@@ -317,7 +437,7 @@ export function createRenderTrace(
|
|
|
317
437
|
},
|
|
318
438
|
recordQueue(sequence, action): void {
|
|
319
439
|
queueDepth = Math.max(0, queueDepth + (action === "admit" ? 1 : -1));
|
|
320
|
-
writer
|
|
440
|
+
writer?.enqueue({
|
|
321
441
|
type: "queue",
|
|
322
442
|
version: RENDER_TRACE_VERSION,
|
|
323
443
|
eventSeq: sequence,
|
|
@@ -328,7 +448,7 @@ export function createRenderTrace(
|
|
|
328
448
|
},
|
|
329
449
|
recordPanelApplied(sequence): void {
|
|
330
450
|
panelHighWater = Math.max(panelHighWater, sequence);
|
|
331
|
-
writer
|
|
451
|
+
writer?.enqueue({
|
|
332
452
|
type: "panel",
|
|
333
453
|
version: RENDER_TRACE_VERSION,
|
|
334
454
|
eventSeq: sequence,
|
|
@@ -339,7 +459,7 @@ export function createRenderTrace(
|
|
|
339
459
|
recordInputIngress(action, bytes, visualExpected = action !== "no-visual-change"): number {
|
|
340
460
|
inputSeq += 1;
|
|
341
461
|
if (visualExpected) inputHighWater = inputSeq;
|
|
342
|
-
|
|
462
|
+
const record: RenderTraceInputIngressRecord = {
|
|
343
463
|
type: "input_ingress",
|
|
344
464
|
version: RENDER_TRACE_VERSION,
|
|
345
465
|
inputSeq,
|
|
@@ -347,7 +467,9 @@ export function createRenderTrace(
|
|
|
347
467
|
at: at(),
|
|
348
468
|
bytes,
|
|
349
469
|
visualExpected,
|
|
350
|
-
}
|
|
470
|
+
};
|
|
471
|
+
inputRing.push(record);
|
|
472
|
+
writer?.enqueue(record);
|
|
351
473
|
return inputSeq;
|
|
352
474
|
},
|
|
353
475
|
beginFrame(fields): FrameState {
|
|
@@ -403,8 +525,11 @@ export function createRenderTrace(
|
|
|
403
525
|
},
|
|
404
526
|
commits: frame.commits,
|
|
405
527
|
};
|
|
406
|
-
writer
|
|
528
|
+
writer?.enqueue(record);
|
|
407
529
|
if (frame.commits.length > 0) {
|
|
530
|
+
// Only a frame that reached stdout answers the question the ring exists
|
|
531
|
+
// for, which is whether the consumer half is still painting.
|
|
532
|
+
frameRing.push(record);
|
|
408
533
|
lastCommitAt = frame.commits.at(-1)?.at ?? endAt;
|
|
409
534
|
if (!firstCommitDelivered) {
|
|
410
535
|
firstCommitDelivered = true;
|
|
@@ -439,6 +564,7 @@ export function createRenderTrace(
|
|
|
439
564
|
backpressured: !fields.returned,
|
|
440
565
|
};
|
|
441
566
|
currentFrame?.commits.push(commit);
|
|
567
|
+
if (writer === null) return writeSeq;
|
|
442
568
|
writer.enqueue({ type: "terminal_write", version: RENDER_TRACE_VERSION, frameId, ...commit });
|
|
443
569
|
if (!fields.returned) pendingDrains.set(writeSeq, { frameId, at: commit.at });
|
|
444
570
|
return writeSeq;
|
|
@@ -448,7 +574,7 @@ export function createRenderTrace(
|
|
|
448
574
|
if (!pending) return;
|
|
449
575
|
pendingDrains.delete(writeId);
|
|
450
576
|
const drainAt = at();
|
|
451
|
-
writer
|
|
577
|
+
writer?.enqueue({
|
|
452
578
|
type: "terminal_drain",
|
|
453
579
|
version: RENDER_TRACE_VERSION,
|
|
454
580
|
writeId,
|
|
@@ -461,7 +587,28 @@ export function createRenderTrace(
|
|
|
461
587
|
onFirstFrameCommit(listener): void {
|
|
462
588
|
firstCommitListener = listener;
|
|
463
589
|
},
|
|
464
|
-
|
|
590
|
+
snapshotInputWedge(): InputWedgeSnapshot {
|
|
591
|
+
const inputIngress = inputRing.toArray();
|
|
592
|
+
const frames = frameRing.toArray();
|
|
593
|
+
const nowAt = at();
|
|
594
|
+
const lastIngressAt = inputIngress.at(-1)?.at;
|
|
595
|
+
const lastFrame = frames.at(-1);
|
|
596
|
+
const lastFrameCommitAt = lastFrame?.commits.at(-1)?.at ?? lastFrame?.endAt;
|
|
597
|
+
return {
|
|
598
|
+
version: RENDER_TRACE_VERSION,
|
|
599
|
+
capacity: INPUT_WEDGE_RING_CAPACITY,
|
|
600
|
+
pid: process.pid,
|
|
601
|
+
openedAtEpochMs,
|
|
602
|
+
atEpochMs: Date.now(),
|
|
603
|
+
at: nowAt,
|
|
604
|
+
classification: classifyInputWedge(inputIngress, frames),
|
|
605
|
+
msSinceLastInputIngress: lastIngressAt === undefined ? null : rounded(nowAt - lastIngressAt),
|
|
606
|
+
msSinceLastCommittedFrame: lastFrameCommitAt === undefined ? null : rounded(nowAt - lastFrameCommitAt),
|
|
607
|
+
inputIngress,
|
|
608
|
+
frames,
|
|
609
|
+
};
|
|
610
|
+
},
|
|
611
|
+
close: () => writer?.close() ?? Promise.resolve(),
|
|
465
612
|
};
|
|
466
613
|
return trace;
|
|
467
614
|
}
|
|
@@ -18,6 +18,7 @@ import { formatSize } from "../../engine/truncate.js";
|
|
|
18
18
|
import { visibleWidth, wrapTextWithAnsi } from "../../engine/tui.js";
|
|
19
19
|
import { classifyResourceRead, toolPresentationPolicy } from "../../tools/presentation.js";
|
|
20
20
|
import { toolResultPresentationPolicy, toolResultPresentationText } from "../../tools/result-disposition.js";
|
|
21
|
+
import { mutationFactsLine } from "../mutation-preview.js";
|
|
21
22
|
import type { ApprovalRequestView } from "../permission-overlay.js";
|
|
22
23
|
import { clioTheme, formatCompactMs, GLYPH } from "../theme/index.js";
|
|
23
24
|
import { renderDiffLines } from "./diff.js";
|
|
@@ -490,6 +491,9 @@ export function renderToolAwaitingApproval(
|
|
|
490
491
|
["action", view.actionClass],
|
|
491
492
|
["axis", axis],
|
|
492
493
|
...(view.target !== undefined && view.target.length > 0 ? [["target", view.target]] : []),
|
|
494
|
+
// Size and digest, never the mutation text: this row is the transcript,
|
|
495
|
+
// which is written, replayed, and shared (issue #254).
|
|
496
|
+
...(view.mutation !== undefined ? [["mutation", mutationFactsLine(view.mutation)]] : []),
|
|
493
497
|
] as const;
|
|
494
498
|
for (const [label, value] of facts) {
|
|
495
499
|
lines.push(...indentAndWrap(`${dim(`${label} ·`)} ${value}`, width, false));
|
|
@@ -13,7 +13,13 @@
|
|
|
13
13
|
* machine without adding an engine seam of its own. Tools are never sent.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import {
|
|
17
|
+
isResponseSchemaRejection,
|
|
18
|
+
type ResponseSchemaDialect,
|
|
19
|
+
responseSchemaDialectFor,
|
|
20
|
+
} from "../core/response-schema.js";
|
|
16
21
|
import { stream } from "../engine/ai.js";
|
|
22
|
+
import { patchResponseSchemaPayloadForDialect } from "../engine/provider-payload.js";
|
|
17
23
|
import type { AgentMessage, EngineModel, Usage } from "../engine/types.js";
|
|
18
24
|
|
|
19
25
|
/**
|
|
@@ -67,6 +73,18 @@ export interface OutOfTurnRoundInput extends Omit<SideQuestionInput, "question">
|
|
|
67
73
|
systemPrompt: string;
|
|
68
74
|
/** The one message appended to the read-only copy of the history. */
|
|
69
75
|
userText: string;
|
|
76
|
+
/**
|
|
77
|
+
* Bind the answer to a JSON schema on the wire, where the runtime takes one.
|
|
78
|
+
*
|
|
79
|
+
* A round that asked for a schema in prose and bound nothing is what made
|
|
80
|
+
* `/handoff` refuse on local targets: the model answered with prose around
|
|
81
|
+
* the object, or with no object at all, and the parser had nothing to work
|
|
82
|
+
* with (issue #223). Absent, or on a runtime with no dialect, the request
|
|
83
|
+
* goes out exactly as before and the prompt-level instruction carries it.
|
|
84
|
+
*/
|
|
85
|
+
responseSchema?: { name: string; schema: Record<string, unknown> };
|
|
86
|
+
/** Resolved runtime id, which is what decides the wire dialect. */
|
|
87
|
+
runtimeId?: string;
|
|
70
88
|
}
|
|
71
89
|
|
|
72
90
|
export interface SideQuestionResult {
|
|
@@ -80,7 +98,12 @@ function positive(value: unknown): number {
|
|
|
80
98
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
81
99
|
}
|
|
82
100
|
|
|
83
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Normalize one provider usage object into the shape `/cost` and the
|
|
103
|
+
* out-of-turn usage store take. Shared with the session pre-warm, which is
|
|
104
|
+
* another call billed beside the session rather than inside it.
|
|
105
|
+
*/
|
|
106
|
+
export function sideQuestionUsage(raw: unknown): SideQuestionUsage | null {
|
|
84
107
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
85
108
|
const usage = raw as Partial<Usage> & { reasoning?: number };
|
|
86
109
|
const input = positive(usage.input);
|
|
@@ -128,11 +151,45 @@ export async function runSideQuestion(input: SideQuestionInput): Promise<SideQue
|
|
|
128
151
|
return runOutOfTurnRound({ ...rest, systemPrompt: SIDE_QUESTION_SYSTEM_PROMPT, userText: question });
|
|
129
152
|
}
|
|
130
153
|
|
|
154
|
+
interface SchemaBinding {
|
|
155
|
+
dialect: ResponseSchemaDialect;
|
|
156
|
+
name: string;
|
|
157
|
+
schema: Record<string, unknown>;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** The schema binding for this round, or null when nothing can be bound on the wire. */
|
|
161
|
+
function schemaBindingFor(input: OutOfTurnRoundInput): SchemaBinding | null {
|
|
162
|
+
if (input.responseSchema === undefined || input.runtimeId === undefined) return null;
|
|
163
|
+
const dialect = responseSchemaDialectFor(input.runtimeId);
|
|
164
|
+
return dialect === null ? null : { dialect, ...input.responseSchema };
|
|
165
|
+
}
|
|
166
|
+
|
|
131
167
|
/** The shared round. See {@link OutOfTurnRoundInput}. */
|
|
132
168
|
export async function runOutOfTurnRound(input: OutOfTurnRoundInput): Promise<SideQuestionResult> {
|
|
169
|
+
const binding = schemaBindingFor(input);
|
|
170
|
+
if (binding === null) return runRound(input, null);
|
|
171
|
+
try {
|
|
172
|
+
return await runRound(input, binding);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
// Native enforcement is an optimization here, never a precondition. A
|
|
175
|
+
// server that refuses the constrained request answers with the same 400
|
|
176
|
+
// the worker seam already recognizes, and the round is worth more
|
|
177
|
+
// unconstrained than not at all. Anything else is a real failure and
|
|
178
|
+
// rejects, so a broken target still costs exactly one round.
|
|
179
|
+
if (input.signal?.aborted === true) throw error;
|
|
180
|
+
if (!isResponseSchemaRejection(error instanceof Error ? error.message : String(error))) throw error;
|
|
181
|
+
return runRound(input, null);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function runRound(input: OutOfTurnRoundInput, binding: SchemaBinding | null): Promise<SideQuestionResult> {
|
|
133
186
|
const options: Record<string, unknown> = { maxTokens: input.maxTokens ?? SIDE_QUESTION_MAX_TOKENS };
|
|
134
187
|
if (input.apiKey !== undefined) options.apiKey = input.apiKey;
|
|
135
188
|
if (input.signal !== undefined) options.signal = input.signal;
|
|
189
|
+
if (binding !== null) {
|
|
190
|
+
options.onPayload = (payload: unknown): unknown | undefined =>
|
|
191
|
+
patchResponseSchemaPayloadForDialect(payload, binding.dialect, binding.schema, binding.name);
|
|
192
|
+
}
|
|
136
193
|
|
|
137
194
|
const context = {
|
|
138
195
|
systemPrompt: input.systemPrompt,
|
|
@@ -6,9 +6,9 @@ import type { AgentSpec } from "../domains/agents/spec.js";
|
|
|
6
6
|
import type { ContextInitOptions } from "../domains/context/init-options.js";
|
|
7
7
|
import type { DispatchContract, DispatchRequest } from "../domains/dispatch/contract.js";
|
|
8
8
|
import { type AgentRoleFactsResolver, requestExecutionRole } from "../domains/dispatch/execution-role.js";
|
|
9
|
-
import type { ReceiptIntegrityResult } from "../domains/dispatch/receipt-integrity.js";
|
|
10
9
|
import type { RunReceipt } from "../domains/dispatch/types.js";
|
|
11
10
|
import type { JobThinkingLevel } from "../domains/dispatch/validation.js";
|
|
11
|
+
import type { ReceiptIntegrityOutcome } from "../domains/evidence/trust-status.js";
|
|
12
12
|
import type { InstalledExtension } from "../domains/extensions/index.js";
|
|
13
13
|
import type { InteropAgentId, InteropProposal, InteropReport } from "../domains/interop/index.js";
|
|
14
14
|
import type { ProvidersContract, ResolvedModelRef } from "../domains/providers/index.js";
|
|
@@ -665,7 +665,7 @@ export interface SlashCommandContext {
|
|
|
665
665
|
* and emit a single status line. Kept on the context so the registry does
|
|
666
666
|
* not import the overlay module.
|
|
667
667
|
*/
|
|
668
|
-
verifyReceipt: (runId: string) =>
|
|
668
|
+
verifyReceipt: (runId: string) => ReceiptIntegrityOutcome;
|
|
669
669
|
/**
|
|
670
670
|
* Handles the "unknown" case: append the text to the chat panel as a user
|
|
671
671
|
* turn, submit to the chat loop, and schedule a re-render. Handlers for
|
|
@@ -1507,6 +1507,11 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
1507
1507
|
const result = ctx.verifyReceipt(command.runId);
|
|
1508
1508
|
if (result.ok) {
|
|
1509
1509
|
ctx.notice("success", `verify ok ${command.runId}`);
|
|
1510
|
+
} else if (result.retired !== undefined) {
|
|
1511
|
+
// A retired seal is the expected state of a run from the previous
|
|
1512
|
+
// release, so it is a warning that names the versions, never the
|
|
1513
|
+
// failure a tampered receipt gets.
|
|
1514
|
+
ctx.notice("warn", `verify retired ${command.runId} ${result.reason}`);
|
|
1510
1515
|
} else {
|
|
1511
1516
|
ctx.notice("error", `verify fail ${command.runId} ${result.reason}`);
|
|
1512
1517
|
}
|
|
@@ -178,6 +178,17 @@ export function createStatusController(deps: StatusControllerDeps): StatusContro
|
|
|
178
178
|
notify(prev, status, force);
|
|
179
179
|
};
|
|
180
180
|
|
|
181
|
+
// The window between the editor and the stream. `preparing` and `idle`
|
|
182
|
+
// bracket it; `compacting` inside it is already carried by the compaction
|
|
183
|
+
// bus overlay, which now lands because `preparing` is an active phase.
|
|
184
|
+
if (deps.chat.onTurnPreparation) {
|
|
185
|
+
unsubscribes.push(
|
|
186
|
+
deps.chat.onTurnPreparation((phase) => {
|
|
187
|
+
apply({ type: phase === "idle" ? "submit_settled" : "submit_accepted" }, true);
|
|
188
|
+
}),
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
181
192
|
unsubscribes.push(
|
|
182
193
|
deps.chat.onEvent((event: ChatLoopEvent) => {
|
|
183
194
|
if (event.type === "agent_status") return;
|
|
@@ -53,6 +53,21 @@ export interface DispatchProgressStatusEvent {
|
|
|
53
53
|
type: "dispatch_progress";
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* A prompt has left the editor and Clio is preparing the turn: capability
|
|
58
|
+
* probe, pre-submit compaction, prompt compile, overflow preflight. None of
|
|
59
|
+
* that produces an engine event, so without this the footer kept reporting the
|
|
60
|
+
* previous turn as done for the whole window (issue #251).
|
|
61
|
+
*/
|
|
62
|
+
export interface SubmitAcceptedStatusEvent {
|
|
63
|
+
type: "submit_accepted";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** The prepared turn was admitted, refused, or failed. Either way the window is over. */
|
|
67
|
+
export interface SubmitSettledStatusEvent {
|
|
68
|
+
type: "submit_settled";
|
|
69
|
+
}
|
|
70
|
+
|
|
56
71
|
export type StatusInputEvent =
|
|
57
72
|
| ChatLoopEvent
|
|
58
73
|
| WatchdogTickEvent
|
|
@@ -60,7 +75,9 @@ export type StatusInputEvent =
|
|
|
60
75
|
| OverlayPopEvent
|
|
61
76
|
| RunAbortedStatusEvent
|
|
62
77
|
| ForceCancelledStatusEvent
|
|
63
|
-
| DispatchProgressStatusEvent
|
|
78
|
+
| DispatchProgressStatusEvent
|
|
79
|
+
| SubmitAcceptedStatusEvent
|
|
80
|
+
| SubmitSettledStatusEvent;
|
|
64
81
|
|
|
65
82
|
const OVERLAY_PHASES = new Set<StatusPhase>(["tool_blocked", "retrying", "compacting", "dispatching", "stuck"]);
|
|
66
83
|
const CORE_ACTIVE_PHASES = new Set<StatusPhase>(["preparing", "waiting_model", "thinking", "writing", "tool_running"]);
|
|
@@ -292,8 +309,43 @@ function retryOverlay(status: {
|
|
|
292
309
|
|
|
293
310
|
export function reduceStatus(prev: AgentStatus, event: StatusInputEvent, ctx: ReduceContext): AgentStatus {
|
|
294
311
|
switch (event.type) {
|
|
295
|
-
|
|
312
|
+
// A consumed prompt occupies `preparing` before any engine event exists,
|
|
313
|
+
// and the previous turn's summary rides along untouched: a refused
|
|
314
|
+
// admission puts the footer back on the last turn that actually ran,
|
|
315
|
+
// which is still the truth about what happened.
|
|
316
|
+
case "submit_accepted":
|
|
296
317
|
if (isActive(prev.phase)) return prev;
|
|
318
|
+
return {
|
|
319
|
+
...prev,
|
|
320
|
+
phase: "preparing",
|
|
321
|
+
since: ctx.now,
|
|
322
|
+
lastMeaningfulAt: ctx.now,
|
|
323
|
+
localRuntime: ctx.localRuntime,
|
|
324
|
+
preparingSubmission: true,
|
|
325
|
+
watchdogTier: 0,
|
|
326
|
+
resumePhase: undefined,
|
|
327
|
+
activePhases: undefined,
|
|
328
|
+
overlayStack: [],
|
|
329
|
+
tool: undefined,
|
|
330
|
+
toolStartedAt: undefined,
|
|
331
|
+
retry: undefined,
|
|
332
|
+
dispatch: undefined,
|
|
333
|
+
};
|
|
334
|
+
case "submit_settled":
|
|
335
|
+
if (prev.preparingSubmission !== true) return prev;
|
|
336
|
+
return {
|
|
337
|
+
...prev,
|
|
338
|
+
phase: prev.summary ? "ended" : "idle",
|
|
339
|
+
since: ctx.now,
|
|
340
|
+
preparingSubmission: undefined,
|
|
341
|
+
resumePhase: undefined,
|
|
342
|
+
activePhases: undefined,
|
|
343
|
+
overlayStack: [],
|
|
344
|
+
};
|
|
345
|
+
case "agent_start":
|
|
346
|
+
// A window this opened is the same turn arriving, not a duplicate
|
|
347
|
+
// start, so the run resets through it rather than being ignored.
|
|
348
|
+
if (isActive(prev.phase) && prev.preparingSubmission !== true) return prev;
|
|
297
349
|
return {
|
|
298
350
|
...INITIAL_STATUS,
|
|
299
351
|
phase: "preparing",
|
|
@@ -106,6 +106,13 @@ export interface AgentStatus {
|
|
|
106
106
|
toolStartedAt?: number | undefined;
|
|
107
107
|
retry?: RetryOverlay | undefined;
|
|
108
108
|
dispatch?: DispatchOverlay | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Set while the `preparing` phase belongs to a consumed prompt that has not
|
|
111
|
+
* yet been admitted, rather than to a run the engine has started. It is what
|
|
112
|
+
* lets `agent_start` take over a window this opened instead of treating an
|
|
113
|
+
* already-active phase as a duplicate start (issue #251).
|
|
114
|
+
*/
|
|
115
|
+
preparingSubmission?: boolean | undefined;
|
|
109
116
|
summary?: TurnSummary | undefined;
|
|
110
117
|
/** Usage settled so far in the active run. Reset by `agent_start`. */
|
|
111
118
|
runTally?: RunTally | undefined;
|
|
@@ -190,6 +190,8 @@ export function createProcessTerminalLease(options: CreateProcessTerminalLeaseOp
|
|
|
190
190
|
getThinkingLabel: () => editorChrome.getThinkingLabel(),
|
|
191
191
|
isStreaming: () => editorChrome.isStreaming?.() ?? false,
|
|
192
192
|
isAwaitingApproval: () => editorChrome.isAwaitingApproval?.() ?? false,
|
|
193
|
+
getPermissionInspection: () => editorChrome.getPermissionInspection?.() ?? "none",
|
|
194
|
+
getTurnPreparation: () => editorChrome.getTurnPreparation?.() ?? "idle",
|
|
193
195
|
willEnterSteer: (text) => editorChrome.willEnterSteer?.(text) ?? false,
|
|
194
196
|
getSubmitKeyLabel: () => editorChrome.getSubmitKeyLabel?.() ?? "Enter",
|
|
195
197
|
getNewlineKeyLabel: () => editorChrome.getNewlineKeyLabel?.() ?? "Shift+Enter",
|