@iowarp/clio-coder 0.3.4 → 0.3.7
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 +65 -2
- package/CONTRIBUTING.md +6 -6
- package/README.md +16 -5
- package/dist/{acp-S5R4RR5B.js → acp-SK4MD6MM.js} +11 -11
- package/dist/{agents-P6DMMVZY.js → agents-2FN2K6ME.js} +33 -26
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-2XCZLPKS.js → auth-QIYZWM5I.js} +15 -15
- package/dist/{chunk-EKMEHE4H.js → chunk-33YXPOE3.js} +2 -3
- package/dist/{chunk-VAWWTKDP.js → chunk-3HAPLH5M.js} +11 -11
- package/dist/{chunk-YCWGATWI.js → chunk-465YSENW.js} +3 -3
- package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
- package/dist/{chunk-UZHIZC5S.js → chunk-4DWFMQDR.js} +61 -76
- package/dist/{chunk-ZWMF7253.js → chunk-5C3AQNDW.js} +328 -9
- package/dist/{chunk-22NAGB7X.js → chunk-5C77SEEY.js} +5 -94
- package/dist/{chunk-WPQLXFOZ.js → chunk-5FR74PWO.js} +3 -2
- package/dist/{chunk-35MKKU5R.js → chunk-5UJ6ECTS.js} +18 -10
- package/dist/{chunk-BRXQQJFP.js → chunk-6M7VS3J3.js} +571 -50
- package/dist/{chunk-QQK64KLB.js → chunk-6TUKSZVF.js} +141 -23
- package/dist/{chunk-N4CZJQRK.js → chunk-AB4XIIVB.js} +8 -6
- package/dist/{chunk-KRPY7NTG.js → chunk-BMWK7ZIZ.js} +14 -20
- package/dist/{chunk-4BPJXDWC.js → chunk-C4JBQ5SR.js} +30 -14
- package/dist/{chunk-ZYKPLLNQ.js → chunk-CEYBNUGC.js} +821 -83
- package/dist/{chunk-VEZEGCGW.js → chunk-D4MDIG46.js} +20 -18
- package/dist/chunk-DJNLUABN.js +843 -0
- package/dist/{chunk-BP4OYD6A.js → chunk-DMD2AGVS.js} +21 -2
- package/dist/{chunk-KOHPCX4K.js → chunk-DOOEX22V.js} +2 -2
- package/dist/chunk-DQA7QLMD.js +123 -0
- package/dist/chunk-DR52UMZW.js +21 -0
- package/dist/{chunk-3HZ5RWN2.js → chunk-EBEFWSGL.js} +9 -7
- package/dist/{chunk-EDRHSCIE.js → chunk-EELBMBT6.js} +128 -13
- package/dist/{chunk-HV5X7OR2.js → chunk-EOOQZZDE.js} +16 -14
- package/dist/{chunk-WR67VIZY.js → chunk-FOT2FX5J.js} +63 -5
- package/dist/{chunk-BPGS2WCQ.js → chunk-GEYXPTRF.js} +2 -1
- package/dist/{chunk-FYYLNIL5.js → chunk-GH5622CP.js} +2 -2
- package/dist/{chunk-BEY543CS.js → chunk-GOXNB3AO.js} +5 -2
- package/dist/chunk-GWS3VEIW.js +195 -0
- package/dist/{chunk-G4BMMOKF.js → chunk-HVDIIIQW.js} +2 -2
- package/dist/chunk-HWUFFB6L.js +83 -0
- package/dist/{chunk-X6COSD2O.js → chunk-J7PIKKWC.js} +8 -436
- package/dist/{chunk-NILBFAPG.js → chunk-JNXPYBB4.js} +2 -2
- package/dist/{chunk-4VP4KH3K.js → chunk-JRIO5UD2.js} +4 -4
- package/dist/{chunk-K6WL7QZT.js → chunk-JTSEDYVQ.js} +7 -7
- package/dist/{chunk-QKMUKYO7.js → chunk-KCMKRQX4.js} +236 -84
- package/dist/chunk-KZ2H5X4G.js +1026 -0
- package/dist/{chunk-A2GZF7DC.js → chunk-LADCF22A.js} +13 -13
- package/dist/chunk-LCGCVYZ4.js +57 -0
- package/dist/chunk-M4AKACEO.js +382 -0
- package/dist/{chunk-POHLU5DW.js → chunk-M6L6IDJG.js} +3 -3
- package/dist/{chunk-4JUF2NNX.js → chunk-MXI6J5JF.js} +7 -7
- package/dist/{chunk-X4RCMKVQ.js → chunk-NDINPTJ4.js} +2 -2
- package/dist/{chunk-TTNYS3EA.js → chunk-OB5HIGJY.js} +1 -1
- package/dist/{chunk-7RXG6QRZ.js → chunk-OBMAI2DP.js} +61 -840
- package/dist/{chunk-5M54SPOL.js → chunk-ODFEOB4F.js} +161 -5
- package/dist/chunk-PD3MESLB.js +242 -0
- package/dist/{chunk-ED4KHGC3.js → chunk-PPAMZ32Z.js} +9 -2
- package/dist/{chunk-VMNQ6OZA.js → chunk-QCTRSGHQ.js} +963 -786
- package/dist/chunk-RVG5JXAL.js +41 -0
- package/dist/{chunk-RD5U66HV.js → chunk-SROCI7ZU.js} +7 -7
- package/dist/{chunk-MFFY33HR.js → chunk-THKY7CD7.js} +466 -205
- package/dist/{chunk-34475P3I.js → chunk-TSHXZTOQ.js} +5 -4
- package/dist/{chunk-PCZJO5TI.js → chunk-UFQ3F4FW.js} +13 -178
- package/dist/{chunk-AD2SYQYC.js → chunk-UHXRNZ2J.js} +121 -3
- package/dist/chunk-UND3GU2L.js +103 -0
- package/dist/{chunk-QQL5RT5M.js → chunk-UUANF5CR.js} +2323 -2114
- package/dist/{chunk-VJWL6YS5.js → chunk-UUVG37B4.js} +2 -2
- package/dist/chunk-UVDSQ6LW.js +472 -0
- package/dist/{chunk-QWU7ZBO7.js → chunk-VQNODYQ4.js} +215 -56
- package/dist/chunk-VREKEFLL.js +37 -0
- package/dist/{chunk-2TZWSW76.js → chunk-WHGPSPT5.js} +2 -2
- package/dist/{chunk-TW3WDMVS.js → chunk-WHJYKASB.js} +2 -2
- package/dist/{chunk-MEQ45TQ4.js → chunk-WJHBC77E.js} +21 -7
- package/dist/{chunk-HXG4IURW.js → chunk-X2KV5FXT.js} +2 -2
- package/dist/{chunk-YHZX5GEU.js → chunk-XAKHZX5N.js} +2 -2
- package/dist/{chunk-2LZI5CAG.js → chunk-XEGB6BCN.js} +228 -36
- package/dist/{chunk-E25LMLRW.js → chunk-YD734TPH.js} +2 -2
- package/dist/{verifiers-4UUM6TEE.js → chunk-YTYFXUI3.js} +121 -372
- package/dist/{chunk-3JLKSKD7.js → chunk-ZGH7FGS5.js} +17 -7
- package/dist/{chunk-VSNATDE6.js → chunk-ZZMN5OM4.js} +2 -2
- package/dist/cli/index.js +34 -32
- package/dist/{clio-J5JIOIDS.js → clio-WBVQEBKO.js} +7 -7
- package/dist/{code-nav-AXCXSBHX.js → code-nav-FGGFIE7L.js} +7 -7
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-KELWS457.js → components-F7OEATSO.js} +5 -5
- package/dist/{config-OEBMIN2U.js → config-TRBL3RCF.js} +48 -41
- package/dist/{configure-PUQOSIXQ.js → configure-OLCVPHNM.js} +17 -17
- package/dist/{context-URSXPBCK.js → context-MJIJ6GOX.js} +12 -12
- package/dist/{context-EKDCKUUZ.js → context-WFPKQSM6.js} +26 -9
- package/dist/{context-MGSE4Z2T.js → context-XEWE3MOJ.js} +44 -37
- package/dist/{context-clear-KDAJRNUK.js → context-clear-KNOS2JPB.js} +44 -37
- package/dist/{context-index-BZ4UYMTC.js → context-index-SSR5ECNE.js} +3 -3
- package/dist/{context-working-set-SBKMPPI2.js → context-working-set-EUXAZI6N.js} +14 -13
- package/dist/{dispatch-runner-MSWN72NK.js → dispatch-runner-B7MTOVKL.js} +321 -60
- package/dist/{docs-2C2LTVT2.js → docs-FLJTIDSE.js} +5 -5
- package/dist/{doctor-7BSE27PJ.js → doctor-RN4YKO2X.js} +15 -15
- package/dist/{eval-IZGDOO4H.js → eval-RUBJVSNQ.js} +52 -236
- package/dist/{evidence-SR7WXB5B.js → evidence-JZNBUOQZ.js} +39 -33
- package/dist/{evolve-K7VE2CBX.js → evolve-FJVC4KKI.js} +39 -33
- package/dist/{extensions-QVDOHDGJ.js → extensions-IQL36S7K.js} +5 -5
- package/dist/{fleet-7XMJNQNF.js → fleet-BDKYJFCP.js} +243 -370
- package/dist/fleet-commands-ZFIWZSB3.js +70 -0
- package/dist/fleet-graph-Y6HPXIVF.js +125 -0
- package/dist/fleet-new-RDVJLHHH.js +48 -0
- package/dist/{fleet-preflight-AQNAH644.js → fleet-preflight-BHSNPBMH.js} +2 -2
- package/dist/fleet-validate-BIYREGIK.js +79 -0
- package/dist/{init-JGNPAYXT.js → init-LQUB5COQ.js} +57 -48
- package/dist/library-NJAHIGG4.js +217 -0
- package/dist/memory-OG6HOYKM.js +472 -0
- package/dist/{models-ZMMLFJNN.js → models-5ZG5XY7J.js} +23 -22
- package/dist/{monitor-2F3T5KHP.js → monitor-TJ7AMTGB.js} +69 -35
- package/dist/{orchestrator-ORHT43JB.js → orchestrator-WZYB54DM.js} +4868 -1189
- package/dist/{paths-UXLN5YYZ.js → paths-XUC7GS6E.js} +5 -5
- package/dist/{reset-NXGTYNUO.js → reset-PXQT45IY.js} +8 -8
- package/dist/{run-RF4WJGMT.js → run-FQ74YF62.js} +82 -62
- package/dist/{share-UT3W6E4M.js → share-FW7SVCL3.js} +34 -10
- package/dist/{skills-PSACKC5Q.js → skills-7E7IRB3R.js} +25 -9
- package/dist/{skills-eval-WJSI55RZ.js → skills-eval-LI75W6OK.js} +43 -35
- package/dist/{targets-PIIRAOYS.js → targets-4CIFKCTW.js} +27 -24
- package/dist/{terminal-lease-ULWXWNVY.js → terminal-lease-WUZY7ZV5.js} +5 -4
- package/dist/{uninstall-FZCQCDKC.js → uninstall-7FV7IP4E.js} +5 -5
- package/dist/{upgrade-346TZ6AV.js → upgrade-K2HVIVMQ.js} +21 -20
- package/dist/{usage-6KKXR32N.js → usage-GTZELZQX.js} +159 -59
- package/dist/verifiers-RLAHT27O.js +336 -0
- package/dist/{verify-X5HDROLA.js → verify-BX3BRKH5.js} +7 -6
- package/dist/{wiki-generate-7STOCIFZ.js → wiki-generate-ASIFASCN.js} +58 -48
- package/dist/worker/entry.js +98 -84
- package/dist/{workspace-G4ZWUIPR.js → workspace-ZJ6BFM3Q.js} +4 -4
- package/docs/README.md +4 -3
- 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 +10 -6
- package/docs/built-in-agents.md +26 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +90 -8
- package/docs/configuration-and-targets.md +90 -2
- package/docs/context-engine.md +4 -2
- package/docs/context-working-set.md +4 -4
- package/docs/development-pipeline.md +1 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +4 -4
- package/docs/documentation-guide.md +4 -4
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +4 -45
- package/docs/evidence-and-memory.md +70 -10
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +4 -1
- package/docs/extensions-and-sharing.md +6 -2
- package/docs/fleet-demo-runbook.md +2 -2
- package/docs/fleet-dispatch.md +224 -11
- package/docs/git-commit-provenance.md +2 -2
- package/docs/glossary.md +1 -1
- package/docs/installation-and-lifecycle.md +2 -2
- package/docs/middleware-and-components.md +20 -2
- package/docs/model-catalog.md +1 -1
- package/docs/observability.md +55 -8
- package/docs/proactive-memory.md +26 -16
- package/docs/prompt-envelope-and-tools.md +4 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +83 -65
- package/docs/resource-library.md +59 -0
- package/docs/safety-model.md +29 -7
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +37 -1
- package/docs/skills-marketplace.md +16 -3
- package/docs/tool-usage.md +14 -7
- 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 +3 -3
- package/package.json +7 -4
- package/src/cli/agents.ts +2 -3
- package/src/cli/argv.ts +14 -1
- package/src/cli/fleet-commands.ts +37 -0
- package/src/cli/fleet-graph.ts +102 -0
- package/src/cli/fleet-new.ts +36 -0
- package/src/cli/fleet-preflight.ts +121 -0
- package/src/cli/fleet-validate.ts +30 -0
- package/src/cli/fleet.ts +188 -335
- package/src/cli/index.ts +4 -2
- package/src/cli/library.ts +190 -0
- 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/share.ts +13 -1
- package/src/cli/targets.ts +12 -3
- package/src/cli/usage.ts +160 -20
- package/src/core/bus-events.ts +7 -0
- package/src/core/commit-attribution.ts +4 -4
- package/src/core/config.ts +130 -0
- package/src/core/defaults.ts +81 -0
- package/src/core/response-model-id.ts +134 -0
- package/src/core/toml.ts +62 -0
- package/src/core/workspace-files.ts +0 -1
- package/src/domains/agents/builtins/architect.md +2 -1
- package/src/domains/agents/builtins/oracle.md +33 -0
- package/src/domains/agents/catalog.ts +18 -5
- package/src/domains/agents/fleet-contract.ts +278 -16
- package/src/domains/agents/index.ts +14 -0
- package/src/domains/agents/recipe.ts +54 -14
- package/src/domains/agents/result-contract.ts +242 -5
- package/src/domains/config/classify.ts +4 -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/policies/index.ts +3 -4
- package/src/domains/dispatch/active-route-planner.ts +14 -0
- package/src/domains/dispatch/backoff.ts +2 -1
- package/src/domains/dispatch/budget-envelope.ts +396 -0
- package/src/domains/dispatch/capability-match.ts +1 -0
- package/src/domains/dispatch/checkout-writer-lease.ts +175 -0
- package/src/domains/dispatch/contract.ts +36 -0
- package/src/domains/dispatch/delegation-plan.ts +167 -0
- package/src/domains/dispatch/execution-plan.ts +76 -5
- package/src/domains/dispatch/execution-role.ts +3 -1
- package/src/domains/dispatch/execution-scheduler.ts +183 -67
- package/src/domains/dispatch/extension.ts +339 -36
- package/src/domains/dispatch/fleet-gate.ts +14 -0
- package/src/domains/dispatch/fleet-plan.ts +63 -3
- package/src/domains/dispatch/fleet-run.ts +737 -0
- package/src/domains/dispatch/gate-role-prompts.ts +9 -0
- package/src/domains/dispatch/host-verification.ts +178 -0
- package/src/domains/dispatch/index.ts +38 -0
- package/src/domains/dispatch/intent.ts +159 -0
- package/src/domains/dispatch/orphan-recovery.ts +1 -0
- package/src/domains/dispatch/receipt-integrity.ts +12 -4
- package/src/domains/dispatch/state.ts +37 -3
- package/src/domains/dispatch/types.ts +61 -9
- package/src/domains/dispatch/validation.ts +80 -6
- 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/trust-status.ts +10 -1
- 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/index.ts +15 -0
- package/src/domains/middleware/memory-intervention.ts +35 -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 +43 -1
- package/src/domains/middleware/types.ts +10 -0
- package/src/domains/middleware/watchdog.ts +281 -0
- package/src/domains/observability/contract.ts +9 -2
- package/src/domains/observability/cost.ts +31 -4
- package/src/domains/observability/extension.ts +2 -2
- package/src/domains/observability/index.ts +10 -0
- package/src/domains/observability/out-of-turn-usage.ts +223 -0
- 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/resources/index.ts +20 -0
- package/src/domains/resources/library.ts +326 -0
- package/src/domains/resources/skills/marketplace.ts +37 -12
- package/src/domains/safety/call-target.ts +211 -14
- package/src/domains/safety/decision-presentation.ts +268 -0
- package/src/domains/safety/redaction.ts +73 -0
- package/src/domains/session/context-ledger.ts +10 -1
- package/src/domains/session/decision-board.ts +4 -0
- package/src/domains/session/entries.ts +3 -0
- package/src/domains/session/handoff.ts +629 -0
- package/src/domains/session/history.ts +68 -19
- package/src/domains/session/usage.ts +24 -7
- package/src/domains/share/archive.ts +67 -2
- package/src/engine/acp/event-mapper.ts +7 -0
- package/src/engine/acp/server.ts +29 -2
- 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/worker-events.ts +4 -3
- package/src/engine/worker-runtime.ts +59 -54
- package/src/entry/orchestrator.ts +55 -1
- package/src/interactive/bus-notices.ts +26 -0
- package/src/interactive/chat-loop-messages.ts +22 -0
- package/src/interactive/chat-loop.ts +248 -1
- package/src/interactive/chat-renderer.ts +41 -3
- package/src/interactive/clio-editor.ts +44 -7
- package/src/interactive/context-overlay.ts +43 -5
- package/src/interactive/cost-overlay.ts +70 -11
- package/src/interactive/council-dispatch.ts +30 -0
- package/src/interactive/council-grid.ts +213 -0
- package/src/interactive/council.ts +99 -0
- package/src/interactive/dispatch-board.ts +471 -50
- package/src/interactive/fleet-run-preview.ts +307 -0
- package/src/interactive/footer/notifications.ts +219 -0
- package/src/interactive/footer/widgets.ts +13 -0
- package/src/interactive/handoff-round.ts +56 -0
- package/src/interactive/interactive-application.ts +49 -2
- package/src/interactive/interactive-event-projection.ts +9 -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 +52 -2
- package/src/interactive/interactive-subscriptions.ts +14 -2
- package/src/interactive/memory-overlay.ts +89 -4
- package/src/interactive/oracle.ts +179 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +7 -1
- package/src/interactive/overlay-frame.ts +5 -2
- package/src/interactive/overlay-general-openers.ts +230 -2
- package/src/interactive/overlay-key-routing.ts +58 -2
- package/src/interactive/overlay-lifecycle.ts +52 -5
- package/src/interactive/overlay-permission-lifecycle.ts +33 -8
- package/src/interactive/overlay-resource-openers.ts +11 -3
- package/src/interactive/overlay-session-lifecycle.ts +234 -2
- 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/overlays/fleet-run-approval.ts +208 -0
- package/src/interactive/overlays/handoff-review.ts +185 -0
- package/src/interactive/overlays/library-install-confirm.ts +151 -0
- package/src/interactive/overlays/list-overlay.ts +168 -2
- package/src/interactive/overlays/settings.ts +101 -4
- package/src/interactive/overlays/side-question.ts +139 -0
- package/src/interactive/overlays/skills-hub.ts +401 -15
- package/src/interactive/permission-hint.ts +35 -0
- package/src/interactive/permission-overlay.ts +95 -45
- package/src/interactive/renderers/tool-execution.ts +19 -49
- package/src/interactive/session-last-turn.ts +8 -1
- package/src/interactive/session-usage-reseed.ts +36 -10
- package/src/interactive/side-question.ts +171 -0
- package/src/interactive/slash-commands.ts +434 -7
- package/src/interactive/slash-spec.ts +19 -6
- 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/theme/tokens.ts +30 -0
- package/src/interactive/turn-context.ts +96 -23
- package/src/interactive/turn-middleware.ts +16 -1
- package/src/interactive/turn-runtime.ts +37 -8
- package/src/interactive/turn-state.ts +3 -0
- package/src/interactive/watchdog-run.ts +75 -0
- package/src/interactive/worker-progress.ts +440 -0
- package/src/interactive/worker-share.ts +56 -1
- package/src/interactive/worker-stream.ts +58 -110
- package/src/tools/agent-tools.ts +28 -3
- package/src/tools/ask-user.ts +21 -1
- package/src/tools/bootstrap.ts +3 -0
- package/src/tools/compete-worktrees.ts +13 -79
- package/src/tools/context/index.ts +2 -2
- package/src/tools/dispatch-admission.ts +242 -8
- package/src/tools/dispatch-arguments.ts +65 -1
- package/src/tools/dispatch-event-text.ts +19 -0
- package/src/tools/dispatch-plan.ts +136 -6
- package/src/tools/dispatch-runner.ts +319 -13
- package/src/tools/dispatch-types.ts +20 -1
- package/src/tools/dispatch.ts +96 -3
- package/src/tools/monitor.ts +31 -0
- package/src/tools/profiles.ts +18 -4
- package/src/tools/registry.ts +15 -5
- package/src/tools/result-disposition.ts +156 -0
- package/src/tools/result-shaping.ts +59 -1
- package/src/tools/task-worktree.ts +238 -0
- package/src/tools/verify/authoring.ts +116 -55
- package/src/tools/verify/scripts.ts +62 -0
- package/src/tools/worker-evidence.ts +21 -1
- package/src/worker/spec-contract.ts +44 -3
- package/dist/chunk-EFADSJET.js +0 -18
- package/dist/chunk-HC4CLZ2Y.js +0 -68
- package/dist/memory-4ALKDJ4Q.js +0 -246
- package/src/domains/eval/metrics/chaos-stream.ts +0 -93
package/src/tools/monitor.ts
CHANGED
|
@@ -2,6 +2,12 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
import { sleep } from "../core/timers.js";
|
|
3
3
|
import { renderAgentLedgerBoard } from "../domains/dispatch/agent-ledger-store.js";
|
|
4
4
|
import type { DurableAssignmentRecord } from "../domains/dispatch/assignment-store.js";
|
|
5
|
+
import {
|
|
6
|
+
formatBudgetPolicy,
|
|
7
|
+
formatBudgetReasons,
|
|
8
|
+
formatBudgetRequest,
|
|
9
|
+
formatEffectiveBudget,
|
|
10
|
+
} from "../domains/dispatch/budget-envelope.js";
|
|
5
11
|
import type { DispatchContract } from "../domains/dispatch/contract.js";
|
|
6
12
|
import { UNVERIFIABLE_RECEIPT_VERIFICATION } from "../domains/dispatch/receipt-findings.js";
|
|
7
13
|
import type { ReceiptIntegrityResult } from "../domains/dispatch/receipt-integrity.js";
|
|
@@ -117,6 +123,19 @@ function runStatus(deps: MonitorToolDeps, runId: string): ToolResult {
|
|
|
117
123
|
`started=${run.startedAt} ended=${run.endedAt ?? "n/a"} exit=${run.exitCode ?? "n/a"}`,
|
|
118
124
|
`tokens=${run.tokenCount} cost=${formatCostAggregate(costAggregateForAmount(run.costUsd, run.costProvenance)) ?? COST_NOT_MEASURED} receipt=${run.receiptPath ?? "n/a"}`,
|
|
119
125
|
];
|
|
126
|
+
if (run.council !== undefined || run.gate?.role === "synthesis") {
|
|
127
|
+
lines.push(
|
|
128
|
+
`council: role=${run.gate?.role === "synthesis" ? "synthesis" : "member"} group=${run.council?.group ?? run.gate?.group ?? "unknown"}${run.council?.label ? ` label=${run.council.label}` : ""}`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (run.budget !== undefined) {
|
|
132
|
+
lines.push(
|
|
133
|
+
`recipe policy: ${formatBudgetPolicy(run.budget)}`,
|
|
134
|
+
`requested envelope: ${formatBudgetRequest(run.budget)}`,
|
|
135
|
+
`effective envelope: ${formatEffectiveBudget(run.budget)}`,
|
|
136
|
+
`clamp or escalation reason: ${formatBudgetReasons(run.budget)}`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
120
139
|
if (live) {
|
|
121
140
|
lines.push(
|
|
122
141
|
`live: phase=${live.outcomePhase} heartbeat=${live.heartbeat} elapsed=${Math.round(live.elapsedMs / 1000)}s tokens=${live.tokens.total}`,
|
|
@@ -143,6 +162,16 @@ function runStatus(deps: MonitorToolDeps, runId: string): ToolResult {
|
|
|
143
162
|
tokenCount: run.tokenCount,
|
|
144
163
|
costUsd: run.costUsd,
|
|
145
164
|
costProvenance: run.costProvenance ?? "unknown",
|
|
165
|
+
budget: run.budget ?? null,
|
|
166
|
+
...(run.council !== undefined || run.gate?.role === "synthesis"
|
|
167
|
+
? {
|
|
168
|
+
council: {
|
|
169
|
+
role: run.gate?.role === "synthesis" ? "synthesis" : "member",
|
|
170
|
+
group: run.council?.group ?? run.gate?.group ?? null,
|
|
171
|
+
...(run.council !== undefined ? { label: run.council.label, round: run.council.round } : {}),
|
|
172
|
+
},
|
|
173
|
+
}
|
|
174
|
+
: {}),
|
|
146
175
|
receiptPath: run.receiptPath,
|
|
147
176
|
running: live !== null,
|
|
148
177
|
},
|
|
@@ -363,6 +392,7 @@ function runReceipt(deps: MonitorToolDeps, runId: string): ToolResult {
|
|
|
363
392
|
...(receipt !== null && receiptIntegrity.ok
|
|
364
393
|
? {
|
|
365
394
|
evidenceVerification: receipt.verification,
|
|
395
|
+
hostVerification: receipt.hostVerification ?? null,
|
|
366
396
|
briefing: receipt.briefing ?? null,
|
|
367
397
|
projectContext: receipt.projectContext ?? null,
|
|
368
398
|
}
|
|
@@ -702,6 +732,7 @@ async function runCollect(
|
|
|
702
732
|
receiptIntegrity: row.evidence.integrity,
|
|
703
733
|
trustStatus: row.evidence.trustStatus,
|
|
704
734
|
evidenceVerification: row.evidence.verification,
|
|
735
|
+
hostVerification: row.evidence.receipt?.hostVerification ?? null,
|
|
705
736
|
briefing: row.evidence.receipt?.briefing ?? null,
|
|
706
737
|
projectContext: row.evidence.receipt?.projectContext ?? null,
|
|
707
738
|
...(output ? { output: { state: output.state, bytes: output.bytes, truncated: output.truncated } } : {}),
|
package/src/tools/profiles.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { type BuiltinToolName, isBuiltinToolName, type ToolName, ToolNames } from "../core/tool-names.js";
|
|
2
2
|
|
|
3
|
-
export type ToolProfileName = "minimal-local" | "science-local" | "full-agent";
|
|
3
|
+
export type ToolProfileName = "minimal-local" | "science-local" | "full-agent" | "council-read-only";
|
|
4
4
|
|
|
5
|
-
export const TOOL_PROFILE_NAMES: ReadonlyArray<ToolProfileName
|
|
5
|
+
export const TOOL_PROFILE_NAMES: ReadonlyArray<Exclude<ToolProfileName, "council-read-only">> = [
|
|
6
|
+
"minimal-local",
|
|
7
|
+
"science-local",
|
|
8
|
+
"full-agent",
|
|
9
|
+
];
|
|
10
|
+
const ALL_TOOL_PROFILE_NAMES: ReadonlyArray<ToolProfileName> = [...TOOL_PROFILE_NAMES, "council-read-only"];
|
|
6
11
|
const CODEWIKI_TOOL_NAMES: ReadonlyArray<BuiltinToolName> = [ToolNames.CodeNav];
|
|
7
12
|
|
|
8
13
|
export interface ToolProfileContext {
|
|
@@ -24,14 +29,23 @@ const MINIMAL_LOCAL_TOOLS: ReadonlyArray<BuiltinToolName> = [
|
|
|
24
29
|
];
|
|
25
30
|
|
|
26
31
|
const SCIENCE_LOCAL_TOOLS: ReadonlyArray<BuiltinToolName> = [...MINIMAL_LOCAL_TOOLS, ToolNames.Verify];
|
|
32
|
+
const COUNCIL_READ_ONLY_TOOLS: ReadonlyArray<BuiltinToolName> = [
|
|
33
|
+
ToolNames.Read,
|
|
34
|
+
ToolNames.Grep,
|
|
35
|
+
ToolNames.Find,
|
|
36
|
+
ToolNames.Ls,
|
|
37
|
+
ToolNames.CodeNav,
|
|
38
|
+
ToolNames.Context,
|
|
39
|
+
];
|
|
27
40
|
|
|
28
41
|
const NARROW_TOOL_PROFILES: Readonly<Record<Exclude<ToolProfileName, "full-agent">, ReadonlySet<BuiltinToolName>>> = {
|
|
29
42
|
"minimal-local": new Set(MINIMAL_LOCAL_TOOLS),
|
|
30
43
|
"science-local": new Set(SCIENCE_LOCAL_TOOLS),
|
|
44
|
+
"council-read-only": new Set(COUNCIL_READ_ONLY_TOOLS),
|
|
31
45
|
};
|
|
32
46
|
|
|
33
47
|
export function isToolProfileName(value: string): value is ToolProfileName {
|
|
34
|
-
return (
|
|
48
|
+
return (ALL_TOOL_PROFILE_NAMES as ReadonlyArray<string>).includes(value);
|
|
35
49
|
}
|
|
36
50
|
|
|
37
51
|
/**
|
|
@@ -72,7 +86,7 @@ export function applyToolProfile(
|
|
|
72
86
|
const allowed = NARROW_TOOL_PROFILES[profile];
|
|
73
87
|
profiled = unique.filter((tool): tool is BuiltinToolName => isBuiltinToolName(tool) && allowed.has(tool));
|
|
74
88
|
}
|
|
75
|
-
return applyCodewikiWorkerPolicy(profiled, context);
|
|
89
|
+
return profile === "council-read-only" ? profiled : applyCodewikiWorkerPolicy(profiled, context);
|
|
76
90
|
}
|
|
77
91
|
|
|
78
92
|
function uniquePreservingOrder(tools: ReadonlyArray<ToolName>): ToolName[] {
|
package/src/tools/registry.ts
CHANGED
|
@@ -22,13 +22,14 @@ import {
|
|
|
22
22
|
mapAutonomy,
|
|
23
23
|
} from "../domains/safety/autonomy.js";
|
|
24
24
|
import type { SafetyContract, SafetyDecision } from "../domains/safety/contract.js";
|
|
25
|
+
import type { DecisionPresentation } from "../domains/safety/decision-presentation.js";
|
|
25
26
|
import { hashToolCall } from "../domains/safety/loop-detector.js";
|
|
26
27
|
import { detectValidationCommand } from "../domains/safety/protected-artifacts.js";
|
|
27
28
|
import { askUserExposure } from "./ask-user.js";
|
|
28
29
|
import { type DispatchPlanView, describeDispatchPlan } from "./dispatch-plan.js";
|
|
29
30
|
import type { ToolPresentationPolicy } from "./presentation.js";
|
|
30
|
-
import type { ToolResultDisposition } from "./result-disposition.js";
|
|
31
|
-
import { DEFAULT_TOOL_RESULT_MAX_BYTES, shapeToolResult } from "./result-shaping.js";
|
|
31
|
+
import type { ToolResultDigest, ToolResultDisposition } from "./result-disposition.js";
|
|
32
|
+
import { DEFAULT_TOOL_RESULT_MAX_BYTES, shapeToolResult, toolResultDigestFor } from "./result-shaping.js";
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* Tool registry. Admission point for every tool call. Delegates classification
|
|
@@ -200,6 +201,8 @@ export interface ToolInvokeOptions {
|
|
|
200
201
|
correlationId?: string;
|
|
201
202
|
pendingSkillPolicy?: PendingSkillToolPolicy;
|
|
202
203
|
askUserPolicy?: AskUserToolPolicy;
|
|
204
|
+
/** Host-derived display copy for an ask_user round. It has no admission authority. */
|
|
205
|
+
decisionPresentation?: DecisionPresentation;
|
|
203
206
|
/** Registry-authenticated one-shot operator approval for this execution. */
|
|
204
207
|
approval?: { requestId: string; requestedBy: string; actionClass: ActionClass };
|
|
205
208
|
/**
|
|
@@ -259,6 +262,8 @@ export interface AskUserToolPolicy {
|
|
|
259
262
|
sessionId?: string;
|
|
260
263
|
turnId?: string;
|
|
261
264
|
transcriptPath?: string;
|
|
265
|
+
/** Monotonic exposure fact for live presentation and durable replay. */
|
|
266
|
+
exposure?: AutonomyExposure;
|
|
262
267
|
summary?: string;
|
|
263
268
|
rounds: AskUserTranscriptRound[];
|
|
264
269
|
decisions: AskUserTranscriptDecision[];
|
|
@@ -421,13 +426,15 @@ export function createRegistry(deps: RegistryDeps): ToolRegistry {
|
|
|
421
426
|
const preparedArgs = prepareToolArgs(spec, call.args ?? {});
|
|
422
427
|
resultDisposition = resolveToolResultDisposition(spec, preparedArgs);
|
|
423
428
|
const result = await spec.run(preparedArgs, options);
|
|
424
|
-
const
|
|
429
|
+
const digest = toolResultDigestFor(spec, result, resultDisposition);
|
|
430
|
+
const afterEffects = runToolHook("after_tool", spec, call, decision, options, result, digest);
|
|
425
431
|
const finalResult = shapeToolResult(spec, applyToolResultEffects(result, afterEffects), options, resultDisposition);
|
|
426
432
|
return { kind: "ok", result: finalResult, decision };
|
|
427
433
|
} catch (err) {
|
|
428
434
|
const message = err instanceof Error ? err.message : String(err);
|
|
429
435
|
const result: ToolResult = { kind: "error", message };
|
|
430
|
-
const
|
|
436
|
+
const digest = toolResultDigestFor(spec, result, resultDisposition);
|
|
437
|
+
const afterEffects = runToolHook("after_tool", spec, call, decision, options, result, digest);
|
|
431
438
|
return {
|
|
432
439
|
kind: "ok",
|
|
433
440
|
result: shapeToolResult(spec, applyToolResultEffects(result, afterEffects), options, resultDisposition),
|
|
@@ -446,9 +453,10 @@ export function createRegistry(deps: RegistryDeps): ToolRegistry {
|
|
|
446
453
|
decision: SafetyDecision,
|
|
447
454
|
options: ToolInvokeOptions | undefined,
|
|
448
455
|
result?: ToolResult,
|
|
456
|
+
resultDigest?: ToolResultDigest,
|
|
449
457
|
): ReadonlyArray<MiddlewareEffect> => {
|
|
450
458
|
if (!deps.middleware) return [];
|
|
451
|
-
const input = buildToolHookInput(hook, spec, call, decision, "operating", options, result);
|
|
459
|
+
const input = buildToolHookInput(hook, spec, call, decision, "operating", options, result, resultDigest);
|
|
452
460
|
const effects = deps.middleware.runHook(input).effects;
|
|
453
461
|
try {
|
|
454
462
|
deps.onMiddlewareEffects?.(effects, input);
|
|
@@ -1135,6 +1143,7 @@ function buildToolHookInput(
|
|
|
1135
1143
|
posture: string,
|
|
1136
1144
|
options: ToolInvokeOptions | undefined,
|
|
1137
1145
|
result: ToolResult | undefined,
|
|
1146
|
+
resultDigest: ToolResultDigest | undefined,
|
|
1138
1147
|
): MiddlewareHookInput {
|
|
1139
1148
|
const metadata: Record<string, MiddlewareMetadataValue> = {
|
|
1140
1149
|
posture,
|
|
@@ -1171,6 +1180,7 @@ function buildToolHookInput(
|
|
|
1171
1180
|
};
|
|
1172
1181
|
if (call.args !== undefined) input.toolArgs = call.args;
|
|
1173
1182
|
if (result?.details !== undefined) input.toolResultDetails = result.details;
|
|
1183
|
+
if (resultDigest !== undefined) input.toolResultDigest = resultDigest;
|
|
1174
1184
|
if (options?.runId !== undefined) input.runId = options.runId;
|
|
1175
1185
|
if (options?.sessionId !== undefined) input.sessionId = options.sessionId;
|
|
1176
1186
|
if (options?.turnId !== undefined) input.turnId = options.turnId;
|
|
@@ -52,6 +52,23 @@ export interface ToolResultSummaryProvenance {
|
|
|
52
52
|
redactions?: number;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
export const TOOL_RESULT_DIGEST_MAX_BYTES = 240;
|
|
56
|
+
|
|
57
|
+
export interface ToolResultDigestProvenance {
|
|
58
|
+
producer: "code";
|
|
59
|
+
source: "canonical-result-disposition" | "legacy-fallback";
|
|
60
|
+
algorithm: "redacted-context-digest-v1" | "redacted-legacy-digest-v1";
|
|
61
|
+
contextMode?: AppliedToolResultContextMode;
|
|
62
|
+
summaryAlgorithm?: ToolResultSummaryProvenance["algorithm"];
|
|
63
|
+
redactions?: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** A bounded diagnostic that is safe to pass to task memory. */
|
|
67
|
+
export interface ToolResultDigest {
|
|
68
|
+
text: string;
|
|
69
|
+
provenance: ToolResultDigestProvenance;
|
|
70
|
+
}
|
|
71
|
+
|
|
55
72
|
export interface ToolResultDispositionMetadata {
|
|
56
73
|
version: 1;
|
|
57
74
|
applications: 1;
|
|
@@ -223,6 +240,14 @@ function capUtf8(text: string, maxBytes: number): string {
|
|
|
223
240
|
return byteLength(text) <= maxBytes ? text : utf8Prefix(text, maxBytes);
|
|
224
241
|
}
|
|
225
242
|
|
|
243
|
+
function capDigestUtf8(text: string, maxBytes: number): string {
|
|
244
|
+
if (byteLength(text) <= maxBytes) return text;
|
|
245
|
+
const marker = "…";
|
|
246
|
+
const markerBytes = byteLength(marker);
|
|
247
|
+
if (markerBytes >= maxBytes) return utf8Prefix(text, maxBytes);
|
|
248
|
+
return `${utf8Prefix(text, maxBytes - markerBytes).trimEnd()}${marker}`;
|
|
249
|
+
}
|
|
250
|
+
|
|
226
251
|
/** A deterministic, UTF-8-safe excerpt whose total bytes never exceed maxBytes. */
|
|
227
252
|
function boundedToolResultExcerpt(text: string, maxBytes: number, bias: ToolResultExcerptBias = "head-tail"): string {
|
|
228
253
|
if (maxBytes <= 0) return "";
|
|
@@ -504,6 +529,137 @@ export function projectToolResultContext(input: ProjectToolResultContextInput):
|
|
|
504
529
|
};
|
|
505
530
|
}
|
|
506
531
|
|
|
532
|
+
const DIGEST_FACT_KEYS = [
|
|
533
|
+
"outcome",
|
|
534
|
+
"exitCode",
|
|
535
|
+
"timedOut",
|
|
536
|
+
"aborted",
|
|
537
|
+
"outputCapped",
|
|
538
|
+
"signal",
|
|
539
|
+
"status",
|
|
540
|
+
"error",
|
|
541
|
+
"decision",
|
|
542
|
+
"next",
|
|
543
|
+
] as const;
|
|
544
|
+
|
|
545
|
+
function digestFactText(details: ToolResultDetails | undefined): string {
|
|
546
|
+
if (details === undefined) return "";
|
|
547
|
+
const facts: string[] = [];
|
|
548
|
+
for (const key of DIGEST_FACT_KEYS) {
|
|
549
|
+
if (details[key] !== undefined) facts.push(`${key}=${stableJson(details[key])}`);
|
|
550
|
+
}
|
|
551
|
+
return facts.join(" ");
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function projectionBody(input: ProjectToolResultContextInput, projection: ToolResultContextProjection): string {
|
|
555
|
+
if (projection.appliedMode === "metadata-only") return "";
|
|
556
|
+
if (projection.appliedMode === "full") {
|
|
557
|
+
const trailer = fullTrailer(input);
|
|
558
|
+
return trailer.length > 0 && projection.text.endsWith(`\n\n${trailer}`)
|
|
559
|
+
? projection.text.slice(0, -(trailer.length + 2))
|
|
560
|
+
: projection.text;
|
|
561
|
+
}
|
|
562
|
+
const header = contextHeader(input, projection.appliedMode, projection.truncated, projection.summaryProvenance);
|
|
563
|
+
const prefix = `${header}\n`;
|
|
564
|
+
return projection.text.startsWith(prefix) ? projection.text.slice(prefix.length) : "";
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function digestText(
|
|
568
|
+
status: string,
|
|
569
|
+
facts: string,
|
|
570
|
+
body: string,
|
|
571
|
+
redactions: number,
|
|
572
|
+
maxBytes: number,
|
|
573
|
+
): { text: string; redactions: number } {
|
|
574
|
+
const tally = createRedactionTally();
|
|
575
|
+
const safeStatus = redactSecretsText(status, tally);
|
|
576
|
+
const safeFacts = redactSecretsText(facts, tally);
|
|
577
|
+
const statusAndFacts = [safeStatus, safeFacts].filter((value) => value.length > 0).join(" ");
|
|
578
|
+
const bodyBudget = Math.max(0, maxBytes - byteLength(statusAndFacts) - 2);
|
|
579
|
+
const selected = deterministicDiagnosticSummary(body, bodyBudget, true);
|
|
580
|
+
const candidate = [statusAndFacts, selected.text.replace(/\s+/gu, " ").trim()]
|
|
581
|
+
.filter((value) => value.length > 0)
|
|
582
|
+
.join("; ");
|
|
583
|
+
return {
|
|
584
|
+
text: capDigestUtf8(candidate, maxBytes),
|
|
585
|
+
redactions: redactions + tally.count + selected.redactions,
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Reuse the applied model-context projection as task memory's diagnostic
|
|
591
|
+
* source. Metadata-only never contributes captured content, and bounded or
|
|
592
|
+
* summarized modes contribute only the body admitted by that projection.
|
|
593
|
+
*/
|
|
594
|
+
export function deterministicToolResultDigest(
|
|
595
|
+
input: ProjectToolResultContextInput,
|
|
596
|
+
maxBytes = TOOL_RESULT_DIGEST_MAX_BYTES,
|
|
597
|
+
): ToolResultDigest {
|
|
598
|
+
const projection = projectToolResultContext(input);
|
|
599
|
+
const status = [
|
|
600
|
+
`kind=${input.kind}`,
|
|
601
|
+
`mode=${projection.appliedMode}`,
|
|
602
|
+
`truncated=${String(projection.truncated)}`,
|
|
603
|
+
...(projection.appliedMode === "metadata-only" || projection.truncated
|
|
604
|
+
? [`capturedBytes=${input.capturedBytes}`]
|
|
605
|
+
: []),
|
|
606
|
+
].join(" ");
|
|
607
|
+
const digest = digestText(
|
|
608
|
+
status,
|
|
609
|
+
digestFactText(input.details),
|
|
610
|
+
projectionBody(input, projection),
|
|
611
|
+
projection.summaryProvenance?.redactions ?? 0,
|
|
612
|
+
Math.max(1, Math.floor(maxBytes)),
|
|
613
|
+
);
|
|
614
|
+
return {
|
|
615
|
+
text: digest.text,
|
|
616
|
+
provenance: {
|
|
617
|
+
producer: "code",
|
|
618
|
+
source: "canonical-result-disposition",
|
|
619
|
+
algorithm: "redacted-context-digest-v1",
|
|
620
|
+
contextMode: projection.appliedMode,
|
|
621
|
+
...(projection.summaryProvenance === undefined ? {} : { summaryAlgorithm: projection.summaryProvenance.algorithm }),
|
|
622
|
+
...(digest.redactions > 0 ? { redactions: digest.redactions } : {}),
|
|
623
|
+
},
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/** Deterministic compatibility path for results without a canonical disposition. */
|
|
628
|
+
export function legacyToolResultDigest(
|
|
629
|
+
text: string,
|
|
630
|
+
options: { outcome: "ok" | "error"; maxBytes?: number },
|
|
631
|
+
): ToolResultDigest {
|
|
632
|
+
const maxBytes = Math.max(1, Math.floor(options.maxBytes ?? TOOL_RESULT_DIGEST_MAX_BYTES));
|
|
633
|
+
const fallback = options.outcome === "error" && text.trim().length === 0 ? "an unknown tool error" : text;
|
|
634
|
+
const digest = digestText("", "", fallback, 0, maxBytes);
|
|
635
|
+
return {
|
|
636
|
+
text: digest.text,
|
|
637
|
+
provenance: {
|
|
638
|
+
producer: "code",
|
|
639
|
+
source: "legacy-fallback",
|
|
640
|
+
algorithm: "redacted-legacy-digest-v1",
|
|
641
|
+
...(digest.redactions > 0 ? { redactions: digest.redactions } : {}),
|
|
642
|
+
},
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/** Reapply the memory boundary's redaction and byte cap to a supplied digest. */
|
|
647
|
+
export function sanitizeToolResultDigest(
|
|
648
|
+
digest: ToolResultDigest,
|
|
649
|
+
maxBytes = TOOL_RESULT_DIGEST_MAX_BYTES,
|
|
650
|
+
): ToolResultDigest {
|
|
651
|
+
const tally = createRedactionTally();
|
|
652
|
+
const safe = redactSecretsText(digest.text, tally).replace(/\s+/gu, " ").trim();
|
|
653
|
+
const redactions = (digest.provenance.redactions ?? 0) + tally.count;
|
|
654
|
+
return {
|
|
655
|
+
text: capDigestUtf8(safe, Math.max(1, Math.floor(maxBytes))),
|
|
656
|
+
provenance: {
|
|
657
|
+
...digest.provenance,
|
|
658
|
+
...(redactions > 0 ? { redactions } : {}),
|
|
659
|
+
},
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
|
|
507
663
|
/** The text inserted into the provider conversation for a registry result. */
|
|
508
664
|
export function toolResultContextText(result: ToolResult): string {
|
|
509
665
|
if (result.modelContext !== undefined) return result.modelContext;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { mkdirSync, readdirSync, rmdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
4
4
|
import { clioStateDir } from "../core/xdg.js";
|
|
5
5
|
import type { ToolInvokeOptions, ToolResult, ToolResultDetails, ToolSpec } from "./registry.js";
|
|
6
6
|
import {
|
|
7
|
+
deterministicToolResultDigest,
|
|
8
|
+
legacyToolResultDigest,
|
|
7
9
|
normalizeToolResultDisposition,
|
|
8
10
|
projectToolResultContext,
|
|
11
|
+
type ToolResultDigest,
|
|
9
12
|
type ToolResultDisposition,
|
|
10
13
|
type ToolResultDispositionFallback,
|
|
11
14
|
type ToolResultDispositionMetadata,
|
|
@@ -21,6 +24,7 @@ export const DEFAULT_TOOL_RESULT_MAX_BYTES = DEFAULT_MAX_BYTES + 2 * 1024;
|
|
|
21
24
|
const RESULT_TRUNCATION_MARKER = "\n[tool result truncated]";
|
|
22
25
|
const RESULT_OFFLOAD_MAX_BYTES = 10 * 1024 * 1024;
|
|
23
26
|
const TAIL_NOTICE_RESERVE_BYTES = 512;
|
|
27
|
+
export const TOOL_OFFLOAD_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000;
|
|
24
28
|
|
|
25
29
|
type ToolResultShapeContext = Pick<ToolInvokeOptions, "sessionId" | "toolCallId">;
|
|
26
30
|
|
|
@@ -49,6 +53,34 @@ function offloadMaxBytesFor(spec: ToolSpec): number {
|
|
|
49
53
|
: RESULT_OFFLOAD_MAX_BYTES;
|
|
50
54
|
}
|
|
51
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Build the task-memory diagnostic from the same normalized disposition that
|
|
58
|
+
* will shape model context. Legacy tools use the explicit compatibility path.
|
|
59
|
+
*/
|
|
60
|
+
export function toolResultDigestFor(
|
|
61
|
+
spec: ToolSpec,
|
|
62
|
+
result: ToolResult,
|
|
63
|
+
requestedDisposition?: ToolResultDisposition,
|
|
64
|
+
): ToolResultDigest {
|
|
65
|
+
const text = resultText(result);
|
|
66
|
+
const disposition = normalizeToolResultDisposition(spec, maxBytesFor(spec), requestedDisposition);
|
|
67
|
+
if (disposition === null) {
|
|
68
|
+
const projected = shapeLegacyToolResult(spec, result);
|
|
69
|
+
return legacyToolResultDigest(resultText(projected), { outcome: result.kind });
|
|
70
|
+
}
|
|
71
|
+
const capturedBytes = capturedBytesFor(result, text);
|
|
72
|
+
return deterministicToolResultDigest({
|
|
73
|
+
text,
|
|
74
|
+
kind: result.kind,
|
|
75
|
+
details: result.details,
|
|
76
|
+
disposition,
|
|
77
|
+
capturedBytes,
|
|
78
|
+
displayedBytes: Math.min(capturedBytes, disposition.presentation.maxBytes),
|
|
79
|
+
offloadPath: existingOffloadPath(result.details),
|
|
80
|
+
followUpHint: followUpHint(spec),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
52
84
|
function detailsRecord(details: ToolResultDetails | undefined, key: string): Record<string, unknown> | null {
|
|
53
85
|
const candidate = details?.[key];
|
|
54
86
|
return candidate !== null && typeof candidate === "object" && !Array.isArray(candidate)
|
|
@@ -91,6 +123,32 @@ function offloadBody(text: string, bytes: number, maxBytes: number): string {
|
|
|
91
123
|
return `${truncateUtf8(text, Math.max(0, prefixBudget), "")}${notice}`;
|
|
92
124
|
}
|
|
93
125
|
|
|
126
|
+
/** Remove regular offload files older than the boot retention cap. */
|
|
127
|
+
export function sweepExpiredToolOffloads(now = Date.now()): number {
|
|
128
|
+
const root = join(clioStateDir(), "scratch");
|
|
129
|
+
const cutoff = now - TOOL_OFFLOAD_MAX_AGE_MS;
|
|
130
|
+
let removed = 0;
|
|
131
|
+
try {
|
|
132
|
+
for (const session of readdirSync(root, { withFileTypes: true })) {
|
|
133
|
+
if (!session.isDirectory()) continue;
|
|
134
|
+
const sessionDir = join(root, session.name);
|
|
135
|
+
for (const entry of readdirSync(sessionDir, { withFileTypes: true })) {
|
|
136
|
+
if (!entry.isFile()) continue;
|
|
137
|
+
const path = join(sessionDir, entry.name);
|
|
138
|
+
try {
|
|
139
|
+
if (statSync(path).mtimeMs >= cutoff) continue;
|
|
140
|
+
rmSync(path, { force: true });
|
|
141
|
+
removed += 1;
|
|
142
|
+
} catch {}
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
if (readdirSync(sessionDir).length === 0) rmdirSync(sessionDir);
|
|
146
|
+
} catch {}
|
|
147
|
+
}
|
|
148
|
+
} catch {}
|
|
149
|
+
return removed;
|
|
150
|
+
}
|
|
151
|
+
|
|
94
152
|
/**
|
|
95
153
|
* Persist the full text of a tool result to a per-session scratch file and
|
|
96
154
|
* return its path (or null if the write fails). Self-shaping callers use this
|