@iowarp/clio-coder 0.3.8 → 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 +49 -0
- package/README.md +7 -3
- package/dist/{acp-U67UHUK2.js → acp-7LOELQFP.js} +6 -6
- package/dist/{agents-YU6SGALZ.js → agents-FIBG2SHA.js} +27 -25
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-5ZPJOIVG.js → auth-OI4LIH2I.js} +11 -12
- package/dist/{builtins-C6JMZVV6.js → builtins-AD25UL3C.js} +5 -5
- package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
- package/dist/chunk-3DPEIQKN.js +113 -0
- package/dist/{chunk-4SPRNWDE.js → chunk-3DUR4WUA.js} +15 -15
- package/dist/{chunk-VHN4MY6O.js → chunk-3MRC2YSQ.js} +2 -2
- package/dist/{chunk-5DHKRSMQ.js → chunk-3UUY7R3Z.js} +11 -7
- package/dist/{chunk-IGWKHNIQ.js → chunk-3V5AYSEQ.js} +8 -8
- package/dist/{chunk-FHJEP5SW.js → chunk-465CC7FK.js} +8 -5
- package/dist/{chunk-5WIGXA4T.js → chunk-47CMYGET.js} +111 -4
- package/dist/{chunk-A3WNZD3P.js → chunk-4H6ULJ3H.js} +67 -21
- package/dist/{chunk-TB5666IT.js → chunk-4LJX2PUC.js} +3 -3
- package/dist/{chunk-XWSF374K.js → chunk-56KB5IJP.js} +2 -2
- package/dist/{chunk-SPULKLCF.js → chunk-5DQRIYDZ.js} +2 -2
- package/dist/{chunk-2HEJ2F35.js → chunk-5HFBWUMU.js} +20 -8
- package/dist/{chunk-WNIJTQQK.js → chunk-5PVQ4SRS.js} +78 -6
- package/dist/{chunk-DYIM5TJT.js → chunk-5QKCQQ3E.js} +262 -6
- package/dist/{chunk-TYPGUK6W.js → chunk-5T7RBWN2.js} +111 -5
- package/dist/{chunk-IIZWH4XA.js → chunk-774ILSRL.js} +2 -2
- package/dist/chunk-7C6RYZGQ.js +391 -0
- package/dist/{chunk-TANS5ZJS.js → chunk-AD7Y7STJ.js} +3 -3
- package/dist/{chunk-RWSI4YD7.js → chunk-AEYBF3TB.js} +33 -12
- package/dist/{chunk-DGSYXYMX.js → chunk-AMKHQW3C.js} +2 -2
- package/dist/{chunk-VWZOAB7K.js → chunk-B5XRQOLB.js} +7 -7
- package/dist/{chunk-WXY7KU3G.js → chunk-BVDVID7E.js} +2 -2
- package/dist/{chunk-PMDBGQSJ.js → chunk-CA42X6KT.js} +2 -2
- package/dist/{chunk-HLE42MG7.js → chunk-D73KXYPF.js} +3 -3
- package/dist/{chunk-5Q2VVUKB.js → chunk-DG4M6ZUE.js} +3 -3
- package/dist/{chunk-ME6CCNFO.js → chunk-EBOC7MT3.js} +6 -6
- package/dist/{chunk-MXKJU4JB.js → chunk-ECUO3KDP.js} +48 -7
- package/dist/{chunk-26LEYJZH.js → chunk-FALJGAWU.js} +2 -2
- package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
- package/dist/{chunk-7RGZWPB6.js → chunk-GAYUJ7LE.js} +67 -13
- package/dist/{chunk-VCBR6CU7.js → chunk-HAY4ZE2P.js} +2 -2
- package/dist/{chunk-FBVTI2TJ.js → chunk-HCBCAYZU.js} +11 -130
- package/dist/{chunk-WSB3FPX7.js → chunk-HJB5IUKP.js} +32 -136
- package/dist/{chunk-J3YUBZWY.js → chunk-HKO36JWF.js} +33 -5
- package/dist/{chunk-E77JEWSD.js → chunk-HPCTNZM2.js} +6 -36
- package/dist/{chunk-FJ3H4MN5.js → chunk-IHKBWSXF.js} +2 -2
- package/dist/{chunk-NMPKI6XL.js → chunk-JEQQR47K.js} +37 -18
- package/dist/{chunk-3BINW3FP.js → chunk-KV2AOLDF.js} +24 -4
- package/dist/{chunk-YS5VLNH5.js → chunk-LXPJXFM5.js} +7 -7
- package/dist/{chunk-7RFXX52T.js → chunk-MIX5N5AC.js} +271 -41
- package/dist/{chunk-K4XHGFR5.js → chunk-MLOK6ZOS.js} +1297 -218
- package/dist/{chunk-ZNLWCMVZ.js → chunk-MV2VUEJC.js} +2 -2
- package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
- package/dist/{chunk-5H3GB5BO.js → chunk-N3PBVRTZ.js} +4 -382
- package/dist/{chunk-2HFZQUHL.js → chunk-N5XKWMDW.js} +17 -7
- package/dist/{chunk-5C3AQNDW.js → chunk-NNNWO6F2.js} +124 -36
- package/dist/{chunk-GU2UIAFZ.js → chunk-NQ6UCCOD.js} +3 -3
- package/dist/{chunk-N22QMJKY.js → chunk-NZU6YDNV.js} +4 -4
- package/dist/{chunk-ZVJ5BLO2.js → chunk-O6I4CIEU.js} +151 -13
- package/dist/{chunk-XN3L4EYL.js → chunk-OEDBCISO.js} +2 -2
- package/dist/{chunk-VAWNZU7Z.js → chunk-P3JGPQFL.js} +2 -2
- package/dist/{chunk-IJ7RPIYJ.js → chunk-PNY46YEY.js} +20 -3
- package/dist/{chunk-U6MBIEMB.js → chunk-PZ4I4JE2.js} +56 -35
- package/dist/{chunk-GPIEI3LY.js → chunk-QQ7EKM72.js} +2 -2
- package/dist/{chunk-WLFILSD5.js → chunk-R7LNVMCS.js} +66 -28
- package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
- package/dist/chunk-RKKLTLYB.js +45 -0
- package/dist/{chunk-TT36MB5S.js → chunk-RKRLDWD3.js} +3 -1
- package/dist/{chunk-TTHACPOM.js → chunk-S4COXYBG.js} +456 -18
- package/dist/{chunk-WWCZ5F23.js → chunk-T3Z6VAAF.js} +69 -10
- package/dist/{chunk-GN57SG4G.js → chunk-TD7UE2L5.js} +9 -7
- package/dist/{chunk-TLQJPP24.js → chunk-TEO2TLVN.js} +523 -322
- package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
- package/dist/{chunk-KTYTFRMB.js → chunk-VKBMFOYV.js} +17 -15
- package/dist/{chunk-PT7HYKEM.js → chunk-VO2LKSTM.js} +2 -2
- package/dist/{chunk-P43ETTHK.js → chunk-VPTUJU4P.js} +2 -2
- package/dist/{chunk-WEH5XRJQ.js → chunk-WIE7ZOSW.js} +2 -2
- package/dist/{chunk-EMYUUSFG.js → chunk-WXCJ7VME.js} +5 -5
- package/dist/{chunk-4DGYLA73.js → chunk-XDOQXGFO.js} +22 -7
- package/dist/{chunk-JOZYP4GM.js → chunk-YKOFT37S.js} +5 -5
- package/dist/chunk-YSEHGPCT.js +127 -0
- package/dist/{chunk-HFSBBKSQ.js → chunk-YW7UVM5V.js} +138 -3
- package/dist/cli/index.js +27 -27
- package/dist/{clio-QVTYJ57A.js → clio-LT5V7SSZ.js} +6 -6
- package/dist/{code-nav-FGGFIE7L.js → code-nav-LMW275PA.js} +4 -4
- package/dist/{config-LW5IJFQN.js → config-RXS5T3JT.js} +71 -43
- package/dist/{configure-7XIZCOU4.js → configure-2WYWSCSD.js} +14 -15
- package/dist/{context-Y6Y7QPR6.js → context-I3BTOTCS.js} +12 -12
- package/dist/{context-L3WL3X7K.js → context-MVOORGMF.js} +34 -33
- package/dist/{context-N52ZA626.js → context-PALKKQYL.js} +20 -20
- package/dist/{context-clear-MBQRLSDQ.js → context-clear-N2WOYZ2K.js} +34 -33
- package/dist/{context-index-HVMFQHK3.js → context-index-HNG3MOME.js} +2 -2
- package/dist/{context-working-set-GS6DSO7F.js → context-working-set-MIEVECVZ.js} +10 -11
- package/dist/{dispatch-runner-22ZCNOM3.js → dispatch-runner-VVA4SRRH.js} +34 -33
- package/dist/doctor-TWBWFK5V.js +165 -0
- package/dist/{eval-BEC2WHDA.js → eval-IJ5VEZDJ.js} +2016 -142
- package/dist/{evidence-REJUMSKM.js → evidence-L5APPXNV.js} +29 -28
- package/dist/{evolve-PY5ZBA5K.js → evolve-RGNKFJ52.js} +29 -28
- package/dist/{extensions-HVKU65YU.js → extensions-7WYWUX5A.js} +9 -3
- package/dist/{fleet-7WZEWRFA.js → fleet-6CNVBZZP.js} +87 -55
- package/dist/{fleet-commands-UVHWM76J.js → fleet-commands-L2SXSYEI.js} +6 -6
- package/dist/{fleet-graph-6ULH7PES.js → fleet-graph-2J3OOIPO.js} +14 -12
- package/dist/{fleet-preflight-J53T6CCE.js → fleet-preflight-CZRJ4JP5.js} +3 -4
- package/dist/{fleet-validate-72PC4SLA.js → fleet-validate-C5RI6DP7.js} +16 -15
- package/dist/{init-OG3TPGQG.js → init-VBN2ACVA.js} +50 -48
- package/dist/{library-CNTMPLRF.js → library-JHGUMLY2.js} +13 -11
- package/dist/{memory-6IS7F275.js → memory-K4OQIYWG.js} +31 -30
- package/dist/{models-ENRJDA5W.js → models-2NCZUWDD.js} +23 -22
- package/dist/{monitor-XLDVO7TN.js → monitor-MMVTJABD.js} +35 -34
- package/dist/{orchestrator-6KSPYRHA.js → orchestrator-ZKBPCHW6.js} +1627 -294
- package/dist/{reset-RZ4ER727.js → reset-DD5JGOY3.js} +3 -3
- package/dist/{run-Y2CNK5RU.js → run-QEGNX7FL.js} +56 -55
- package/dist/{share-A55GYP6Z.js → share-JKD3BQMW.js} +13 -11
- package/dist/{skills-ALC5J6AT.js → skills-LMQIKDOZ.js} +14 -12
- package/dist/{skills-eval-JPBEBYQU.js → skills-eval-I7X2774U.js} +34 -32
- package/dist/{steer-GGWFUJUD.js → steer-CF5TDANS.js} +3 -3
- package/dist/{support-MIETYA5E.js → support-I7LOJLIF.js} +4 -4
- package/dist/{targets-VGNXIR3S.js → targets-RUSR6B5Z.js} +58 -32
- package/dist/{terminal-lease-WOBR64YA.js → terminal-lease-QYVORFR4.js} +6 -4
- package/dist/{trace-PNCASAXC.js → trace-ODOQIVIW.js} +61 -6
- package/dist/{upgrade-FUSUAGHR.js → upgrade-XANW3FXB.js} +17 -16
- package/dist/{usage-N4MKVHKD.js → usage-4H7ZRXQT.js} +88 -44
- package/dist/{verifiers-YAWOJ3H2.js → verifiers-UZXNBZEB.js} +6 -6
- package/dist/{verify-LTDHYBGY.js → verify-BVKWTNDL.js} +5 -5
- package/dist/{wiki-generate-6M7GHTBJ.js → wiki-generate-MY7WV2QI.js} +49 -47
- package/dist/worker/entry.js +29 -33
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +1 -1
- package/docs/artifact-versions.md +6 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +23 -2
- package/docs/commands-and-modes.md +1 -1
- package/docs/configuration-and-targets.md +30 -3
- 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 +11 -10
- package/docs/evolution.md +1 -1
- package/docs/extensions-and-sharing.md +3 -1
- package/docs/fleet-dispatch.md +4 -4
- 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 +53 -2
- package/docs/proactive-memory.md +127 -14
- package/docs/prompt-envelope-and-tools.md +19 -1
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +19 -3
- 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 -1
- package/src/cli/agents.ts +1 -1
- package/src/cli/config-inspect.ts +33 -6
- package/src/cli/config.ts +1 -1
- package/src/cli/doctor-state-size.ts +82 -0
- package/src/cli/doctor.ts +3 -1
- package/src/cli/eval.ts +80 -16
- package/src/cli/extensions.ts +5 -1
- package/src/cli/fleet.ts +32 -3
- package/src/cli/targets.ts +44 -13
- package/src/cli/trace.ts +63 -4
- package/src/cli/usage.ts +63 -14
- package/src/core/bus-events.ts +29 -1
- package/src/core/cache-telemetry.ts +42 -0
- 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/residency-target-key.ts +25 -0
- package/src/core/response-schema.ts +36 -2
- package/src/domains/config/classify.ts +3 -0
- package/src/domains/context/codewiki/coordinator.ts +12 -4
- package/src/domains/dispatch/admission.ts +40 -3
- package/src/domains/dispatch/capacity-lease.ts +98 -9
- package/src/domains/dispatch/contract.ts +11 -0
- package/src/domains/dispatch/execution-plan.ts +44 -4
- package/src/domains/dispatch/extension.ts +166 -42
- package/src/domains/dispatch/fleet-run.ts +23 -3
- package/src/domains/dispatch/heartbeat.ts +32 -8
- package/src/domains/dispatch/index.ts +3 -0
- package/src/domains/dispatch/orphan-recovery.ts +5 -0
- package/src/domains/dispatch/reservation-store.ts +116 -8
- package/src/domains/dispatch/state.ts +4 -0
- package/src/domains/dispatch/worker-spawn.ts +25 -11
- package/src/domains/dispatch/write-boundary-enforcer.ts +20 -3
- package/src/domains/dispatch/write-boundary.ts +62 -1
- 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/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 +127 -0
- 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 +2 -13
- package/src/domains/evidence/eval.ts +2 -12
- package/src/domains/evidence/findings-markdown.ts +33 -0
- package/src/domains/evidence/run-trust.ts +7 -113
- package/src/domains/evidence/trust-projection.ts +2 -2
- package/src/domains/extensions/compatibility.ts +285 -0
- package/src/domains/extensions/discovery.ts +38 -3
- package/src/domains/extensions/resources.ts +1 -1
- package/src/domains/extensions/state.ts +12 -3
- package/src/domains/extensions/types.ts +2 -0
- package/src/domains/lifecycle/doctor.ts +69 -1
- 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/providers/endpoint-capacity.ts +96 -0
- 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/prompts/loader.ts +95 -33
- package/src/domains/safety/call-target.ts +52 -0
- package/src/domains/safety/run-effects.ts +35 -4
- 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/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/provider-payload.ts +29 -1
- 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 +84 -12
- 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-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 +35 -1
- 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/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/view-overlay.ts +28 -3
- package/src/tools/ask-user.ts +43 -2
- package/src/tools/dispatch-plan.ts +17 -9
- package/src/tools/dispatch-scout.ts +1 -1
- package/src/tools/registry.ts +16 -0
- package/dist/chunk-AOCYTWAV.js +0 -449
- package/dist/chunk-HWUFFB6L.js +0 -83
- package/dist/chunk-R346GLFC.js +0 -31
- package/dist/doctor-M7YEDGAE.js +0 -91
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type RunStatus,
|
|
25
25
|
runKindSupportsLiveSteering,
|
|
26
26
|
} from "../domains/dispatch/types.js";
|
|
27
|
+
import { describeWriteBoundaryAttributionDowngrade } from "../domains/dispatch/write-boundary.js";
|
|
27
28
|
import {
|
|
28
29
|
summarizeTrustStatus,
|
|
29
30
|
type TrustSummaryProjection,
|
|
@@ -36,7 +37,7 @@ import {
|
|
|
36
37
|
type ObservabilityNotice,
|
|
37
38
|
type ObservabilitySnapshot,
|
|
38
39
|
} from "../domains/observability/index.js";
|
|
39
|
-
import type
|
|
40
|
+
import { type CostProvenance, foregroundStreamUsage } from "../domains/providers/index.js";
|
|
40
41
|
import { sanitizeCallTargetText } from "../domains/safety/call-target.js";
|
|
41
42
|
import { type Component, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../engine/tui.js";
|
|
42
43
|
import { formatWorkerContextMeter } from "./context-meter.js";
|
|
@@ -88,6 +89,12 @@ export interface DispatchSteerAcknowledgement {
|
|
|
88
89
|
chars: number;
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
export interface DispatchWriteRecordDowngrade {
|
|
93
|
+
reason: "opaque_tool_succeeded";
|
|
94
|
+
tool: string;
|
|
95
|
+
toolCallId: string;
|
|
96
|
+
}
|
|
97
|
+
|
|
91
98
|
export interface DispatchBoardRow {
|
|
92
99
|
runId: string;
|
|
93
100
|
agentId: string;
|
|
@@ -97,6 +104,8 @@ export interface DispatchBoardRow {
|
|
|
97
104
|
runtimeId: string;
|
|
98
105
|
targetId: string;
|
|
99
106
|
wireModelId: string;
|
|
107
|
+
/** Canonical inference scheduler and its independent request-slot bound. */
|
|
108
|
+
endpoint?: { key: string; label: string; limit: number };
|
|
100
109
|
/** Sanitized, one-line summary of the task assigned to this run. */
|
|
101
110
|
taskSummary?: string;
|
|
102
111
|
/** Immutable budget admission provenance for this run. */
|
|
@@ -156,6 +165,8 @@ export interface DispatchBoardRow {
|
|
|
156
165
|
retry?: DispatchRetryPresentation;
|
|
157
166
|
/** Most recent worker delivery acknowledgement for an operator steer. */
|
|
158
167
|
steerAcknowledgement?: DispatchSteerAcknowledgement;
|
|
168
|
+
/** First successful opaque call that opened this run's write record. */
|
|
169
|
+
writeRecordDowngrade?: DispatchWriteRecordDowngrade;
|
|
159
170
|
/**
|
|
160
171
|
* Where this run sits in a fleet plan: the wave the step was scheduled in
|
|
161
172
|
* and the step id it executes. Present only for runs a fleet plan
|
|
@@ -598,11 +609,29 @@ function progressAnswerLines(
|
|
|
598
609
|
return body.map((row, index) => `${index === 0 ? cardKvKey(theme, "answer") : " ".repeat(gutter)}${row}`);
|
|
599
610
|
}
|
|
600
611
|
|
|
612
|
+
/** Keep the canonical tier and every summary clause visible by wrapping the value under its card key. */
|
|
613
|
+
function trustCardLines(theme: ClioTheme, row: DispatchBoardRow, contentWidth: number): string[] {
|
|
614
|
+
const gutter = CARD_KV_KEY_WIDTH + 1;
|
|
615
|
+
const valueWidth = Math.max(1, contentWidth - gutter);
|
|
616
|
+
const trust =
|
|
617
|
+
row.trust === undefined
|
|
618
|
+
? theme.fg("dim", isTerminalStatus(row.status) ? "receipt not read back" : "not sealed yet")
|
|
619
|
+
: theme.fg(
|
|
620
|
+
trustVerdictToken(row.trust.verdict),
|
|
621
|
+
`${trustVerdictGlyph(row.trust.verdict)} ${row.trust.verdict}; ${row.trust.text}`,
|
|
622
|
+
);
|
|
623
|
+
const host =
|
|
624
|
+
row.hostVerification === undefined ? "" : ` · ${theme.fg("muted", `host checks ${row.hostVerification}`)}`;
|
|
625
|
+
return wrapTextWithAnsi(`${trust}${host}`, valueWidth).map(
|
|
626
|
+
(line, index) => `${index === 0 ? cardKvKey(theme, "trust") : " ".repeat(gutter)}${line}`,
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
|
|
601
630
|
export function renderDispatchCard(
|
|
602
631
|
row: DispatchBoardRow,
|
|
603
632
|
width: number,
|
|
604
633
|
evidence?: RunEvidencePresentation,
|
|
605
|
-
options: { selected?: boolean; expanded?: boolean } = {},
|
|
634
|
+
options: { selected?: boolean; expanded?: boolean; endpointActive?: number } = {},
|
|
606
635
|
): string[] {
|
|
607
636
|
const theme = clioTheme();
|
|
608
637
|
const contentWidth = Math.max(0, width - 4);
|
|
@@ -653,6 +682,9 @@ export function renderDispatchCard(
|
|
|
653
682
|
const statusUnits = [
|
|
654
683
|
statusStr,
|
|
655
684
|
theme.fg("muted", `node ${row.node ?? "local"}`),
|
|
685
|
+
...(row.endpoint !== undefined
|
|
686
|
+
? [theme.fg("info", `slots ${options.endpointActive ?? 0}/${row.endpoint.limit} ${row.endpoint.label}`)]
|
|
687
|
+
: []),
|
|
656
688
|
...(row.gate !== undefined ? [theme.fg("info", `gate ${row.gate.role} c${row.gate.cycle}`)] : []),
|
|
657
689
|
...(row.rerouteCount !== undefined && row.rerouteCount > 0
|
|
658
690
|
? [theme.fg("warning", `rerouted x${row.rerouteCount}`)]
|
|
@@ -663,15 +695,6 @@ export function renderDispatchCard(
|
|
|
663
695
|
`${theme.fg("dim", "ttft")} ${theme.fg("muted", ttft)}`,
|
|
664
696
|
`${theme.fg("dim", "cost")} ${theme.fg("muted", cost)}`,
|
|
665
697
|
];
|
|
666
|
-
// The trust line is the canonical projection, styled by its verdict tier;
|
|
667
|
-
// a host check is folded into that projection as validation grounding, so
|
|
668
|
-
// it is named as a secondary fact and never as independent verification.
|
|
669
|
-
const trustUnits = [
|
|
670
|
-
row.trust === undefined
|
|
671
|
-
? theme.fg("dim", isTerminalStatus(row.status) ? "trust: receipt not read back" : "trust: not sealed yet")
|
|
672
|
-
: theme.fg(trustVerdictToken(row.trust.verdict), `${trustVerdictGlyph(row.trust.verdict)} ${row.trust.text}`),
|
|
673
|
-
...(row.hostVerification !== undefined ? [theme.fg("muted", `host checks ${row.hostVerification}`)] : []),
|
|
674
|
-
];
|
|
675
698
|
const contextUnit = formatWorkerContextMeter(row.lastContextTokens ?? 0, row.contextWindow, theme);
|
|
676
699
|
// The phase column: a fleet step says which wave it belongs to and which
|
|
677
700
|
// step it is; every other run leaves the cell empty rather than inventing a
|
|
@@ -690,7 +713,7 @@ export function renderDispatchCard(
|
|
|
690
713
|
? [truncateToWidth(`${cardKvKey(theme, "task")}${theme.fg("muted", row.taskSummary)}`, contentWidth, "…", false)]
|
|
691
714
|
: []),
|
|
692
715
|
cardUnitsLine(theme, "status", statusUnits, contentWidth),
|
|
693
|
-
|
|
716
|
+
...trustCardLines(theme, row, contentWidth),
|
|
694
717
|
...(row.budget !== undefined
|
|
695
718
|
? [
|
|
696
719
|
truncateToWidth(
|
|
@@ -751,6 +774,16 @@ export function renderDispatchCard(
|
|
|
751
774
|
),
|
|
752
775
|
);
|
|
753
776
|
}
|
|
777
|
+
if (row.writeRecordDowngrade) {
|
|
778
|
+
const warning = describeWriteBoundaryAttributionDowngrade({
|
|
779
|
+
...row.writeRecordDowngrade,
|
|
780
|
+
runId: row.runId,
|
|
781
|
+
stepId: row.phase?.stepId ?? null,
|
|
782
|
+
});
|
|
783
|
+
bodyLines.push(
|
|
784
|
+
...wrapTextWithAnsi(`${cardKvKey(theme, "record")}${theme.fg("warning", `open: ${warning}`)}`, contentWidth),
|
|
785
|
+
);
|
|
786
|
+
}
|
|
754
787
|
// The proof row is present only when the observability projection knows an
|
|
755
788
|
// evidence state for this run; an unknown/none state adds no line, so cards
|
|
756
789
|
// without evidence keep their existing three-line body.
|
|
@@ -969,6 +1002,16 @@ export function formatDispatchBoardLines(
|
|
|
969
1002
|
});
|
|
970
1003
|
}
|
|
971
1004
|
|
|
1005
|
+
const endpointActive: Record<string, number> = { ...foregroundStreamUsage() };
|
|
1006
|
+
for (const row of rows) {
|
|
1007
|
+
if (
|
|
1008
|
+
row.endpoint !== undefined &&
|
|
1009
|
+
(row.status === "running" || row.status === "stale" || row.status === "enqueued" || row.status === "cancelling")
|
|
1010
|
+
) {
|
|
1011
|
+
endpointActive[row.endpoint.key] = (endpointActive[row.endpoint.key] ?? 0) + 1;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
972
1015
|
// A council is one question asked of several members, so its rows render as
|
|
973
1016
|
// one card holding the whole group rather than as unrelated neighbours.
|
|
974
1017
|
const cards = dispatchBoardItems(rows, selectedRunId).map((item) =>
|
|
@@ -977,6 +1020,7 @@ export function formatDispatchBoardLines(
|
|
|
977
1020
|
: renderDispatchCard(item.row, width, deriveRunEvidenceState(observability, item.row.runId), {
|
|
978
1021
|
selected: item.row.runId === selectedRunId,
|
|
979
1022
|
expanded: detailExpanded && item.row.runId === selectedRunId,
|
|
1023
|
+
...(item.row.endpoint !== undefined ? { endpointActive: endpointActive[item.row.endpoint.key] ?? 0 } : {}),
|
|
980
1024
|
}),
|
|
981
1025
|
);
|
|
982
1026
|
const body: string[] = [];
|
|
@@ -1155,6 +1199,15 @@ function parseGateBadge(value: unknown): { role: string; cycle: number } | undef
|
|
|
1155
1199
|
return { role: record.role, cycle };
|
|
1156
1200
|
}
|
|
1157
1201
|
|
|
1202
|
+
function parseEndpointCapacity(value: unknown): DispatchBoardRow["endpoint"] | undefined {
|
|
1203
|
+
if (typeof value !== "object" || value === null) return undefined;
|
|
1204
|
+
const record = value as { key?: unknown; label?: unknown; limit?: unknown };
|
|
1205
|
+
const key = parseNonEmptyString(record.key);
|
|
1206
|
+
const label = parseNonEmptyString(record.label);
|
|
1207
|
+
const limit = parsePositiveInt(record.limit);
|
|
1208
|
+
return key === undefined || label === undefined || limit === undefined ? undefined : { key, label, limit };
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1158
1211
|
function parseCouncilBadge(value: unknown): DispatchBoardRow["council"] | undefined {
|
|
1159
1212
|
if (typeof value !== "object" || value === null) return undefined;
|
|
1160
1213
|
const record = value as { group?: unknown; label?: unknown; color?: unknown; round?: unknown };
|
|
@@ -1351,6 +1404,7 @@ function toRow(entry: DispatchBoardEntry, now: number): DispatchBoardRow {
|
|
|
1351
1404
|
runtimeId: entry.runtimeId,
|
|
1352
1405
|
targetId: entry.targetId,
|
|
1353
1406
|
wireModelId: entry.wireModelId,
|
|
1407
|
+
...(entry.endpoint !== undefined ? { endpoint: { ...entry.endpoint } } : {}),
|
|
1354
1408
|
...(entry.taskSummary !== undefined ? { taskSummary: entry.taskSummary } : {}),
|
|
1355
1409
|
...(entry.budget !== undefined ? { budget: entry.budget } : {}),
|
|
1356
1410
|
status: retry ? "retrying" : entry.status,
|
|
@@ -1379,6 +1433,7 @@ function toRow(entry: DispatchBoardEntry, now: number): DispatchBoardRow {
|
|
|
1379
1433
|
recentTools: progress.recentActions.map((action) => action.tool),
|
|
1380
1434
|
...(retry ? { retry: { ...retry } } : {}),
|
|
1381
1435
|
...(entry.steerAcknowledgement ? { steerAcknowledgement: { ...entry.steerAcknowledgement } } : {}),
|
|
1436
|
+
...(entry.writeRecordDowngrade ? { writeRecordDowngrade: { ...entry.writeRecordDowngrade } } : {}),
|
|
1382
1437
|
};
|
|
1383
1438
|
}
|
|
1384
1439
|
|
|
@@ -1461,6 +1516,7 @@ export function createDispatchBoardStore(
|
|
|
1461
1516
|
const agentAudience = parseAgentAudience(raw.agentAudience, previous?.agentAudience);
|
|
1462
1517
|
const requestOrigin = parseRequestOrigin(raw.requestOrigin, previous?.requestOrigin);
|
|
1463
1518
|
const node = parseNonEmptyString(raw.node) ?? previous?.node;
|
|
1519
|
+
const endpoint = parseEndpointCapacity(raw.endpoint) ?? previous?.endpoint;
|
|
1464
1520
|
const gate = parseGateBadge(raw.gate) ?? previous?.gate;
|
|
1465
1521
|
const council = parseCouncilBadge(raw.council) ?? previous?.council;
|
|
1466
1522
|
const rerouteCount = parsePositiveInt(raw.rerouteCount) ?? previous?.rerouteCount;
|
|
@@ -1477,6 +1533,7 @@ export function createDispatchBoardStore(
|
|
|
1477
1533
|
runtimeId: parseText(raw.runtimeId, previous?.runtimeId ?? "-"),
|
|
1478
1534
|
targetId: parseText(raw.targetId, previous?.targetId ?? "-"),
|
|
1479
1535
|
wireModelId: parseText(raw.wireModelId, previous?.wireModelId ?? "-"),
|
|
1536
|
+
...(endpoint !== undefined ? { endpoint } : {}),
|
|
1480
1537
|
...(taskSummary !== undefined ? { taskSummary } : {}),
|
|
1481
1538
|
...(budget !== undefined ? { budget } : {}),
|
|
1482
1539
|
status,
|
|
@@ -1505,6 +1562,7 @@ export function createDispatchBoardStore(
|
|
|
1505
1562
|
progress: previous?.progress ?? createWorkerProgressFold(),
|
|
1506
1563
|
...(previous?.retry ? { retry: { ...previous.retry } } : {}),
|
|
1507
1564
|
...(previous?.steerAcknowledgement ? { steerAcknowledgement: { ...previous.steerAcknowledgement } } : {}),
|
|
1565
|
+
...(previous?.writeRecordDowngrade ? { writeRecordDowngrade: { ...previous.writeRecordDowngrade } } : {}),
|
|
1508
1566
|
};
|
|
1509
1567
|
entries.set(runId, entry);
|
|
1510
1568
|
pruneEntries(entries, (evicted) => fleetPhases.delete(evicted));
|
|
@@ -1654,6 +1712,20 @@ export function createDispatchBoardStore(
|
|
|
1654
1712
|
entry.ttftMs = Math.round(performance.now() - entry.startedAtClockMs);
|
|
1655
1713
|
}
|
|
1656
1714
|
}
|
|
1715
|
+
if (type === "clio_write_record_downgraded") {
|
|
1716
|
+
const rawPayload = (workerEvent as { payload?: unknown }).payload;
|
|
1717
|
+
const payload =
|
|
1718
|
+
typeof rawPayload === "object" && rawPayload !== null ? (rawPayload as Record<string, unknown>) : null;
|
|
1719
|
+
const tool = payload === null ? undefined : parseNonEmptyString(payload.tool);
|
|
1720
|
+
const toolCallId = payload === null ? undefined : parseNonEmptyString(payload.toolCallId);
|
|
1721
|
+
if (payload?.reason === "opaque_tool_succeeded" && tool !== undefined && toolCallId !== undefined) {
|
|
1722
|
+
entry.writeRecordDowngrade = {
|
|
1723
|
+
reason: "opaque_tool_succeeded",
|
|
1724
|
+
tool: sanitizeCallTargetText(tool),
|
|
1725
|
+
toolCallId: sanitizeCallTargetText(toolCallId),
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1657
1729
|
// The one fold that reads worker prose and tool activity. Everything the
|
|
1658
1730
|
// board says about what a worker is saying or touching comes from here,
|
|
1659
1731
|
// so the board and the transcript block cannot tell two stories.
|
|
@@ -26,7 +26,11 @@ import {
|
|
|
26
26
|
validateFleetGraph,
|
|
27
27
|
} from "../domains/agents/index.js";
|
|
28
28
|
import type { AgentSpec } from "../domains/agents/spec.js";
|
|
29
|
-
import
|
|
29
|
+
import {
|
|
30
|
+
bindExecutionPlanEndpoints,
|
|
31
|
+
type ExecutionPlan,
|
|
32
|
+
type ExecutionPlanStep,
|
|
33
|
+
} from "../domains/dispatch/execution-plan.js";
|
|
30
34
|
import {
|
|
31
35
|
type AgentRoleFactsResolver,
|
|
32
36
|
requestExecutionRole,
|
|
@@ -40,6 +44,7 @@ export interface FleetRunPreviewRoute {
|
|
|
40
44
|
targetId: string;
|
|
41
45
|
wireModelId: string;
|
|
42
46
|
nodeId: string;
|
|
47
|
+
endpoint?: { key: string; label: string; limit: number; foregroundHeld?: number };
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
export interface FleetRunPreviewStep {
|
|
@@ -207,6 +212,40 @@ export function compileFleetRunPreview(input: FleetRunPreviewInput): FleetRunPre
|
|
|
207
212
|
diagnostics.push(describeError(error));
|
|
208
213
|
return fail();
|
|
209
214
|
}
|
|
215
|
+
const routes = new Map<string, FleetRunPreviewRoute>();
|
|
216
|
+
if (input.resolveRoute !== undefined) {
|
|
217
|
+
for (const step of plan.steps) {
|
|
218
|
+
if (step.kind === "code") continue;
|
|
219
|
+
try {
|
|
220
|
+
const route = input.resolveRoute({
|
|
221
|
+
stepId: step.id,
|
|
222
|
+
agentId: step.agentId,
|
|
223
|
+
task: step.task,
|
|
224
|
+
scope: step.scope,
|
|
225
|
+
...(step.target !== undefined ? { target: step.target } : {}),
|
|
226
|
+
...(step.profile !== undefined ? { profile: step.profile } : {}),
|
|
227
|
+
});
|
|
228
|
+
if (route !== null) routes.set(step.id, route);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
diagnostics.push(`step '${step.id}' route preflight failed: ${describeError(error)}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
plan = bindExecutionPlanEndpoints(
|
|
234
|
+
plan,
|
|
235
|
+
Object.fromEntries(
|
|
236
|
+
[...routes].map(([stepId, route]) => [
|
|
237
|
+
stepId,
|
|
238
|
+
route.endpoint === undefined
|
|
239
|
+
? undefined
|
|
240
|
+
: {
|
|
241
|
+
key: route.endpoint.key,
|
|
242
|
+
limit: route.endpoint.limit,
|
|
243
|
+
...(route.endpoint.foregroundHeld !== undefined ? { foregroundHeld: route.endpoint.foregroundHeld } : {}),
|
|
244
|
+
},
|
|
245
|
+
]),
|
|
246
|
+
),
|
|
247
|
+
);
|
|
248
|
+
}
|
|
210
249
|
|
|
211
250
|
// A declared boundary is verified against the checkout, so the checkout has
|
|
212
251
|
// to be one this can read. Refused here, before any dispatch, rather than
|
|
@@ -261,20 +300,7 @@ export function compileFleetRunPreview(input: FleetRunPreviewInput): FleetRunPre
|
|
|
261
300
|
},
|
|
262
301
|
];
|
|
263
302
|
}
|
|
264
|
-
|
|
265
|
-
try {
|
|
266
|
-
route =
|
|
267
|
-
input.resolveRoute?.({
|
|
268
|
-
stepId: step.id,
|
|
269
|
-
agentId: step.agentId,
|
|
270
|
-
task: step.task,
|
|
271
|
-
scope: step.scope,
|
|
272
|
-
...(step.target !== undefined ? { target: step.target } : {}),
|
|
273
|
-
...(step.profile !== undefined ? { profile: step.profile } : {}),
|
|
274
|
-
}) ?? null;
|
|
275
|
-
} catch (error) {
|
|
276
|
-
diagnostics.push(`step '${step.id}' route preflight failed: ${describeError(error)}`);
|
|
277
|
-
}
|
|
303
|
+
const route = routes.get(step.id) ?? null;
|
|
278
304
|
return [
|
|
279
305
|
{
|
|
280
306
|
...base,
|
|
@@ -34,6 +34,22 @@ export const HANDOFF_SYSTEM_PROMPT = [
|
|
|
34
34
|
/** A handoff record is a list of short entries, so the budget is modest. */
|
|
35
35
|
export const HANDOFF_MAX_TOKENS = 4096;
|
|
36
36
|
|
|
37
|
+
/** The name the wire dialect gives the schema, where it takes one. */
|
|
38
|
+
export const HANDOFF_SCHEMA_NAME = "handoff_record";
|
|
39
|
+
|
|
40
|
+
/** Characters of the refused answer quoted back to the model in the repair round. */
|
|
41
|
+
export const HANDOFF_REPAIR_QUOTE_CHARS = 600;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* What the first round returned and why the parser refused it. The repair round
|
|
45
|
+
* shows the model both, because "return one JSON object" repeated verbatim is
|
|
46
|
+
* the instruction it already failed (issue #223).
|
|
47
|
+
*/
|
|
48
|
+
export interface HandoffRepairInput {
|
|
49
|
+
complaint: string;
|
|
50
|
+
previous: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
37
53
|
export interface HandoffRoundInput {
|
|
38
54
|
model: EngineModel;
|
|
39
55
|
/** Read-only. The round copies before appending its own message. */
|
|
@@ -42,15 +58,38 @@ export interface HandoffRoundInput {
|
|
|
42
58
|
apiKey?: string;
|
|
43
59
|
signal?: AbortSignal;
|
|
44
60
|
maxTokens?: number;
|
|
61
|
+
/** Resolved runtime id, which decides whether the schema can be bound on the wire. */
|
|
62
|
+
runtimeId?: string;
|
|
63
|
+
/** Set on the second and last round, after the parser refused the first. */
|
|
64
|
+
repair?: HandoffRepairInput;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function repairText(goal: string, repair: HandoffRepairInput): string {
|
|
68
|
+
const quoted = repair.previous.slice(0, HANDOFF_REPAIR_QUOTE_CHARS);
|
|
69
|
+
return [
|
|
70
|
+
`The next session's goal is: ${goal}`,
|
|
71
|
+
"",
|
|
72
|
+
"Your previous answer could not be read as a handoff record.",
|
|
73
|
+
`The parser said: ${repair.complaint}`,
|
|
74
|
+
"This is what you returned, verbatim:",
|
|
75
|
+
"---",
|
|
76
|
+
quoted.length > 0 ? quoted : "(nothing)",
|
|
77
|
+
"---",
|
|
78
|
+
"Answer again with one JSON object matching the schema and nothing else.",
|
|
79
|
+
"No prose before it, no prose after it, no code fence.",
|
|
80
|
+
].join("\n");
|
|
45
81
|
}
|
|
46
82
|
|
|
47
83
|
/** Run the round. Provider failures reject; the caller renders the reason. */
|
|
48
84
|
export async function runHandoffRound(input: HandoffRoundInput): Promise<SideQuestionResult> {
|
|
49
|
-
const { goal, ...rest } = input;
|
|
85
|
+
const { goal, repair, ...rest } = input;
|
|
50
86
|
return runOutOfTurnRound({
|
|
51
87
|
...rest,
|
|
52
88
|
maxTokens: input.maxTokens ?? HANDOFF_MAX_TOKENS,
|
|
53
89
|
systemPrompt: HANDOFF_SYSTEM_PROMPT,
|
|
54
|
-
|
|
90
|
+
responseSchema: { name: HANDOFF_SCHEMA_NAME, schema: HANDOFF_RESPONSE_SCHEMA },
|
|
91
|
+
userText: repair
|
|
92
|
+
? repairText(goal, repair)
|
|
93
|
+
: `The next session's goal is: ${goal}\n\nExtract the handoff record for that goal now.`,
|
|
55
94
|
});
|
|
56
95
|
}
|
|
@@ -3,6 +3,7 @@ import type { ClioSettings } from "../core/config.js";
|
|
|
3
3
|
import type { SafeEventBus } from "../core/event-bus.js";
|
|
4
4
|
import { expandInlineFileReferencesAsync } from "../core/file-references.js";
|
|
5
5
|
import type { PendingSkillRequest } from "../core/skill-activation.js";
|
|
6
|
+
import { clioStateDir } from "../core/xdg.js";
|
|
6
7
|
import type { AgentsContract } from "../domains/agents/contract.js";
|
|
7
8
|
import type { ClioKeybinding } from "../domains/config/keybindings.js";
|
|
8
9
|
import type { ContextState } from "../domains/context/index.js";
|
|
@@ -41,6 +42,7 @@ import { createInteractiveSubscriptions } from "./interactive-subscriptions.js";
|
|
|
41
42
|
import { createInteractiveTickers } from "./interactive-tickers.js";
|
|
42
43
|
import { createOverlayLifecycle, type OverlayLifecycleController, type OverlayState } from "./overlay-lifecycle.js";
|
|
43
44
|
import { interopOverlaySurface } from "./overlays/interop.js";
|
|
45
|
+
import { writeInputWedgeDump } from "./render-trace.js";
|
|
44
46
|
import { settleChatBeforeSessionSwitch } from "./session-switch-settlement.js";
|
|
45
47
|
import { createSessionTranscript } from "./session-transcript.js";
|
|
46
48
|
import type {
|
|
@@ -429,6 +431,21 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
429
431
|
});
|
|
430
432
|
const { terminal, tui } = shell;
|
|
431
433
|
const renderTrace = getActiveRenderTrace();
|
|
434
|
+
// SIGTERM is the kill an operator reaches for when a pane stops answering, so
|
|
435
|
+
// it is where the always-on input-wedge ring has to land (#224). It writes
|
|
436
|
+
// synchronously from its own listener rather than from a termination hook: a
|
|
437
|
+
// session wedged badly enough to be killed may never reach the coordinator's
|
|
438
|
+
// asynchronous drain, and this dump has to survive that.
|
|
439
|
+
const dumpInputWedgeOnTerminate = renderTrace
|
|
440
|
+
? (): void => {
|
|
441
|
+
try {
|
|
442
|
+
writeInputWedgeDump(clioStateDir(), renderTrace.snapshotInputWedge());
|
|
443
|
+
} catch {
|
|
444
|
+
// Best effort. The process is ending either way.
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
: null;
|
|
448
|
+
if (dumpInputWedgeOnTerminate) process.on("SIGTERM", dumpInputWedgeOnTerminate);
|
|
432
449
|
const visibleEventIngress = new WeakMap<
|
|
433
450
|
object,
|
|
434
451
|
{ sequence: number; traceSequence: number; generation: number; ingressAt: number }
|
|
@@ -498,6 +515,11 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
498
515
|
getLeaderArmed: () => leaderArmed,
|
|
499
516
|
getShutdownArmed: () => shutdownArmed,
|
|
500
517
|
isAwaitingApproval: () => overlayLifecycle?.getState() === "permission-confirm",
|
|
518
|
+
getPermissionInspection: () => {
|
|
519
|
+
if (overlayLifecycle === undefined || overlayLifecycle === null) return "none";
|
|
520
|
+
if (!overlayLifecycle.canInspectMutation()) return "none";
|
|
521
|
+
return overlayLifecycle.isInspectingMutation() ? "open" : "closed";
|
|
522
|
+
},
|
|
501
523
|
resolveVisibleEventSequence: (event) => visibleEventIngress.get(event)?.traceSequence ?? null,
|
|
502
524
|
resolveStreamIngress: (event) => visibleEventIngress.get(event) ?? null,
|
|
503
525
|
commitFrame: (reason) => shell.commitCurrentFrame(reason === "teardown" ? 300 : 30_000),
|
|
@@ -618,7 +640,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
618
640
|
chat: deps.chat,
|
|
619
641
|
chatPanel: {
|
|
620
642
|
appendReplayBlock: (...args) => chatRenderer.mutate(() => chatPanel.appendReplayBlock(...args), "slash-output"),
|
|
621
|
-
appendUser: (text) => chatRenderer.mutate(() => chatPanel.appendUser(text), "user-submit"),
|
|
643
|
+
appendUser: (text, status) => chatRenderer.mutate(() => chatPanel.appendUser(text, status), "user-submit"),
|
|
622
644
|
clearFoldOverrides: () => chatRenderer.mutate(() => chatPanel.clearFoldOverrides(), "output-detail"),
|
|
623
645
|
},
|
|
624
646
|
beforeSemanticSubmit: () => chatRenderer.flush(),
|
|
@@ -949,6 +971,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
949
971
|
cancelParkedCalls: (reason) => deps.toolRegistry?.cancelParkedCalls(reason),
|
|
950
972
|
onShutdown: async () => {
|
|
951
973
|
try {
|
|
974
|
+
if (dumpInputWedgeOnTerminate) process.off("SIGTERM", dumpInputWedgeOnTerminate);
|
|
952
975
|
await deps.onShutdown();
|
|
953
976
|
} finally {
|
|
954
977
|
if (lease) await lease.close();
|
|
@@ -60,6 +60,10 @@ export interface InteractiveInputRuntimeDeps {
|
|
|
60
60
|
closeOverlay(): void;
|
|
61
61
|
confirmPermission(): void;
|
|
62
62
|
stopTurnFromPermission(): void;
|
|
63
|
+
canInspectMutation(): boolean;
|
|
64
|
+
isInspectingMutation(): boolean;
|
|
65
|
+
toggleMutationInspection(): void;
|
|
66
|
+
scrollMutationInspection(delta: number): void;
|
|
63
67
|
cancelAskUser(): void;
|
|
64
68
|
toggleFooterDashboardState(): void;
|
|
65
69
|
toggleDispatchBoardOverlay(): void;
|
|
@@ -213,6 +217,10 @@ export function createInteractiveInputRuntime(deps: InteractiveInputRuntimeDeps)
|
|
|
213
217
|
confirmPermission: () => deps.overlay.confirmPermission(),
|
|
214
218
|
stopTurnFromPermission: () => deps.overlay.stopTurnFromPermission(),
|
|
215
219
|
composerHasDraft: () => deps.editor.getText().length > 0,
|
|
220
|
+
canInspectMutation: () => deps.overlay.canInspectMutation(),
|
|
221
|
+
isInspectingMutation: () => deps.overlay.isInspectingMutation(),
|
|
222
|
+
toggleMutationInspection: () => deps.overlay.toggleMutationInspection(),
|
|
223
|
+
scrollMutationInspection: (delta) => deps.overlay.scrollMutationInspection(delta),
|
|
216
224
|
editDraft: (data) => {
|
|
217
225
|
deps.editor.handleInput?.(data);
|
|
218
226
|
deps.requestRender();
|
|
@@ -99,6 +99,8 @@ export interface InteractivePresentationDeps {
|
|
|
99
99
|
getShutdownArmed?: () => boolean;
|
|
100
100
|
/** Whether a permission prompt owns the keyboard, for the composer's CONFIRM rail. */
|
|
101
101
|
isAwaitingApproval?: () => boolean;
|
|
102
|
+
/** Whether that prompt has a mutation to inspect, and whether it is open (issue #254). */
|
|
103
|
+
getPermissionInspection?: () => import("./permission-hint.js").PermissionInspectionHint;
|
|
102
104
|
getCwd?: () => string;
|
|
103
105
|
resolveVisibleEventSequence?: (event: ChatLoopEvent) => number | null;
|
|
104
106
|
resolveStreamIngress?: (
|
|
@@ -418,6 +420,8 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
|
|
|
418
420
|
},
|
|
419
421
|
isStreaming: () => deps.chat.isStreaming(),
|
|
420
422
|
...(deps.isAwaitingApproval ? { isAwaitingApproval: deps.isAwaitingApproval } : {}),
|
|
423
|
+
...(deps.getPermissionInspection ? { getPermissionInspection: deps.getPermissionInspection } : {}),
|
|
424
|
+
getTurnPreparation: () => deps.chat.turnPreparation().phase,
|
|
421
425
|
willEnterSteer: (text) => willEnterSteerActiveWork(deps, text),
|
|
422
426
|
getSubmitKeyLabel: () => formatKeyLabel(keybindings.getKeys("tui.input.submit")[0], "Enter"),
|
|
423
427
|
getNewlineKeyLabel: () => formatKeyLabel(keybindings.getKeys("tui.input.newLine")[0], "Shift+Enter"),
|
|
@@ -158,9 +158,11 @@ export function createInteractiveShell<TTerminal extends Terminal, TTui extends
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
/**
|
|
161
|
-
* Trace for the current process, created once
|
|
162
|
-
*
|
|
163
|
-
*
|
|
161
|
+
* Trace for the current process, created once per interactive shell. It writes
|
|
162
|
+
* a JSONL file when CLIO_CODER_RENDER_TRACE names one and otherwise keeps only
|
|
163
|
+
* its bounded input-wedge ring in memory. The panel wires its render metrics
|
|
164
|
+
* into the same instance, so the frame rows carry both the build cost and the
|
|
165
|
+
* write cost.
|
|
164
166
|
*/
|
|
165
167
|
let activeRenderTrace: RenderTrace | null = null;
|
|
166
168
|
|
|
@@ -203,20 +205,21 @@ export function createProcessInteractiveShell(
|
|
|
203
205
|
let restoreRoot: (() => void) | null = null;
|
|
204
206
|
let backpressure: StdoutBackpressureGate | null = null;
|
|
205
207
|
let observedBackpressure = false;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
|
|
208
|
+
let candidate: RenderTrace | null = null;
|
|
209
|
+
try {
|
|
210
|
+
// A null path is the ring-only mode: no file, but the input-wedge ring still
|
|
211
|
+
// fills, because the operator who hits a wedge did not arm a trace before it
|
|
212
|
+
// happened (#224).
|
|
213
|
+
candidate = createRenderTrace(tracePath);
|
|
214
|
+
restoreStdout = traceProcessStdout(candidate);
|
|
215
|
+
activeRenderTrace = candidate;
|
|
216
|
+
} catch {
|
|
217
|
+
// A diagnostics path must never prevent the interactive application from starting.
|
|
218
|
+
restoreStdout?.();
|
|
219
|
+
restoreStdout = null;
|
|
220
|
+
void candidate?.close().catch(() => {});
|
|
221
|
+
activeRenderTrace = null;
|
|
222
|
+
}
|
|
220
223
|
const trace = activeRenderTrace;
|
|
221
224
|
if (trace && options.onFirstFrameCommit) trace.onFirstFrameCommit(options.onFirstFrameCommit);
|
|
222
225
|
let firstFrameDelivered = false;
|
|
@@ -62,6 +62,7 @@ export interface InteractiveSlashSubmitExpansion {
|
|
|
62
62
|
|
|
63
63
|
type SlashChat = Pick<ChatLoop, "getSessionId" | "isStreaming" | "submit">;
|
|
64
64
|
type SlashChatPanel = Pick<ChatPanel, "appendReplayBlock" | "appendUser" | "clearFoldOverrides">;
|
|
65
|
+
type UserTurnStatus = import("./chat-panel.js").UserTurnStatus;
|
|
65
66
|
type SlashResources = Pick<ResourcesContract, "prompts" | "expandPromptTemplate" | "reload">;
|
|
66
67
|
type SlashExtensions = Pick<ExtensionsContract, "list">;
|
|
67
68
|
type SlashAgents = Pick<AgentsContract, "getSpec" | "listSpecs">;
|
|
@@ -245,9 +246,13 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
|
|
|
245
246
|
const willQueue = deps.chat.isStreaming();
|
|
246
247
|
deps.recordSubmittedTurn();
|
|
247
248
|
deps.refreshFooter();
|
|
248
|
-
|
|
249
|
+
// The row is painted now, so the operator sees their prompt land, but
|
|
250
|
+
// it is marked pending until the durable append at admission: nothing
|
|
251
|
+
// is in the ledger yet, and a refused preflight must not leave a row
|
|
252
|
+
// that reads like a committed turn (issue #251).
|
|
253
|
+
let rowStatus: UserTurnStatus = "pending";
|
|
254
|
+
if (!willQueue) deps.chatPanel.appendUser(sub.text, () => rowStatus);
|
|
249
255
|
deps.requestRender();
|
|
250
|
-
deps.beforeSemanticSubmit?.();
|
|
251
256
|
let acknowledgeAdmission = (): void => {};
|
|
252
257
|
const admitted = new Promise<void>((resolve) => {
|
|
253
258
|
acknowledgeAdmission = resolve;
|
|
@@ -257,7 +262,19 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
|
|
|
257
262
|
...(sub.workingContextPaths.length > 0 ? { workingContextPaths: sub.workingContextPaths } : {}),
|
|
258
263
|
...(sub.pendingSkillRequests.length > 0 ? { pendingSkillRequests: sub.pendingSkillRequests } : {}),
|
|
259
264
|
...(awaitAdmission && willQueue ? { steering: "end-of-turn" as const } : {}),
|
|
260
|
-
...(
|
|
265
|
+
...(!willQueue
|
|
266
|
+
? {
|
|
267
|
+
onPreparationVisible: async () => {
|
|
268
|
+
deps.beforeSemanticSubmit?.();
|
|
269
|
+
await deps.settleVisibleFrame?.("submit-preparing");
|
|
270
|
+
},
|
|
271
|
+
}
|
|
272
|
+
: {}),
|
|
273
|
+
onAdmitted: () => {
|
|
274
|
+
rowStatus = "committed";
|
|
275
|
+
deps.requestRender();
|
|
276
|
+
if (awaitAdmission) acknowledgeAdmission();
|
|
277
|
+
},
|
|
261
278
|
});
|
|
262
279
|
const settlement = turn
|
|
263
280
|
.then(() => deps.settleVisibleFrame?.("submit-return"))
|
|
@@ -265,7 +282,13 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
|
|
|
265
282
|
const msg = err instanceof Error ? err.message : String(err);
|
|
266
283
|
deps.io.stderr(`[interactive] chat failed: ${msg}\n`);
|
|
267
284
|
})
|
|
268
|
-
.finally(
|
|
285
|
+
.finally(() => {
|
|
286
|
+
// Settlement without admission is a refusal: the probe failed, the
|
|
287
|
+
// overflow preflight blocked the request, or the submit became a
|
|
288
|
+
// steer. Say so on the row rather than leaving a phantom turn.
|
|
289
|
+
if (rowStatus === "pending") rowStatus = willQueue ? "committed" : "refused";
|
|
290
|
+
deps.requestRender();
|
|
291
|
+
});
|
|
269
292
|
return awaitAdmission ? Promise.race([admitted, settlement]) : settlement;
|
|
270
293
|
} catch (err) {
|
|
271
294
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
describeTaskMemoryActivity,
|
|
3
|
+
formatTaskMemorySpend,
|
|
3
4
|
type MemoryProposalResult,
|
|
4
5
|
type MemoryRecord,
|
|
5
6
|
type TaskMemoryActivityEvent,
|
|
@@ -38,6 +39,12 @@ export function formatMemoryStatusLine(status: TaskMemoryOperatorStatus, content
|
|
|
38
39
|
theme.fg("muted", `last ${status.lastDecision ?? "none"}`),
|
|
39
40
|
];
|
|
40
41
|
if (status.stepInFlight) units.push(theme.fg("reason", "step running"));
|
|
42
|
+
// Lifetime cost of the background plane, beside the state of the current
|
|
43
|
+
// session. The tier spent 137,205 tokens over 14 days on the operator's own
|
|
44
|
+
// machine before any surface said so (#229), and a hit rate is the one figure
|
|
45
|
+
// that says whether that spend is buying anything.
|
|
46
|
+
const spend = status.spend === null || status.spend === undefined ? "" : formatTaskMemorySpend(status.spend);
|
|
47
|
+
if (spend.length > 0) units.push(theme.fg("dim", spend));
|
|
41
48
|
return fitUnits(theme, "", units, width);
|
|
42
49
|
}
|
|
43
50
|
|
|
@@ -172,6 +179,7 @@ function memorySignature(status: TaskMemoryOperatorStatus, records: ReadonlyArra
|
|
|
172
179
|
String(status.size),
|
|
173
180
|
status.lastDecision ?? "none",
|
|
174
181
|
status.stepInFlight ? "running" : "idle",
|
|
182
|
+
`${status.spend?.llmSteps ?? 0}:${status.spend?.injections ?? 0}:${status.spend?.totalTokens ?? 0}`,
|
|
175
183
|
];
|
|
176
184
|
for (const record of records) parts.push(`r:${record.id}:${record.approved}:${record.rejectedAt ?? ""}`);
|
|
177
185
|
for (const entry of bankEntries(status.bank)) {
|