@sema-agent/server 7.146.0 → 7.148.0
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/MIGRATION.md +1423 -24
- package/README.md +21 -8
- package/README.zh-CN.md +15 -9
- package/USAGE.md +537 -216
- package/deploy/facts/lanes.json +7 -0
- package/deploy/sema-up/README.md +18 -7
- package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
- package/deploy/sema-up/chart/templates/_helpers.tpl +42 -4
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -4
- package/deploy/sema-up/chart/templates/server.yaml +5 -4
- package/deploy/sema-up/chart/values.yaml +4 -3
- package/deploy/sema-up/cluster-up.sh +75 -176
- package/deploy/sema-up/kube-up.sh +29 -49
- package/deploy/sema-up/lib/chart-run.sh +23 -0
- package/deploy/sema-up/lib/dataroot.sh +3 -3
- package/deploy/sema-up/lib/flagshape.sh +4 -0
- package/deploy/sema-up/lib/health.sh +62 -13
- package/deploy/sema-up/lib/helm-values-cluster.py +18 -0
- package/deploy/sema-up/lib/helm-values-kube.py +35 -0
- package/deploy/sema-up/lib/lanes.json +2 -5
- package/deploy/sema-up/lib/regcred.py +8 -0
- package/deploy/sema-up/lib/remote/helm-install.sh +3 -0
- package/deploy/sema-up/lib/remote/image-import.sh +6 -0
- package/deploy/sema-up/lib/remote/machine-precheck.sh +11 -0
- package/deploy/sema-up/lib/remote/region-probe.sh +3 -0
- package/deploy/sema-up/lib/remote/stack-ready.sh +26 -0
- package/deploy/sema-up/lib/remote/vxlan-guard.sh +8 -0
- package/deploy/sema-up/lib/render-stack.py +17 -0
- package/deploy/sema-up/lib/shell-text.sh +87 -0
- package/deploy/sema-up/lib/usage-flags.txt +10 -0
- package/deploy/sema-up/lib/usage-head.txt +1 -0
- package/deploy/sema-up/lib/usage-tail.txt +13 -0
- package/deploy/sema-up/preflight.sh +10 -8
- package/deploy/sema-up/sema-up.sh +26 -48
- package/deploy/sema-up/smoke.sh +7 -6
- package/deploy/sema-up/stack/compose.dataroot.yaml +3 -0
- package/deploy/sema-up/stack/compose.yaml +18 -5
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +25 -3
- package/dist/adoption/plan.d.ts +24 -0
- package/dist/adoption/plan.js +53 -1
- package/dist/adoption/runner.d.ts +10 -1
- package/dist/adoption/runner.js +36 -16
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +32 -34
- package/dist/approval-gate-currency.js +3 -2
- package/dist/approval-reconciler.d.ts +4 -13
- package/dist/approval-reconciler.js +2 -2
- package/dist/approval.d.ts +16 -14
- package/dist/approval.js +3 -3
- package/dist/audit.d.ts +10 -3
- package/dist/audit.js +17 -9
- package/dist/auth-bridge.d.ts +0 -14
- package/dist/auth-bridge.js +0 -7
- package/dist/auto-mode-face.d.ts +10 -7
- package/dist/auto-mode-face.js +7 -4
- package/dist/background-agent-name.d.ts +19 -1
- package/dist/background-agent-name.js +12 -2
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.js +9 -6
- package/dist/bench/s1/arms.js +6 -5
- package/dist/bench/s1/live-deps.js +8 -3
- package/dist/bench/s1/run-firm.js +6 -5
- package/dist/bind-host.d.ts +25 -0
- package/dist/bind-host.js +25 -0
- package/dist/boot/adoption.d.ts +3 -0
- package/dist/boot/adoption.js +1 -0
- package/dist/boot/crash-last.js +2 -1
- package/dist/boot/deployment-mods.d.ts +1 -1
- package/dist/boot/device-lane.js +5 -5
- package/dist/boot/engine-lease.d.ts +12 -11
- package/dist/boot/execution-env.d.ts +19 -8
- package/dist/boot/execution-env.js +80 -62
- package/dist/boot/execution-lane.d.ts +37 -9
- package/dist/boot/execution-lane.js +74 -20
- package/dist/boot/exit-boundary.d.ts +3 -3
- package/dist/boot/exit-boundary.js +6 -5
- package/dist/boot/exit-last.js +2 -1
- package/dist/boot/fatal-exit.d.ts +3 -5
- package/dist/boot/fatal-exit.js +2 -2
- package/dist/boot/governance-seams.d.ts +2 -2
- package/dist/boot/leader.d.ts +15 -0
- package/dist/boot/leader.js +18 -16
- package/dist/boot/memory-boundary.d.ts +11 -11
- package/dist/boot/memory-boundary.js +3 -3
- package/dist/boot/memory-consolidation.d.ts +50 -53
- package/dist/boot/memory-consolidation.js +11 -18
- package/dist/boot/org-memory.js +4 -3
- package/dist/boot/parked-revive-gate.d.ts +1 -1
- package/dist/boot/parked-revive-gate.js +3 -3
- package/dist/boot/reapers.d.ts +4 -3
- package/dist/boot/reapers.js +20 -17
- package/dist/boot/resolve-spec.d.ts +5 -3
- package/dist/boot/resolve-spec.js +133 -165
- package/dist/boot/retention-lane.d.ts +7 -45
- package/dist/boot/retention-lane.js +2 -2
- package/dist/boot/runner-deps.d.ts +28 -7
- package/dist/boot/runner-deps.js +11 -4
- package/dist/boot/runtime-caps.d.ts +2 -2
- package/dist/boot/runtime-caps.js +16 -2
- package/dist/boot/session-faces.d.ts +17 -7
- package/dist/boot/session-faces.js +122 -96
- package/dist/boot/shutdown.d.ts +5 -4
- package/dist/boot/shutdown.js +6 -4
- package/dist/boot/stage-01-config.d.ts +1 -1
- package/dist/boot/stage-01-config.js +14 -2
- package/dist/boot/stage-02-web-admin-pull.d.ts +2 -1
- package/dist/boot/stage-02-web-admin-pull.js +15 -8
- package/dist/boot/stage-03-store-backend.d.ts +4 -1
- package/dist/boot/stage-03-store-backend.js +4 -3
- package/dist/boot/stage-04-stores.d.ts +3 -1
- package/dist/boot/stage-04-stores.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +9 -5
- package/dist/boot/stage-05-execution-env.js +5 -5
- package/dist/boot/stage-06-runners.d.ts +13 -15
- package/dist/boot/stage-06-runners.js +24 -18
- package/dist/boot/stage-07-capability-layer.d.ts +14 -11
- package/dist/boot/stage-07-capability-layer.js +9 -12
- package/dist/boot/stage-08-reapers.d.ts +14 -11
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +16 -18
- package/dist/boot/stage-09-leader.js +12 -4
- package/dist/boot/stage-10-http-server.d.ts +16 -18
- package/dist/boot/stage-10-http-server.js +9 -5
- package/dist/boot/store-evidence.d.ts +20 -0
- package/dist/boot/store-evidence.js +13 -0
- package/dist/boot/stores.d.ts +12 -0
- package/dist/boot/stores.js +39 -17
- package/dist/boot/task-list-lane.d.ts +4 -4
- package/dist/boot/web-admin.d.ts +4 -2
- package/dist/boot/web-admin.js +58 -38
- package/dist/boot/webfetch-summarize-lane.d.ts +1 -1
- package/dist/boot-reclaim.d.ts +3 -1
- package/dist/boot-reclaim.js +1 -1
- package/dist/brain.d.ts +7 -18
- package/dist/brain.js +5 -17
- package/dist/budget.js +6 -6
- package/dist/capabilities/center-plugins.d.ts +9 -1
- package/dist/capabilities/center-plugins.js +37 -11
- package/dist/capabilities/center-wiring.js +1 -1
- package/dist/capabilities/composite-members.d.ts +3 -2
- package/dist/capabilities/composite-members.js +3 -2
- package/dist/capabilities/execution-lane.d.ts +7 -7
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +1 -1
- package/dist/capabilities/repo-tools.d.ts +2 -0
- package/dist/capabilities/repo-tools.js +14 -12
- package/dist/capabilities/scenarios.d.ts +38 -33
- package/dist/capabilities/scenarios.js +24 -25
- package/dist/capabilities/settings-contract.d.ts +29 -0
- package/dist/capabilities/settings-contract.js +14 -0
- package/dist/capabilities/skills.d.ts +6 -6
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +69 -4
- package/dist/capability-facts.js +77 -5
- package/dist/card-void.d.ts +4 -4
- package/dist/card-void.js +1 -1
- package/dist/center-credential-renewer.d.ts +6 -2
- package/dist/center-credential-renewer.js +10 -5
- package/dist/config-catalog.d.ts +16 -1
- package/dist/config-catalog.js +68 -61
- package/dist/config-dir-trust.d.ts +37 -4
- package/dist/config-dir-trust.js +88 -44
- package/dist/config-invariants.d.ts +58 -4
- package/dist/config-invariants.js +104 -23
- package/dist/config-lkg.d.ts +24 -2
- package/dist/config-lkg.js +22 -9
- package/dist/config-provider.d.ts +9 -9
- package/dist/config-provider.js +25 -108
- package/dist/config-pull-failure.d.ts +50 -0
- package/dist/config-pull-failure.js +48 -0
- package/dist/config-types.d.ts +215 -202
- package/dist/config.d.ts +69 -14
- package/dist/config.js +188 -96
- package/dist/degenerate-instrument.js +1 -1
- package/dist/delegated-session-owner.d.ts +1 -1
- package/dist/deleted-session-ids.d.ts +3 -2
- package/dist/deploy-facts.js +3 -2
- package/dist/deployment-governance.d.ts +3 -3
- package/dist/deployment-shape.d.ts +51 -16
- package/dist/deployment-shape.js +31 -6
- package/dist/egress-redirect.d.ts +25 -7
- package/dist/egress-redirect.js +20 -2
- package/dist/elicitation.d.ts +6 -5
- package/dist/elicitation.js +23 -22
- package/dist/engine-identity.d.ts +28 -0
- package/dist/engine-identity.js +10 -0
- package/dist/entry-problems.d.ts +5 -7
- package/dist/entry-problems.js +1 -1
- package/dist/env-facts.d.ts +7 -5
- package/dist/env-facts.js +12 -7
- package/dist/env-witness.d.ts +7 -0
- package/dist/env-witness.js +16 -0
- package/dist/execution-config-root.d.ts +5 -5
- package/dist/execution-config-root.js +5 -5
- package/dist/execution-env-purpose.d.ts +14 -0
- package/dist/execution-env-purpose.js +29 -0
- package/dist/execution-lane-caps.d.ts +53 -103
- package/dist/execution-lane-caps.js +51 -83
- package/dist/execution-placement.d.ts +65 -9
- package/dist/execution-placement.js +58 -0
- package/dist/field-conflict.d.ts +7 -11
- package/dist/field-conflict.js +3 -3
- package/dist/file-history-capture.d.ts +3 -3
- package/dist/file-history-disclosure.d.ts +2 -2
- package/dist/file-history-disclosure.js +1 -0
- package/dist/fleet/drain-entry.d.ts +17 -10
- package/dist/fleet/drain-entry.js +1 -1
- package/dist/fleet/fleet-bus.d.ts +21 -3
- package/dist/fleet/fleet-bus.js +35 -25
- package/dist/fleet/fleet-reconciler.js +2 -2
- package/dist/fleet/serving-lease.js +6 -7
- package/dist/fleet-client.js +3 -3
- package/dist/fleet-lease.d.ts +0 -1
- package/dist/fleet-lease.js +4 -5
- package/dist/history-anchor.d.ts +42 -0
- package/dist/history-anchor.js +34 -0
- package/dist/hitl-delivery.d.ts +90 -0
- package/dist/hitl-delivery.js +98 -0
- package/dist/hooks/classic-stations.d.ts +8 -11
- package/dist/hooks/classic-stations.js +0 -7
- package/dist/hooks/command-spawn.d.ts +1 -4
- package/dist/hooks/command-spawn.js +0 -11
- package/dist/hooks/hook-llm.d.ts +5 -1
- package/dist/hooks/hook-llm.js +24 -15
- package/dist/hooks/hook-runner.d.ts +119 -65
- package/dist/hooks/hook-runner.js +415 -217
- package/dist/host-lsp-manager.d.ts +22 -8
- package/dist/host-lsp-manager.js +4 -1
- package/dist/http/active-run-conflict.d.ts +2 -43
- package/dist/http/active-run-conflict.js +3 -7
- package/dist/http/admission.d.ts +4 -18
- package/dist/http/admission.js +75 -78
- package/dist/http/approval-sweeps.d.ts +5 -8
- package/dist/http/approval-sweeps.js +55 -30
- package/dist/http/caller-trust.d.ts +8 -10
- package/dist/http/caller-trust.js +1 -2
- package/dist/http/checkpoint-ctx.d.ts +17 -0
- package/dist/http/checkpoint-ctx.js +6 -0
- package/dist/http/claim-heartbeat.d.ts +49 -0
- package/dist/http/claim-heartbeat.js +46 -0
- package/dist/http/claim-latency.d.ts +10 -0
- package/dist/http/claim-latency.js +12 -0
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/dispatch.d.ts +8 -1
- package/dist/http/dispatch.js +77 -31
- package/dist/http/durable-run-leg.d.ts +3 -3
- package/dist/http/durable-run-leg.js +18 -12
- package/dist/http/execution-context.d.ts +18 -42
- package/dist/http/execution-context.js +11 -5
- package/dist/http/health-reader.d.ts +36 -0
- package/dist/http/health-reader.js +21 -0
- package/dist/http/health-self-report.d.ts +9 -9
- package/dist/http/health-self-report.js +4 -4
- package/dist/http/idempotency.d.ts +9 -5
- package/dist/http/idempotency.js +4 -4
- package/dist/http/memory-compliance-failure-reply.d.ts +15 -16
- package/dist/http/memory-compliance-failure-reply.js +7 -2
- package/dist/http/memory-face-fault-reply.d.ts +67 -0
- package/dist/http/memory-face-fault-reply.js +71 -0
- package/dist/http/memory-store-refusal-reply.d.ts +3 -3
- package/dist/http/memory-store-refusal-reply.js +6 -0
- package/dist/http/owner-access.d.ts +391 -56
- package/dist/http/owner-access.js +372 -33
- package/dist/http/principal-gate.d.ts +26 -94
- package/dist/http/principal-gate.js +24 -81
- package/dist/http/refusal-body.d.ts +35 -2
- package/dist/http/refusal-body.js +34 -0
- package/dist/http/request-guards.d.ts +10 -14
- package/dist/http/request-guards.js +34 -68
- package/dist/http/resume-composition.d.ts +37 -0
- package/dist/http/resume-composition.js +18 -0
- package/dist/http/resume-ctx-read.d.ts +35 -12
- package/dist/http/resume-ctx-read.js +25 -6
- package/dist/http/resume-legs.d.ts +24 -24
- package/dist/http/resume-legs.js +260 -171
- package/dist/http/retired-skill-manifest.d.ts +1 -1
- package/dist/http/rewind-files-reply.d.ts +34 -0
- package/dist/http/rewind-files-reply.js +36 -0
- package/dist/http/route-ctx.d.ts +56 -47
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.d.ts +43 -5
- package/dist/http/routes/a2a-serve.js +58 -37
- package/dist/http/routes/admin-config-refresh.js +2 -2
- package/dist/http/routes/admin-drain.js +2 -2
- package/dist/http/routes/admin-memory-optout.js +4 -3
- package/dist/http/routes/adoption.d.ts +3 -0
- package/dist/http/routes/adoption.js +17 -10
- package/dist/http/routes/agents-roster.js +13 -7
- package/dist/http/routes/approvals-assistant.js +73 -88
- package/dist/http/routes/attachments.js +2 -2
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/background.js +9 -17
- package/dist/http/routes/capabilities.js +23 -20
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.d.ts +3 -3
- package/dist/http/routes/devices.js +5 -5
- package/dist/http/routes/diagnostics.d.ts +27 -3
- package/dist/http/routes/diagnostics.js +27 -21
- package/dist/http/routes/engine.js +2 -2
- package/dist/http/routes/fleet.js +5 -3
- package/dist/http/routes/images.js +10 -6
- package/dist/http/routes/leader.d.ts +7 -2
- package/dist/http/routes/leader.js +12 -3
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +7 -15
- package/dist/http/routes/memory-bundle.js +4 -7
- package/dist/http/routes/memory-compliance.js +4 -4
- package/dist/http/routes/memory-consolidation.js +6 -9
- package/dist/http/routes/memory-origin.d.ts +3 -1
- package/dist/http/routes/memory-origin.js +7 -8
- package/dist/http/routes/memory-policy.js +17 -12
- package/dist/http/routes/notify-wake.js +12 -20
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/principal-inbox.d.ts +1 -1
- package/dist/http/routes/principal-inbox.js +2 -2
- package/dist/http/routes/projects.d.ts +70 -0
- package/dist/http/routes/projects.js +87 -0
- package/dist/http/routes/retention-ops.js +6 -9
- package/dist/http/routes/rules.js +50 -7
- package/dist/http/routes/run-memory-capture.d.ts +2 -2
- package/dist/http/routes/run-memory-capture.js +6 -12
- package/dist/http/routes/run-permission-mode.d.ts +2 -2
- package/dist/http/routes/run-permission-mode.js +10 -17
- package/dist/http/routes/runs.js +148 -233
- package/dist/http/routes/session-memory-sync.d.ts +2 -2
- package/dist/http/routes/session-memory-sync.js +7 -13
- package/dist/http/routes/session-sync.d.ts +4 -2
- package/dist/http/routes/session-sync.js +48 -30
- package/dist/http/routes/sessions-list.d.ts +3 -3
- package/dist/http/routes/sessions-list.js +9 -9
- package/dist/http/routes/sessions.d.ts +7 -1
- package/dist/http/routes/sessions.js +177 -112
- package/dist/http/routes/shared-memory.js +6 -6
- package/dist/http/routes/side-query.js +2 -2
- package/dist/http/routes/tasks.js +144 -122
- package/dist/http/routes/trace-usage.d.ts +0 -12
- package/dist/http/routes/trace-usage.js +40 -46
- package/dist/http/routes/workflows.d.ts +39 -4
- package/dist/http/routes/workflows.js +42 -14
- package/dist/http/run-concurrency-cap.d.ts +20 -12
- package/dist/http/run-concurrency-cap.js +39 -26
- package/dist/http/run-read-face.d.ts +3 -5
- package/dist/http/run-read-face.js +8 -13
- package/dist/http/send.d.ts +12 -3
- package/dist/http/send.js +42 -6
- package/dist/http/server.d.ts +63 -50
- package/dist/http/server.js +52 -16
- package/dist/http/sse-log.d.ts +17 -10
- package/dist/http/sse-log.js +7 -7
- package/dist/http/stored-body-replay.d.ts +17 -3
- package/dist/http/stored-body-replay.js +11 -2
- package/dist/http/submit-ctx.d.ts +16 -8
- package/dist/http/submit-ctx.js +6 -2
- package/dist/http/submit-replay.d.ts +19 -6
- package/dist/http/submit-replay.js +18 -6
- package/dist/http/sync-submit-body.d.ts +3 -4
- package/dist/http/sync-submit-body.js +4 -5
- package/dist/http/wire-types.d.ts +23 -13
- package/dist/identity-source.d.ts +36 -5
- package/dist/identity-source.js +27 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/instruction-source-notice.d.ts +1 -1
- package/dist/key-resolver.d.ts +32 -0
- package/dist/key-resolver.js +23 -9
- package/dist/leader/diffup.js +2 -1
- package/dist/leader/endpoint.d.ts +26 -5
- package/dist/leader/endpoint.js +154 -14
- package/dist/leader/fanout.d.ts +3 -0
- package/dist/leader/fanout.js +78 -63
- package/dist/leader/leader.d.ts +16 -0
- package/dist/leader/leader.js +43 -3
- package/dist/leader/merge.d.ts +9 -1
- package/dist/leader/merge.js +16 -1
- package/dist/leader/repair-wire.js +1 -1
- package/dist/leader/wire.d.ts +36 -3
- package/dist/leader/wire.js +59 -18
- package/dist/lsp-evict.d.ts +6 -4
- package/dist/lsp-evict.js +2 -3
- package/dist/memory-embedder-reembed.d.ts +38 -0
- package/dist/memory-embedder-reembed.js +20 -0
- package/dist/memory-incident-sink.d.ts +0 -28
- package/dist/memory-incident-sink.js +5 -0
- package/dist/memory-operator-faces.d.ts +5 -4
- package/dist/memory-operator-faces.js +1 -1
- package/dist/memory-scope.d.ts +31 -4
- package/dist/memory-scope.js +65 -16
- package/dist/memory-store-refusal.d.ts +20 -4
- package/dist/memory-store-refusal.js +1 -1
- package/dist/memory-sync-client.d.ts +5 -2
- package/dist/memory-sync-client.js +19 -14
- package/dist/memory-sync.js +1 -1
- package/dist/model-compat.d.ts +51 -28
- package/dist/model-compat.js +55 -23
- package/dist/model-context-window.d.ts +18 -0
- package/dist/model-context-window.js +2 -0
- package/dist/model-entry-headers.d.ts +46 -4
- package/dist/model-entry-headers.js +2 -2
- package/dist/model-entry-refusal.d.ts +46 -17
- package/dist/model-entry-refusal.js +47 -27
- package/dist/model-plane-face.d.ts +19 -11
- package/dist/model-plane-face.js +9 -1
- package/dist/model-plane-probe.d.ts +2 -0
- package/dist/model-plane-probe.js +17 -0
- package/dist/model-provider.d.ts +3 -3
- package/dist/model-route-endpoint.d.ts +9 -5
- package/dist/model-route-endpoint.js +29 -7
- package/dist/model-select.d.ts +16 -0
- package/dist/model-select.js +4 -0
- package/dist/mountinfo.d.ts +37 -0
- package/dist/mountinfo.js +47 -0
- package/dist/namespaced-rule-name.d.ts +28 -2
- package/dist/namespaced-rule-name.js +10 -1
- package/dist/net-address.d.ts +1 -1
- package/dist/observability/corrupt-read-seat.d.ts +4 -4
- package/dist/observability/corrupt-read-seat.js +5 -3
- package/dist/observability/fail-open.d.ts +75 -47
- package/dist/observability/fail-open.js +77 -47
- package/dist/observability/logger.d.ts +22 -1
- package/dist/observability/logger.js +89 -12
- package/dist/observability/metrics.d.ts +2 -0
- package/dist/observability/metrics.js +5 -4
- package/dist/observability/otel-exporter.js +2 -1
- package/dist/observability/principal-context.d.ts +14 -7
- package/dist/observability/principal-context.js +8 -3
- package/dist/observability/run-terminal.d.ts +7 -1
- package/dist/observability/run-terminal.js +5 -2
- package/dist/observability/secret-env-scrub.d.ts +30 -4
- package/dist/observability/secret-env-scrub.js +15 -3
- package/dist/orchestration/hardened-vm-runner.d.ts +1 -0
- package/dist/orchestration/hardened-vm-runner.js +11 -5
- package/dist/orchestration/hardened-vm-worker-runner.d.ts +0 -14
- package/dist/orchestration/hardened-vm-worker-runner.js +5 -0
- package/dist/orchestration/hardened-vm-worker.js +2 -1
- package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
- package/dist/orchestration/workflow-agent-session-index.js +1 -6
- package/dist/orchestration/workflow-completion-inbox.d.ts +29 -9
- package/dist/orchestration/workflow-completion-inbox.js +65 -46
- package/dist/org-delivery-gate.d.ts +5 -4
- package/dist/org-delivery-gate.js +7 -6
- package/dist/org-memory-admission.d.ts +5 -2
- package/dist/org-memory-admission.js +25 -10
- package/dist/outbound-dispatcher.d.ts +1 -1
- package/dist/outbound-dispatcher.js +6 -12
- package/dist/owner-brands.d.ts +81 -0
- package/dist/owner-brands.js +42 -0
- package/dist/owner-faces.d.ts +531 -0
- package/dist/owner-faces.js +126 -0
- package/dist/parked-decide.d.ts +100 -31
- package/dist/parked-decide.js +162 -48
- package/dist/parked-revive-surface.d.ts +14 -4
- package/dist/parked-revive-surface.js +5 -4
- package/dist/peer-directory.d.ts +6 -8
- package/dist/peer-directory.js +3 -2
- package/dist/permission-rule-vocab.d.ts +53 -8
- package/dist/permission-rule-vocab.js +30 -2
- package/dist/plugins/adoption-log-sql.d.ts +0 -22
- package/dist/plugins/adoption-log-sql.js +5 -3
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.d.ts +7 -0
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.js +17 -0
- package/dist/plugins/approval-ask-store-file.d.ts +28 -9
- package/dist/plugins/approval-ask-store-file.js +74 -18
- package/dist/plugins/approval-ask-store-memory.d.ts +17 -7
- package/dist/plugins/approval-ask-store-memory.js +35 -12
- package/dist/plugins/approval-ask-store-sql.d.ts +42 -20
- package/dist/plugins/approval-ask-store-sql.js +44 -11
- package/dist/plugins/approval-exemption-skill-m46.d.ts +20 -0
- package/dist/plugins/approval-exemption-skill-m46.js +25 -0
- package/dist/plugins/approval-exemption-store.d.ts +6 -1
- package/dist/plugins/approval-exemption-store.js +14 -0
- package/dist/plugins/approval-nonce-store.d.ts +39 -12
- package/dist/plugins/approval-nonce-store.js +72 -23
- package/dist/plugins/blob-backend.d.ts +40 -195
- package/dist/plugins/blob-backend.js +41 -234
- package/dist/plugins/caching-session-store.d.ts +22 -5
- package/dist/plugins/caching-session-store.js +43 -4
- package/dist/plugins/checkpoint-index-columns.d.ts +33 -6
- package/dist/plugins/checkpoint-index-columns.js +39 -3
- package/dist/plugins/checkpoint-store-face.d.ts +84 -11
- package/dist/plugins/checkpoint-store-face.js +18 -1
- package/dist/plugins/device-store-sql.d.ts +2 -2
- package/dist/plugins/device-store-sql.js +6 -10
- package/dist/plugins/ensure-index.d.ts +13 -1
- package/dist/plugins/ensure-index.js +154 -21
- package/dist/plugins/ensure-schema-lock-policy.d.ts +0 -15
- package/dist/plugins/ensure-schema-lock-policy.js +3 -2
- package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
- package/dist/plugins/execution-lane-rename-m40.js +10 -0
- package/dist/plugins/execution-placement-sql.d.ts +63 -88
- package/dist/plugins/execution-placement-sql.js +94 -54
- package/dist/plugins/file-run-store.d.ts +89 -35
- package/dist/plugins/file-run-store.js +197 -142
- package/dist/plugins/host-platform.d.ts +24 -3
- package/dist/plugins/host-platform.js +15 -1
- package/dist/plugins/image-bake-store-sql.js +2 -0
- package/dist/plugins/imported-layer-root-retirement.d.ts +19 -10
- package/dist/plugins/imported-layer-root-retirement.js +4 -8
- package/dist/plugins/inbox-payload-column.d.ts +14 -0
- package/dist/plugins/inbox-payload-column.js +13 -0
- package/dist/plugins/k8s-pod-reaper.d.ts +1 -3
- package/dist/plugins/k8s-pod-reaper.js +0 -1
- package/dist/plugins/leader-run-store-sql.d.ts +22 -0
- package/dist/plugins/leader-run-store-sql.js +34 -4
- package/dist/plugins/local-checkpoint-store.d.ts +63 -23
- package/dist/plugins/local-checkpoint-store.js +204 -81
- package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
- package/dist/plugins/local-data-dir-modes-m39.js +183 -0
- package/dist/plugins/local-docker-capacity.d.ts +93 -0
- package/dist/plugins/local-docker-capacity.js +194 -0
- package/dist/plugins/local-docker-reaper.d.ts +92 -0
- package/dist/plugins/local-docker-reaper.js +102 -0
- package/dist/plugins/local-engine-high-water.d.ts +13 -0
- package/dist/plugins/local-engine-high-water.js +62 -0
- package/dist/plugins/local-session-store.d.ts +442 -143
- package/dist/plugins/local-session-store.js +941 -289
- package/dist/plugins/local-session-window.d.ts +3 -2
- package/dist/plugins/local-session-window.js +3 -2
- package/dist/plugins/local-sidecar-quarantine.js +3 -2
- package/dist/plugins/local-task-attachment-store.d.ts +20 -1
- package/dist/plugins/local-task-attachment-store.js +32 -12
- package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
- package/dist/plugins/memory-embedder-fingerprint.js +52 -12
- package/dist/plugins/memory-embedder.d.ts +1 -1
- package/dist/plugins/memory-embedder.js +11 -9
- package/dist/plugins/memory-engine-pg.d.ts +7 -5
- package/dist/plugins/memory-engine-pg.js +18 -9
- package/dist/plugins/memory-engine-sql-apply.d.ts +21 -8
- package/dist/plugins/memory-engine-sql-apply.js +7 -9
- package/dist/plugins/memory-engine-tidb.d.ts +12 -7
- package/dist/plugins/memory-engine-tidb.js +18 -10
- package/dist/plugins/memory-optout-grant-store-sql.d.ts +1 -1
- package/dist/plugins/memory-optout-grant-store-sql.js +3 -3
- package/dist/plugins/memory-run-store.d.ts +39 -27
- package/dist/plugins/memory-run-store.js +72 -70
- package/dist/plugins/one-time-migration-marker.d.ts +10 -0
- package/dist/plugins/one-time-migration-marker.js +7 -0
- package/dist/plugins/one-time-migrations.d.ts +325 -74
- package/dist/plugins/one-time-migrations.js +705 -230
- package/dist/plugins/org-delivery-quota-store.js +2 -1
- package/dist/plugins/owner-only-file-mode.d.ts +29 -0
- package/dist/plugins/owner-only-file-mode.js +141 -0
- package/dist/plugins/permission-rule-store-file.d.ts +11 -11
- package/dist/plugins/permission-rule-store-file.js +14 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +4 -63
- package/dist/plugins/permission-rule-store-sql.js +6 -86
- package/dist/plugins/pg-pool.d.ts +3 -32
- package/dist/plugins/pg-pool.js +27 -11
- package/dist/plugins/release-version.d.ts +20 -0
- package/dist/plugins/release-version.js +28 -0
- package/dist/plugins/remote-env-adb.d.ts +20 -4
- package/dist/plugins/remote-env-adb.js +39 -11
- package/dist/plugins/remote-env-e2b.d.ts +19 -28
- package/dist/plugins/remote-env-e2b.js +40 -29
- package/dist/plugins/remote-env-host.d.ts +11 -10
- package/dist/plugins/remote-env-host.js +40 -27
- package/dist/plugins/remote-env-k8s.d.ts +45 -47
- package/dist/plugins/remote-env-k8s.js +122 -62
- package/dist/plugins/remote-env-local-docker.d.ts +152 -15
- package/dist/plugins/remote-env-local-docker.js +370 -75
- package/dist/plugins/remote-env-ssh.d.ts +8 -2
- package/dist/plugins/remote-env-ssh.js +26 -24
- package/dist/plugins/remote-scratchpad.js +4 -0
- package/dist/plugins/remote-shell.d.ts +59 -30
- package/dist/plugins/remote-shell.js +175 -62
- package/dist/plugins/retention-declaration.d.ts +37 -0
- package/dist/plugins/retention-declaration.js +9 -0
- package/dist/plugins/retention-deployment.d.ts +158 -0
- package/dist/plugins/retention-deployment.js +119 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
- package/dist/plugins/retention-lane-store-sql.js +103 -1
- package/dist/plugins/retention-sql.d.ts +29 -0
- package/dist/plugins/retention-sql.js +8 -0
- package/dist/plugins/run-preview-m45.d.ts +11 -0
- package/dist/plugins/run-preview-m45.js +19 -0
- package/dist/plugins/run-store-sql.d.ts +56 -68
- package/dist/plugins/run-store-sql.js +127 -116
- package/dist/plugins/s3-answer.d.ts +2 -1
- package/dist/plugins/sandbox-reaper.d.ts +26 -0
- package/dist/plugins/sandbox-reaper.js +2 -0
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +54 -0
- package/dist/plugins/scenario-prefix-switch-m42.js +55 -0
- package/dist/plugins/scheduler-support.d.ts +16 -1
- package/dist/plugins/scheduler-support.js +22 -2
- package/dist/plugins/schema-consistency.d.ts +42 -15
- package/dist/plugins/schema-consistency.js +213 -13
- package/dist/plugins/schema-drift-sentence.d.ts +4 -1
- package/dist/plugins/schema-drift-sentence.js +4 -4
- package/dist/plugins/schema-ensure-legs.d.ts +10 -1
- package/dist/plugins/schema-ensure-legs.js +12 -2
- package/dist/plugins/schema-indexes.js +3 -0
- package/dist/plugins/schema-live-columns.d.ts +14 -5
- package/dist/plugins/schema-live-columns.js +10 -10
- package/dist/plugins/send-user-file.js +2 -1
- package/dist/plugins/session-birth.d.ts +37 -0
- package/dist/plugins/session-birth.js +38 -0
- package/dist/plugins/session-epoch-anchor.d.ts +40 -12
- package/dist/plugins/session-epoch-anchor.js +33 -11
- package/dist/plugins/session-ext-table.d.ts +98 -0
- package/dist/plugins/session-ext-table.js +134 -0
- package/dist/plugins/session-fork.d.ts +16 -2
- package/dist/plugins/session-fork.js +3 -0
- package/dist/plugins/session-ownership.d.ts +1 -1
- package/dist/plugins/session-placement.d.ts +22 -16
- package/dist/plugins/session-placement.js +15 -12
- package/dist/plugins/session-row-sql.d.ts +20 -7
- package/dist/plugins/session-row-sql.js +16 -8
- package/dist/plugins/session-run-rollup.d.ts +29 -0
- package/dist/plugins/session-run-rollup.js +40 -0
- package/dist/plugins/session-store-sql.d.ts +157 -0
- package/dist/plugins/session-store-sql.js +398 -0
- package/dist/plugins/session-withdraw-sql.d.ts +36 -0
- package/dist/plugins/session-withdraw-sql.js +42 -0
- package/dist/plugins/session-workspace-cell.d.ts +2 -2
- package/dist/plugins/session-workspace-cell.js +2 -2
- package/dist/plugins/shared-memory-store-sql.d.ts +10 -69
- package/dist/plugins/shared-memory-store-sql.js +15 -14
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +20 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +3 -0
- package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
- package/dist/plugins/snapshot-bucket-presence.js +1 -1
- package/dist/plugins/sql-driver.d.ts +24 -8
- package/dist/plugins/sql-driver.js +43 -9
- package/dist/plugins/sql-errors.d.ts +35 -5
- package/dist/plugins/sql-errors.js +55 -3
- package/dist/plugins/sql-json-column.d.ts +8 -7
- package/dist/plugins/sql-json-column.js +10 -6
- package/dist/plugins/store-backend.d.ts +114 -18
- package/dist/plugins/store-backend.js +340 -87
- package/dist/plugins/store-contracts.d.ts +97 -30
- package/dist/plugins/store-contracts.js +23 -1
- package/dist/plugins/store-fault.d.ts +28 -2
- package/dist/plugins/store-fault.js +20 -2
- package/dist/plugins/task-attachment-store.d.ts +21 -11
- package/dist/plugins/task-attachment-store.js +37 -19
- package/dist/plugins/task-list-store-sql.d.ts +1 -1
- package/dist/plugins/text-column-capacity.d.ts +21 -0
- package/dist/plugins/text-column-capacity.js +5 -0
- package/dist/plugins/tidb-pool.d.ts +3 -2
- package/dist/plugins/tidb-pool.js +42 -39
- package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
- package/dist/plugins/web-search.js +5 -3
- package/dist/plugins/workflow-run-store-sql.d.ts +6 -1
- package/dist/plugins/workflow-run-store-sql.js +11 -5
- package/dist/principal-jwt.d.ts +4 -4
- package/dist/principal-jwt.js +20 -5
- package/dist/principal-shape.d.ts +41 -0
- package/dist/principal-shape.js +19 -0
- package/dist/question.d.ts +13 -23
- package/dist/question.js +21 -39
- package/dist/read-face-posture.d.ts +6 -6
- package/dist/read-face-posture.js +2 -2
- package/dist/request-declaration-refusal.d.ts +35 -12
- package/dist/request-declaration-refusal.js +21 -9
- package/dist/request-form.d.ts +58 -0
- package/dist/request-form.js +72 -0
- package/dist/request-image-urls.d.ts +8 -2
- package/dist/request-image-urls.js +2 -1
- package/dist/request-images.d.ts +20 -0
- package/dist/request-images.js +59 -0
- package/dist/request-key-closure.d.ts +6 -7
- package/dist/request-key-closure.js +15 -2
- package/dist/request-value-closure.d.ts +5 -5
- package/dist/request-value-closure.js +1 -1
- package/dist/resource-suspend.d.ts +7 -16
- package/dist/resource-suspend.js +1 -1
- package/dist/retired-name-host-notice.d.ts +21 -0
- package/dist/retired-name-host-notice.js +12 -0
- package/dist/rule-entry-list.d.ts +2 -2
- package/dist/rule-entry-list.js +3 -4
- package/dist/rule-issue-reading.d.ts +58 -0
- package/dist/rule-issue-reading.js +14 -0
- package/dist/rules-consent.d.ts +46 -16
- package/dist/rules-consent.js +102 -53
- package/dist/run-acceptance.d.ts +3 -1
- package/dist/run-acceptance.js +3 -0
- package/dist/run-local.d.ts +14 -6
- package/dist/run-local.js +109 -93
- package/dist/run-stale-default.d.ts +7 -0
- package/dist/run-stale-default.js +2 -0
- package/dist/runs.d.ts +73 -44
- package/dist/runs.js +65 -43
- package/dist/runtime-caps-resolver.d.ts +36 -14
- package/dist/runtime-caps-resolver.js +31 -14
- package/dist/runtime-governance.d.ts +2 -2
- package/dist/runtime-governance.js +5 -3
- package/dist/sealed-key-layout.d.ts +12 -6
- package/dist/sealed-key-layout.js +5 -1
- package/dist/sealed-key.d.ts +12 -2
- package/dist/sealed-key.js +116 -26
- package/dist/security.d.ts +133 -161
- package/dist/security.js +163 -59
- package/dist/sema-config-dir.d.ts +20 -0
- package/dist/sema-config-dir.js +27 -2
- package/dist/server-secret-env.d.ts +23 -5
- package/dist/server-secret-env.js +14 -4
- package/dist/service-version.d.ts +2 -1
- package/dist/service-version.js +2 -2
- package/dist/session-children-retire.d.ts +7 -5
- package/dist/session-children-retire.js +7 -2
- package/dist/session-deletion.d.ts +88 -0
- package/dist/session-deletion.js +8 -0
- package/dist/session-erase.d.ts +145 -0
- package/dist/session-erase.js +115 -0
- package/dist/session-error-wire.d.ts +6 -6
- package/dist/session-error-wire.js +1 -1
- package/dist/session-incarnation.d.ts +60 -10
- package/dist/session-incarnation.js +19 -2
- package/dist/session-policy-wire.d.ts +6 -3
- package/dist/session-policy-wire.js +11 -1
- package/dist/session-resident-background.d.ts +29 -47
- package/dist/session-resident-background.js +77 -8
- package/dist/session-row.d.ts +3 -2
- package/dist/session-rules-seat.d.ts +12 -0
- package/dist/session-rules-seat.js +19 -0
- package/dist/session-sync-kernel.d.ts +1 -1
- package/dist/session-titler.d.ts +7 -15
- package/dist/session-titler.js +1 -1
- package/dist/session-workspace.d.ts +11 -2
- package/dist/session-workspace.js +5 -0
- package/dist/sighup-idle.d.ts +1 -1
- package/dist/spec-fields.d.ts +57 -3
- package/dist/spec-fields.js +72 -51
- package/dist/store-posture.d.ts +138 -21
- package/dist/store-posture.js +188 -3
- package/dist/stored-request-hooks-m20.d.ts +3 -2
- package/dist/stored-request-hooks-m20.js +21 -16
- package/dist/stores-sql/background-agent-store-sql.d.ts +11 -2
- package/dist/stores-sql/background-agent-store-sql.js +73 -20
- package/dist/stores-sql/blob-index-sql.d.ts +148 -0
- package/dist/stores-sql/blob-index-sql.js +154 -0
- package/dist/stores-sql/checkpoint-store-sql.d.ts +34 -29
- package/dist/stores-sql/checkpoint-store-sql.js +86 -71
- package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
- package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
- package/dist/stores-sql/mailbox-store-sql.d.ts +7 -4
- package/dist/stores-sql/mailbox-store-sql.js +31 -32
- package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +30 -81
- package/dist/{plugins → stores-sql}/pg-session-storage.js +123 -244
- package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +197 -223
- package/dist/{plugins → stores-sql}/retention-store-sql.js +148 -207
- package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
- package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
- package/dist/stores-sql/session-policy-store-sql.d.ts +33 -11
- package/dist/stores-sql/session-policy-store-sql.js +44 -36
- package/dist/stores-sql/session-write-hooks.d.ts +65 -0
- package/dist/stores-sql/session-write-hooks.js +2 -0
- package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +14 -15
- package/dist/{plugins → stores-sql}/tidb-session-storage.js +22 -28
- package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +67 -138
- package/dist/{plugins → stores-sql}/tidb-session-store.js +130 -200
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +1 -1
- package/dist/stores-sql/windowed-session-storage.d.ts +61 -0
- package/dist/stores-sql/windowed-session-storage.js +70 -0
- package/dist/submission-exit.d.ts +50 -0
- package/dist/submission-exit.js +108 -0
- package/dist/task-a2a.d.ts +7 -1
- package/dist/task-a2a.js +18 -17
- package/dist/task-cwd.d.ts +31 -3
- package/dist/task-cwd.js +25 -1
- package/dist/task-mcp.d.ts +11 -3
- package/dist/task-mcp.js +16 -19
- package/dist/task-settings.d.ts +23 -14
- package/dist/task-settings.js +35 -13
- package/dist/terminal.d.ts +25 -43
- package/dist/terminal.js +31 -11
- package/dist/tool-approval.d.ts +152 -137
- package/dist/tool-approval.js +199 -199
- package/dist/trace/core-keyset-guard.d.ts +22 -9
- package/dist/trace/core-vocab-wire.d.ts +95 -0
- package/dist/trace/core-vocab-wire.js +15 -0
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +52 -4
- package/dist/trace/exit-seat.js +43 -36
- package/dist/trace/extension-call-face.d.ts +3 -2
- package/dist/trace/extension-call-face.js +3 -1
- package/dist/trace/ledger-events.d.ts +4 -7
- package/dist/trace/ledger-sink.d.ts +1 -30
- package/dist/trace/ledger-sink.js +0 -11
- package/dist/trace/model-segment.d.ts +5 -5
- package/dist/trace/model-segment.js +5 -5
- package/dist/trace/project.d.ts +88 -58
- package/dist/trace/project.js +64 -28
- package/dist/trace/redact.d.ts +124 -28
- package/dist/trace/redact.js +936 -328
- package/dist/trace/self-minted-wire.d.ts +750 -29
- package/dist/trace/self-minted-wire.js +262 -25
- package/dist/trace/sema-provenance.d.ts +45 -41
- package/dist/trace/sema-provenance.js +81 -10
- package/dist/trace/task-notification-facets.d.ts +70 -2
- package/dist/trace/task-notification-facets.js +71 -1
- package/dist/trace/wire-projection-faces.d.ts +43 -8
- package/dist/trace/wire-projection-faces.js +28 -3
- package/dist/unread-request-members.d.ts +66 -0
- package/dist/unread-request-members.js +41 -0
- package/dist/upstream-body.d.ts +23 -0
- package/dist/upstream-body.js +16 -0
- package/dist/url-refusal.d.ts +3 -3
- package/dist/url-refusal.js +11 -4
- package/dist/user-authored-text.d.ts +1 -1
- package/dist/user-input-ledger.d.ts +7 -8
- package/dist/user-input-ledger.js +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +6 -3
- package/dist/web-admin-client/apply-effective.js +33 -40
- package/dist/web-admin-client/apply-ledger.d.ts +16 -7
- package/dist/web-admin-client/apply-ledger.js +5 -2
- package/dist/web-admin-client/candidate-gate.d.ts +35 -3
- package/dist/web-admin-client/candidate-gate.js +53 -5
- package/dist/web-admin-client/center-request.d.ts +6 -3
- package/dist/web-admin-client/center-request.js +17 -16
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.js +1 -2
- package/dist/web-admin-client/entry-metadata.d.ts +8 -0
- package/dist/web-admin-client/entry-metadata.js +13 -0
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/http-client.d.ts +2 -1
- package/dist/web-admin-client/http-client.js +40 -13
- package/dist/web-admin-client/mcp-revocation.d.ts +1 -1
- package/dist/web-admin-client/mcp-revocation.js +2 -1
- package/dist/web-admin-client/read-warnings.d.ts +1 -0
- package/dist/web-admin-client/read-warnings.js +1 -0
- package/dist/web-admin-client/restart-signal.js +13 -6
- package/dist/web-admin-client/skills-mcp.d.ts +22 -8
- package/dist/web-admin-client/skills-mcp.js +26 -21
- package/dist/web-admin-client/types.d.ts +35 -51
- package/dist/workspace-space.d.ts +3 -2
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +4 -4
- package/package.json +16 -12
- package/scripts/drain-check-local.mjs +118 -173
- package/scripts/drain-check.mysql.sql +20 -16
- package/scripts/drain-check.pg.sql +20 -16
- package/wire-changes/server@7.147.0.json +813 -0
- package/wire-changes/server@7.148.0.json +1517 -0
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +0 -25
- package/dist/http/memory-control-plane-corrupt-reply.js +0 -19
- package/dist/http/memory-layer-reply.d.ts +0 -30
- package/dist/http/memory-layer-reply.js +0 -24
- package/dist/lsp/e2b-bridge.d.ts +0 -57
- package/dist/lsp/e2b-bridge.js +0 -139
- package/dist/lsp/e2b-manager.d.ts +0 -93
- package/dist/lsp/e2b-manager.js +0 -178
- package/dist/lsp/lsp-frames.d.ts +0 -14
- package/dist/lsp/lsp-frames.js +0 -25
- package/dist/lsp/manager.d.ts +0 -129
- package/dist/lsp/manager.js +0 -127
- package/dist/lsp/types.d.ts +0 -12
- package/dist/lsp/types.js +0 -2
- package/dist/lsp/ws-transport.d.ts +0 -40
- package/dist/lsp/ws-transport.js +0 -210
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { composeHostSubprocessEnv, hostSubprocessEnv } from "../server-secret-env.js";
|
|
3
3
|
import vm from "node:vm";
|
|
4
|
-
import { hostShell, resolveHostShell, adoptHostForegroundChild, killTreeSoft, killTreeHard } from "../plugins/host-platform.js";
|
|
4
|
+
import { hostShell, resolveHostShell, adoptHostForegroundChild, killTreeSoft, killTreeHard, signalProcessTree, reapedLeaderGroupAlive } from "../plugins/host-platform.js";
|
|
5
5
|
import { classifyHooksConfig, DEFAULT_HOOK_TIMEOUT_SECONDS, HOOK_ENTRY_TYPES, HOOK_EVENTS, HOOK_EVENT_OWNER, HOOK_EVENT_MATCHER_FIELD, hookMatcherForm, hookMatcherSelects, interpolateHookEnvVars, } from "@sema-agent/settings-schema/hooks";
|
|
6
|
-
import { findUrlCredential,
|
|
6
|
+
import { findUrlCredential, outgoingPath } from "@sema-agent/settings-schema";
|
|
7
7
|
import { httpHookEnvVarsAllowed, httpHookUrlVerdict } from "@sema-agent/settings-schema";
|
|
8
8
|
import { ENGINE_OWNED_HOOK_EVENTS } from "@sema-agent/settings-schema/hooks";
|
|
9
9
|
import { describeToolCatalog } from "@sema-agent/core";
|
|
10
|
-
import { hangClassic
|
|
10
|
+
import { hangClassic } from "./classic-stations.js";
|
|
11
11
|
import { MAX_HOOK_NOTICE_TEXT_CHARS, boundedNoticeText } from "../fleet/fleet-bus.js";
|
|
12
12
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
13
|
-
import { LIMIT_REASONS } from "../limit-refusal.js";
|
|
13
|
+
import { LIMIT_REASONS, limitFacts } from "../limit-refusal.js";
|
|
14
|
+
import { fieldCoordinate } from "../http/refusal-body.js";
|
|
14
15
|
import { clipDataText, echoCallerText } from "../caller-text-echo.js";
|
|
15
16
|
import { seatText } from "../trace/exit-seat.js";
|
|
16
17
|
import { redactSecrets, buildDisplaySafeUrl } from "../trace/redact.js";
|
|
17
18
|
import { canonicalJsonStringify } from "@sema-agent/core";
|
|
18
19
|
import { ccPromptSystemFor, wrapCondition, parseCcVerdict, CC_EVALUATOR_MAX_OUTPUT_TOKENS } from "./cc-stop-prompt.js";
|
|
19
20
|
import { ccAgentHookSystemFor } from "./cc-agent-hook-prompt.js";
|
|
21
|
+
import { createEgressFetch } from "../egress-redirect.js";
|
|
20
22
|
import { renderBranchTranscript } from "./branch-transcript.js";
|
|
21
23
|
import { buildRequestUrlCredentialRefusal, urlCredentialHeaderExit } from "../url-credential-refusal.js";
|
|
22
24
|
import { HOOK_PHASES, HOOK_SOURCE_VOCABULARY_SENTENCE, hookLaneOf, hookPhaseOf, readHookGroupSource } from "./hook-source.js";
|
|
23
|
-
import { commandLineChars, composeHookEnvLayer, hookPluginChars, planCommandSpawn,
|
|
25
|
+
import { commandLineChars, composeHookEnvLayer, hookPluginChars, planCommandSpawn, readHookPlugin } from "./command-spawn.js";
|
|
24
26
|
export const MAX_HOOK_ENTRIES_PER_EVENT = 32;
|
|
25
27
|
export const MAX_HOOK_COMMAND_CHARS = 8_192;
|
|
26
28
|
export const MAX_HOOK_TIMEOUT_SECONDS = 600;
|
|
@@ -42,31 +44,26 @@ function hookEnv(ctx) {
|
|
|
42
44
|
return hookChildEnv(composeHookEnvLayer(ctx.shellEnv, ctx.cwd, undefined), false);
|
|
43
45
|
}
|
|
44
46
|
export const SETTINGS_HOOK_STATIONS = {
|
|
45
|
-
PreToolUse:
|
|
46
|
-
PostToolUse:
|
|
47
|
-
PostToolUseFailure:
|
|
48
|
-
PostToolBatch:
|
|
49
|
-
UserPromptSubmit:
|
|
50
|
-
Stop:
|
|
51
|
-
StopFailure:
|
|
52
|
-
PreCompact:
|
|
53
|
-
PostCompact:
|
|
47
|
+
PreToolUse: "classic.PreToolUse",
|
|
48
|
+
PostToolUse: "classic.PostToolUse",
|
|
49
|
+
PostToolUseFailure: "classic.PostToolUseFailure",
|
|
50
|
+
PostToolBatch: "classic.PostToolBatch",
|
|
51
|
+
UserPromptSubmit: "classic.UserPromptSubmit",
|
|
52
|
+
Stop: "classic.Stop",
|
|
53
|
+
StopFailure: "classic.StopFailure",
|
|
54
|
+
PreCompact: "classic.PreCompact",
|
|
55
|
+
PostCompact: "classic.PostCompact",
|
|
54
56
|
};
|
|
55
57
|
function chainsBelowTaskOn(patterns, station) {
|
|
56
58
|
return patterns.some((p) => p === station || (p.endsWith(".*") && station.startsWith(p.slice(0, -1))));
|
|
57
59
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const MANAGED_REWRITE_UNSHOWN_REASON = "a managed PreToolUse hook rewrote this call's input, but this deployment runs its own handler for this call after the request's hooks and that handler never sees a rewrite made above it, so the rewrite cannot be honored and the call was not executed";
|
|
62
|
-
const MANAGED_ALLOW_UNJUDGED_REASON = "a managed PreToolUse hook allowed this call, but this deployment runs its own handler for this call after the request's hooks, and a request hook's allow does not stand in for that handler's judgment, so the call was not executed (the same outcome as the same hook without a managed source)";
|
|
63
|
-
function hangTranslator(on, event, translators, lane) {
|
|
60
|
+
const REQUEST_HOOK_REWRITE_UNSHOWN_REASON = "a request PreToolUse hook rewrote this call's input, but this deployment runs its own handler for this call after the request's hooks and that handler never sees a rewrite made above it, so the rewrite cannot be honored and the call was not executed";
|
|
61
|
+
const REQUEST_HOOK_ALLOW_UNJUDGED_REASON = "a request PreToolUse hook allowed this call, but this deployment runs its own handler for this call after the request's hooks, and a request hook's allow does not stand in for that handler's judgment, so the call was not executed";
|
|
62
|
+
function hangTranslator(on, event, translators) {
|
|
64
63
|
const translate = translators[event];
|
|
65
64
|
if (translate === undefined)
|
|
66
65
|
return;
|
|
67
|
-
|
|
68
|
-
for (const station of SETTINGS_HOOK_STATIONS[event])
|
|
69
|
-
hang(on, station, translate);
|
|
66
|
+
hangClassic(on, SETTINGS_HOOK_STATIONS[event], translate);
|
|
70
67
|
}
|
|
71
68
|
export const SETTINGS_HOOKS_REGISTRATIONS = {
|
|
72
69
|
managed: "settings.hooks.managed",
|
|
@@ -235,7 +232,6 @@ const HOOKS_WIRE_KEY_SHAPE = {
|
|
|
235
232
|
source: `source must be one of ${HOOK_SOURCE_VOCABULARY_SENTENCE}`,
|
|
236
233
|
plugin: "plugin must be { name, root, dataDir?, options? } — name a non-empty string, root and dataDir absolute paths with no \"..\" segment and no NUL byte, " +
|
|
237
234
|
"options an object of string values whose keys are identifiers ([A-Za-z_][A-Za-z0-9_]*); nothing else",
|
|
238
|
-
args: "args must be an array of strings without NUL bytes (exec form: command is the executable, args its arguments)",
|
|
239
235
|
};
|
|
240
236
|
function hooksCapIssue(limit, event, path, count) {
|
|
241
237
|
const c = HOOKS_CAPS[limit];
|
|
@@ -243,54 +239,61 @@ function hooksCapIssue(limit, event, path, count) {
|
|
|
243
239
|
}
|
|
244
240
|
const matcherPath = (event, groupIndex) => ["hooks", event, groupIndex, "matcher"];
|
|
245
241
|
export function buildHooksRefusal(issue) {
|
|
246
|
-
const field = "settings.hooks";
|
|
247
242
|
switch (issue.reason) {
|
|
248
|
-
case "dead_alias":
|
|
243
|
+
case "dead_alias": {
|
|
244
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
249
245
|
return {
|
|
250
246
|
message: `settings.hooks.${issue.event}: matcher "${issue.alias}" is an alias; tool-event matchers match the tool's wire name (PostToolUse / PostToolUseFailure since 7.107.0) — use "${issue.canonical}"`,
|
|
251
|
-
field,
|
|
252
|
-
detail: { reason: issue.reason, event: issue.event, alias: issue.alias, canonical: issue.canonical, path: matcherPath(issue.event, issue.groupIndex) },
|
|
247
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, alias: issue.alias, canonical: issue.canonical },
|
|
253
248
|
};
|
|
254
|
-
|
|
249
|
+
}
|
|
250
|
+
case "over_budget": {
|
|
251
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
255
252
|
return {
|
|
256
|
-
message:
|
|
257
|
-
field,
|
|
258
|
-
detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, budgetMs: issue.budgetMs, path: matcherPath(issue.event, issue.groupIndex) },
|
|
253
|
+
message: `${field}: evaluating the pattern did not finish within ${issue.budgetMs} ms (catastrophic regex backtracking) — rewrite it as a tool-name list or a pattern without nested repetition`,
|
|
254
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, budgetMs: issue.budgetMs },
|
|
259
255
|
};
|
|
260
|
-
|
|
256
|
+
}
|
|
257
|
+
case "budget_exceeded": {
|
|
258
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
261
259
|
return {
|
|
262
|
-
message:
|
|
263
|
-
field,
|
|
264
|
-
detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, totalMs: issue.totalMs, path: matcherPath(issue.event, issue.groupIndex) },
|
|
260
|
+
message: `${field}: evaluating this configuration's regular-expression matchers took longer than ${issue.totalMs} ms in total (very slow patterns) — write tool names as a list such as "Read|Edit", or simplify the patterns`,
|
|
261
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, totalMs: issue.totalMs },
|
|
265
262
|
};
|
|
266
|
-
|
|
263
|
+
}
|
|
264
|
+
case "invalid_regex": {
|
|
265
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
267
266
|
return {
|
|
268
|
-
message:
|
|
269
|
-
field,
|
|
270
|
-
detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, path: matcherPath(issue.event, issue.groupIndex) },
|
|
267
|
+
message: `${field}: ${JSON.stringify(issue.matcher)} is not a valid regular expression (${issue.compileError}) — fix the pattern, or write the tool names as a list such as "Read|Edit"`,
|
|
268
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex },
|
|
271
269
|
};
|
|
272
|
-
|
|
270
|
+
}
|
|
271
|
+
case "unsupported_entry_type": {
|
|
272
|
+
const field = hooksFieldCoordinate(issue.path);
|
|
273
273
|
return {
|
|
274
|
-
message: `${
|
|
275
|
-
field,
|
|
276
|
-
detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path), type: issue.type },
|
|
274
|
+
message: `${field}: this server does not run hook entries of type ${issue.type}; supported: ${SUPPORTED_HOOK_ENTRY_TYPES.join(" / ")}`,
|
|
275
|
+
facts: { field, reason: issue.reason, type: issue.type },
|
|
277
276
|
};
|
|
277
|
+
}
|
|
278
278
|
case "over_cap":
|
|
279
279
|
case "too_long": {
|
|
280
280
|
const cap = issue;
|
|
281
|
-
return { message: HOOKS_CAPS[cap.limit].sentence(cap.event, cap.count),
|
|
281
|
+
return { message: HOOKS_CAPS[cap.limit].sentence(cap.event, cap.count), facts: { ...limitFacts(hooksFieldCoordinate(cap.path), HOOKS_CAPS[cap.limit].measure, cap.count, cap.cap), reason: cap.reason } };
|
|
282
|
+
}
|
|
283
|
+
case "unnamed_refusal": {
|
|
284
|
+
const field = hooksFieldCoordinate(issue.path);
|
|
285
|
+
return { message: `${field}: the hooks reader refused this configuration without naming a piece`, facts: { field, reason: issue.reason } };
|
|
286
|
+
}
|
|
287
|
+
case "wire_key_invalid": {
|
|
288
|
+
const field = hooksFieldCoordinate(issue.path);
|
|
289
|
+
return { message: `${field}: ${HOOKS_WIRE_KEY_SHAPE[issue.key]}`, facts: { field, reason: issue.reason, key: issue.key } };
|
|
282
290
|
}
|
|
283
|
-
case "unnamed_refusal":
|
|
284
|
-
return { message: `${hooksCoordinate(issue.path)}: the hooks reader refused this configuration without naming a piece`, field, detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path) } };
|
|
285
|
-
case "wire_key_invalid":
|
|
286
|
-
return { message: `${hooksCoordinate(issue.path)}: ${HOOKS_WIRE_KEY_SHAPE[issue.key]}`, field, detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path), key: issue.key } };
|
|
287
291
|
default: {
|
|
288
292
|
const piece = issue;
|
|
289
293
|
const key = piece.key !== undefined ? hooksOutgoingKey(piece.key) : undefined;
|
|
290
294
|
return {
|
|
291
295
|
message: hooksPieceRefusal(piece),
|
|
292
|
-
field,
|
|
293
|
-
detail: { reason: piece.reason, path: hooksOutgoingPath(piece.path), ...(key !== undefined ? { key } : {}) },
|
|
296
|
+
facts: { field: hooksFieldCoordinate(piece.path), reason: piece.reason, ...(key !== undefined ? { key } : {}) },
|
|
294
297
|
};
|
|
295
298
|
}
|
|
296
299
|
}
|
|
@@ -353,8 +356,8 @@ export function hooksUrlCredentialIssue(config) {
|
|
|
353
356
|
return undefined;
|
|
354
357
|
}
|
|
355
358
|
export function buildHooksUrlCredentialRefusal(issue) {
|
|
356
|
-
const entry =
|
|
357
|
-
return buildRequestUrlCredentialRefusal(
|
|
359
|
+
const entry = ["hooks", issue.event, issue.groupIndex, "hooks", issue.entryIndex];
|
|
360
|
+
return buildRequestUrlCredentialRefusal(hooksFieldCoordinate([...entry, "url"]), issue.credential, urlCredentialHeaderExit(hooksFieldCoordinate([...entry, "headers"])));
|
|
358
361
|
}
|
|
359
362
|
const HOOKS_PIECE_MEANING = {
|
|
360
363
|
"hooks-not-object": "`hooks` must be an object keyed by hook event name",
|
|
@@ -372,8 +375,8 @@ const HOOKS_PIECE_MEANING = {
|
|
|
372
375
|
export function hooksOutgoingPath(path) {
|
|
373
376
|
return outgoingPath(path).map((seg) => (typeof seg === "string" ? echoCallerText(seg) : seg));
|
|
374
377
|
}
|
|
375
|
-
export function
|
|
376
|
-
return
|
|
378
|
+
export function hooksFieldCoordinate(path) {
|
|
379
|
+
return fieldCoordinate("settings", hooksOutgoingPath(path));
|
|
377
380
|
}
|
|
378
381
|
function hooksOutgoingKey(key) {
|
|
379
382
|
return echoCallerText(String(outgoingPath([key])[0] ?? ""));
|
|
@@ -383,7 +386,7 @@ function hooksPieceIssue(piece) {
|
|
|
383
386
|
}
|
|
384
387
|
function hooksPieceRefusal(piece) {
|
|
385
388
|
const field = piece.key !== undefined ? ` (field: ${hooksOutgoingKey(piece.key)})` : "";
|
|
386
|
-
return `${
|
|
389
|
+
return `${hooksFieldCoordinate(piece.path)}: ${piece.reason} — ${HOOKS_PIECE_MEANING[piece.reason]}${field}`;
|
|
387
390
|
}
|
|
388
391
|
function hooksRefused(issue, pieces) {
|
|
389
392
|
const error = buildHooksRefusal(issue).message;
|
|
@@ -432,16 +435,12 @@ export function parseHooksConfig(raw) {
|
|
|
432
435
|
return hooksRefused({ reason: "unsupported_entry_type", path: [...at, "type"], type: contractEntry.type });
|
|
433
436
|
let entry = contractEntry;
|
|
434
437
|
if (entry.type === "command") {
|
|
435
|
-
const
|
|
436
|
-
const rawArgs = rawMember(rawEntry, "args");
|
|
437
|
-
const rawPlugin = rawMember(rawEntry, "plugin");
|
|
438
|
-
const args = rawArgs === undefined ? undefined : readHookArgs(rawArgs);
|
|
439
|
-
if (rawArgs !== undefined && args === undefined)
|
|
440
|
-
return hooksRefused({ reason: "wire_key_invalid", path: [...at, "args"], key: "args" });
|
|
438
|
+
const rawPlugin = rawMember(rawMember(rawMember(rawGroup, "hooks"), entryIndex), "plugin");
|
|
441
439
|
const plugin = rawPlugin === undefined ? undefined : readHookPlugin(rawPlugin);
|
|
442
440
|
if (rawPlugin !== undefined && plugin === undefined)
|
|
443
441
|
return hooksRefused({ reason: "wire_key_invalid", path: [...at, "plugin"], key: "plugin" });
|
|
444
|
-
|
|
442
|
+
if (plugin !== undefined)
|
|
443
|
+
entry = { ...entry, plugin };
|
|
445
444
|
const line = commandLineChars(entry);
|
|
446
445
|
if (line > MAX_HOOK_COMMAND_CHARS)
|
|
447
446
|
return hooksRefused(hooksCapIssue("command", event, [...at, "command"], line));
|
|
@@ -600,7 +599,7 @@ function noteMatcherOverBudget(ctx, args) {
|
|
|
600
599
|
detail: `${what} \`${expression}\` did not finish within ${budgetMs} ms on \`${value}\`; treated as selected (${count} ${count === 1 ? "entry" : "entries"})`,
|
|
601
600
|
});
|
|
602
601
|
}
|
|
603
|
-
function matcherGroupSelected(ctx, event, group, value, toolName) {
|
|
602
|
+
function matcherGroupSelected(ctx, event, group, value, toolName, entries) {
|
|
604
603
|
const answer = hookMatcherMatches(group.matcher, value);
|
|
605
604
|
switch (answer) {
|
|
606
605
|
case true:
|
|
@@ -611,7 +610,7 @@ function matcherGroupSelected(ctx, event, group, value, toolName) {
|
|
|
611
610
|
ctx.logger.warn("hook_matcher_invalid", { event, matcher: echoCallerText(group.matcher ?? "", { maxChars: MATCHER_ECHO_CHARS }) });
|
|
612
611
|
return "invalid";
|
|
613
612
|
case "over_budget":
|
|
614
|
-
noteMatcherOverBudget(ctx, { event, scope: "matcher", expression: group.matcher ?? "", value, entries
|
|
613
|
+
noteMatcherOverBudget(ctx, { event, scope: "matcher", expression: group.matcher ?? "", value, entries, ...(toolName !== undefined ? { toolName } : {}) });
|
|
615
614
|
return "over_budget";
|
|
616
615
|
default: {
|
|
617
616
|
const unreachable = answer;
|
|
@@ -654,6 +653,41 @@ export const PERMISSIVE_VERDICT_EVENTS = {
|
|
|
654
653
|
PreModelSwitch: false,
|
|
655
654
|
PostModelSwitch: false,
|
|
656
655
|
};
|
|
656
|
+
export const ON_FAILURE_BLOCK_EVENTS = {
|
|
657
|
+
PreToolUse: true,
|
|
658
|
+
PostToolUse: true,
|
|
659
|
+
PostToolUseFailure: true,
|
|
660
|
+
PostToolBatch: true,
|
|
661
|
+
Notification: true,
|
|
662
|
+
UserPromptSubmit: true,
|
|
663
|
+
UserPromptExpansion: true,
|
|
664
|
+
SessionStart: true,
|
|
665
|
+
SessionEnd: true,
|
|
666
|
+
Stop: false,
|
|
667
|
+
StopFailure: false,
|
|
668
|
+
SubagentStart: true,
|
|
669
|
+
SubagentStop: false,
|
|
670
|
+
PreCompact: true,
|
|
671
|
+
PostCompact: false,
|
|
672
|
+
PermissionRequest: true,
|
|
673
|
+
PermissionDenied: true,
|
|
674
|
+
Setup: true,
|
|
675
|
+
TeammateIdle: false,
|
|
676
|
+
TaskCreated: true,
|
|
677
|
+
TaskCompleted: false,
|
|
678
|
+
Elicitation: true,
|
|
679
|
+
ElicitationResult: true,
|
|
680
|
+
ConfigChange: true,
|
|
681
|
+
WorktreeCreate: true,
|
|
682
|
+
WorktreeRemove: true,
|
|
683
|
+
InstructionsLoaded: true,
|
|
684
|
+
CwdChanged: true,
|
|
685
|
+
FileChanged: true,
|
|
686
|
+
MessageDisplay: true,
|
|
687
|
+
DirectoryAdded: true,
|
|
688
|
+
PreModelSwitch: true,
|
|
689
|
+
PostModelSwitch: true,
|
|
690
|
+
};
|
|
657
691
|
const DISTRUST_DETAIL = {
|
|
658
692
|
input_truncated: `the hook did not receive the whole payload (tool_input over ${MAX_TOOL_INPUT_CHARS} characters was replaced by a truncation marker, or a prompt / agent entry's payload text was clipped at that size); its allow / updatedInput are not honored`,
|
|
659
693
|
matcher_over_budget: "the matcher (or the if condition's tool-name part) did not finish within its budget; the entry ran as selected, so its allow / updatedInput are not honored",
|
|
@@ -703,24 +737,26 @@ const VERDICT_GAP_CAUSE = {
|
|
|
703
737
|
input_truncated: "verdict_unreadable",
|
|
704
738
|
matcher_over_budget: "verdict_unreadable",
|
|
705
739
|
};
|
|
706
|
-
function createUnrunLedger(ctx, event, toolName) {
|
|
740
|
+
function createUnrunLedger(ctx, event, toolName, once) {
|
|
707
741
|
let managedVerdictGap;
|
|
708
742
|
let haltNoted = false;
|
|
709
743
|
const ledger = {
|
|
710
744
|
halted(source, entry) {
|
|
711
|
-
if (haltNoted)
|
|
745
|
+
if (haltNoted || !isSyncEntry(entry))
|
|
712
746
|
return;
|
|
713
747
|
haltNoted = true;
|
|
714
748
|
ledger.unrun(source, entry, "budget_exhausted", ENGINE_BUDGET_SPENT_DETAIL);
|
|
715
749
|
},
|
|
716
750
|
untrusted(source, entry, reason) {
|
|
751
|
+
once.unsettled(entry);
|
|
717
752
|
if (hookLaneOf(source) === "unmanaged")
|
|
718
753
|
return;
|
|
719
754
|
managedVerdictGap ??= VERDICT_GAP_CAUSE[reason];
|
|
720
755
|
noteVerdictUntrusted(ctx, { event, reason, entry, source, toolName });
|
|
721
756
|
},
|
|
722
757
|
unrun(source, entry, reason, detail) {
|
|
723
|
-
|
|
758
|
+
once.unsettled(entry);
|
|
759
|
+
if (source === undefined || hookLaneOf(source) === "unmanaged" || !isSyncEntry(entry))
|
|
724
760
|
return;
|
|
725
761
|
managedVerdictGap ??= VERDICT_GAP_CAUSE[reason];
|
|
726
762
|
ctx.logger.warn("hook_managed_unrun", { event, reason, source: echoCallerText(source), type: entry.type, ...(toolName !== undefined ? { tool: toolName } : {}) });
|
|
@@ -800,6 +836,13 @@ function withBelowContext(parts, below) {
|
|
|
800
836
|
const tail = belowString(below, "additionalContext");
|
|
801
837
|
return tail === undefined ? [...parts] : [...parts, tail];
|
|
802
838
|
}
|
|
839
|
+
const ALSO_ASKS_SPEAKER = {
|
|
840
|
+
managed: "a managed PreToolUse hook",
|
|
841
|
+
unmanaged: "a PreToolUse hook",
|
|
842
|
+
};
|
|
843
|
+
function alsoAsks(lane, below, own) {
|
|
844
|
+
return below === undefined || below === own ? own : `${below} (${ALSO_ASKS_SPEAKER[lane]} also asks: ${own})`;
|
|
845
|
+
}
|
|
803
846
|
function readBelowPreToolUse(below) {
|
|
804
847
|
const action = belowString(below, "action");
|
|
805
848
|
const message = belowString(below, "message") ?? "a PreToolUse hook requires approval";
|
|
@@ -812,7 +855,7 @@ function readBelowPreToolUse(below) {
|
|
|
812
855
|
allowed: action === "allow",
|
|
813
856
|
...(action === "ask" && (cause === undefined || cause === "asked") ? { asked: message } : {}),
|
|
814
857
|
...(action === "ask" && cause !== undefined && cause !== "asked" ? { unreadable: { message, cause: unreadableCause } } : {}),
|
|
815
|
-
|
|
858
|
+
...(action === "ask" && typeof below === "object" && below !== null && Object.hasOwn(below, "requiresRealApproval") && Reflect.get(below, "requiresRealApproval") === true ? { realApproval: true } : {}),
|
|
816
859
|
...(rewrite !== null && typeof rewrite === "object" ? { updatedInput: rewrite } : {}),
|
|
817
860
|
...(additionalContext !== undefined ? { additionalContext } : {}),
|
|
818
861
|
};
|
|
@@ -824,7 +867,65 @@ function spawnPlannedCommand(plan, ctx, stdio) {
|
|
|
824
867
|
const sh = hostShell();
|
|
825
868
|
return spawn(sh.shell, [...sh.args, plan.command], { cwd: ctx.cwd, env, stdio, detached: true });
|
|
826
869
|
}
|
|
827
|
-
|
|
870
|
+
function createHookTreeLadder(child, ctx, event) {
|
|
871
|
+
const leaderOurs = () => child.pid !== undefined && child.exitCode === null && child.signalCode === null;
|
|
872
|
+
const alive = () => leaderOurs() || (child.pid !== undefined && reapedLeaderGroupAlive(child.pid));
|
|
873
|
+
const shoot = (sig) => {
|
|
874
|
+
const pid = child.pid;
|
|
875
|
+
if (pid === undefined) {
|
|
876
|
+
child.kill(sig);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
if (leaderOurs()) {
|
|
880
|
+
signalProcessTree(pid, sig);
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
if (!reapedLeaderGroupAlive(pid))
|
|
884
|
+
return;
|
|
885
|
+
try {
|
|
886
|
+
(sig === "SIGTERM" ? killTreeSoft : killTreeHard)(pid);
|
|
887
|
+
}
|
|
888
|
+
catch {
|
|
889
|
+
child.kill(sig);
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
let hardFired = false;
|
|
893
|
+
const hard = (end) => {
|
|
894
|
+
if (hardFired)
|
|
895
|
+
return;
|
|
896
|
+
hardFired = true;
|
|
897
|
+
shoot("SIGKILL");
|
|
898
|
+
const recheck = setTimeout(() => {
|
|
899
|
+
const clean = !alive();
|
|
900
|
+
if (!clean)
|
|
901
|
+
shoot("SIGKILL");
|
|
902
|
+
const fields = { event, type: "command", end, shots: clean ? 1 : 2, clean };
|
|
903
|
+
if (clean)
|
|
904
|
+
ctx.logger.info("hook_command_tree_swept", fields);
|
|
905
|
+
else
|
|
906
|
+
ctx.logger.warn("hook_command_tree_swept", fields);
|
|
907
|
+
}, HOOK_KILL_GRACE_MS);
|
|
908
|
+
recheck.unref();
|
|
909
|
+
};
|
|
910
|
+
return {
|
|
911
|
+
halt(onEscalate) {
|
|
912
|
+
shoot("SIGTERM");
|
|
913
|
+
const escalate = setTimeout(() => {
|
|
914
|
+
if (hardFired || !alive())
|
|
915
|
+
return;
|
|
916
|
+
onEscalate();
|
|
917
|
+
hard("halt");
|
|
918
|
+
}, HOOK_KILL_GRACE_MS);
|
|
919
|
+
escalate.unref();
|
|
920
|
+
},
|
|
921
|
+
kill: hard,
|
|
922
|
+
ended() {
|
|
923
|
+
if (alive())
|
|
924
|
+
hard("exit");
|
|
925
|
+
},
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
async function runCommandHook(entry, payload, ctx, halt, event) {
|
|
828
929
|
const plan = await planCommandSpawn(entry, ctx.cwd, ctx.shellEnv);
|
|
829
930
|
if (plan.kind === "refused")
|
|
830
931
|
return { code: null, stdout: "", stderr: "", timedOut: false, spawnError: plan.error };
|
|
@@ -849,6 +950,7 @@ async function runCommandHook(entry, payload, ctx, halt) {
|
|
|
849
950
|
return;
|
|
850
951
|
}
|
|
851
952
|
const ticket = adoptHostForegroundChild(child);
|
|
953
|
+
const tree = createHookTreeLadder(child, ctx, event);
|
|
852
954
|
let stdout = "";
|
|
853
955
|
let stderr = "";
|
|
854
956
|
let timedOut = false;
|
|
@@ -867,40 +969,16 @@ async function runCommandHook(entry, payload, ctx, halt) {
|
|
|
867
969
|
timedOut = true;
|
|
868
970
|
if (sent !== undefined)
|
|
869
971
|
sent = "SIGKILL";
|
|
870
|
-
try {
|
|
871
|
-
if (child.pid)
|
|
872
|
-
process.kill(-child.pid, "SIGKILL");
|
|
873
|
-
else
|
|
874
|
-
child.kill("SIGKILL");
|
|
875
|
-
}
|
|
876
|
-
catch {
|
|
877
|
-
child.kill("SIGKILL");
|
|
878
|
-
}
|
|
879
972
|
settle(null);
|
|
973
|
+
tree.kill("timeout");
|
|
880
974
|
}, timeoutMs);
|
|
881
|
-
const signalGroup = (sig) => {
|
|
882
|
-
try {
|
|
883
|
-
if (child.pid)
|
|
884
|
-
(sig === "SIGTERM" ? killTreeSoft : killTreeHard)(child.pid);
|
|
885
|
-
else
|
|
886
|
-
child.kill(sig);
|
|
887
|
-
}
|
|
888
|
-
catch {
|
|
889
|
-
child.kill(sig);
|
|
890
|
-
}
|
|
891
|
-
};
|
|
892
975
|
const onHalt = () => {
|
|
893
976
|
if (settled)
|
|
894
977
|
return;
|
|
895
978
|
sent = "SIGTERM";
|
|
896
|
-
|
|
897
|
-
const escalate = setTimeout(() => {
|
|
898
|
-
if (child.exitCode !== null || child.signalCode !== null)
|
|
899
|
-
return;
|
|
979
|
+
tree.halt(() => {
|
|
900
980
|
sent = "SIGKILL";
|
|
901
|
-
|
|
902
|
-
}, HOOK_KILL_GRACE_MS);
|
|
903
|
-
escalate.unref();
|
|
981
|
+
});
|
|
904
982
|
};
|
|
905
983
|
halt.addEventListener("abort", onHalt, { once: true });
|
|
906
984
|
child.stdout?.on("data", (d) => {
|
|
@@ -919,7 +997,12 @@ async function runCommandHook(entry, payload, ctx, halt) {
|
|
|
919
997
|
resolve({ code: null, stdout, stderr, timedOut, spawnError: String(e) });
|
|
920
998
|
}
|
|
921
999
|
});
|
|
922
|
-
child.on("close", (code) =>
|
|
1000
|
+
child.on("close", (code) => {
|
|
1001
|
+
const natural = !settled && sent === undefined;
|
|
1002
|
+
settle(code);
|
|
1003
|
+
if (natural)
|
|
1004
|
+
tree.ended();
|
|
1005
|
+
});
|
|
923
1006
|
child.stdin?.on("error", () => { });
|
|
924
1007
|
child.stdin?.end(`${JSON.stringify(boundedToolInputPayload(payload))}\n`);
|
|
925
1008
|
});
|
|
@@ -937,18 +1020,11 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
|
|
|
937
1020
|
return;
|
|
938
1021
|
const child = spawnPlannedCommand(plan, ctx, ["pipe", "ignore", rewake ? "pipe" : "ignore"]);
|
|
939
1022
|
const ticket = adoptHostForegroundChild(child);
|
|
1023
|
+
const tree = createHookTreeLadder(child, ctx, event);
|
|
940
1024
|
let killedByTimeout = false;
|
|
941
1025
|
const timer = setTimeout(() => {
|
|
942
1026
|
killedByTimeout = true;
|
|
943
|
-
|
|
944
|
-
if (child.pid)
|
|
945
|
-
process.kill(-child.pid, "SIGKILL");
|
|
946
|
-
else
|
|
947
|
-
child.kill("SIGKILL");
|
|
948
|
-
}
|
|
949
|
-
catch {
|
|
950
|
-
child.kill("SIGKILL");
|
|
951
|
-
}
|
|
1027
|
+
tree.kill("timeout");
|
|
952
1028
|
}, timeoutMs);
|
|
953
1029
|
timer.unref?.();
|
|
954
1030
|
let stderr = "";
|
|
@@ -967,6 +1043,8 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
|
|
|
967
1043
|
child.on("close", (code) => {
|
|
968
1044
|
clearTimeout(timer);
|
|
969
1045
|
ticket?.release();
|
|
1046
|
+
if (!killedByTimeout)
|
|
1047
|
+
tree.ended();
|
|
970
1048
|
noteAsyncOutcome(entry, ctx, event, payload, { code, rewake, killedByTimeout });
|
|
971
1049
|
if (!rewake || code !== 2)
|
|
972
1050
|
return;
|
|
@@ -1086,6 +1164,7 @@ function httpHookWithheldSentence(event, block) {
|
|
|
1086
1164
|
return `settings.hooks.${event}: http hook not sent — ${why} (rule: ${block.rule}); ${exit}`;
|
|
1087
1165
|
}
|
|
1088
1166
|
const MAX_BLANKED_REFERENCES_LOGGED = 16;
|
|
1167
|
+
const httpHookFetch = createEgressFetch("declare the final address as this hook entry's url");
|
|
1089
1168
|
async function runHttpHook(entry, payload, ctx, event) {
|
|
1090
1169
|
const block = httpHookUrlVerdict(entry.url, ctx.httpHookAllowlistLayers, SERVER_WORKSPACE_TRUST);
|
|
1091
1170
|
if (block !== undefined)
|
|
@@ -1113,12 +1192,11 @@ async function runHttpHook(entry, payload, ctx, event) {
|
|
|
1113
1192
|
const ac = new AbortController();
|
|
1114
1193
|
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
1115
1194
|
try {
|
|
1116
|
-
const res = await
|
|
1195
|
+
const res = await httpHookFetch(entry.url, {
|
|
1117
1196
|
method: "POST",
|
|
1118
1197
|
headers,
|
|
1119
1198
|
body: `${JSON.stringify(boundedToolInputPayload(payload))}\n`,
|
|
1120
1199
|
signal: ac.signal,
|
|
1121
|
-
redirect: "error",
|
|
1122
1200
|
});
|
|
1123
1201
|
let body = "";
|
|
1124
1202
|
const reader = res.body?.getReader();
|
|
@@ -1190,18 +1268,39 @@ function boundedToolInputPayload(payload) {
|
|
|
1190
1268
|
return bounded === p.tool_input ? payload : { ...p, tool_input: bounded };
|
|
1191
1269
|
}
|
|
1192
1270
|
function readHookStdout(ran, event, ctx, payload, ledger) {
|
|
1193
|
-
const
|
|
1194
|
-
const out = parseHookStdout(run.stdout);
|
|
1271
|
+
const out = parseHookStdout(ran.run.stdout);
|
|
1195
1272
|
if (out !== undefined)
|
|
1196
1273
|
return out;
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
ctx.logger.warn("hook_bad_json_output", { event, type: entry.type, preview: seatText("operator-log-text", t) });
|
|
1200
|
-
noteHookFailure(ctx, { event, entry, reason: "bad_json", exitCode: run.code, stderr: run.stderr, toolName: toolNameOf(payload) });
|
|
1201
|
-
ledger.unrun(ran.source, entry, "bad_json");
|
|
1202
|
-
}
|
|
1274
|
+
if (stdoutVerdictUnreadable(ran.run.stdout))
|
|
1275
|
+
noteBadJson(ctx, ledger, event, ran, toolNameOf(payload));
|
|
1203
1276
|
return undefined;
|
|
1204
1277
|
}
|
|
1278
|
+
function stdoutVerdictUnreadable(stdout) {
|
|
1279
|
+
if (parseHookStdout(stdout) !== undefined)
|
|
1280
|
+
return false;
|
|
1281
|
+
const t = stdout.trim();
|
|
1282
|
+
return t.startsWith("{") || t.startsWith("[");
|
|
1283
|
+
}
|
|
1284
|
+
function noteBadJson(ctx, ledger, event, ran, toolName) {
|
|
1285
|
+
const { run, entry } = ran;
|
|
1286
|
+
ctx.logger.warn("hook_bad_json_output", { event, type: entry.type, preview: seatText("operator-log-text", run.stdout.trim()) });
|
|
1287
|
+
noteHookFailure(ctx, { event, entry, reason: "bad_json", exitCode: run.code, stderr: run.stderr, toolName });
|
|
1288
|
+
ledger.unrun(ran.source, entry, "bad_json");
|
|
1289
|
+
}
|
|
1290
|
+
const PERMISSION_DECISION_WORDS = new Set(["allow", "deny", "ask"]);
|
|
1291
|
+
function preToolUseDecisionOf(out) {
|
|
1292
|
+
const hso = out?.hookSpecificOutput;
|
|
1293
|
+
return hso !== null && typeof hso === "object" && hso.hookEventName === "PreToolUse" ? hso.permissionDecision : undefined;
|
|
1294
|
+
}
|
|
1295
|
+
function noteDecisionOutOfSet(ctx, ledger, ran, decision, toolName, effect) {
|
|
1296
|
+
ctx.logger.warn("hook_permission_decision_unknown", {
|
|
1297
|
+
event: "PreToolUse",
|
|
1298
|
+
decision: seatText("operator-log-text", typeof decision === "string" ? decision : typeof decision),
|
|
1299
|
+
tool: toolName,
|
|
1300
|
+
effect,
|
|
1301
|
+
});
|
|
1302
|
+
ledger.unrun(ran.source, ran.entry, "decision_out_of_set");
|
|
1303
|
+
}
|
|
1205
1304
|
function parseHookStdout(stdout) {
|
|
1206
1305
|
const t = stdout.trim();
|
|
1207
1306
|
if (!t.startsWith("{"))
|
|
@@ -1223,7 +1322,7 @@ function runRunnableEntry(entry, payload, ctx, event, llmExtra, halt) {
|
|
|
1223
1322
|
case "agent":
|
|
1224
1323
|
return runLlmHook(entry, payload, ctx, { system: ccAgentHookSystemFor(event), event });
|
|
1225
1324
|
case "command":
|
|
1226
|
-
return runCommandHook(entry, payload, ctx, halt);
|
|
1325
|
+
return runCommandHook(entry, payload, ctx, halt, event);
|
|
1227
1326
|
default: {
|
|
1228
1327
|
const unreachable = entry;
|
|
1229
1328
|
void unreachable;
|
|
@@ -1231,19 +1330,110 @@ function runRunnableEntry(entry, payload, ctx, event, llmExtra, halt) {
|
|
|
1231
1330
|
}
|
|
1232
1331
|
}
|
|
1233
1332
|
}
|
|
1333
|
+
async function settleOnce(spentOf, body) {
|
|
1334
|
+
const candidates = new Set();
|
|
1335
|
+
let refused = false;
|
|
1336
|
+
const once = {
|
|
1337
|
+
spent: (entry) => spentOf.has(entry),
|
|
1338
|
+
ran: (entry) => {
|
|
1339
|
+
if (entry.once)
|
|
1340
|
+
candidates.add(entry);
|
|
1341
|
+
},
|
|
1342
|
+
handedOff: (entry) => {
|
|
1343
|
+
if (entry.once)
|
|
1344
|
+
spentOf.add(entry);
|
|
1345
|
+
},
|
|
1346
|
+
unsettled: (entry) => {
|
|
1347
|
+
candidates.delete(entry);
|
|
1348
|
+
},
|
|
1349
|
+
refused: (answer) => {
|
|
1350
|
+
refused = true;
|
|
1351
|
+
return answer;
|
|
1352
|
+
},
|
|
1353
|
+
mark: () => {
|
|
1354
|
+
const at = new Set(candidates);
|
|
1355
|
+
return () => {
|
|
1356
|
+
candidates.clear();
|
|
1357
|
+
for (const entry of at)
|
|
1358
|
+
candidates.add(entry);
|
|
1359
|
+
};
|
|
1360
|
+
},
|
|
1361
|
+
};
|
|
1362
|
+
const answer = await body(once);
|
|
1363
|
+
if (!refused)
|
|
1364
|
+
for (const entry of candidates)
|
|
1365
|
+
spentOf.add(entry);
|
|
1366
|
+
return answer;
|
|
1367
|
+
}
|
|
1234
1368
|
function isSyncEntry(entry) {
|
|
1235
1369
|
return !(entry.type === "command" && (entry.async === true || entry.asyncRewake === true));
|
|
1236
1370
|
}
|
|
1237
|
-
|
|
1371
|
+
function blocksOnFailure(entry, event) {
|
|
1372
|
+
if (!ON_FAILURE_BLOCK_EVENTS[event] || !isSyncEntry(entry))
|
|
1373
|
+
return false;
|
|
1374
|
+
if (entry.type !== "command" && entry.type !== "http")
|
|
1375
|
+
return false;
|
|
1376
|
+
const word = entry.onFailure;
|
|
1377
|
+
switch (word) {
|
|
1378
|
+
case "block":
|
|
1379
|
+
return true;
|
|
1380
|
+
case "continue":
|
|
1381
|
+
case undefined:
|
|
1382
|
+
return false;
|
|
1383
|
+
default: {
|
|
1384
|
+
const unreachable = word;
|
|
1385
|
+
void unreachable;
|
|
1386
|
+
return true;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
function blockingFailureRun(event, cause) {
|
|
1391
|
+
return { code: 2, stdout: "", stderr: `${event} hook did not reach a verdict (${cause}); blocking because onFailure is "block"`, timedOut: false };
|
|
1392
|
+
}
|
|
1393
|
+
function ranVerdictFlaw(event, run) {
|
|
1394
|
+
if (run.code === 2)
|
|
1395
|
+
return undefined;
|
|
1396
|
+
if (run.code !== 0)
|
|
1397
|
+
return { reason: "exit_nonzero" };
|
|
1398
|
+
if (stdoutVerdictUnreadable(run.stdout))
|
|
1399
|
+
return { reason: "bad_json" };
|
|
1400
|
+
if (event !== "PreToolUse")
|
|
1401
|
+
return undefined;
|
|
1402
|
+
const out = parseHookStdout(run.stdout);
|
|
1403
|
+
if (out?.continue === false || out?.decision === "block")
|
|
1404
|
+
return undefined;
|
|
1405
|
+
const decision = preToolUseDecisionOf(out);
|
|
1406
|
+
return decision !== undefined && !PERMISSION_DECISION_WORDS.has(decision) ? { reason: "decision_out_of_set", decision } : undefined;
|
|
1407
|
+
}
|
|
1408
|
+
function noteRanVerdictFlaw(ctx, ledger, event, ran, flaw, toolName) {
|
|
1409
|
+
switch (flaw.reason) {
|
|
1410
|
+
case "exit_nonzero":
|
|
1411
|
+
noteExitNonzero(ctx, ledger, event, ran, toolName);
|
|
1412
|
+
return;
|
|
1413
|
+
case "bad_json":
|
|
1414
|
+
noteBadJson(ctx, ledger, event, ran, toolName);
|
|
1415
|
+
return;
|
|
1416
|
+
case "decision_out_of_set":
|
|
1417
|
+
noteDecisionOutOfSet(ctx, ledger, ran, flaw.decision, toolName, 'hook ruling not honored (closed word set is allow|deny|ask); the entry\'s onFailure is "block", so this call is denied');
|
|
1418
|
+
return;
|
|
1419
|
+
default: {
|
|
1420
|
+
const unreachable = flaw;
|
|
1421
|
+
void unreachable;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
async function runMatchingEntries(event, groups, matchValue, payload, ctx, once, halt, deadlineAt, ledger, llmExtra) {
|
|
1238
1426
|
const results = [];
|
|
1239
1427
|
let llmEntries = 0;
|
|
1240
1428
|
const toolName = toolNameOf(payload);
|
|
1241
1429
|
const inputTruncated = boundedToolInputPayload(payload) !== payload;
|
|
1242
1430
|
const truncatedFor = (entry) => (entry.type === "prompt" || entry.type === "agent" ? llmHookArguments(payload).truncated : inputTruncated);
|
|
1243
|
-
const
|
|
1431
|
+
const blockedBy = (entry, source, cause) => ({ entry, run: blockingFailureRun(event, cause), source });
|
|
1432
|
+
let laneSpent = false;
|
|
1433
|
+
const settle = async (entry) => {
|
|
1244
1434
|
if (halt.signal.aborted)
|
|
1245
1435
|
return { kind: "halted" };
|
|
1246
|
-
if (entry.once &&
|
|
1436
|
+
if (entry.once && once.spent(entry))
|
|
1247
1437
|
return { kind: "passed" };
|
|
1248
1438
|
let ifOverBudget = false;
|
|
1249
1439
|
if (entry.if !== undefined) {
|
|
@@ -1269,7 +1459,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1269
1459
|
}
|
|
1270
1460
|
if (entry.type === "command" && entry.shell === "powershell") {
|
|
1271
1461
|
ctx.logger.warn("hook_entries_skipped", { event, type: entry.type, reason: "powershell_not_supported" });
|
|
1272
|
-
return
|
|
1462
|
+
return { kind: "unrun", reason: "powershell_unsupported" };
|
|
1273
1463
|
}
|
|
1274
1464
|
if (entry.type === "prompt" || entry.type === "agent") {
|
|
1275
1465
|
const carrier = entry.type === "prompt" ? ctx.hookLlm : ctx.hookAgent;
|
|
@@ -1283,17 +1473,15 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1283
1473
|
}
|
|
1284
1474
|
}
|
|
1285
1475
|
if (entry.type === "command" && (entry.async || entry.asyncRewake)) {
|
|
1286
|
-
|
|
1287
|
-
onceFired.add(onceKey);
|
|
1476
|
+
once.handedOff(entry);
|
|
1288
1477
|
void fireAsyncCommandHook(entry, payload, ctx, event, halt.signal);
|
|
1289
1478
|
return { kind: "passed" };
|
|
1290
1479
|
}
|
|
1291
|
-
if (Date.now() > deadlineAt) {
|
|
1292
|
-
|
|
1480
|
+
if (laneSpent || Date.now() > deadlineAt) {
|
|
1481
|
+
if (!laneSpent)
|
|
1482
|
+
ctx.logger.warn("hook_event_deadline_exceeded", { event, budgetSec: MAX_HOOK_EVENT_TOTAL_SECONDS });
|
|
1293
1483
|
return { kind: "unrun", reason: "budget_exhausted" };
|
|
1294
1484
|
}
|
|
1295
|
-
if (entry.once)
|
|
1296
|
-
onceFired.add(onceKey);
|
|
1297
1485
|
if (entry.type === "prompt" || entry.type === "agent")
|
|
1298
1486
|
llmEntries++;
|
|
1299
1487
|
const run = await runRunnableEntry(entry, payload, ctx, event, llmExtra, halt.signal);
|
|
@@ -1326,20 +1514,35 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1326
1514
|
return { kind: "unrun", reason: "bad_json" };
|
|
1327
1515
|
return ifOverBudget ? { kind: "ran", run, overBudget: true } : { kind: "ran", run };
|
|
1328
1516
|
};
|
|
1329
|
-
for (const
|
|
1330
|
-
const
|
|
1517
|
+
for (const group of groups) {
|
|
1518
|
+
const pending = laneSpent ? group.hooks.filter((entry) => blocksOnFailure(entry, event)) : group.hooks;
|
|
1519
|
+
if (laneSpent && pending.length === 0)
|
|
1520
|
+
continue;
|
|
1521
|
+
const selected = matcherGroupSelected(ctx, event, group, matchValue, toolName, pending);
|
|
1331
1522
|
if (selected === "invalid") {
|
|
1332
|
-
for (const entry of
|
|
1333
|
-
if (
|
|
1523
|
+
for (const entry of pending) {
|
|
1524
|
+
if (!laneSpent)
|
|
1334
1525
|
ledger.unrun(group.source, entry, "matcher_invalid");
|
|
1526
|
+
if (blocksOnFailure(entry, event))
|
|
1527
|
+
results.push(blockedBy(entry, group.source, "matcher_invalid"));
|
|
1528
|
+
}
|
|
1335
1529
|
continue;
|
|
1336
1530
|
}
|
|
1337
1531
|
if (selected === false)
|
|
1338
1532
|
continue;
|
|
1339
|
-
for (const
|
|
1340
|
-
|
|
1533
|
+
for (const entry of group.hooks) {
|
|
1534
|
+
if (laneSpent && !blocksOnFailure(entry, event))
|
|
1535
|
+
continue;
|
|
1536
|
+
const fate = await settle(entry);
|
|
1341
1537
|
switch (fate.kind) {
|
|
1342
1538
|
case "ran": {
|
|
1539
|
+
once.ran(entry);
|
|
1540
|
+
const flaw = blocksOnFailure(entry, event) ? ranVerdictFlaw(event, fate.run) : undefined;
|
|
1541
|
+
if (flaw !== undefined) {
|
|
1542
|
+
noteRanVerdictFlaw(ctx, ledger, event, { entry, run: fate.run, source: group.source }, flaw, toolName);
|
|
1543
|
+
results.push(blockedBy(entry, group.source, flaw.reason));
|
|
1544
|
+
break;
|
|
1545
|
+
}
|
|
1343
1546
|
const distrust = !PERMISSIVE_VERDICT_EVENTS[event]
|
|
1344
1547
|
? undefined
|
|
1345
1548
|
: truncatedFor(entry)
|
|
@@ -1353,14 +1556,17 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1353
1556
|
break;
|
|
1354
1557
|
}
|
|
1355
1558
|
case "unrun":
|
|
1356
|
-
|
|
1559
|
+
if (!laneSpent)
|
|
1560
|
+
ledger.unrun(group.source, entry, fate.reason);
|
|
1561
|
+
if (blocksOnFailure(entry, event))
|
|
1562
|
+
results.push(blockedBy(entry, group.source, fate.reason));
|
|
1357
1563
|
if (fate.reason === "budget_exhausted")
|
|
1358
|
-
|
|
1564
|
+
laneSpent = true;
|
|
1359
1565
|
break;
|
|
1360
1566
|
case "passed":
|
|
1361
1567
|
break;
|
|
1362
1568
|
case "halted":
|
|
1363
|
-
if (
|
|
1569
|
+
if (halt.budgetSpent())
|
|
1364
1570
|
ledger.halted(group.source, entry);
|
|
1365
1571
|
return results;
|
|
1366
1572
|
default: {
|
|
@@ -1378,17 +1584,16 @@ function createEventClock() {
|
|
|
1378
1584
|
}
|
|
1379
1585
|
const ENGINE_BUDGET_SPENT_DETAIL = "the managed lane's handler ran past its engine budget (HOOKS_TIMEOUT_MS); the managed entries after this one did not run on this event";
|
|
1380
1586
|
function hookPhasesOf(groups) {
|
|
1381
|
-
|
|
1382
|
-
return HOOK_PHASES.map((phase) => ({ phase, groups: indexed.filter((g) => g.phase === phase).map(({ group, index }) => ({ group, index })) })).filter((l) => l.groups.length > 0);
|
|
1587
|
+
return HOOK_PHASES.map((phase) => ({ phase, groups: groups.filter((g) => hookPhaseOf(g.source) === phase) })).filter((l) => l.groups.length > 0);
|
|
1383
1588
|
}
|
|
1384
1589
|
function trustRank(phase) {
|
|
1385
1590
|
return HOOK_PHASES.length - 1 - HOOK_PHASES.indexOf(phase);
|
|
1386
1591
|
}
|
|
1387
|
-
async function runEventLanes(event, groups, matchValue, payload, ctx,
|
|
1592
|
+
async function runEventLanes(event, groups, matchValue, payload, ctx, once, halt, ledger, llmExtra) {
|
|
1388
1593
|
const deadline = createEventClock();
|
|
1389
1594
|
const ran = [];
|
|
1390
1595
|
for (const lane of hookPhasesOf(groups)) {
|
|
1391
|
-
for (const r of await runMatchingEntries(event, lane.groups, matchValue, payload, ctx,
|
|
1596
|
+
for (const r of await runMatchingEntries(event, lane.groups, matchValue, payload, ctx, once, halt, deadline(), ledger, llmExtra))
|
|
1392
1597
|
ran.push({ ...r, phase: lane.phase });
|
|
1393
1598
|
}
|
|
1394
1599
|
return ran.sort((a, b) => trustRank(a.phase) - trustRank(b.phase)).map(({ entry, run, source }) => ({ entry, run, source }));
|
|
@@ -1404,9 +1609,9 @@ function basePayload(ctx, permissionMode) {
|
|
|
1404
1609
|
function ignoreMatchers(groups) {
|
|
1405
1610
|
return groups.map((g) => (g.matcher === undefined ? g : { ...g, matcher: undefined }));
|
|
1406
1611
|
}
|
|
1407
|
-
async function runObserveOnlyEvent(event, groups, matchValue, payload, ctx,
|
|
1408
|
-
const ledger = createUnrunLedger(ctx, event, toolNameOf(payload));
|
|
1409
|
-
const singles = await runEventLanes(event, groups, matchValue, payload, ctx,
|
|
1612
|
+
async function runObserveOnlyEvent(event, groups, matchValue, payload, ctx, once, halt) {
|
|
1613
|
+
const ledger = createUnrunLedger(ctx, event, toolNameOf(payload), once);
|
|
1614
|
+
const singles = await runEventLanes(event, groups, matchValue, payload, ctx, once, halt, ledger);
|
|
1410
1615
|
for (const ran of singles) {
|
|
1411
1616
|
const { run } = ran;
|
|
1412
1617
|
if (run.code !== 0) {
|
|
@@ -1459,17 +1664,16 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1459
1664
|
if (!pre && !post && !postFailure && !postBatch && !promptSubmit && !stopEntries && !stopFailureEntries && !preCompactEntries && !postCompactEntries) {
|
|
1460
1665
|
return undefined;
|
|
1461
1666
|
}
|
|
1462
|
-
const
|
|
1667
|
+
const onceSpent = new Set();
|
|
1463
1668
|
const translators = {};
|
|
1464
1669
|
if (pre) {
|
|
1465
|
-
const tightenOnly =
|
|
1466
|
-
translators.PreToolUse =
|
|
1670
|
+
const tightenOnly = chainsBelowTaskOn(ctx.belowTaskChainPatterns, "classic.PreToolUse");
|
|
1671
|
+
translators.PreToolUse = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1467
1672
|
const prior = readBelowPreToolUse(below);
|
|
1468
|
-
const realApproval = prior.realApproval ? { requiresRealApproval: true } : {};
|
|
1469
1673
|
if (prior.denied)
|
|
1470
1674
|
return undefined;
|
|
1471
1675
|
const toolName = e.tool;
|
|
1472
|
-
const ledger = createUnrunLedger(ctx, "PreToolUse", toolName);
|
|
1676
|
+
const ledger = createUnrunLedger(ctx, "PreToolUse", toolName, once);
|
|
1473
1677
|
const deadline = createEventClock();
|
|
1474
1678
|
let currentInput = prior.updatedInput ?? e.input;
|
|
1475
1679
|
let rewritten = prior.updatedInput !== undefined;
|
|
@@ -1479,9 +1683,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1479
1683
|
let unknownDecision = false;
|
|
1480
1684
|
const contexts = { unmanaged: [], managedPlugin: [], managedPolicy: [] };
|
|
1481
1685
|
const contextField = () => buildHookContextField([...[...HOOK_PHASES].sort((a, b) => trustRank(a) - trustRank(b)).flatMap((p) => contexts[p]), ...(prior.additionalContext !== undefined ? [prior.additionalContext] : [])]);
|
|
1482
|
-
const
|
|
1686
|
+
const strictness = prior.realApproval === true ? { requiresRealApproval: true } : {};
|
|
1687
|
+
const runPass = async (phase, groups) => {
|
|
1483
1688
|
let rewroteBy;
|
|
1484
|
-
for (const
|
|
1689
|
+
for (const group of groups) {
|
|
1485
1690
|
const groupInput = currentInput;
|
|
1486
1691
|
const payload = {
|
|
1487
1692
|
...basePayload(ctx, e.permissionMode),
|
|
@@ -1490,7 +1695,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1490
1695
|
tool_input: groupInput,
|
|
1491
1696
|
tool_use_id: e.tool_use_id,
|
|
1492
1697
|
};
|
|
1493
|
-
const singles = await runMatchingEntries("PreToolUse", [
|
|
1698
|
+
const singles = await runMatchingEntries("PreToolUse", [group], toolName, payload, ctx, once, halt, deadline(), ledger);
|
|
1494
1699
|
for (const ran of singles) {
|
|
1495
1700
|
const { entry, run } = ran;
|
|
1496
1701
|
if (run.code === 2) {
|
|
@@ -1521,7 +1726,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1521
1726
|
contexts[phase].push(clipDataText(h.additionalContext, MAX_HOOK_FEEDBACK_CHARS));
|
|
1522
1727
|
spoke = true;
|
|
1523
1728
|
}
|
|
1524
|
-
const decision =
|
|
1729
|
+
const decision = preToolUseDecisionOf(out);
|
|
1525
1730
|
if (decision === "deny") {
|
|
1526
1731
|
const reason = clipDataText(typeof h.permissionDecisionReason === "string" ? h.permissionDecisionReason : "denied by a PreToolUse hook", MAX_HOOK_FEEDBACK_CHARS);
|
|
1527
1732
|
return { deny: { action: "deny", message: reason, ...contextField() } };
|
|
@@ -1529,10 +1734,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1529
1734
|
const proposed = h.updatedInput !== null && typeof h.updatedInput === "object" ? h.updatedInput : undefined;
|
|
1530
1735
|
const proposesRewrite = proposed !== undefined && canonicalJsonStringify(proposed) !== canonicalJsonStringify(groupInput);
|
|
1531
1736
|
if (tightenOnly && ran.distrust === undefined && (decision === "allow" || (proposesRewrite && (decision === "ask" || decision === undefined)))) {
|
|
1532
|
-
return { deny: { action: "deny", message: proposesRewrite ?
|
|
1737
|
+
return { deny: { action: "deny", message: proposesRewrite ? REQUEST_HOOK_REWRITE_UNSHOWN_REASON : REQUEST_HOOK_ALLOW_UNJUDGED_REASON, ...contextField() } };
|
|
1533
1738
|
}
|
|
1534
1739
|
if (decision === "ask") {
|
|
1535
|
-
asked = clipDataText(typeof h.permissionDecisionReason === "string" ? h.permissionDecisionReason : "a PreToolUse hook requires approval", MAX_HOOK_FEEDBACK_CHARS);
|
|
1740
|
+
asked = alsoAsks(lane, prior.asked ?? prior.unreadable?.message, clipDataText(typeof h.permissionDecisionReason === "string" ? h.permissionDecisionReason : "a PreToolUse hook requires approval", MAX_HOOK_FEEDBACK_CHARS));
|
|
1536
1741
|
spoke = true;
|
|
1537
1742
|
}
|
|
1538
1743
|
if (decision === "allow" || decision === undefined) {
|
|
@@ -1552,16 +1757,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1552
1757
|
spoke = true;
|
|
1553
1758
|
}
|
|
1554
1759
|
}
|
|
1555
|
-
else if (decision
|
|
1760
|
+
else if (!PERMISSION_DECISION_WORDS.has(decision)) {
|
|
1556
1761
|
unknownDecision = true;
|
|
1557
1762
|
spoke = true;
|
|
1558
|
-
ctx
|
|
1559
|
-
event: "PreToolUse",
|
|
1560
|
-
decision: seatText("operator-log-text", typeof decision === "string" ? decision : typeof decision),
|
|
1561
|
-
tool: toolName,
|
|
1562
|
-
effect: "hook ruling not honored (closed word set is allow|deny|ask); this call falls back to the engine gate",
|
|
1563
|
-
});
|
|
1564
|
-
ledger.unrun(ran.source, entry, "decision_out_of_set");
|
|
1763
|
+
noteDecisionOutOfSet(ctx, ledger, ran, decision, toolName, "hook ruling not honored (closed word set is allow|deny|ask); this call falls back to the engine gate");
|
|
1565
1764
|
}
|
|
1566
1765
|
}
|
|
1567
1766
|
}
|
|
@@ -1570,54 +1769,52 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1570
1769
|
};
|
|
1571
1770
|
for (const lane of hookPhasesOf(pre)) {
|
|
1572
1771
|
if (lane.phase === "unmanaged") {
|
|
1573
|
-
const pass = await runPass(lane.phase, lane.groups
|
|
1772
|
+
const pass = await runPass(lane.phase, lane.groups);
|
|
1574
1773
|
if (pass.deny !== undefined)
|
|
1575
|
-
return pass.deny;
|
|
1774
|
+
return once.refused(pass.deny);
|
|
1576
1775
|
continue;
|
|
1577
1776
|
}
|
|
1578
|
-
const
|
|
1579
|
-
const first = await runPass(lane.phase, lane.groups
|
|
1777
|
+
const rollback = once.mark();
|
|
1778
|
+
const first = await runPass(lane.phase, lane.groups);
|
|
1580
1779
|
if (first.deny !== undefined)
|
|
1581
|
-
return first.deny;
|
|
1780
|
+
return once.refused(first.deny);
|
|
1582
1781
|
if (first.rewroteBy === undefined)
|
|
1583
1782
|
continue;
|
|
1584
1783
|
contexts[lane.phase].length = 0;
|
|
1585
|
-
|
|
1586
|
-
const second = await runPass(lane.phase, lane.groups
|
|
1587
|
-
for (const key of rejudgeOnce)
|
|
1588
|
-
onceFired.add(key);
|
|
1784
|
+
rollback();
|
|
1785
|
+
const second = await runPass(lane.phase, lane.groups);
|
|
1589
1786
|
if (second.deny !== undefined)
|
|
1590
|
-
return second.deny;
|
|
1787
|
+
return once.refused(second.deny);
|
|
1591
1788
|
if (second.rewroteBy !== undefined) {
|
|
1592
1789
|
ledger.unrun(second.rewroteBy.source, second.rewroteBy.entry, "rewrite_unsettled", "the managed hooks of this phase rewrote the tool input again after being re-run on their own rewrite; approval required");
|
|
1593
1790
|
}
|
|
1594
1791
|
}
|
|
1595
1792
|
const managedGap = ledger.managedVerdictGap;
|
|
1596
|
-
if (
|
|
1793
|
+
if (!spoke && managedGap === undefined)
|
|
1597
1794
|
return undefined;
|
|
1598
1795
|
if (asked !== undefined) {
|
|
1599
|
-
return { action: "ask", message: asked, questionCause: "asked", ...(rewritten ? { updatedInput: currentInput } : {}), ...
|
|
1796
|
+
return { action: "ask", message: asked, questionCause: "asked", ...strictness, ...(rewritten ? { updatedInput: currentInput } : {}), ...contextField() };
|
|
1600
1797
|
}
|
|
1601
1798
|
if (managedGap !== undefined) {
|
|
1602
1799
|
return {
|
|
1603
1800
|
action: "ask",
|
|
1604
1801
|
message: "a managed PreToolUse hook did not run to a verdict — approval required",
|
|
1605
1802
|
questionCause: managedGap,
|
|
1803
|
+
...strictness,
|
|
1606
1804
|
...(rewritten ? { updatedInput: currentInput } : {}),
|
|
1607
|
-
...realApproval,
|
|
1608
1805
|
...contextField(),
|
|
1609
1806
|
};
|
|
1610
1807
|
}
|
|
1611
1808
|
if (prior.unreadable !== undefined) {
|
|
1612
|
-
return { action: "ask", message: prior.unreadable.message, questionCause: prior.unreadable.cause, ...(rewritten ? { updatedInput: currentInput } : {}), ...
|
|
1809
|
+
return { action: "ask", message: prior.unreadable.message, questionCause: prior.unreadable.cause, ...strictness, ...(rewritten ? { updatedInput: currentInput } : {}), ...contextField() };
|
|
1613
1810
|
}
|
|
1614
1811
|
if (unknownDecision) {
|
|
1615
1812
|
return {
|
|
1616
1813
|
action: "ask",
|
|
1617
1814
|
message: "a PreToolUse hook returned an unrecognized permissionDecision — approval required",
|
|
1618
1815
|
questionCause: "verdict_unreadable",
|
|
1816
|
+
...strictness,
|
|
1619
1817
|
...(rewritten ? { updatedInput: currentInput } : {}),
|
|
1620
|
-
...realApproval,
|
|
1621
1818
|
...contextField(),
|
|
1622
1819
|
};
|
|
1623
1820
|
}
|
|
@@ -1627,10 +1824,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1627
1824
|
if (rewritten || HOOK_PHASES.some((p) => contexts[p].length > 0) || prior.additionalContext !== undefined)
|
|
1628
1825
|
return carried;
|
|
1629
1826
|
return undefined;
|
|
1630
|
-
};
|
|
1827
|
+
});
|
|
1631
1828
|
}
|
|
1632
1829
|
if (post) {
|
|
1633
|
-
translators.PostToolUse =
|
|
1830
|
+
translators.PostToolUse = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1634
1831
|
const toolName = e.tool;
|
|
1635
1832
|
const input = e.input;
|
|
1636
1833
|
const output = e.output;
|
|
@@ -1646,8 +1843,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1646
1843
|
tool_response: { isError: output.isError, text: clipDataText(responseText, MAX_TOOL_RESPONSE_CHARS) },
|
|
1647
1844
|
tool_use_id: e.tool_use_id,
|
|
1648
1845
|
};
|
|
1649
|
-
const ledger = createUnrunLedger(ctx, "PostToolUse", toolName);
|
|
1650
|
-
const singles = await runEventLanes("PostToolUse", post, toolName, payload, ctx,
|
|
1846
|
+
const ledger = createUnrunLedger(ctx, "PostToolUse", toolName, once);
|
|
1847
|
+
const singles = await runEventLanes("PostToolUse", post, toolName, payload, ctx, once, halt, ledger);
|
|
1651
1848
|
for (const ran of singles) {
|
|
1652
1849
|
const { entry, run } = ran;
|
|
1653
1850
|
if (run.code === 2) {
|
|
@@ -1683,10 +1880,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1683
1880
|
if (contexts.length === 0)
|
|
1684
1881
|
return undefined;
|
|
1685
1882
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1686
|
-
};
|
|
1883
|
+
});
|
|
1687
1884
|
}
|
|
1688
1885
|
if (postFailure) {
|
|
1689
|
-
translators.PostToolUseFailure =
|
|
1886
|
+
translators.PostToolUseFailure = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1690
1887
|
const toolName = e.tool;
|
|
1691
1888
|
const f = e.failure;
|
|
1692
1889
|
const contexts = [];
|
|
@@ -1699,8 +1896,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1699
1896
|
error: clipDataText(f.error, MAX_TOOL_RESPONSE_CHARS),
|
|
1700
1897
|
is_interrupt: f.isInterrupt,
|
|
1701
1898
|
};
|
|
1702
|
-
const ledger = createUnrunLedger(ctx, "PostToolUseFailure", toolName);
|
|
1703
|
-
const singles = await runEventLanes("PostToolUseFailure", postFailure, toolName, payload, ctx,
|
|
1899
|
+
const ledger = createUnrunLedger(ctx, "PostToolUseFailure", toolName, once);
|
|
1900
|
+
const singles = await runEventLanes("PostToolUseFailure", postFailure, toolName, payload, ctx, once, halt, ledger);
|
|
1704
1901
|
for (const ran of singles) {
|
|
1705
1902
|
const { entry, run } = ran;
|
|
1706
1903
|
if (run.code === 2) {
|
|
@@ -1732,10 +1929,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1732
1929
|
if (contexts.length === 0)
|
|
1733
1930
|
return undefined;
|
|
1734
1931
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1735
|
-
};
|
|
1932
|
+
});
|
|
1736
1933
|
}
|
|
1737
1934
|
if (postBatch) {
|
|
1738
|
-
translators.PostToolBatch =
|
|
1935
|
+
translators.PostToolBatch = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1739
1936
|
const contexts = [];
|
|
1740
1937
|
const payload = {
|
|
1741
1938
|
...basePayload(ctx, e.permissionMode),
|
|
@@ -1747,8 +1944,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1747
1944
|
tool_response: { isError: c.isError, ...(c.response !== undefined ? { text: clipDataText(c.response, MAX_TOOL_RESPONSE_CHARS) } : {}) },
|
|
1748
1945
|
})),
|
|
1749
1946
|
};
|
|
1750
|
-
const ledger = createUnrunLedger(ctx, "PostToolBatch", undefined);
|
|
1751
|
-
const singles = await runEventLanes("PostToolBatch", ignoreMatchers(postBatch), "", payload, ctx,
|
|
1947
|
+
const ledger = createUnrunLedger(ctx, "PostToolBatch", undefined, once);
|
|
1948
|
+
const singles = await runEventLanes("PostToolBatch", ignoreMatchers(postBatch), "", payload, ctx, once, halt, ledger);
|
|
1752
1949
|
for (const ran of singles) {
|
|
1753
1950
|
const { entry, run } = ran;
|
|
1754
1951
|
if (run.code === 2) {
|
|
@@ -1776,19 +1973,19 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1776
1973
|
if (contexts.length === 0)
|
|
1777
1974
|
return undefined;
|
|
1778
1975
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1779
|
-
};
|
|
1976
|
+
});
|
|
1780
1977
|
}
|
|
1781
1978
|
if (promptSubmit) {
|
|
1782
|
-
translators.UserPromptSubmit =
|
|
1979
|
+
translators.UserPromptSubmit = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1783
1980
|
const contexts = [];
|
|
1784
1981
|
const payload = { ...basePayload(ctx, e.permissionMode), hook_event_name: "UserPromptSubmit", prompt: clipDataText(e.prompt, MAX_TOOL_INPUT_CHARS) };
|
|
1785
|
-
const ledger = createUnrunLedger(ctx, "UserPromptSubmit", undefined);
|
|
1786
|
-
const singles = await runEventLanes("UserPromptSubmit", ignoreMatchers(promptSubmit), "", payload, ctx,
|
|
1982
|
+
const ledger = createUnrunLedger(ctx, "UserPromptSubmit", undefined, once);
|
|
1983
|
+
const singles = await runEventLanes("UserPromptSubmit", ignoreMatchers(promptSubmit), "", payload, ctx, once, halt, ledger);
|
|
1787
1984
|
for (const ran of singles) {
|
|
1788
1985
|
const { entry, run } = ran;
|
|
1789
1986
|
if (run.code === 2) {
|
|
1790
1987
|
const reason = clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a UserPromptSubmit hook";
|
|
1791
|
-
return { block: reason, ...buildHookContextField(contexts) };
|
|
1988
|
+
return once.refused({ block: reason, ...buildHookContextField(contexts) });
|
|
1792
1989
|
}
|
|
1793
1990
|
if (run.code !== 0) {
|
|
1794
1991
|
noteExitNonzero(ctx, ledger, "UserPromptSubmit", ran);
|
|
@@ -1801,11 +1998,11 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1801
1998
|
logHookSystemMessage(ctx, "UserPromptSubmit", out.systemMessage);
|
|
1802
1999
|
if (out.continue === false) {
|
|
1803
2000
|
const reason = clipDataText(typeof out.stopReason === "string" ? out.stopReason : "hook requested stop", MAX_HOOK_FEEDBACK_CHARS);
|
|
1804
|
-
return { block: reason, ...buildHookContextField(contexts) };
|
|
2001
|
+
return once.refused({ block: reason, ...buildHookContextField(contexts) });
|
|
1805
2002
|
}
|
|
1806
2003
|
if (out.decision === "block") {
|
|
1807
2004
|
const reason = clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a UserPromptSubmit hook", MAX_HOOK_FEEDBACK_CHARS);
|
|
1808
|
-
return { block: reason, ...buildHookContextField(contexts) };
|
|
2005
|
+
return once.refused({ block: reason, ...buildHookContextField(contexts) });
|
|
1809
2006
|
}
|
|
1810
2007
|
const hso = out.hookSpecificOutput;
|
|
1811
2008
|
if (hso !== null && typeof hso === "object" && hso.hookEventName === "UserPromptSubmit") {
|
|
@@ -1817,10 +2014,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1817
2014
|
if (contexts.length === 0)
|
|
1818
2015
|
return undefined;
|
|
1819
2016
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1820
|
-
};
|
|
2017
|
+
});
|
|
1821
2018
|
}
|
|
1822
2019
|
if (stopEntries) {
|
|
1823
|
-
translators.Stop =
|
|
2020
|
+
translators.Stop = (sctx, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1824
2021
|
const payload = { ...basePayload(ctx, sctx.permissionMode), hook_event_name: "Stop", stop_hook_active: sctx.stopHookActive };
|
|
1825
2022
|
let llmExtra;
|
|
1826
2023
|
const wantsPrompt = stopEntries.some((g) => g.hooks.some((h) => h.type === "prompt"));
|
|
@@ -1848,7 +2045,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1848
2045
|
}
|
|
1849
2046
|
}
|
|
1850
2047
|
const stopGroups = ignoreMatchers(stopEntries);
|
|
1851
|
-
const ledger = createUnrunLedger(ctx, "Stop", undefined);
|
|
2048
|
+
const ledger = createUnrunLedger(ctx, "Stop", undefined, once);
|
|
1852
2049
|
if (!llmExtra && wantsPrompt) {
|
|
1853
2050
|
for (const g of stopGroups)
|
|
1854
2051
|
for (const h of g.hooks)
|
|
@@ -1858,7 +2055,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1858
2055
|
const effectiveGroups = llmExtra || !wantsPrompt
|
|
1859
2056
|
? stopGroups
|
|
1860
2057
|
: stopGroups.map((g) => ({ ...g, hooks: g.hooks.filter((h) => h.type !== "prompt") })).filter((g) => g.hooks.length > 0);
|
|
1861
|
-
const singles = await runEventLanes("Stop", effectiveGroups, "", payload, ctx,
|
|
2058
|
+
const singles = await runEventLanes("Stop", effectiveGroups, "", payload, ctx, once, halt, ledger, llmExtra);
|
|
1862
2059
|
let block;
|
|
1863
2060
|
let sawContinueFalse = false;
|
|
1864
2061
|
const contexts = [];
|
|
@@ -1912,15 +2109,16 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1912
2109
|
return undefined;
|
|
1913
2110
|
if (block === undefined && contexts.length === 0)
|
|
1914
2111
|
return undefined;
|
|
1915
|
-
|
|
2112
|
+
const answer = {
|
|
1916
2113
|
...belowMembers(below),
|
|
1917
2114
|
...(block !== undefined ? { block } : {}),
|
|
1918
2115
|
...buildHookContextField(withBelowContext(contexts, below)),
|
|
1919
2116
|
};
|
|
1920
|
-
|
|
2117
|
+
return block !== undefined ? once.refused(answer) : answer;
|
|
2118
|
+
});
|
|
1921
2119
|
}
|
|
1922
2120
|
if (stopFailureEntries) {
|
|
1923
|
-
translators.StopFailure =
|
|
2121
|
+
translators.StopFailure = (fctx, halt) => settleOnce(onceSpent, async (once) => {
|
|
1924
2122
|
const turnError = toAssistantTurnError(fctx.errorKind);
|
|
1925
2123
|
const payload = {
|
|
1926
2124
|
...basePayload(ctx, undefined),
|
|
@@ -1928,23 +2126,23 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1928
2126
|
error: turnError,
|
|
1929
2127
|
...(fctx.error ? { error_details: clipDataText(redactSecrets(fctx.error), MAX_HOOK_FEEDBACK_CHARS) } : {}),
|
|
1930
2128
|
};
|
|
1931
|
-
await runObserveOnlyEvent("StopFailure", stopFailureEntries, turnError, payload, ctx,
|
|
1932
|
-
};
|
|
2129
|
+
await runObserveOnlyEvent("StopFailure", stopFailureEntries, turnError, payload, ctx, once, halt);
|
|
2130
|
+
});
|
|
1933
2131
|
}
|
|
1934
2132
|
if (preCompactEntries) {
|
|
1935
|
-
translators.PreCompact =
|
|
2133
|
+
translators.PreCompact = (pctx, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1936
2134
|
const payload = {
|
|
1937
2135
|
...basePayload(ctx, undefined),
|
|
1938
2136
|
hook_event_name: "PreCompact",
|
|
1939
2137
|
trigger: pctx.trigger,
|
|
1940
2138
|
custom_instructions: pctx.customInstructions ?? null,
|
|
1941
2139
|
};
|
|
1942
|
-
const ledger = createUnrunLedger(ctx, "PreCompact", undefined);
|
|
1943
|
-
const singles = await runEventLanes("PreCompact", preCompactEntries, pctx.trigger, payload, ctx,
|
|
2140
|
+
const ledger = createUnrunLedger(ctx, "PreCompact", undefined, once);
|
|
2141
|
+
const singles = await runEventLanes("PreCompact", preCompactEntries, pctx.trigger, payload, ctx, once, halt, ledger);
|
|
1944
2142
|
for (const ran of singles) {
|
|
1945
2143
|
const { entry, run } = ran;
|
|
1946
2144
|
if (run.code === 2) {
|
|
1947
|
-
return { ...belowMembers(below), block: clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a PreCompact hook" };
|
|
2145
|
+
return once.refused({ ...belowMembers(below), block: clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a PreCompact hook" });
|
|
1948
2146
|
}
|
|
1949
2147
|
if (run.code !== 0) {
|
|
1950
2148
|
noteExitNonzero(ctx, ledger, "PreCompact", ran);
|
|
@@ -1959,31 +2157,31 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1959
2157
|
ctx.logger.warn("hook_continue_false_unsupported", { event: "PreCompact" });
|
|
1960
2158
|
}
|
|
1961
2159
|
if (out.decision === "block") {
|
|
1962
|
-
return { ...belowMembers(below), block: clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a PreCompact hook", MAX_HOOK_FEEDBACK_CHARS) };
|
|
2160
|
+
return once.refused({ ...belowMembers(below), block: clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a PreCompact hook", MAX_HOOK_FEEDBACK_CHARS) });
|
|
1963
2161
|
}
|
|
1964
2162
|
}
|
|
1965
2163
|
return undefined;
|
|
1966
|
-
};
|
|
2164
|
+
});
|
|
1967
2165
|
}
|
|
1968
2166
|
if (postCompactEntries) {
|
|
1969
|
-
translators.PostCompact =
|
|
2167
|
+
translators.PostCompact = (cctx, halt) => settleOnce(onceSpent, async (once) => {
|
|
1970
2168
|
const payload = {
|
|
1971
2169
|
...basePayload(ctx, undefined),
|
|
1972
2170
|
hook_event_name: "PostCompact",
|
|
1973
2171
|
trigger: cctx.trigger,
|
|
1974
2172
|
compact_summary: clipDataText(cctx.summary, MAX_TOOL_RESPONSE_CHARS),
|
|
1975
2173
|
};
|
|
1976
|
-
await runObserveOnlyEvent("PostCompact", postCompactEntries, cctx.trigger, payload, ctx,
|
|
1977
|
-
};
|
|
2174
|
+
await runObserveOnlyEvent("PostCompact", postCompactEntries, cctx.trigger, payload, ctx, once, halt);
|
|
2175
|
+
});
|
|
1978
2176
|
}
|
|
1979
2177
|
const events = Object.keys(translators);
|
|
1980
2178
|
return {
|
|
1981
2179
|
name: SETTINGS_HOOKS_REGISTRATIONS[lane],
|
|
1982
|
-
uses: { events: events.
|
|
2180
|
+
uses: { events: events.map((event) => SETTINGS_HOOK_STATIONS[event]), calls: [] },
|
|
1983
2181
|
budgetMs,
|
|
1984
2182
|
register(on) {
|
|
1985
2183
|
for (const event of events)
|
|
1986
|
-
hangTranslator(on, event, translators
|
|
2184
|
+
hangTranslator(on, event, translators);
|
|
1987
2185
|
},
|
|
1988
2186
|
};
|
|
1989
2187
|
}
|