@iowarp/clio-coder 0.3.3 → 0.3.6
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 +74 -0
- package/CONTRIBUTING.md +7 -7
- package/README.md +3 -3
- package/dist/{acp-P2AQILE2.js → acp-2BEHC4DL.js} +9 -8
- package/dist/{agents-72W3BI7I.js → agents-LNNFTM53.js} +29 -24
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-5TWEIYDN.js → auth-KXXFI2VS.js} +14 -10
- package/dist/{chunk-GGXXDWE4.js → chunk-22NAGB7X.js} +2 -2
- package/dist/{chunk-YCWGATWI.js → chunk-24I7BN55.js} +2 -2
- package/dist/{chunk-EKMEHE4H.js → chunk-33YXPOE3.js} +2 -3
- package/dist/chunk-3BPUFZDL.js +37 -0
- package/dist/chunk-43AOLP7E.js +375 -0
- package/dist/{chunk-ZDOOVTXZ.js → chunk-4OC57DA6.js} +27 -4
- package/dist/{chunk-6SGHMWE3.js → chunk-5JGRAMKL.js} +5 -5
- package/dist/{chunk-V6RTAOC2.js → chunk-6US73PDB.js} +572 -51
- package/dist/{chunk-5UFT4SUX.js → chunk-6XXKFVSN.js} +3 -3
- package/dist/{chunk-A3CYT5EX.js → chunk-AD2SYQYC.js} +55 -2
- package/dist/chunk-AOCYTWAV.js +449 -0
- package/dist/chunk-CFGTUFWB.js +67 -0
- package/dist/chunk-CJUB2JJ2.js +1478 -0
- package/dist/{chunk-FNTMWMX5.js → chunk-CKXWIANG.js} +14 -12
- package/dist/{chunk-PIWWS5BL.js → chunk-CYQKWTG3.js} +63 -78
- package/dist/{chunk-LZSJBIVT.js → chunk-DJVECN66.js} +271 -762
- package/dist/{chunk-CBCAPZAA.js → chunk-E25LMLRW.js} +2 -2
- package/dist/{chunk-ZWMF7253.js → chunk-E2ER4LJF.js} +304 -9
- package/dist/{chunk-STBPMHSX.js → chunk-EKY57CSP.js} +51 -84
- package/dist/{chunk-DUYJ5IO6.js → chunk-EYPA3EGJ.js} +12 -4
- package/dist/{chunk-M6SHUN7Q.js → chunk-FO5ZOVUY.js} +2 -2
- package/dist/chunk-FYYLNIL5.js +313 -0
- package/dist/{chunk-OQ33BKR3.js → chunk-G7MUEIGA.js} +3 -60
- package/dist/chunk-GEYXPTRF.js +613 -0
- package/dist/chunk-GOXNB3AO.js +261 -0
- package/dist/{chunk-G4BMMOKF.js → chunk-HVDIIIQW.js} +2 -2
- package/dist/chunk-HWUFFB6L.js +83 -0
- package/dist/{chunk-4XUGQOHA.js → chunk-K7T3E2SR.js} +15 -8
- package/dist/chunk-K7VKOLQQ.js +15 -0
- package/dist/{chunk-UFIIWP2H.js → chunk-KHSFENX2.js} +8 -8
- package/dist/{chunk-BMEMKKIT.js → chunk-KOHPCX4K.js} +2 -2
- package/dist/chunk-LCGCVYZ4.js +57 -0
- package/dist/chunk-LL4KHSZI.js +22 -0
- package/dist/{chunk-PAJK6MAQ.js → chunk-LYF7OHWH.js} +42 -15
- package/dist/{chunk-POHLU5DW.js → chunk-M6L6IDJG.js} +3 -3
- package/dist/{chunk-5UUP6MWO.js → chunk-MV3K5QF2.js} +5 -436
- package/dist/{chunk-X4RCMKVQ.js → chunk-NDINPTJ4.js} +2 -2
- package/dist/{chunk-TZK7PACC.js → chunk-NILBFAPG.js} +14 -8
- package/dist/chunk-ODFEOB4F.js +1082 -0
- package/dist/{chunk-AGYYIBLL.js → chunk-OH3TOQTB.js} +6 -2
- package/dist/chunk-OZNBF4L3.js +23 -0
- package/dist/{chunk-DSELYM6W.js → chunk-PBTHKCPN.js} +30 -10
- package/dist/{verify-375KUB3Y.js → chunk-PCZJO5TI.js} +127 -42
- package/dist/{chunk-ED4KHGC3.js → chunk-PPAMZ32Z.js} +9 -2
- package/dist/{chunk-SRDMMSEP.js → chunk-QM3F2GKX.js} +1063 -1645
- package/dist/{chunk-X6IAEBZR.js → chunk-QNQHSOLF.js} +7 -7
- package/dist/{chunk-OC7FIQPC.js → chunk-R46L2BIR.js} +10 -7
- package/dist/{chunk-2TLUCQVG.js → chunk-RD5U66HV.js} +3 -3
- package/dist/{chunk-6N5PTWMY.js → chunk-RY3LY4J5.js} +50 -13
- package/dist/{chunk-OKGUZO2U.js → chunk-SPULKLCF.js} +4 -3
- package/dist/{chunk-OOJYHWRB.js → chunk-TSHXZTOQ.js} +6 -5
- package/dist/chunk-TZSKNMZG.js +434 -0
- package/dist/{chunk-7MNJORFF.js → chunk-UL3WSD3F.js} +6 -1
- package/dist/{chunk-VJWL6YS5.js → chunk-UUVG37B4.js} +2 -2
- package/dist/{chunk-COU2UHX6.js → chunk-VEZEGCGW.js} +170 -2
- package/dist/chunk-W6GROXXM.js +69 -0
- package/dist/{chunk-OAO4GE4M.js → chunk-WHGPSPT5.js} +2 -2
- package/dist/chunk-WHJYKASB.js +677 -0
- package/dist/{chunk-ORBHGJC5.js → chunk-WR67VIZY.js} +3 -3
- package/dist/{chunk-YHZX5GEU.js → chunk-XAKHZX5N.js} +2 -2
- package/dist/{chunk-TZTZS7QK.js → chunk-XE2VEJHX.js} +5 -3
- package/dist/{chunk-LM5TQCJZ.js → chunk-XF5N4U5A.js} +8 -7
- package/dist/{chunk-LWLEKMDQ.js → chunk-XXQNGV4M.js} +1073 -552
- package/dist/{chunk-KZWTDYJF.js → chunk-XYDYPRZI.js} +7 -7
- package/dist/chunk-ZGVHUX3M.js +66 -0
- package/dist/{chunk-LW6DSM3M.js → chunk-ZRGEBJ4T.js} +1192 -1119
- package/dist/{chunk-2DJ2KNFG.js → chunk-ZXF4XRKW.js} +202 -40
- package/dist/chunk-ZZMN5OM4.js +122 -0
- package/dist/cli/index.js +34 -30
- package/dist/{clio-JOU4FXVA.js → clio-M2KGYUFZ.js} +7 -6
- package/dist/{code-nav-7AX6FYE6.js → code-nav-GQNL7XA6.js} +8 -6
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-KELWS457.js → components-5TTYYX6G.js} +3 -3
- package/dist/{config-XCDVKR23.js → config-XUUYQIWO.js} +47 -35
- package/dist/{configure-4GAP54ZW.js → configure-IHJ7YOMV.js} +18 -15
- package/dist/{context-77FM5DV5.js → context-74JLXAWD.js} +18 -10
- package/dist/{context-4UOGGLQ5.js → context-75MIWW3U.js} +41 -29
- package/dist/{context-5VKGUVJJ.js → context-ZQ7SIFJV.js} +85 -9
- package/dist/{context-clear-XXJRLCJJ.js → context-clear-GYKWNUML.js} +41 -29
- package/dist/{context-index-BZ4UYMTC.js → context-index-SSR5ECNE.js} +3 -3
- package/dist/context-working-set-UX5KEP4J.js +1553 -0
- package/dist/{dispatch-runner-QPRDDBDX.js → dispatch-runner-GIJBHNFL.js} +47 -32
- package/dist/{docs-2C2LTVT2.js → docs-6FZSCG5B.js} +3 -3
- package/dist/{doctor-HR46URBJ.js → doctor-SVJ5BZCW.js} +12 -12
- package/dist/{eval-XSSNATB4.js → eval-CG6LLBLD.js} +54 -238
- package/dist/{evidence-6HG2PY2B.js → evidence-ZYFIEN42.js} +57 -28
- package/dist/{evolve-K7YU3NCY.js → evolve-QGEXEMDW.js} +36 -25
- package/dist/{extensions-QVDOHDGJ.js → extensions-ADGNCJJD.js} +3 -3
- package/dist/{fleet-VY3HHKN6.js → fleet-S5R4ZOQY.js} +73 -44
- package/dist/{fleet-preflight-DDN536IT.js → fleet-preflight-BHSNPBMH.js} +3 -3
- package/dist/{init-JYGXI3FK.js → init-5DRU55YR.js} +49 -37
- package/dist/memory-7YKKR6UC.js +467 -0
- package/dist/{models-I5QWSEOM.js → models-ZPOLRU2C.js} +24 -21
- package/dist/{monitor-GE4ID3IA.js → monitor-US5F5YGZ.js} +73 -46
- package/dist/{orchestrator-EM5MC3HM.js → orchestrator-E2AL4T5N.js} +1624 -1007
- package/dist/{paths-UXLN5YYZ.js → paths-E7KYAQWE.js} +3 -3
- package/dist/{reset-L2FQEE3E.js → reset-KZ652EK6.js} +6 -5
- package/dist/{run-ZU3QMZPZ.js → run-SRNBKDWD.js} +76 -54
- package/dist/{share-S5BZQC5I.js → share-CGZE33UP.js} +7 -6
- package/dist/{skills-X5VXCRNQ.js → skills-S2X4DLY5.js} +4 -4
- package/dist/{skills-eval-WKIHWTHR.js → skills-eval-W2GGIC4R.js} +40 -29
- package/dist/{targets-SNCPI2NR.js → targets-54SWINWB.js} +28 -23
- package/dist/{terminal-lease-BNAHVHBS.js → terminal-lease-SAIF2OGY.js} +6 -4
- package/dist/{uninstall-FZCQCDKC.js → uninstall-BVLWXKBT.js} +3 -3
- package/dist/{upgrade-JQHHPQ4K.js → upgrade-JKAR27XC.js} +20 -19
- package/dist/{usage-OR4O5SMZ.js → usage-MSAWCLX4.js} +79 -36
- package/dist/verifiers-NCBTHHN2.js +1220 -0
- package/dist/verify-X5HDROLA.js +25 -0
- package/dist/{wiki-generate-UEXP2ARI.js → wiki-generate-GUSOQ6ZP.js} +50 -37
- package/dist/worker/entry.js +90 -70
- package/dist/{workspace-G4ZWUIPR.js → workspace-ZJ6BFM3Q.js} +4 -4
- package/docs/README.md +8 -7
- package/docs/acp.md +1 -1
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/artifact-placement.md +1 -2
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +60 -26
- package/docs/config-knobs-audit.md +1 -2
- package/docs/configuration-and-targets.md +26 -1
- package/docs/context-engine.md +67 -13
- package/docs/context-working-set.md +194 -0
- package/docs/development-pipeline.md +1 -1
- package/docs/documentation-coverage.md +6 -6
- package/docs/documentation-guide.md +7 -6
- package/docs/environment-variables.md +2 -1
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +4 -32
- package/docs/evidence-and-memory.md +139 -7
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +1 -1
- package/docs/extensions-and-sharing.md +2 -2
- package/docs/fleet-dispatch.md +49 -8
- package/docs/glossary.md +21 -1
- package/docs/installation-and-lifecycle.md +2 -2
- package/docs/middleware-and-components.md +19 -2
- package/docs/model-catalog.md +7 -9
- package/docs/observability.md +4 -4
- package/docs/proactive-memory.md +26 -16
- package/docs/prompt-envelope-and-tools.md +7 -5
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +43 -40
- package/docs/safety-model.md +49 -8
- package/docs/scientific-validation.md +21 -3
- package/docs/session-lifecycle.md +3 -3
- package/docs/skills-marketplace.md +1 -1
- package/docs/tool-usage.md +79 -12
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +38 -4
- package/docs/worker-dispatch-mechanics.md +11 -1
- package/package.json +13 -13
- package/skills/meta/clio-test/SKILL.md +20 -17
- package/skills/meta/clio-test/evals.md +3 -3
- package/skills/meta/clio-test/references/harness.md +35 -6
- package/skills/meta/clio-test/references/test-map.md +20 -10
- package/skills/registry.yaml +2 -2
- package/skills/skill-marketplace.json +1 -1
- package/src/cli/agents.ts +2 -3
- package/src/cli/argv.ts +14 -1
- package/src/cli/context-working-set.ts +513 -0
- package/src/cli/context.ts +8 -0
- package/src/cli/evidence.ts +20 -2
- package/src/cli/fleet.ts +15 -0
- package/src/cli/index.ts +5 -1
- package/src/cli/memory.ts +272 -10
- package/src/cli/modes/json-stream.ts +2 -2
- package/src/cli/modes/print.ts +12 -1
- package/src/cli/run.ts +22 -2
- package/src/cli/targets.ts +12 -3
- package/src/cli/usage.ts +55 -7
- package/src/cli/verifiers.ts +325 -0
- package/src/core/bash-exec.ts +39 -14
- package/src/core/bus-events.ts +22 -4
- package/src/core/config.ts +54 -0
- package/src/core/defaults.ts +50 -3
- package/src/core/response-model-id.ts +134 -0
- package/src/core/toml.ts +62 -0
- package/src/core/verification-scripts.ts +6 -0
- package/src/core/workspace-files.ts +0 -1
- package/src/domains/agents/builtins/architect.md +1 -1
- package/src/domains/agents/builtins/verifier.md +3 -0
- package/src/domains/agents/catalog.ts +5 -4
- package/src/domains/agents/recipe.ts +54 -14
- package/src/domains/agents/result-contract.ts +7 -4
- package/src/domains/config/classify.ts +1 -0
- package/src/domains/context/bootstrap.ts +36 -27
- package/src/domains/context/project-metadata.ts +19 -63
- package/src/domains/context/prompt-context.ts +8 -0
- package/src/domains/context/working-set/contract.ts +161 -0
- package/src/domains/context/working-set/defaults.ts +28 -0
- package/src/domains/context/working-set/engine.ts +203 -0
- package/src/domains/context/working-set/fold.ts +62 -0
- package/src/domains/context/working-set/horizon.ts +38 -0
- package/src/domains/context/working-set/marker.ts +103 -0
- package/src/domains/context/working-set/path-index.ts +436 -0
- package/src/domains/context/working-set/payload.ts +152 -0
- package/src/domains/context/working-set/policies/age-horizon.ts +55 -0
- package/src/domains/context/working-set/policies/index.ts +20 -0
- package/src/domains/context/working-set/policies/structural.ts +160 -0
- package/src/domains/context/working-set/project.ts +132 -0
- package/src/domains/context/working-set/protect.ts +109 -0
- package/src/domains/context/working-set/recall.ts +177 -0
- package/src/domains/context/working-set/replay/controls.ts +112 -0
- package/src/domains/context/working-set/replay/load-clio.ts +199 -0
- package/src/domains/context/working-set/replay/metrics.ts +185 -0
- package/src/domains/context/working-set/replay/reference-graph.ts +79 -0
- package/src/domains/context/working-set/replay/report.ts +139 -0
- package/src/domains/context/working-set/replay/runner.ts +325 -0
- package/src/domains/context/working-set/replay/synthetic.ts +422 -0
- package/src/domains/context/working-set/replay/trace.ts +21 -0
- package/src/domains/context/working-set/visible.ts +54 -0
- package/src/domains/dispatch/budget-envelope.ts +396 -0
- package/src/domains/dispatch/contract.ts +2 -0
- package/src/domains/dispatch/extension.ts +81 -27
- package/src/domains/dispatch/orphan-recovery.ts +1 -0
- package/src/domains/dispatch/receipt-integrity.ts +4 -0
- package/src/domains/dispatch/state.ts +1 -0
- package/src/domains/dispatch/types.ts +10 -3
- package/src/domains/dispatch/validation.ts +14 -0
- package/src/domains/dispatch/worker-spawn.ts +14 -3
- package/src/domains/eval/metrics/evidence.ts +0 -116
- package/src/domains/eval/metrics/invariants.ts +1 -1
- package/src/domains/eval/runners/clio-run.ts +1 -10
- package/src/domains/eval/runners/external-command.ts +2 -29
- package/src/domains/eval/schema/suite.ts +0 -7
- package/src/domains/eval/suites/run.ts +1 -7
- package/src/domains/evidence/build.ts +112 -45
- package/src/domains/evidence/eval.ts +24 -7
- package/src/domains/evidence/index.ts +53 -0
- package/src/domains/evidence/ordering.ts +12 -0
- package/src/domains/evidence/run-trust.ts +221 -0
- package/src/domains/evidence/store.ts +46 -6
- package/src/domains/evidence/trust-status.ts +854 -0
- package/src/domains/evidence/types.ts +26 -0
- package/src/domains/memory/index.ts +22 -0
- package/src/domains/memory/operations.ts +58 -1
- package/src/domains/memory/promotion.ts +281 -0
- package/src/domains/memory/prompt-section.ts +25 -5
- package/src/domains/memory/proposal.ts +51 -7
- package/src/domains/memory/task-bank.ts +3 -2
- package/src/domains/memory/task-memory-handoff.ts +181 -24
- package/src/domains/memory/task-memory-policy.ts +3 -1
- package/src/domains/memory/types.ts +37 -0
- package/src/domains/memory/validate.ts +178 -0
- package/src/domains/middleware/memory-intervention.ts +38 -25
- package/src/domains/middleware/runtime.ts +6 -0
- package/src/domains/middleware/skills-reminder.ts +19 -4
- package/src/domains/middleware/stalled-turn.ts +208 -5
- package/src/domains/middleware/types.ts +10 -0
- package/src/domains/observability/contract.ts +6 -1
- package/src/domains/observability/cost.ts +20 -4
- package/src/domains/observability/extension.ts +2 -2
- package/src/domains/providers/index.ts +3 -0
- package/src/domains/providers/model-discovery.ts +9 -0
- package/src/domains/providers/runtime-resolution.ts +38 -1
- package/src/domains/providers/runtimes/common/probe-helpers.ts +97 -16
- package/src/domains/providers/types/context-window-slots.ts +18 -0
- package/src/domains/providers/types/runtime-descriptor.ts +3 -1
- package/src/domains/safety/autonomy.ts +1 -1
- package/src/domains/safety/call-target.ts +211 -14
- package/src/domains/safety/decision-presentation.ts +268 -0
- package/src/domains/safety/default-path-policy.ts +8 -0
- package/src/domains/safety/finish-contract.ts +4 -3
- package/src/domains/safety/policy-engine.ts +48 -6
- package/src/domains/safety/redaction.ts +73 -0
- package/src/domains/session/compaction/compact.ts +23 -1
- package/src/domains/session/compaction/cut-point.ts +2 -0
- package/src/domains/session/compaction/tokens.ts +16 -1
- package/src/domains/session/context-ledger.ts +12 -1
- package/src/domains/session/decision-board.ts +4 -0
- package/src/domains/session/entries.ts +110 -1
- package/src/domains/session/history.ts +68 -19
- package/src/domains/session/manager.ts +9 -2
- package/src/domains/session/migrations/index.ts +22 -3
- package/src/domains/session/usage.ts +24 -7
- package/src/engine/acp/event-mapper.ts +7 -0
- package/src/engine/acp/server.ts +32 -2
- package/src/engine/agent.ts +18 -1
- package/src/engine/apis/lmstudio.ts +25 -4
- package/src/engine/apis/openai-completions.ts +147 -22
- package/src/engine/claude/sdk-runtime.ts +8 -2
- package/src/engine/claude/tool-safety.ts +13 -0
- package/src/engine/loop-guard.ts +27 -3
- package/src/engine/session.ts +9 -3
- package/src/engine/worker-events.ts +4 -3
- package/src/engine/worker-runtime.ts +59 -54
- package/src/entry/orchestrator.ts +34 -5
- package/src/interactive/chat-loop-messages.ts +40 -6
- package/src/interactive/chat-loop.ts +13 -0
- package/src/interactive/chat-panel.ts +17 -1
- package/src/interactive/chat-renderer.ts +49 -24
- package/src/interactive/clio-editor.ts +44 -7
- package/src/interactive/context-meter.ts +10 -0
- package/src/interactive/context-overlay.ts +120 -7
- package/src/interactive/context-recall-command.ts +110 -0
- package/src/interactive/cost-overlay.ts +39 -8
- package/src/interactive/dispatch-board.ts +212 -35
- package/src/interactive/footer/widgets.ts +13 -0
- package/src/interactive/interactive-application.ts +6 -1
- package/src/interactive/interactive-input-runtime.ts +11 -1
- package/src/interactive/interactive-presentation.ts +11 -1
- package/src/interactive/interactive-slash-runtime.ts +37 -1
- package/src/interactive/memory-overlay.ts +89 -4
- package/src/interactive/model-session-replay.ts +21 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +1 -1
- package/src/interactive/overlay-frame.ts +5 -2
- package/src/interactive/overlay-general-openers.ts +46 -1
- package/src/interactive/overlay-key-routing.ts +41 -1
- package/src/interactive/overlay-lifecycle.ts +11 -4
- package/src/interactive/overlay-permission-lifecycle.ts +23 -8
- package/src/interactive/overlay-session-lifecycle.ts +8 -4
- package/src/interactive/overlay-transitions.ts +11 -0
- package/src/interactive/overlays/ask-user.ts +74 -30
- package/src/interactive/overlays/decisions.ts +3 -1
- package/src/interactive/permission-hint.ts +35 -0
- package/src/interactive/permission-overlay.ts +95 -45
- package/src/interactive/renderers/tool-execution.ts +37 -51
- package/src/interactive/session-last-turn.ts +8 -1
- package/src/interactive/session-transcript.ts +2 -2
- package/src/interactive/session-usage-reseed.ts +36 -10
- package/src/interactive/slash-commands.ts +31 -4
- package/src/interactive/status/summary.ts +5 -0
- package/src/interactive/status/types.ts +5 -0
- package/src/interactive/terminal-lease.ts +1 -0
- package/src/interactive/turn-context.ts +333 -110
- package/src/interactive/turn-middleware.ts +7 -6
- package/src/interactive/turn-runtime.ts +37 -8
- package/src/interactive/turn-state.ts +3 -0
- package/src/interactive/worker-progress.ts +440 -0
- package/src/interactive/worker-stream.ts +51 -110
- package/src/tools/agent-tools.ts +39 -7
- package/src/tools/ask-user.ts +21 -1
- package/src/tools/bash.ts +144 -82
- package/src/tools/builtin-tool-catalog.ts +11 -5
- package/src/tools/context/index.ts +107 -5
- package/src/tools/context/surface.ts +3 -2
- package/src/tools/core-bootstrap.ts +21 -0
- package/src/tools/dispatch-arguments.ts +8 -0
- package/src/tools/dispatch-event-text.ts +19 -0
- package/src/tools/dispatch-runner.ts +9 -7
- package/src/tools/dispatch.ts +24 -1
- package/src/tools/monitor.ts +43 -20
- package/src/tools/registry.ts +72 -10
- package/src/tools/result-disposition.ts +706 -0
- package/src/tools/result-shaping.ts +321 -20
- package/src/tools/safe-exec.ts +2 -0
- package/src/tools/verify/authoring.ts +1120 -0
- package/src/tools/verify/catalog.ts +346 -0
- package/src/tools/verify/index.ts +13 -3
- package/src/tools/verify/scripts.ts +135 -37
- package/src/tools/verify/surface.ts +9 -5
- package/src/tools/worker-evidence.ts +54 -12
- package/src/worker/spec-contract.ts +43 -3
- package/dist/chunk-J7CWMCQD.js +0 -255
- package/dist/chunk-T6YILFSB.js +0 -80
- package/dist/chunk-VAKQQHWR.js +0 -434
- package/dist/chunk-VPAYEGVX.js +0 -184
- package/dist/chunk-XBXAASKX.js +0 -18
- package/dist/memory-WFZMGYHX.js +0 -236
- package/src/domains/eval/metrics/chaos-stream.ts +0 -93
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
9
|
import { settingsPath } from "../core/config.js";
|
|
10
|
+
import {
|
|
11
|
+
addResponseModelIdObservationCount,
|
|
12
|
+
emptyResponseModelIdObservationCounts,
|
|
13
|
+
type ResponseModelIdObservation,
|
|
14
|
+
type ResponseModelIdObservationCounts,
|
|
15
|
+
responseModelIdObservationFromRecord,
|
|
16
|
+
} from "../core/response-model-id.js";
|
|
10
17
|
import type { PendingSkillRequest, PendingSkillToolPolicy, SkillDeclaredToolPolicy } from "../core/skill-activation.js";
|
|
11
18
|
import { ToolNames } from "../core/tool-names.js";
|
|
12
19
|
import { canonicalJson, sha256 } from "../domains/prompts/hash.js";
|
|
@@ -334,6 +341,7 @@ export function createAskUserToolPolicy(activeTools: ReadonlyArray<{ name: strin
|
|
|
334
341
|
status: "idle",
|
|
335
342
|
startedAt: now,
|
|
336
343
|
updatedAt: now,
|
|
344
|
+
exposure: "local",
|
|
337
345
|
rounds: [],
|
|
338
346
|
decisions: [],
|
|
339
347
|
inFlight: false,
|
|
@@ -356,6 +364,9 @@ export interface RunUsageSummary {
|
|
|
356
364
|
apiCalls: number;
|
|
357
365
|
hadReasoning: boolean;
|
|
358
366
|
hadUsage: boolean;
|
|
367
|
+
responseModelIdObservationCounts: ResponseModelIdObservationCounts;
|
|
368
|
+
lastResponseModelIdObservation: ResponseModelIdObservation;
|
|
369
|
+
lastDifferingResponseModelId: string | null;
|
|
359
370
|
}
|
|
360
371
|
|
|
361
372
|
/**
|
|
@@ -380,6 +391,9 @@ export function sumRunUsage(messages: ReadonlyArray<AgentMessage>): RunUsageSumm
|
|
|
380
391
|
apiCalls: 0,
|
|
381
392
|
hadReasoning: false,
|
|
382
393
|
hadUsage: false,
|
|
394
|
+
responseModelIdObservationCounts: emptyResponseModelIdObservationCounts(),
|
|
395
|
+
lastResponseModelIdObservation: { state: "not-observed" },
|
|
396
|
+
lastDifferingResponseModelId: null,
|
|
383
397
|
};
|
|
384
398
|
for (const raw of messages) {
|
|
385
399
|
const message = raw as
|
|
@@ -397,8 +411,15 @@ export function sumRunUsage(messages: ReadonlyArray<AgentMessage>): RunUsageSumm
|
|
|
397
411
|
};
|
|
398
412
|
if (!message || typeof message !== "object") continue;
|
|
399
413
|
if (message.role !== "assistant") continue;
|
|
414
|
+
const record = message as unknown as Record<string, unknown>;
|
|
400
415
|
const usage = message.usage;
|
|
401
416
|
if (!usage || typeof usage !== "object") continue;
|
|
417
|
+
summary.lastResponseModelIdObservation = responseModelIdObservationFromRecord(record, "not-observed");
|
|
418
|
+
addResponseModelIdObservationCount(summary.responseModelIdObservationCounts, summary.lastResponseModelIdObservation);
|
|
419
|
+
summary.lastDifferingResponseModelId =
|
|
420
|
+
typeof record.responseModel === "string" && record.responseModel.trim().length > 0
|
|
421
|
+
? record.responseModel.trim()
|
|
422
|
+
: null;
|
|
402
423
|
summary.hadUsage = true;
|
|
403
424
|
summary.apiCalls += 1;
|
|
404
425
|
const input = typeof usage.input === "number" ? usage.input : 0;
|
|
@@ -459,6 +480,7 @@ export function assistantSessionPayload(
|
|
|
459
480
|
const raw = message as unknown as Record<string, unknown>;
|
|
460
481
|
if (Array.isArray(raw.content)) payload.content = raw.content;
|
|
461
482
|
if (thinking.length > 0) payload.thinking = thinking;
|
|
483
|
+
payload.responseModelIdObservation = responseModelIdObservationFromRecord(raw, "not-observed");
|
|
462
484
|
for (const key of ["usage", "api", "provider", "model", "responseModel", "responseId", "diagnostics"]) {
|
|
463
485
|
if (raw[key] !== undefined) payload[key] = raw[key];
|
|
464
486
|
}
|
|
@@ -555,21 +577,33 @@ export function toolResultSummary(result: unknown): Record<string, unknown> {
|
|
|
555
577
|
const bytes = Buffer.byteLength(text, "utf8");
|
|
556
578
|
const details = recordValue(obj?.details);
|
|
557
579
|
const size = recordValue(details?.resultSize);
|
|
580
|
+
const disposition = recordValue(details?.resultDisposition);
|
|
558
581
|
const truncation = recordValue(details?.truncation);
|
|
559
582
|
const observation = recordValue(details?.observation);
|
|
560
583
|
const offloadPath =
|
|
561
|
-
typeof
|
|
562
|
-
?
|
|
563
|
-
: typeof
|
|
564
|
-
?
|
|
565
|
-
:
|
|
584
|
+
typeof disposition?.offloadPath === "string"
|
|
585
|
+
? disposition.offloadPath
|
|
586
|
+
: typeof observation?.offloadPath === "string"
|
|
587
|
+
? observation.offloadPath
|
|
588
|
+
: typeof size?.offloadPath === "string"
|
|
589
|
+
? size.offloadPath
|
|
590
|
+
: null;
|
|
591
|
+
const displayedBytes =
|
|
592
|
+
typeof disposition?.displayedBytes === "number" && Number.isFinite(disposition.displayedBytes)
|
|
593
|
+
? disposition.displayedBytes
|
|
594
|
+
: bytes;
|
|
566
595
|
return {
|
|
567
|
-
bytes,
|
|
596
|
+
bytes: displayedBytes,
|
|
568
597
|
truncated:
|
|
598
|
+
disposition?.presentationTruncated === true ||
|
|
569
599
|
size?.truncated === true ||
|
|
570
600
|
truncation?.truncated === true ||
|
|
571
601
|
observation?.truncated === true ||
|
|
572
602
|
text.includes("[tool result truncated]"),
|
|
603
|
+
...(typeof disposition?.capturedBytes === "number" ? { capturedBytes: disposition.capturedBytes } : {}),
|
|
604
|
+
...(typeof disposition?.displayedBytes === "number" ? { displayedBytes: disposition.displayedBytes } : {}),
|
|
605
|
+
...(typeof disposition?.contextBytes === "number" ? { contextBytes: disposition.contextBytes } : {}),
|
|
606
|
+
...(disposition?.contextTruncated === true ? { contextTruncated: true } : {}),
|
|
573
607
|
...(typeof size?.policy === "string" ? { policy: size.policy } : {}),
|
|
574
608
|
...(typeof size?.followUpHint === "string" ? { followUpHint: size.followUpHint } : {}),
|
|
575
609
|
...(offloadPath !== null ? { offloadPath } : {}),
|
|
@@ -549,6 +549,12 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
|
|
|
549
549
|
emitNotice,
|
|
550
550
|
toolStartTimes,
|
|
551
551
|
});
|
|
552
|
+
// A fresh ledger and footer render before the first submit. Start the same
|
|
553
|
+
// live capability probe that submit and resume use so those boot surfaces
|
|
554
|
+
// refresh to the probed model window as soon as provider discovery lands.
|
|
555
|
+
// The turn runtime coalesces the first submit onto this request, then its
|
|
556
|
+
// target and model TTL keeps later submits from repeating it.
|
|
557
|
+
void turnRuntime.ensureLiveCapabilitiesForSelectedModel().catch(() => {});
|
|
552
558
|
|
|
553
559
|
// --- bus subscriptions --------------------------------------------------
|
|
554
560
|
|
|
@@ -664,6 +670,7 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
|
|
|
664
670
|
// 1. Accept the prompt: reset per-turn accounting, freeze the tool
|
|
665
671
|
// surface, fire turn_start, and assemble the submitted text.
|
|
666
672
|
state.turnToolCalls = 0;
|
|
673
|
+
state.turnToolNames = [];
|
|
667
674
|
state.turnSharedWorkerNote = isWorkerShareNote(text);
|
|
668
675
|
middlewareToolChoice.reset();
|
|
669
676
|
if (options.requestContinuation !== true) state.stalledTurnNudgeSpent = false;
|
|
@@ -988,6 +995,12 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
|
|
|
988
995
|
middlewareToolChoice.reset();
|
|
989
996
|
state.lastTurnId = leafTurnId;
|
|
990
997
|
context.resetForSession();
|
|
998
|
+
// The resumed ledger renders before the first new turn (issue #189),
|
|
999
|
+
// and the window it renders against should be the probed one rather
|
|
1000
|
+
// than the catalog's, so the live capability probe the first submit
|
|
1001
|
+
// would run runs now, under the same TTL; the footer refreshes on the
|
|
1002
|
+
// provider-health event the probe publishes.
|
|
1003
|
+
void turnRuntime.ensureLiveCapabilitiesForSelectedModel().catch(() => {});
|
|
991
1004
|
state.replayedContextMessages = replayMessages ? [...replayMessages] : [];
|
|
992
1005
|
if (state.runtime) {
|
|
993
1006
|
state.runtime.agent.state.messages = [...state.replayedContextMessages];
|
|
@@ -5,6 +5,7 @@ import { rawDurationMs } from "../core/timers.js";
|
|
|
5
5
|
import { type Component, Markdown, truncateToWidth, wrapTextWithAnsi } from "../engine/tui.js";
|
|
6
6
|
import type { AgentMessage } from "../engine/types.js";
|
|
7
7
|
import { toolPresentationPolicy } from "../tools/presentation.js";
|
|
8
|
+
import { toolResultPresentationPolicy } from "../tools/result-disposition.js";
|
|
8
9
|
import type { ChatLoopEvent, RetryStatusPayload } from "./chat-loop.js";
|
|
9
10
|
import { extractText, isSelfExplainingAbort } from "./chat-loop-messages.js";
|
|
10
11
|
import type { ApprovalRequestView } from "./permission-overlay.js";
|
|
@@ -202,6 +203,12 @@ type ToolSegment = {
|
|
|
202
203
|
* was refused and leaves the operator no way to learn why.
|
|
203
204
|
*/
|
|
204
205
|
blockReason?: string | undefined;
|
|
206
|
+
/**
|
|
207
|
+
* Working-set eviction reason for a replayed result whose body the
|
|
208
|
+
* projection has replaced. Set only on rehydrate, from the folded ledger;
|
|
209
|
+
* a live call is never evicted while it is still being rendered.
|
|
210
|
+
*/
|
|
211
|
+
evictedReason?: string | undefined;
|
|
205
212
|
/** View-only marker: historical calls render mutation diffs without live color. */
|
|
206
213
|
replayed?: true;
|
|
207
214
|
};
|
|
@@ -835,7 +842,7 @@ function styleStatusVerb(text: string, toneHint: VerbRender["toneHint"]): string
|
|
|
835
842
|
function policySegmentFold(seg: ToolSegment, detail: TranscriptDetailPolicy): Fold {
|
|
836
843
|
if (!seg.finished) return policyRunningToolFold(detail);
|
|
837
844
|
if (seg.isError && detail.errors === "body") return "expanded";
|
|
838
|
-
return policyToolFold(detail, toolPresentationPolicy(seg.name, seg.args));
|
|
845
|
+
return policyToolFold(detail, toolResultPresentationPolicy(seg.result) ?? toolPresentationPolicy(seg.name, seg.args));
|
|
839
846
|
}
|
|
840
847
|
|
|
841
848
|
/** Effective state of a tool segment: the operator's override, else the policy. */
|
|
@@ -884,6 +891,7 @@ function renderToolSegmentLines(
|
|
|
884
891
|
resultSummary: seg.resultSummary,
|
|
885
892
|
outcome: seg.settlement,
|
|
886
893
|
blockReason: seg.blockReason,
|
|
894
|
+
evictedReason: seg.evictedReason,
|
|
887
895
|
}
|
|
888
896
|
: { toolCallId: seg.id, toolName: seg.name, args: seg.args, elapsedMs, phase },
|
|
889
897
|
width,
|
|
@@ -916,6 +924,7 @@ function renderToolSegmentLines(
|
|
|
916
924
|
resultSummary: seg.resultSummary,
|
|
917
925
|
outcome: seg.settlement,
|
|
918
926
|
blockReason: seg.blockReason,
|
|
927
|
+
evictedReason: seg.evictedReason,
|
|
919
928
|
},
|
|
920
929
|
width,
|
|
921
930
|
{ unbounded: unboundedToolBodies, diffStyle: seg.replayed === true ? "plain" : "color" },
|
|
@@ -1936,7 +1945,14 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1936
1945
|
resultSummary?: unknown;
|
|
1937
1946
|
outcome?: unknown;
|
|
1938
1947
|
blockReason?: unknown;
|
|
1948
|
+
evictedReason?: unknown;
|
|
1939
1949
|
};
|
|
1950
|
+
// Replay-only: the rehydrator reads the working-set fold and tags
|
|
1951
|
+
// the rows whose bodies the projection has replaced for the model.
|
|
1952
|
+
tool.evictedReason =
|
|
1953
|
+
typeof enriched.evictedReason === "string" && enriched.evictedReason.length > 0
|
|
1954
|
+
? enriched.evictedReason
|
|
1955
|
+
: undefined;
|
|
1940
1956
|
// Settlement is that verdict, never an inference from result text.
|
|
1941
1957
|
// The text of a tool result is the tool's own output: `node --test`
|
|
1942
1958
|
// prints `cancelled 0` on every run and a linter can print
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
* `isTransparentAssistantWrapper`.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import { existsSync } from "node:fs";
|
|
16
17
|
import { ToolNames } from "../core/tool-names.js";
|
|
18
|
+
import { foldWorkingSet } from "../domains/context/working-set/fold.js";
|
|
19
|
+
import { compactionCut } from "../domains/context/working-set/visible.js";
|
|
17
20
|
import type {
|
|
18
21
|
BashExecutionEntry,
|
|
19
22
|
BranchSummaryEntry,
|
|
@@ -40,8 +43,9 @@ import {
|
|
|
40
43
|
import { wrapTextWithAnsi } from "../engine/tui.js";
|
|
41
44
|
import type { AgentMessage } from "../engine/types.js";
|
|
42
45
|
import { toolPresentationPolicy } from "../tools/presentation.js";
|
|
46
|
+
import { toolResultPresentationText } from "../tools/result-disposition.js";
|
|
43
47
|
import type { ChatLoopEvent, RetryStatusPayload } from "./chat-loop.js";
|
|
44
|
-
import { isSelfExplainingAbort } from "./chat-loop-messages.js";
|
|
48
|
+
import { isSelfExplainingAbort, toolResultSummary } from "./chat-loop-messages.js";
|
|
45
49
|
import type { ChatPanel } from "./chat-panel.js";
|
|
46
50
|
import { renderBranchSummaryEntry } from "./renderers/branch-summary.js";
|
|
47
51
|
import { renderCompactionSummaryEntry } from "./renderers/compaction-summary.js";
|
|
@@ -437,6 +441,7 @@ function richMessageFromEntry(entry: MessageEntry, maxTextChars?: number): Agent
|
|
|
437
441
|
"api",
|
|
438
442
|
"provider",
|
|
439
443
|
"model",
|
|
444
|
+
"responseModelIdObservation",
|
|
440
445
|
"responseModel",
|
|
441
446
|
"responseId",
|
|
442
447
|
"diagnostics",
|
|
@@ -482,7 +487,11 @@ function toolResultContent(result: unknown, unbounded = false): unknown[] {
|
|
|
482
487
|
}
|
|
483
488
|
|
|
484
489
|
function displayReplayToolResult(result: unknown, unbounded = false): unknown {
|
|
485
|
-
const
|
|
490
|
+
const presentationText = toolResultPresentationText(result);
|
|
491
|
+
const content =
|
|
492
|
+
presentationText === null
|
|
493
|
+
? toolResultContent(result, unbounded)
|
|
494
|
+
: [{ type: "text", text: unbounded ? presentationText : truncateReplayText(presentationText) }];
|
|
486
495
|
// Preserve the details record (observation envelope, exec records) so the
|
|
487
496
|
// replayed ledger line carries the same outcome facts as the live one.
|
|
488
497
|
const details = payloadObject(result)?.details;
|
|
@@ -664,6 +673,19 @@ interface ReplayToolResult {
|
|
|
664
673
|
blockReason?: string;
|
|
665
674
|
}
|
|
666
675
|
|
|
676
|
+
/**
|
|
677
|
+
* Resolve a replayed offload pointer once, when the ledger row becomes a
|
|
678
|
+
* display event. Terminal repaints consume the recorded fact and never touch
|
|
679
|
+
* the filesystem.
|
|
680
|
+
*/
|
|
681
|
+
function replayResultSummary(result: ReplayToolResult): Record<string, unknown> | undefined {
|
|
682
|
+
const summary = result.resultSummary ?? toolResultSummary(result.result);
|
|
683
|
+
const offloadPath =
|
|
684
|
+
typeof summary.offloadPath === "string" && summary.offloadPath.length > 0 ? summary.offloadPath : null;
|
|
685
|
+
if (offloadPath === null) return result.resultSummary;
|
|
686
|
+
return { ...summary, offloadFileMissing: !existsSync(offloadPath) };
|
|
687
|
+
}
|
|
688
|
+
|
|
667
689
|
function extractToolResult(entry: MessageEntry): ReplayToolResult {
|
|
668
690
|
const payload = entry.payload;
|
|
669
691
|
const obj = payloadObject(payload);
|
|
@@ -835,13 +857,6 @@ function truncateAtTurn(entries: ReadonlyArray<SessionEntry>, uptoTurnId?: strin
|
|
|
835
857
|
return entries.slice(0, index + 1);
|
|
836
858
|
}
|
|
837
859
|
|
|
838
|
-
function latestCompactionIndex(entries: ReadonlyArray<SessionEntry>): number {
|
|
839
|
-
for (let i = entries.length - 1; i >= 0; i--) {
|
|
840
|
-
if (entries[i]?.kind === "compactionSummary") return i;
|
|
841
|
-
}
|
|
842
|
-
return -1;
|
|
843
|
-
}
|
|
844
|
-
|
|
845
860
|
function toolCallIdsInEntry(entry: SessionEntry): string[] {
|
|
846
861
|
if (entry.kind !== "message") return [];
|
|
847
862
|
if (entry.role === "tool_call") return [extractToolCall(entry).id];
|
|
@@ -919,19 +934,13 @@ export function selectReplayEntries(
|
|
|
919
934
|
): SessionEntry[] {
|
|
920
935
|
const active = filterEntriesToActivePath(turns, options.activeLeafTurnId ?? options.uptoTurnId);
|
|
921
936
|
const entries = truncateAtTurn(active, options.uptoTurnId);
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
const
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
: -1;
|
|
930
|
-
if (firstKeptIndex >= 0 && firstKeptIndex < compactionIndex) {
|
|
931
|
-
selected.push(...entries.slice(firstKeptIndex, compactionIndex));
|
|
932
|
-
}
|
|
933
|
-
selected.push(...entries.slice(compactionIndex + 1));
|
|
934
|
-
return dropLegacyToolResultAssistantDuplicates(repairToolResultOrphans(entries, selected, compactionIndex));
|
|
937
|
+
// The cut itself is the working-set layer's definition of "what the model
|
|
938
|
+
// can see", shared with the eviction policy input so the two cannot drift.
|
|
939
|
+
const cut = compactionCut(entries);
|
|
940
|
+
if (cut.compactionIndex < 0) return dropLegacyToolResultAssistantDuplicates(entries);
|
|
941
|
+
const compaction = entries[cut.compactionIndex] as CompactionSummaryEntry;
|
|
942
|
+
const selected: SessionEntry[] = [compaction, ...cut.visible];
|
|
943
|
+
return dropLegacyToolResultAssistantDuplicates(repairToolResultOrphans(entries, selected, cut.compactionIndex));
|
|
935
944
|
}
|
|
936
945
|
|
|
937
946
|
function dropLegacyToolResultAssistantDuplicates(entries: ReadonlyArray<SessionEntry>): SessionEntry[] {
|
|
@@ -1043,6 +1052,11 @@ export function buildReplayAgentMessagesFromTurns(
|
|
|
1043
1052
|
// It reaches the model only when an operator shares it, and a share
|
|
1044
1053
|
// is already a user message by the time it lands in the ledger.
|
|
1045
1054
|
case "workerRun":
|
|
1055
|
+
// Working-set entries are folded into a view by the context domain
|
|
1056
|
+
// and applied as a projection before this builder runs; the
|
|
1057
|
+
// entries themselves never become messages.
|
|
1058
|
+
case "contextEviction":
|
|
1059
|
+
case "contextRecall":
|
|
1046
1060
|
break;
|
|
1047
1061
|
}
|
|
1048
1062
|
}
|
|
@@ -1080,6 +1094,11 @@ export function rehydrateChatPanelFromTurns(
|
|
|
1080
1094
|
const pendingToolIds: string[] = [];
|
|
1081
1095
|
let runAssistantMessages: AgentMessage[] = [];
|
|
1082
1096
|
const selected = selectReplayEntries(turns, options);
|
|
1097
|
+
// The transcript shows the ledger, never the projection: an evicted result
|
|
1098
|
+
// still renders its full body here, tagged with the reason it left the
|
|
1099
|
+
// model's working set. Folded once over the same active path the replay
|
|
1100
|
+
// uses, so a /tree switch cannot tag a row from an abandoned branch.
|
|
1101
|
+
const workingSet = foldWorkingSet(turns, options.activeLeafTurnId ?? options.uptoTurnId);
|
|
1083
1102
|
// One block per assignment, drawn where its first attempt started. Later
|
|
1084
1103
|
// attempts of the same assignment fold into that block as `↻` rail lines, so
|
|
1085
1104
|
// a failover replays as the one run it was rather than as two.
|
|
@@ -1127,6 +1146,8 @@ export function rehydrateChatPanelFromTurns(
|
|
|
1127
1146
|
}
|
|
1128
1147
|
if (entry.role === "tool_result") {
|
|
1129
1148
|
const result = extractToolResult(entry);
|
|
1149
|
+
const resultSummary = replayResultSummary(result);
|
|
1150
|
+
const evictedReason = workingSet.evicted.get(entry.turnId)?.reason;
|
|
1130
1151
|
const fallbackId = result.id ?? pendingToolIds.pop() ?? null;
|
|
1131
1152
|
if (fallbackId) {
|
|
1132
1153
|
const pendingIndex = pendingToolIds.indexOf(fallbackId);
|
|
@@ -1138,9 +1159,10 @@ export function rehydrateChatPanelFromTurns(
|
|
|
1138
1159
|
result: displayReplayToolResult(result.result, options.unboundedToolBodies === true),
|
|
1139
1160
|
isError: result.isError,
|
|
1140
1161
|
...(result.durationMs !== undefined ? { durationMs: result.durationMs } : {}),
|
|
1141
|
-
...(
|
|
1162
|
+
...(resultSummary !== undefined ? { resultSummary } : {}),
|
|
1142
1163
|
...(result.outcome !== undefined ? { outcome: result.outcome } : {}),
|
|
1143
1164
|
...(result.blockReason !== undefined ? { blockReason: result.blockReason } : {}),
|
|
1165
|
+
...(evictedReason !== undefined ? { evictedReason } : {}),
|
|
1144
1166
|
} as ChatLoopEvent);
|
|
1145
1167
|
} else {
|
|
1146
1168
|
chatPanel.appendReplayBlock((width) =>
|
|
@@ -1151,9 +1173,10 @@ export function rehydrateChatPanelFromTurns(
|
|
|
1151
1173
|
result: displayReplayToolResult(result.result, options.unboundedToolBodies === true),
|
|
1152
1174
|
isError: result.isError,
|
|
1153
1175
|
...(result.durationMs !== undefined ? { durationMs: result.durationMs } : {}),
|
|
1154
|
-
...(
|
|
1176
|
+
...(resultSummary !== undefined ? { resultSummary } : {}),
|
|
1155
1177
|
...(result.outcome === "blocked" ? { outcome: "blocked" as const } : {}),
|
|
1156
1178
|
...(result.blockReason !== undefined ? { blockReason: result.blockReason } : {}),
|
|
1179
|
+
...(evictedReason !== undefined ? { evictedReason } : {}),
|
|
1157
1180
|
},
|
|
1158
1181
|
width,
|
|
1159
1182
|
{ unbounded: options.unboundedToolBodies === true },
|
|
@@ -1239,6 +1262,8 @@ export function rehydrateChatPanelFromTurns(
|
|
|
1239
1262
|
case "label":
|
|
1240
1263
|
case "taskLedger":
|
|
1241
1264
|
case "decisionLedger":
|
|
1265
|
+
case "contextEviction":
|
|
1266
|
+
case "contextRecall":
|
|
1242
1267
|
break;
|
|
1243
1268
|
}
|
|
1244
1269
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { Editor, stripTerminalSequences, type TUI, truncateToWidth, visibleWidth } from "../engine/tui.js";
|
|
2
|
+
import { fitHintEntries } from "./overlay-frame.js";
|
|
3
|
+
import { permissionHintEntries } from "./permission-hint.js";
|
|
2
4
|
import type { ClioTheme } from "./theme/index.js";
|
|
3
5
|
import { clioTheme, editorTheme, GLYPH, rule } from "./theme/index.js";
|
|
4
6
|
|
|
5
7
|
const REVERSE_VIDEO_BLANK = `${String.fromCharCode(27)}[7m ${String.fromCharCode(27)}[0m`;
|
|
6
8
|
const EMPTY_PROMPT = "Ask Clio… / for commands";
|
|
9
|
+
const CONFIRM_PROMPT = "A parked call is waiting for your decision";
|
|
7
10
|
const MIN_HINT_WIDTH = 60;
|
|
8
11
|
|
|
9
12
|
function hasScrollIndicator(line: string): boolean {
|
|
@@ -18,6 +21,13 @@ export interface EditorChrome {
|
|
|
18
21
|
getThinkingLabel: () => string;
|
|
19
22
|
/** Whether Enter currently targets the active Clio response. */
|
|
20
23
|
isStreaming?: () => boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Whether a permission prompt owns the keyboard. The dialog once sat at the
|
|
26
|
+
* vertical center of a tall viewport, far from the composer. It now anchors
|
|
27
|
+
* above that composer, while the rail still says CONFIRM and carries the
|
|
28
|
+
* dialog's keys whenever the prompt owns input (issues #186 and #194).
|
|
29
|
+
*/
|
|
30
|
+
isAwaitingApproval?: () => boolean;
|
|
21
31
|
/** Whether the current draft will actually steer Clio or live dispatch work on Enter. */
|
|
22
32
|
willEnterSteer?: (text: string) => boolean;
|
|
23
33
|
/** Resolved submit binding, formatted for display. */
|
|
@@ -26,7 +36,7 @@ export interface EditorChrome {
|
|
|
26
36
|
getNewlineKeyLabel?: () => string;
|
|
27
37
|
}
|
|
28
38
|
|
|
29
|
-
type ComposerMode = "MESSAGE" | "FOLLOW-UP" | "STEER";
|
|
39
|
+
type ComposerMode = "MESSAGE" | "FOLLOW-UP" | "STEER" | "CONFIRM";
|
|
30
40
|
|
|
31
41
|
function normalizeThinkingHint(value: string): string {
|
|
32
42
|
return value
|
|
@@ -61,6 +71,7 @@ function styledRailLabel(theme: ClioTheme, chrome: EditorChrome): string {
|
|
|
61
71
|
}
|
|
62
72
|
|
|
63
73
|
function composerMode(chrome: EditorChrome, text: string): ComposerMode {
|
|
74
|
+
if (chrome.isAwaitingApproval?.() ?? false) return "CONFIRM";
|
|
64
75
|
if (!(chrome.isStreaming?.() ?? false)) return "MESSAGE";
|
|
65
76
|
const willSteer = chrome.willEnterSteer?.(text) ?? text.trim().length > 0;
|
|
66
77
|
return willSteer ? "STEER" : "FOLLOW-UP";
|
|
@@ -73,12 +84,27 @@ function lowerRailHint(theme: ClioTheme, chrome: EditorChrome): string {
|
|
|
73
84
|
);
|
|
74
85
|
}
|
|
75
86
|
|
|
76
|
-
|
|
87
|
+
/**
|
|
88
|
+
* The permission keys on the composer rail, fitted like the dialog footer so
|
|
89
|
+
* both surfaces narrow in the same order and never drop allow or stop first.
|
|
90
|
+
* The rule spends three columns around a right label, hence the subtraction.
|
|
91
|
+
*/
|
|
92
|
+
function confirmRailHint(theme: ClioTheme, width: number, hasDraft: boolean): string {
|
|
93
|
+
return theme.fg("warning", fitHintEntries(permissionHintEntries(hasDraft), Math.max(1, width - 3)));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function modeToken(mode: ComposerMode): "action" | "accentDeep" | "warning" {
|
|
97
|
+
if (mode === "STEER") return "action";
|
|
98
|
+
if (mode === "CONFIRM") return "warning";
|
|
99
|
+
return "accentDeep";
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function renderEmptyPrompt(line: string, width: number, theme: ClioTheme, text = EMPTY_PROMPT): string {
|
|
77
103
|
const cursorAt = line.indexOf(REVERSE_VIDEO_BLANK);
|
|
78
104
|
if (cursorAt < 0) return line;
|
|
79
105
|
const afterCursorAt = cursorAt + REVERSE_VIDEO_BLANK.length;
|
|
80
106
|
const available = Math.max(0, width - 1);
|
|
81
|
-
const prompt = truncateToWidth(theme.fg("dim",
|
|
107
|
+
const prompt = truncateToWidth(theme.fg("dim", text), available, "…", false);
|
|
82
108
|
const consumed = visibleWidth(prompt);
|
|
83
109
|
return `${line.slice(0, afterCursorAt)}${prompt}${line.slice(afterCursorAt + consumed)}`;
|
|
84
110
|
}
|
|
@@ -111,12 +137,12 @@ export class ClioEditor extends Editor {
|
|
|
111
137
|
// The base editor has already fitted the scroll indicator to this width.
|
|
112
138
|
// Prefix the mode and trim only the indicator rail's trailing fill, keeping
|
|
113
139
|
// its direction/count text and its own narrow-width fallback intact.
|
|
114
|
-
const modeLabel = theme.style(mode
|
|
140
|
+
const modeLabel = theme.style(modeToken(mode), mode, { bold: true });
|
|
115
141
|
lines[0] = truncateToWidth(`${modeLabel} ${lines[0] ?? ""}`, safeWidth, "", true);
|
|
116
142
|
} else {
|
|
117
143
|
lines[0] = rule(theme, safeWidth, {
|
|
118
144
|
left: mode,
|
|
119
|
-
leftToken: mode
|
|
145
|
+
leftToken: modeToken(mode),
|
|
120
146
|
right: styledRailLabel(theme, this.chrome),
|
|
121
147
|
fillToken: "frameStrong",
|
|
122
148
|
rightRaw: true,
|
|
@@ -124,10 +150,21 @@ export class ClioEditor extends Editor {
|
|
|
124
150
|
});
|
|
125
151
|
}
|
|
126
152
|
|
|
127
|
-
if (text.length === 0 && lines[1])
|
|
153
|
+
if (text.length === 0 && lines[1]) {
|
|
154
|
+
lines[1] = renderEmptyPrompt(lines[1], safeWidth, theme, mode === "CONFIRM" ? CONFIRM_PROMPT : EMPTY_PROMPT);
|
|
155
|
+
}
|
|
128
156
|
|
|
129
157
|
const bottomRail = findBottomRail(lines, safeWidth);
|
|
130
|
-
|
|
158
|
+
// The confirm keys render at every width: the send hint is a convenience
|
|
159
|
+
// that a narrow composer can drop, the allow and deny keys are not.
|
|
160
|
+
if (bottomRail >= 0 && mode === "CONFIRM") {
|
|
161
|
+
lines[bottomRail] = rule(theme, safeWidth, {
|
|
162
|
+
right: confirmRailHint(theme, safeWidth, text.length > 0),
|
|
163
|
+
fillToken: "frameStrong",
|
|
164
|
+
rightRaw: true,
|
|
165
|
+
rightTail: theme.style("frameStrong", "─", { bold: true }),
|
|
166
|
+
});
|
|
167
|
+
} else if (bottomRail >= 0 && safeWidth >= MIN_HINT_WIDTH) {
|
|
131
168
|
lines[bottomRail] = rule(theme, safeWidth, {
|
|
132
169
|
right: lowerRailHint(theme, this.chrome),
|
|
133
170
|
fillToken: "frameStrong",
|
|
@@ -156,6 +156,16 @@ export function renderContextMeterGrid(
|
|
|
156
156
|
return lines;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Evicted tokens live outside the window: the working-set projection removed
|
|
161
|
+
* them from what the model sees, so they are not a meter category and must
|
|
162
|
+
* not claim cells or a legend row. One line after the legend names them.
|
|
163
|
+
*/
|
|
164
|
+
export function renderEvictedTokensLine(evictedTokens: number, theme: ClioTheme = clioTheme()): string {
|
|
165
|
+
const tokens = Math.round(Math.max(0, evictedTokens)).toLocaleString("en-US");
|
|
166
|
+
return `${theme.fg("dim", GLYPH.contextReserve)} ${theme.fg("muted", "evicted (outside window)")} ${theme.fg("dim", `${tokens} tokens`)}`;
|
|
167
|
+
}
|
|
168
|
+
|
|
159
169
|
/** A small colored swatch for a category, for inline legends. */
|
|
160
170
|
export function contextCategorySwatch(category: ContextLedgerCategory, theme: ClioTheme = clioTheme()): string {
|
|
161
171
|
return theme.fg(CONTEXT_CATEGORY_TOKEN[category], contextCategoryGlyph(category));
|