@sema-agent/server 7.147.0 → 7.149.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 +1468 -24
- package/README.md +35 -7
- package/README.zh-CN.md +18 -8
- package/USAGE.md +444 -193
- package/deploy/sema-up/README.md +16 -5
- package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
- package/deploy/sema-up/chart/templates/_helpers.tpl +20 -4
- package/deploy/sema-up/chart/values.yaml +3 -2
- package/deploy/sema-up/cluster-up.sh +74 -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/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/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 +14 -39
- 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 +13 -1
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +21 -0
- 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/approval-card.d.ts +36 -38
- package/dist/approval-gate-currency.js +3 -2
- package/dist/approval-leg-origin.d.ts +33 -0
- package/dist/approval-leg-origin.js +4 -0
- package/dist/approval-reconciler.d.ts +4 -13
- package/dist/approval-reconciler.js +2 -2
- package/dist/approval.d.ts +13 -11
- package/dist/approval.js +3 -3
- package/dist/audit.d.ts +10 -3
- package/dist/audit.js +15 -7
- package/dist/auth-bridge.d.ts +9 -15
- package/dist/auth-bridge.js +4 -11
- package/dist/auth-keys.d.ts +10 -1
- package/dist/auth-keys.js +8 -0
- 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 +5 -2
- 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/deployment-mods.d.ts +1 -1
- package/dist/boot/execution-env.d.ts +17 -7
- package/dist/boot/execution-env.js +47 -42
- package/dist/boot/execution-lane.d.ts +6 -4
- package/dist/boot/execution-lane.js +3 -1
- package/dist/boot/exit-boundary.d.ts +2 -2
- package/dist/boot/exit-boundary.js +6 -5
- package/dist/boot/fatal-exit.d.ts +3 -5
- package/dist/boot/fatal-exit.js +2 -2
- package/dist/boot/leader.d.ts +15 -0
- package/dist/boot/leader.js +17 -15
- package/dist/boot/memory-consolidation.d.ts +37 -29
- package/dist/boot/memory-consolidation.js +11 -5
- package/dist/boot/org-delivery.d.ts +3 -2
- package/dist/boot/org-memory.js +1 -1
- package/dist/boot/parked-revive-gate.js +2 -2
- package/dist/boot/reapers.d.ts +4 -3
- package/dist/boot/reapers.js +19 -16
- package/dist/boot/resolve-spec.d.ts +5 -3
- package/dist/boot/resolve-spec.js +60 -70
- package/dist/boot/retention-lane.d.ts +4 -4
- package/dist/boot/retention-lane.js +2 -2
- package/dist/boot/runner-deps.d.ts +28 -7
- package/dist/boot/runner-deps.js +14 -5
- package/dist/boot/runtime-caps.d.ts +2 -2
- package/dist/boot/runtime-caps.js +16 -2
- package/dist/boot/session-faces.d.ts +16 -7
- package/dist/boot/session-faces.js +114 -94
- package/dist/boot/shutdown.d.ts +5 -4
- package/dist/boot/shutdown.js +6 -4
- package/dist/boot/stage-01-config.d.ts +1 -0
- package/dist/boot/stage-01-config.js +13 -4
- package/dist/boot/stage-02-web-admin-pull.d.ts +2 -0
- package/dist/boot/stage-02-web-admin-pull.js +16 -3
- package/dist/boot/stage-03-store-backend.d.ts +4 -0
- package/dist/boot/stage-03-store-backend.js +4 -3
- package/dist/boot/stage-04-stores.d.ts +3 -0
- package/dist/boot/stage-04-stores.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +8 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +12 -13
- package/dist/boot/stage-06-runners.js +23 -15
- package/dist/boot/stage-07-capability-layer.d.ts +13 -9
- package/dist/boot/stage-07-capability-layer.js +5 -3
- package/dist/boot/stage-08-reapers.d.ts +13 -9
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +14 -16
- package/dist/boot/stage-09-leader.js +12 -4
- package/dist/boot/stage-10-http-server.d.ts +14 -16
- package/dist/boot/stage-10-http-server.js +7 -4
- package/dist/boot/store-evidence.d.ts +20 -0
- package/dist/boot/store-evidence.js +13 -0
- package/dist/boot/stores.d.ts +6 -0
- package/dist/boot/stores.js +41 -27
- 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 +55 -35
- 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 +7 -1
- package/dist/capabilities/center-plugins.js +32 -10
- package/dist/capabilities/center-wiring.js +1 -1
- package/dist/capabilities/composite-members.d.ts +2 -2
- package/dist/capabilities/composite-members.js +2 -2
- package/dist/capabilities/repo-tools.d.ts +2 -0
- package/dist/capabilities/repo-tools.js +14 -12
- package/dist/capabilities/scenarios.d.ts +6 -15
- package/dist/capabilities/scenarios.js +11 -16
- package/dist/capabilities/skills.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +39 -11
- package/dist/capability-facts.js +35 -7
- package/dist/card-settle-stored-scope.d.ts +56 -0
- package/dist/card-settle-stored-scope.js +27 -0
- package/dist/card-void.d.ts +8 -13
- package/dist/card-void.js +2 -7
- package/dist/center-credential-renewer.d.ts +6 -2
- package/dist/center-credential-renewer.js +7 -3
- package/dist/config-catalog.d.ts +28 -1
- package/dist/config-catalog.js +95 -85
- package/dist/config-dir-trust.d.ts +37 -4
- package/dist/config-dir-trust.js +88 -44
- package/dist/config-invariants.d.ts +43 -3
- package/dist/config-invariants.js +69 -5
- package/dist/config-lkg.d.ts +23 -1
- package/dist/config-lkg.js +17 -3
- package/dist/config-provider.d.ts +9 -9
- package/dist/config-provider.js +25 -110
- package/dist/config-pull-failure.d.ts +50 -0
- package/dist/config-pull-failure.js +48 -0
- package/dist/config-types.d.ts +62 -21
- package/dist/config.d.ts +14 -21
- package/dist/config.js +141 -64
- package/dist/context-window-notice.d.ts +31 -0
- package/dist/context-window-notice.js +28 -0
- package/dist/delegated-session-owner.d.ts +1 -1
- package/dist/deleted-session-ids.d.ts +3 -2
- package/dist/deployment-governance.d.ts +3 -3
- package/dist/deployment-shape.d.ts +46 -11
- package/dist/deployment-shape.js +8 -0
- 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.js +2 -1
- package/dist/env-name-allowlist-knobs.d.ts +6 -5
- package/dist/env-name-allowlist-knobs.js +5 -0
- package/dist/env-witness.d.ts +7 -0
- package/dist/env-witness.js +16 -0
- package/dist/execution-lane-caps.d.ts +25 -23
- package/dist/execution-lane-caps.js +18 -26
- package/dist/execution-placement.d.ts +58 -18
- package/dist/execution-placement.js +41 -2
- 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.js +1 -0
- 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 +3 -3
- 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 +23 -3
- package/dist/history-anchor.js +24 -4
- 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 +7 -2
- package/dist/hooks/command-spawn.js +13 -6
- package/dist/hooks/hook-llm.d.ts +5 -1
- package/dist/hooks/hook-llm.js +24 -15
- package/dist/hooks/hook-runner.d.ts +72 -57
- package/dist/hooks/hook-runner.js +271 -193
- 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 +76 -79
- package/dist/http/approval-sweeps.d.ts +3 -3
- package/dist/http/approval-sweeps.js +56 -31
- package/dist/http/caller-trust.d.ts +8 -10
- package/dist/http/caller-trust.js +1 -2
- package/dist/http/claim-heartbeat.d.ts +49 -0
- package/dist/http/claim-heartbeat.js +46 -0
- package/dist/http/claimed-run.d.ts +16 -8
- package/dist/http/claimed-run.js +8 -0
- package/dist/http/dispatch.d.ts +8 -1
- package/dist/http/dispatch.js +78 -30
- package/dist/http/durable-run-leg.d.ts +11 -4
- package/dist/http/durable-run-leg.js +45 -21
- package/dist/http/execution-context.d.ts +122 -47
- package/dist/http/execution-context.js +135 -43
- 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 +4 -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 +1 -1
- package/dist/http/memory-store-refusal-reply.js +3 -0
- package/dist/http/owner-access.d.ts +392 -67
- package/dist/http/owner-access.js +370 -35
- package/dist/http/principal-gate.d.ts +39 -89
- package/dist/http/principal-gate.js +26 -68
- package/dist/http/refusal-body.d.ts +35 -2
- package/dist/http/refusal-body.js +34 -0
- package/dist/http/request-guards.d.ts +9 -13
- 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 +46 -12
- package/dist/http/resume-ctx-read.js +31 -6
- package/dist/http/resume-legs.d.ts +54 -19
- package/dist/http/resume-legs.js +408 -196
- package/dist/http/retired-skill-manifest.d.ts +1 -1
- package/dist/http/route-ctx.d.ts +31 -32
- package/dist/http/routes/a2a-serve.d.ts +43 -5
- package/dist/http/routes/a2a-serve.js +60 -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 -67
- 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 +16 -19
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.d.ts +3 -3
- package/dist/http/routes/devices.js +4 -4
- package/dist/http/routes/diagnostics.d.ts +29 -3
- package/dist/http/routes/diagnostics.js +49 -18
- 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 +2 -0
- 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 +10 -19
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/principal-inbox.d.ts +4 -2
- package/dist/http/routes/principal-inbox.js +5 -4
- package/dist/http/routes/projects.d.ts +1 -1
- package/dist/http/routes/projects.js +3 -2
- package/dist/http/routes/retention-ops.js +6 -9
- package/dist/http/routes/rules.js +20 -5
- 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 +155 -237
- 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 +28 -7
- package/dist/http/routes/session-sync.js +63 -50
- package/dist/http/routes/sessions-list.d.ts +3 -3
- package/dist/http/routes/sessions-list.js +9 -9
- package/dist/http/routes/sessions.js +87 -124
- package/dist/http/routes/shared-memory.js +6 -6
- package/dist/http/routes/side-query.js +2 -2
- package/dist/http/routes/tasks.js +237 -187
- 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 +43 -45
- package/dist/http/server.js +61 -11
- 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 +12 -0
- package/dist/http/stored-body-replay.js +2 -2
- package/dist/http/submit-ctx.d.ts +17 -8
- package/dist/http/submit-ctx.js +8 -5
- 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 +4 -3
- package/dist/identity-source.d.ts +36 -5
- package/dist/identity-source.js +27 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -0
- 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/leg-facts.d.ts +7 -2
- package/dist/leg-facts.js +1 -0
- package/dist/local-store-declaration.d.ts +54 -0
- package/dist/local-store-declaration.js +59 -0
- package/dist/lsp-evict.d.ts +6 -4
- package/dist/lsp-evict.js +2 -3
- package/dist/mcp-assertion-header.d.ts +1 -1
- package/dist/mcp-assertion-header.js +1 -1
- package/dist/memory-operator-faces.d.ts +5 -4
- package/dist/memory-operator-faces.js +1 -1
- package/dist/memory-project-layer.js +1 -1
- package/dist/memory-scope.d.ts +33 -6
- package/dist/memory-scope.js +68 -19
- package/dist/memory-store-refusal.d.ts +5 -2
- package/dist/memory-sync-client.d.ts +3 -2
- package/dist/memory-sync-client.js +8 -5
- package/dist/model-compat.d.ts +17 -8
- package/dist/model-compat.js +6 -2
- package/dist/model-context-window.d.ts +57 -0
- package/dist/model-context-window.js +21 -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 +40 -20
- package/dist/model-entry-refusal.js +57 -30
- 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-reach-scope.d.ts +2 -1
- 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 +23 -14
- package/dist/namespaced-rule-name.js +8 -11
- 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 +72 -40
- package/dist/observability/fail-open.js +74 -40
- package/dist/observability/logger.d.ts +22 -1
- package/dist/observability/logger.js +89 -12
- package/dist/observability/metrics.js +4 -5
- 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 +6 -2
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- 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-completion-inbox.d.ts +3 -3
- package/dist/orchestration/workflow-completion-inbox.js +3 -2
- package/dist/org-delivery-gate.d.ts +36 -10
- package/dist/org-delivery-gate.js +12 -8
- 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 +532 -0
- package/dist/owner-faces.js +126 -0
- package/dist/park-row-commit.d.ts +67 -0
- package/dist/park-row-commit.js +76 -0
- package/dist/parked-decide.d.ts +76 -12
- package/dist/parked-decide.js +152 -11
- package/dist/parked-revive-surface.d.ts +14 -4
- package/dist/parked-revive-surface.js +5 -4
- package/dist/peer-directory.d.ts +7 -9
- 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 +3 -25
- package/dist/plugins/adoption-log-sql.js +23 -21
- 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 +18 -7
- package/dist/plugins/approval-ask-store-file.js +37 -14
- package/dist/plugins/approval-ask-store-memory.d.ts +12 -4
- package/dist/plugins/approval-ask-store-memory.js +24 -10
- package/dist/plugins/approval-ask-store-sql.d.ts +40 -21
- package/dist/plugins/approval-ask-store-sql.js +44 -15
- package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
- package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
- package/dist/plugins/approval-exemption-skill-m46.d.ts +14 -0
- package/dist/plugins/approval-exemption-skill-m46.js +21 -0
- package/dist/plugins/approval-exemption-store.d.ts +32 -2
- package/dist/plugins/approval-exemption-store.js +42 -19
- 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 +2 -0
- package/dist/plugins/blob-backend.js +9 -6
- package/dist/plugins/caching-session-store.d.ts +13 -1
- package/dist/plugins/caching-session-store.js +43 -4
- package/dist/plugins/checkpoint-index-columns.d.ts +32 -5
- package/dist/plugins/checkpoint-index-columns.js +36 -1
- package/dist/plugins/checkpoint-store-face.d.ts +83 -10
- package/dist/plugins/checkpoint-store-face.js +18 -1
- package/dist/plugins/device-store-sql.js +1 -0
- 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 +36 -18
- package/dist/plugins/ensure-schema-lock-policy.js +76 -9
- package/dist/plugins/file-run-store.d.ts +85 -32
- package/dist/plugins/file-run-store.js +177 -94
- 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 +2 -2
- 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 +62 -23
- package/dist/plugins/local-checkpoint-store.js +197 -77
- package/dist/plugins/local-data-dir-modes-m39.js +2 -1
- package/dist/plugins/local-data-root-admission.d.ts +52 -0
- package/dist/plugins/local-data-root-admission.js +100 -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 +29 -6
- package/dist/plugins/local-engine-high-water.js +27 -19
- package/dist/plugins/local-session-store.d.ts +458 -140
- package/dist/plugins/local-session-store.js +906 -292
- 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 +18 -1
- package/dist/plugins/local-task-attachment-store.js +22 -1
- package/dist/plugins/memory-embedder.js +9 -7
- package/dist/plugins/memory-engine-pg.d.ts +3 -2
- package/dist/plugins/memory-engine-pg.js +14 -5
- package/dist/plugins/memory-engine-sql-apply.d.ts +8 -4
- package/dist/plugins/memory-engine-sql-apply.js +6 -8
- package/dist/plugins/memory-engine-tidb.d.ts +4 -2
- package/dist/plugins/memory-engine-tidb.js +11 -2
- 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 +53 -36
- package/dist/plugins/memory-run-store.js +116 -88
- package/dist/plugins/one-time-migration-marker.d.ts +26 -0
- package/dist/plugins/one-time-migration-marker.js +13 -0
- package/dist/plugins/one-time-migrations.d.ts +214 -47
- package/dist/plugins/one-time-migrations.js +481 -135
- package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
- package/dist/plugins/org-delivery-quota-store.js +31 -15
- package/dist/plugins/permission-rule-store-file.d.ts +3 -3
- package/dist/plugins/permission-rule-store-sql.d.ts +5 -64
- package/dist/plugins/permission-rule-store-sql.js +11 -95
- package/dist/plugins/pg-pool.d.ts +2 -32
- package/dist/plugins/pg-pool.js +24 -17
- package/dist/plugins/remote-env-device.d.ts +3 -2
- package/dist/plugins/remote-env-e2b.d.ts +8 -32
- package/dist/plugins/remote-env-e2b.js +44 -32
- package/dist/plugins/remote-env-host.d.ts +51 -17
- package/dist/plugins/remote-env-host.js +111 -42
- package/dist/plugins/remote-env-k8s.d.ts +40 -45
- package/dist/plugins/remote-env-k8s.js +111 -60
- package/dist/plugins/remote-env-local-docker.d.ts +152 -15
- package/dist/plugins/remote-env-local-docker.js +352 -72
- package/dist/plugins/remote-scratchpad.js +4 -0
- package/dist/plugins/retention-deployment.d.ts +49 -17
- package/dist/plugins/retention-deployment.js +39 -8
- 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 +82 -75
- package/dist/plugins/run-store-sql.js +164 -125
- 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 +56 -0
- package/dist/plugins/scenario-prefix-switch-m42.js +56 -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 +131 -14
- package/dist/plugins/schema-consistency.js +388 -18
- package/dist/plugins/schema-drift-sentence.d.ts +10 -6
- package/dist/plugins/schema-drift-sentence.js +15 -7
- package/dist/plugins/schema-ensure-legs.d.ts +9 -0
- package/dist/plugins/schema-ensure-legs.js +1 -1
- 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 +27 -3
- package/dist/plugins/session-ext-table.js +19 -6
- package/dist/plugins/session-fork.d.ts +15 -1
- package/dist/plugins/session-fork.js +3 -0
- package/dist/plugins/session-ownership.d.ts +1 -1
- package/dist/plugins/session-placement.d.ts +27 -20
- package/dist/plugins/session-placement.js +15 -12
- package/dist/plugins/session-row-sql.d.ts +12 -0
- package/dist/plugins/session-row-sql.js +3 -3
- 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 +38 -12
- package/dist/plugins/session-store-sql.js +130 -30
- package/dist/plugins/session-withdraw-sql.d.ts +36 -0
- package/dist/plugins/session-withdraw-sql.js +42 -0
- package/dist/plugins/shared-memory-store-sql.d.ts +0 -69
- package/dist/plugins/shared-memory-store-sql.js +2 -1
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +42 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +9 -0
- package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
- package/dist/plugins/sql-driver.d.ts +1 -1
- package/dist/plugins/sql-driver.js +2 -1
- package/dist/plugins/sql-errors.d.ts +32 -5
- package/dist/plugins/sql-errors.js +55 -7
- package/dist/plugins/sql-json-column.d.ts +8 -7
- package/dist/plugins/sql-json-column.js +10 -6
- package/dist/plugins/stop-then-start-sentence.d.ts +16 -0
- package/dist/plugins/stop-then-start-sentence.js +7 -0
- package/dist/plugins/store-backend.d.ts +99 -16
- package/dist/plugins/store-backend.js +230 -65
- package/dist/plugins/store-contracts.d.ts +123 -33
- package/dist/plugins/store-contracts.js +38 -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 +15 -3
- package/dist/plugins/task-attachment-store.js +22 -9
- package/dist/plugins/tidb-pool.d.ts +11 -6
- package/dist/plugins/tidb-pool.js +39 -18
- 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/plugins/workspace-custody.d.ts +44 -0
- package/dist/plugins/workspace-custody.js +47 -0
- 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/project-identity.d.ts +8 -7
- package/dist/project-identity.js +40 -17
- package/dist/project-layer-key.d.ts +13 -2
- package/dist/project-layer-key.js +9 -1
- package/dist/question.d.ts +13 -23
- package/dist/question.js +21 -39
- package/dist/read-deny-floor-notice.d.ts +36 -0
- package/dist/read-deny-floor-notice.js +40 -0
- package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
- package/dist/request-declaration-disposition.js +39 -0
- 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/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 +5 -3
- package/dist/rules-consent.js +1 -0
- package/dist/run-acceptance.d.ts +3 -1
- package/dist/run-acceptance.js +3 -0
- package/dist/run-cancel-card.d.ts +28 -0
- package/dist/run-cancel-card.js +19 -0
- package/dist/run-cancel-context.d.ts +10 -0
- package/dist/run-cancel-context.js +1 -0
- package/dist/run-local.d.ts +14 -6
- package/dist/run-local.js +117 -90
- package/dist/run-stale-default.d.ts +7 -0
- package/dist/run-stale-default.js +2 -0
- package/dist/runs.d.ts +56 -21
- package/dist/runs.js +73 -43
- package/dist/runtime-caps-resolver.d.ts +21 -6
- package/dist/runtime-caps-resolver.js +17 -4
- package/dist/runtime-governance.d.ts +2 -2
- package/dist/runtime-governance.js +5 -3
- package/dist/sealed-key-layout.d.ts +12 -5
- package/dist/sealed-key-layout.js +5 -0
- package/dist/sealed-key.d.ts +12 -2
- package/dist/sealed-key.js +115 -27
- package/dist/security.d.ts +128 -158
- package/dist/security.js +163 -59
- package/dist/sema-config-dir.d.ts +20 -0
- package/dist/sema-config-dir.js +25 -0
- package/dist/server-secret-env.d.ts +55 -25
- package/dist/server-secret-env.js +75 -22
- package/dist/session-agent.d.ts +3 -2
- package/dist/session-children-retire.d.ts +13 -8
- package/dist/session-children-retire.js +9 -7
- 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 +5 -5
- package/dist/session-error-wire.js +1 -1
- package/dist/session-incarnation.d.ts +52 -5
- 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 +0 -71
- package/dist/session-resident-background.js +4 -3
- package/dist/session-row.d.ts +2 -1
- package/dist/session-rules-seat.d.ts +12 -0
- package/dist/session-rules-seat.js +19 -0
- package/dist/session-titler.d.ts +7 -15
- package/dist/session-titler.js +1 -1
- package/dist/session-workspace.d.ts +3 -3
- package/dist/spec-fields.d.ts +57 -3
- package/dist/spec-fields.js +72 -51
- package/dist/store-admission.d.ts +33 -0
- package/dist/store-admission.js +49 -0
- package/dist/store-posture.d.ts +141 -20
- package/dist/store-posture.js +205 -3
- package/dist/stored-request-hooks-m20.js +2 -2
- 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/checkpoint-store-sql.d.ts +34 -29
- package/dist/stores-sql/checkpoint-store-sql.js +78 -49
- package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
- package/dist/stores-sql/file-history-store-sql.js +3 -5
- package/dist/stores-sql/mailbox-store-sql.d.ts +7 -4
- package/dist/stores-sql/mailbox-store-sql.js +31 -32
- package/dist/stores-sql/pg-session-storage.d.ts +7 -5
- package/dist/stores-sql/pg-session-storage.js +54 -46
- package/dist/stores-sql/retention-store-sql.d.ts +87 -19
- package/dist/stores-sql/retention-store-sql.js +92 -27
- package/dist/stores-sql/session-policy-store-sql.d.ts +32 -10
- package/dist/stores-sql/session-policy-store-sql.js +44 -36
- package/dist/stores-sql/session-write-hooks.d.ts +12 -6
- package/dist/stores-sql/tidb-session-storage.d.ts +4 -4
- package/dist/stores-sql/tidb-session-storage.js +13 -8
- package/dist/stores-sql/tidb-session-store.d.ts +36 -17
- package/dist/stores-sql/tidb-session-store.js +69 -39
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +4 -6
- package/dist/stores-sql/windowed-session-storage.d.ts +5 -0
- package/dist/stores-sql/windowed-session-storage.js +9 -0
- package/dist/submission-exit.d.ts +50 -0
- package/dist/submission-exit.js +108 -0
- package/dist/task-a2a.d.ts +3 -8
- package/dist/task-a2a.js +28 -30
- package/dist/task-cwd.d.ts +43 -7
- package/dist/task-cwd.js +11 -0
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +4 -4
- package/dist/task-settings.d.ts +14 -10
- package/dist/task-settings.js +19 -7
- package/dist/terminal.d.ts +27 -43
- package/dist/terminal.js +49 -14
- package/dist/tool-approval.d.ts +173 -163
- package/dist/tool-approval.js +247 -232
- package/dist/trace/core-keyset-guard.d.ts +13 -6
- 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 +24 -21
- package/dist/trace/engine-notice-wire.js +7 -3
- package/dist/trace/exit-seat.d.ts +30 -4
- package/dist/trace/exit-seat.js +40 -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 +4 -31
- 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 +59 -44
- package/dist/trace/project.js +60 -26
- package/dist/trace/redact.d.ts +135 -27
- package/dist/trace/redact.js +884 -260
- package/dist/trace/self-minted-wire.d.ts +567 -20
- package/dist/trace/self-minted-wire.js +205 -24
- package/dist/trace/wire-projection-faces.d.ts +5 -6
- package/dist/trace/wire-projection-faces.js +2 -2
- 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 -23
- 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/center-request.d.ts +2 -2
- package/dist/web-admin-client/center-request.js +15 -15
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.js +1 -1
- 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/http-client.d.ts +1 -1
- package/dist/web-admin-client/http-client.js +23 -4
- 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 +8 -4
- package/dist/web-admin-client/skills-mcp.d.ts +2 -2
- package/dist/web-admin-client/types.d.ts +1 -2
- package/dist/workspace-space.d.ts +3 -2
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +4 -4
- package/docs/error-text-lexicon.json +317 -0
- package/package.json +8 -3
- package/scripts/drain-check-local.mjs +118 -147
- package/scripts/drain-check.mysql.sql +22 -2
- package/scripts/drain-check.pg.sql +22 -2
- package/scripts/embed-minimal.mjs +183 -0
- package/wire-changes/server@7.148.0.json +1517 -0
- package/wire-changes/server@7.149.0.json +372 -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
- package/dist/plain-string-record.js +0 -70
|
@@ -1,22 +1,24 @@
|
|
|
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";
|
|
@@ -34,39 +36,37 @@ const MIN_HOOK_CONTEXT_PARTIAL_CHARS = 256;
|
|
|
34
36
|
const MAX_TOOL_RESPONSE_CHARS = 32_768;
|
|
35
37
|
const MAX_TOOL_INPUT_CHARS = 262_144;
|
|
36
38
|
const HOOK_ENV_ALLOWLIST = ["PATH", "HOME", "SHELL", "USER", "LOGNAME", "TERM", "TZ", "LANG", "LC_ALL", "LC_CTYPE", "LC_MESSAGES", "TMPDIR"];
|
|
37
|
-
function hookChildEnv(layer, spawning) {
|
|
38
|
-
const o = { policy: [...HOOK_ENV_ALLOWLIST], allow:
|
|
39
|
+
function hookChildEnv(layer, putBack, spawning) {
|
|
40
|
+
const o = { policy: [...HOOK_ENV_ALLOWLIST], allow: putBack, grants: [layer] };
|
|
39
41
|
return spawning ? hostSubprocessEnv({ site: "server.hooks.spawn-env", ...o }) : composeHostSubprocessEnv(o);
|
|
40
42
|
}
|
|
43
|
+
function hookChildView(ctx) {
|
|
44
|
+
return (layer) => hookChildEnv(layer, ctx.hookEnvAllow, false);
|
|
45
|
+
}
|
|
41
46
|
function hookEnv(ctx) {
|
|
42
|
-
return
|
|
47
|
+
return hookChildView(ctx)(composeHookEnvLayer(ctx.shellEnv, ctx.cwd, undefined));
|
|
43
48
|
}
|
|
44
49
|
export const SETTINGS_HOOK_STATIONS = {
|
|
45
|
-
PreToolUse:
|
|
46
|
-
PostToolUse:
|
|
47
|
-
PostToolUseFailure:
|
|
48
|
-
PostToolBatch:
|
|
49
|
-
UserPromptSubmit:
|
|
50
|
-
Stop:
|
|
51
|
-
StopFailure:
|
|
52
|
-
PreCompact:
|
|
53
|
-
PostCompact:
|
|
50
|
+
PreToolUse: "classic.PreToolUse",
|
|
51
|
+
PostToolUse: "classic.PostToolUse",
|
|
52
|
+
PostToolUseFailure: "classic.PostToolUseFailure",
|
|
53
|
+
PostToolBatch: "classic.PostToolBatch",
|
|
54
|
+
UserPromptSubmit: "classic.UserPromptSubmit",
|
|
55
|
+
Stop: "classic.Stop",
|
|
56
|
+
StopFailure: "classic.StopFailure",
|
|
57
|
+
PreCompact: "classic.PreCompact",
|
|
58
|
+
PostCompact: "classic.PostCompact",
|
|
54
59
|
};
|
|
55
60
|
function chainsBelowTaskOn(patterns, station) {
|
|
56
61
|
return patterns.some((p) => p === station || (p.endsWith(".*") && station.startsWith(p.slice(0, -1))));
|
|
57
62
|
}
|
|
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) {
|
|
63
|
+
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";
|
|
64
|
+
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";
|
|
65
|
+
function hangTranslator(on, event, translators) {
|
|
64
66
|
const translate = translators[event];
|
|
65
67
|
if (translate === undefined)
|
|
66
68
|
return;
|
|
67
|
-
|
|
68
|
-
for (const station of SETTINGS_HOOK_STATIONS[event])
|
|
69
|
-
hang(on, station, translate);
|
|
69
|
+
hangClassic(on, SETTINGS_HOOK_STATIONS[event], translate);
|
|
70
70
|
}
|
|
71
71
|
export const SETTINGS_HOOKS_REGISTRATIONS = {
|
|
72
72
|
managed: "settings.hooks.managed",
|
|
@@ -242,54 +242,61 @@ function hooksCapIssue(limit, event, path, count) {
|
|
|
242
242
|
}
|
|
243
243
|
const matcherPath = (event, groupIndex) => ["hooks", event, groupIndex, "matcher"];
|
|
244
244
|
export function buildHooksRefusal(issue) {
|
|
245
|
-
const field = "settings.hooks";
|
|
246
245
|
switch (issue.reason) {
|
|
247
|
-
case "dead_alias":
|
|
246
|
+
case "dead_alias": {
|
|
247
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
248
248
|
return {
|
|
249
249
|
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}"`,
|
|
250
|
-
field,
|
|
251
|
-
detail: { reason: issue.reason, event: issue.event, alias: issue.alias, canonical: issue.canonical, path: matcherPath(issue.event, issue.groupIndex) },
|
|
250
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, alias: issue.alias, canonical: issue.canonical },
|
|
252
251
|
};
|
|
253
|
-
|
|
252
|
+
}
|
|
253
|
+
case "over_budget": {
|
|
254
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
254
255
|
return {
|
|
255
|
-
message:
|
|
256
|
-
field,
|
|
257
|
-
detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, budgetMs: issue.budgetMs, path: matcherPath(issue.event, issue.groupIndex) },
|
|
256
|
+
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`,
|
|
257
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, budgetMs: issue.budgetMs },
|
|
258
258
|
};
|
|
259
|
-
|
|
259
|
+
}
|
|
260
|
+
case "budget_exceeded": {
|
|
261
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
260
262
|
return {
|
|
261
|
-
message:
|
|
262
|
-
field,
|
|
263
|
-
detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, totalMs: issue.totalMs, path: matcherPath(issue.event, issue.groupIndex) },
|
|
263
|
+
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`,
|
|
264
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, totalMs: issue.totalMs },
|
|
264
265
|
};
|
|
265
|
-
|
|
266
|
+
}
|
|
267
|
+
case "invalid_regex": {
|
|
268
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
266
269
|
return {
|
|
267
|
-
message:
|
|
268
|
-
field,
|
|
269
|
-
detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, path: matcherPath(issue.event, issue.groupIndex) },
|
|
270
|
+
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"`,
|
|
271
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex },
|
|
270
272
|
};
|
|
271
|
-
|
|
273
|
+
}
|
|
274
|
+
case "unsupported_entry_type": {
|
|
275
|
+
const field = hooksFieldCoordinate(issue.path);
|
|
272
276
|
return {
|
|
273
|
-
message: `${
|
|
274
|
-
field,
|
|
275
|
-
detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path), type: issue.type },
|
|
277
|
+
message: `${field}: this server does not run hook entries of type ${issue.type}; supported: ${SUPPORTED_HOOK_ENTRY_TYPES.join(" / ")}`,
|
|
278
|
+
facts: { field, reason: issue.reason, type: issue.type },
|
|
276
279
|
};
|
|
280
|
+
}
|
|
277
281
|
case "over_cap":
|
|
278
282
|
case "too_long": {
|
|
279
283
|
const cap = issue;
|
|
280
|
-
return { message: HOOKS_CAPS[cap.limit].sentence(cap.event, cap.count),
|
|
284
|
+
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 } };
|
|
285
|
+
}
|
|
286
|
+
case "unnamed_refusal": {
|
|
287
|
+
const field = hooksFieldCoordinate(issue.path);
|
|
288
|
+
return { message: `${field}: the hooks reader refused this configuration without naming a piece`, facts: { field, reason: issue.reason } };
|
|
289
|
+
}
|
|
290
|
+
case "wire_key_invalid": {
|
|
291
|
+
const field = hooksFieldCoordinate(issue.path);
|
|
292
|
+
return { message: `${field}: ${HOOKS_WIRE_KEY_SHAPE[issue.key]}`, facts: { field, reason: issue.reason, key: issue.key } };
|
|
281
293
|
}
|
|
282
|
-
case "unnamed_refusal":
|
|
283
|
-
return { message: `${hooksCoordinate(issue.path)}: the hooks reader refused this configuration without naming a piece`, field, detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path) } };
|
|
284
|
-
case "wire_key_invalid":
|
|
285
|
-
return { message: `${hooksCoordinate(issue.path)}: ${HOOKS_WIRE_KEY_SHAPE[issue.key]}`, field, detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path), key: issue.key } };
|
|
286
294
|
default: {
|
|
287
295
|
const piece = issue;
|
|
288
296
|
const key = piece.key !== undefined ? hooksOutgoingKey(piece.key) : undefined;
|
|
289
297
|
return {
|
|
290
298
|
message: hooksPieceRefusal(piece),
|
|
291
|
-
field,
|
|
292
|
-
detail: { reason: piece.reason, path: hooksOutgoingPath(piece.path), ...(key !== undefined ? { key } : {}) },
|
|
299
|
+
facts: { field: hooksFieldCoordinate(piece.path), reason: piece.reason, ...(key !== undefined ? { key } : {}) },
|
|
293
300
|
};
|
|
294
301
|
}
|
|
295
302
|
}
|
|
@@ -352,8 +359,8 @@ export function hooksUrlCredentialIssue(config) {
|
|
|
352
359
|
return undefined;
|
|
353
360
|
}
|
|
354
361
|
export function buildHooksUrlCredentialRefusal(issue) {
|
|
355
|
-
const entry =
|
|
356
|
-
return buildRequestUrlCredentialRefusal(
|
|
362
|
+
const entry = ["hooks", issue.event, issue.groupIndex, "hooks", issue.entryIndex];
|
|
363
|
+
return buildRequestUrlCredentialRefusal(hooksFieldCoordinate([...entry, "url"]), issue.credential, urlCredentialHeaderExit(hooksFieldCoordinate([...entry, "headers"])));
|
|
357
364
|
}
|
|
358
365
|
const HOOKS_PIECE_MEANING = {
|
|
359
366
|
"hooks-not-object": "`hooks` must be an object keyed by hook event name",
|
|
@@ -371,8 +378,8 @@ const HOOKS_PIECE_MEANING = {
|
|
|
371
378
|
export function hooksOutgoingPath(path) {
|
|
372
379
|
return outgoingPath(path).map((seg) => (typeof seg === "string" ? echoCallerText(seg) : seg));
|
|
373
380
|
}
|
|
374
|
-
export function
|
|
375
|
-
return
|
|
381
|
+
export function hooksFieldCoordinate(path) {
|
|
382
|
+
return fieldCoordinate("settings", hooksOutgoingPath(path));
|
|
376
383
|
}
|
|
377
384
|
function hooksOutgoingKey(key) {
|
|
378
385
|
return echoCallerText(String(outgoingPath([key])[0] ?? ""));
|
|
@@ -382,7 +389,7 @@ function hooksPieceIssue(piece) {
|
|
|
382
389
|
}
|
|
383
390
|
function hooksPieceRefusal(piece) {
|
|
384
391
|
const field = piece.key !== undefined ? ` (field: ${hooksOutgoingKey(piece.key)})` : "";
|
|
385
|
-
return `${
|
|
392
|
+
return `${hooksFieldCoordinate(piece.path)}: ${piece.reason} — ${HOOKS_PIECE_MEANING[piece.reason]}${field}`;
|
|
386
393
|
}
|
|
387
394
|
function hooksRefused(issue, pieces) {
|
|
388
395
|
const error = buildHooksRefusal(issue).message;
|
|
@@ -733,24 +740,26 @@ const VERDICT_GAP_CAUSE = {
|
|
|
733
740
|
input_truncated: "verdict_unreadable",
|
|
734
741
|
matcher_over_budget: "verdict_unreadable",
|
|
735
742
|
};
|
|
736
|
-
function createUnrunLedger(ctx, event, toolName) {
|
|
743
|
+
function createUnrunLedger(ctx, event, toolName, once) {
|
|
737
744
|
let managedVerdictGap;
|
|
738
745
|
let haltNoted = false;
|
|
739
746
|
const ledger = {
|
|
740
747
|
halted(source, entry) {
|
|
741
|
-
if (haltNoted)
|
|
748
|
+
if (haltNoted || !isSyncEntry(entry))
|
|
742
749
|
return;
|
|
743
750
|
haltNoted = true;
|
|
744
751
|
ledger.unrun(source, entry, "budget_exhausted", ENGINE_BUDGET_SPENT_DETAIL);
|
|
745
752
|
},
|
|
746
753
|
untrusted(source, entry, reason) {
|
|
754
|
+
once.unsettled(entry);
|
|
747
755
|
if (hookLaneOf(source) === "unmanaged")
|
|
748
756
|
return;
|
|
749
757
|
managedVerdictGap ??= VERDICT_GAP_CAUSE[reason];
|
|
750
758
|
noteVerdictUntrusted(ctx, { event, reason, entry, source, toolName });
|
|
751
759
|
},
|
|
752
760
|
unrun(source, entry, reason, detail) {
|
|
753
|
-
|
|
761
|
+
once.unsettled(entry);
|
|
762
|
+
if (source === undefined || hookLaneOf(source) === "unmanaged" || !isSyncEntry(entry))
|
|
754
763
|
return;
|
|
755
764
|
managedVerdictGap ??= VERDICT_GAP_CAUSE[reason];
|
|
756
765
|
ctx.logger.warn("hook_managed_unrun", { event, reason, source: echoCallerText(source), type: entry.type, ...(toolName !== undefined ? { tool: toolName } : {}) });
|
|
@@ -830,8 +839,12 @@ function withBelowContext(parts, below) {
|
|
|
830
839
|
const tail = belowString(below, "additionalContext");
|
|
831
840
|
return tail === undefined ? [...parts] : [...parts, tail];
|
|
832
841
|
}
|
|
833
|
-
|
|
834
|
-
|
|
842
|
+
const ALSO_ASKS_SPEAKER = {
|
|
843
|
+
managed: "a managed PreToolUse hook",
|
|
844
|
+
unmanaged: "a PreToolUse hook",
|
|
845
|
+
};
|
|
846
|
+
function alsoAsks(lane, below, own) {
|
|
847
|
+
return below === undefined || below === own ? own : `${below} (${ALSO_ASKS_SPEAKER[lane]} also asks: ${own})`;
|
|
835
848
|
}
|
|
836
849
|
function readBelowPreToolUse(below) {
|
|
837
850
|
const action = belowString(below, "action");
|
|
@@ -845,20 +858,78 @@ function readBelowPreToolUse(below) {
|
|
|
845
858
|
allowed: action === "allow",
|
|
846
859
|
...(action === "ask" && (cause === undefined || cause === "asked") ? { asked: message } : {}),
|
|
847
860
|
...(action === "ask" && cause !== undefined && cause !== "asked" ? { unreadable: { message, cause: unreadableCause } } : {}),
|
|
848
|
-
|
|
861
|
+
...(action === "ask" && typeof below === "object" && below !== null && Object.hasOwn(below, "requiresRealApproval") && Reflect.get(below, "requiresRealApproval") === true ? { realApproval: true } : {}),
|
|
849
862
|
...(rewrite !== null && typeof rewrite === "object" ? { updatedInput: rewrite } : {}),
|
|
850
863
|
...(additionalContext !== undefined ? { additionalContext } : {}),
|
|
851
864
|
};
|
|
852
865
|
}
|
|
853
866
|
function spawnPlannedCommand(plan, ctx, stdio) {
|
|
854
|
-
const env = hookChildEnv(plan.env, true);
|
|
867
|
+
const env = hookChildEnv(plan.env, ctx.hookEnvAllow, true);
|
|
855
868
|
if (plan.kind === "exec")
|
|
856
869
|
return spawn(plan.file, [...plan.args], { cwd: ctx.cwd, env, stdio, detached: true });
|
|
857
870
|
const sh = hostShell();
|
|
858
871
|
return spawn(sh.shell, [...sh.args, plan.command], { cwd: ctx.cwd, env, stdio, detached: true });
|
|
859
872
|
}
|
|
860
|
-
|
|
861
|
-
const
|
|
873
|
+
function createHookTreeLadder(child, ctx, event) {
|
|
874
|
+
const leaderOurs = () => child.pid !== undefined && child.exitCode === null && child.signalCode === null;
|
|
875
|
+
const alive = () => leaderOurs() || (child.pid !== undefined && reapedLeaderGroupAlive(child.pid));
|
|
876
|
+
const shoot = (sig) => {
|
|
877
|
+
const pid = child.pid;
|
|
878
|
+
if (pid === undefined) {
|
|
879
|
+
child.kill(sig);
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
if (leaderOurs()) {
|
|
883
|
+
signalProcessTree(pid, sig);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
if (!reapedLeaderGroupAlive(pid))
|
|
887
|
+
return;
|
|
888
|
+
try {
|
|
889
|
+
(sig === "SIGTERM" ? killTreeSoft : killTreeHard)(pid);
|
|
890
|
+
}
|
|
891
|
+
catch {
|
|
892
|
+
child.kill(sig);
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
let hardFired = false;
|
|
896
|
+
const hard = (end) => {
|
|
897
|
+
if (hardFired)
|
|
898
|
+
return;
|
|
899
|
+
hardFired = true;
|
|
900
|
+
shoot("SIGKILL");
|
|
901
|
+
const recheck = setTimeout(() => {
|
|
902
|
+
const clean = !alive();
|
|
903
|
+
if (!clean)
|
|
904
|
+
shoot("SIGKILL");
|
|
905
|
+
const fields = { event, type: "command", end, shots: clean ? 1 : 2, clean };
|
|
906
|
+
if (clean)
|
|
907
|
+
ctx.logger.info("hook_command_tree_swept", fields);
|
|
908
|
+
else
|
|
909
|
+
ctx.logger.warn("hook_command_tree_swept", fields);
|
|
910
|
+
}, HOOK_KILL_GRACE_MS);
|
|
911
|
+
recheck.unref();
|
|
912
|
+
};
|
|
913
|
+
return {
|
|
914
|
+
halt(onEscalate) {
|
|
915
|
+
shoot("SIGTERM");
|
|
916
|
+
const escalate = setTimeout(() => {
|
|
917
|
+
if (hardFired || !alive())
|
|
918
|
+
return;
|
|
919
|
+
onEscalate();
|
|
920
|
+
hard("halt");
|
|
921
|
+
}, HOOK_KILL_GRACE_MS);
|
|
922
|
+
escalate.unref();
|
|
923
|
+
},
|
|
924
|
+
kill: hard,
|
|
925
|
+
ended() {
|
|
926
|
+
if (alive())
|
|
927
|
+
hard("exit");
|
|
928
|
+
},
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
async function runCommandHook(entry, payload, ctx, halt, event) {
|
|
932
|
+
const plan = await planCommandSpawn(entry, ctx.cwd, ctx.shellEnv, hookChildView(ctx));
|
|
862
933
|
if (plan.kind === "refused")
|
|
863
934
|
return { code: null, stdout: "", stderr: "", timedOut: false, spawnError: plan.error };
|
|
864
935
|
if (plan.kind === "shell") {
|
|
@@ -882,6 +953,7 @@ async function runCommandHook(entry, payload, ctx, halt) {
|
|
|
882
953
|
return;
|
|
883
954
|
}
|
|
884
955
|
const ticket = adoptHostForegroundChild(child);
|
|
956
|
+
const tree = createHookTreeLadder(child, ctx, event);
|
|
885
957
|
let stdout = "";
|
|
886
958
|
let stderr = "";
|
|
887
959
|
let timedOut = false;
|
|
@@ -900,40 +972,16 @@ async function runCommandHook(entry, payload, ctx, halt) {
|
|
|
900
972
|
timedOut = true;
|
|
901
973
|
if (sent !== undefined)
|
|
902
974
|
sent = "SIGKILL";
|
|
903
|
-
try {
|
|
904
|
-
if (child.pid)
|
|
905
|
-
process.kill(-child.pid, "SIGKILL");
|
|
906
|
-
else
|
|
907
|
-
child.kill("SIGKILL");
|
|
908
|
-
}
|
|
909
|
-
catch {
|
|
910
|
-
child.kill("SIGKILL");
|
|
911
|
-
}
|
|
912
975
|
settle(null);
|
|
976
|
+
tree.kill("timeout");
|
|
913
977
|
}, timeoutMs);
|
|
914
|
-
const signalGroup = (sig) => {
|
|
915
|
-
try {
|
|
916
|
-
if (child.pid)
|
|
917
|
-
(sig === "SIGTERM" ? killTreeSoft : killTreeHard)(child.pid);
|
|
918
|
-
else
|
|
919
|
-
child.kill(sig);
|
|
920
|
-
}
|
|
921
|
-
catch {
|
|
922
|
-
child.kill(sig);
|
|
923
|
-
}
|
|
924
|
-
};
|
|
925
978
|
const onHalt = () => {
|
|
926
979
|
if (settled)
|
|
927
980
|
return;
|
|
928
981
|
sent = "SIGTERM";
|
|
929
|
-
|
|
930
|
-
const escalate = setTimeout(() => {
|
|
931
|
-
if (child.exitCode !== null || child.signalCode !== null)
|
|
932
|
-
return;
|
|
982
|
+
tree.halt(() => {
|
|
933
983
|
sent = "SIGKILL";
|
|
934
|
-
|
|
935
|
-
}, HOOK_KILL_GRACE_MS);
|
|
936
|
-
escalate.unref();
|
|
984
|
+
});
|
|
937
985
|
};
|
|
938
986
|
halt.addEventListener("abort", onHalt, { once: true });
|
|
939
987
|
child.stdout?.on("data", (d) => {
|
|
@@ -952,7 +1000,12 @@ async function runCommandHook(entry, payload, ctx, halt) {
|
|
|
952
1000
|
resolve({ code: null, stdout, stderr, timedOut, spawnError: String(e) });
|
|
953
1001
|
}
|
|
954
1002
|
});
|
|
955
|
-
child.on("close", (code) =>
|
|
1003
|
+
child.on("close", (code) => {
|
|
1004
|
+
const natural = !settled && sent === undefined;
|
|
1005
|
+
settle(code);
|
|
1006
|
+
if (natural)
|
|
1007
|
+
tree.ended();
|
|
1008
|
+
});
|
|
956
1009
|
child.stdin?.on("error", () => { });
|
|
957
1010
|
child.stdin?.end(`${JSON.stringify(boundedToolInputPayload(payload))}\n`);
|
|
958
1011
|
});
|
|
@@ -961,7 +1014,7 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
|
|
|
961
1014
|
try {
|
|
962
1015
|
const rewake = entry.asyncRewake === true;
|
|
963
1016
|
const timeoutMs = Math.min(entry.timeout ?? DEFAULT_HOOK_TIMEOUT_SECONDS, MAX_HOOK_TIMEOUT_SECONDS) * 1000;
|
|
964
|
-
const plan = await planCommandSpawn(entry, ctx.cwd, ctx.shellEnv);
|
|
1017
|
+
const plan = await planCommandSpawn(entry, ctx.cwd, ctx.shellEnv, hookChildView(ctx));
|
|
965
1018
|
if (plan.kind === "refused")
|
|
966
1019
|
throw new Error(plan.error);
|
|
967
1020
|
if (plan.kind === "shell")
|
|
@@ -970,18 +1023,11 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
|
|
|
970
1023
|
return;
|
|
971
1024
|
const child = spawnPlannedCommand(plan, ctx, ["pipe", "ignore", rewake ? "pipe" : "ignore"]);
|
|
972
1025
|
const ticket = adoptHostForegroundChild(child);
|
|
1026
|
+
const tree = createHookTreeLadder(child, ctx, event);
|
|
973
1027
|
let killedByTimeout = false;
|
|
974
1028
|
const timer = setTimeout(() => {
|
|
975
1029
|
killedByTimeout = true;
|
|
976
|
-
|
|
977
|
-
if (child.pid)
|
|
978
|
-
process.kill(-child.pid, "SIGKILL");
|
|
979
|
-
else
|
|
980
|
-
child.kill("SIGKILL");
|
|
981
|
-
}
|
|
982
|
-
catch {
|
|
983
|
-
child.kill("SIGKILL");
|
|
984
|
-
}
|
|
1030
|
+
tree.kill("timeout");
|
|
985
1031
|
}, timeoutMs);
|
|
986
1032
|
timer.unref?.();
|
|
987
1033
|
let stderr = "";
|
|
@@ -1000,6 +1046,8 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
|
|
|
1000
1046
|
child.on("close", (code) => {
|
|
1001
1047
|
clearTimeout(timer);
|
|
1002
1048
|
ticket?.release();
|
|
1049
|
+
if (!killedByTimeout)
|
|
1050
|
+
tree.ended();
|
|
1003
1051
|
noteAsyncOutcome(entry, ctx, event, payload, { code, rewake, killedByTimeout });
|
|
1004
1052
|
if (!rewake || code !== 2)
|
|
1005
1053
|
return;
|
|
@@ -1119,6 +1167,7 @@ function httpHookWithheldSentence(event, block) {
|
|
|
1119
1167
|
return `settings.hooks.${event}: http hook not sent — ${why} (rule: ${block.rule}); ${exit}`;
|
|
1120
1168
|
}
|
|
1121
1169
|
const MAX_BLANKED_REFERENCES_LOGGED = 16;
|
|
1170
|
+
const httpHookFetch = createEgressFetch("declare the final address as this hook entry's url");
|
|
1122
1171
|
async function runHttpHook(entry, payload, ctx, event) {
|
|
1123
1172
|
const block = httpHookUrlVerdict(entry.url, ctx.httpHookAllowlistLayers, SERVER_WORKSPACE_TRUST);
|
|
1124
1173
|
if (block !== undefined)
|
|
@@ -1146,12 +1195,11 @@ async function runHttpHook(entry, payload, ctx, event) {
|
|
|
1146
1195
|
const ac = new AbortController();
|
|
1147
1196
|
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
1148
1197
|
try {
|
|
1149
|
-
const res = await
|
|
1198
|
+
const res = await httpHookFetch(entry.url, {
|
|
1150
1199
|
method: "POST",
|
|
1151
1200
|
headers,
|
|
1152
1201
|
body: `${JSON.stringify(boundedToolInputPayload(payload))}\n`,
|
|
1153
1202
|
signal: ac.signal,
|
|
1154
|
-
redirect: "error",
|
|
1155
1203
|
});
|
|
1156
1204
|
let body = "";
|
|
1157
1205
|
const reader = res.body?.getReader();
|
|
@@ -1277,7 +1325,7 @@ function runRunnableEntry(entry, payload, ctx, event, llmExtra, halt) {
|
|
|
1277
1325
|
case "agent":
|
|
1278
1326
|
return runLlmHook(entry, payload, ctx, { system: ccAgentHookSystemFor(event), event });
|
|
1279
1327
|
case "command":
|
|
1280
|
-
return runCommandHook(entry, payload, ctx, halt);
|
|
1328
|
+
return runCommandHook(entry, payload, ctx, halt, event);
|
|
1281
1329
|
default: {
|
|
1282
1330
|
const unreachable = entry;
|
|
1283
1331
|
void unreachable;
|
|
@@ -1285,6 +1333,41 @@ function runRunnableEntry(entry, payload, ctx, event, llmExtra, halt) {
|
|
|
1285
1333
|
}
|
|
1286
1334
|
}
|
|
1287
1335
|
}
|
|
1336
|
+
async function settleOnce(spentOf, body) {
|
|
1337
|
+
const candidates = new Set();
|
|
1338
|
+
let refused = false;
|
|
1339
|
+
const once = {
|
|
1340
|
+
spent: (entry) => spentOf.has(entry),
|
|
1341
|
+
ran: (entry) => {
|
|
1342
|
+
if (entry.once)
|
|
1343
|
+
candidates.add(entry);
|
|
1344
|
+
},
|
|
1345
|
+
handedOff: (entry) => {
|
|
1346
|
+
if (entry.once)
|
|
1347
|
+
spentOf.add(entry);
|
|
1348
|
+
},
|
|
1349
|
+
unsettled: (entry) => {
|
|
1350
|
+
candidates.delete(entry);
|
|
1351
|
+
},
|
|
1352
|
+
refused: (answer) => {
|
|
1353
|
+
refused = true;
|
|
1354
|
+
return answer;
|
|
1355
|
+
},
|
|
1356
|
+
mark: () => {
|
|
1357
|
+
const at = new Set(candidates);
|
|
1358
|
+
return () => {
|
|
1359
|
+
candidates.clear();
|
|
1360
|
+
for (const entry of at)
|
|
1361
|
+
candidates.add(entry);
|
|
1362
|
+
};
|
|
1363
|
+
},
|
|
1364
|
+
};
|
|
1365
|
+
const answer = await body(once);
|
|
1366
|
+
if (!refused)
|
|
1367
|
+
for (const entry of candidates)
|
|
1368
|
+
spentOf.add(entry);
|
|
1369
|
+
return answer;
|
|
1370
|
+
}
|
|
1288
1371
|
function isSyncEntry(entry) {
|
|
1289
1372
|
return !(entry.type === "command" && (entry.async === true || entry.asyncRewake === true));
|
|
1290
1373
|
}
|
|
@@ -1342,7 +1425,7 @@ function noteRanVerdictFlaw(ctx, ledger, event, ran, flaw, toolName) {
|
|
|
1342
1425
|
}
|
|
1343
1426
|
}
|
|
1344
1427
|
}
|
|
1345
|
-
async function runMatchingEntries(event, groups, matchValue, payload, ctx,
|
|
1428
|
+
async function runMatchingEntries(event, groups, matchValue, payload, ctx, once, halt, deadlineAt, ledger, llmExtra) {
|
|
1346
1429
|
const results = [];
|
|
1347
1430
|
let llmEntries = 0;
|
|
1348
1431
|
const toolName = toolNameOf(payload);
|
|
@@ -1350,10 +1433,10 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1350
1433
|
const truncatedFor = (entry) => (entry.type === "prompt" || entry.type === "agent" ? llmHookArguments(payload).truncated : inputTruncated);
|
|
1351
1434
|
const blockedBy = (entry, source, cause) => ({ entry, run: blockingFailureRun(event, cause), source });
|
|
1352
1435
|
let laneSpent = false;
|
|
1353
|
-
const settle = async (entry
|
|
1436
|
+
const settle = async (entry) => {
|
|
1354
1437
|
if (halt.signal.aborted)
|
|
1355
1438
|
return { kind: "halted" };
|
|
1356
|
-
if (entry.once &&
|
|
1439
|
+
if (entry.once && once.spent(entry))
|
|
1357
1440
|
return { kind: "passed" };
|
|
1358
1441
|
let ifOverBudget = false;
|
|
1359
1442
|
if (entry.if !== undefined) {
|
|
@@ -1379,7 +1462,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1379
1462
|
}
|
|
1380
1463
|
if (entry.type === "command" && entry.shell === "powershell") {
|
|
1381
1464
|
ctx.logger.warn("hook_entries_skipped", { event, type: entry.type, reason: "powershell_not_supported" });
|
|
1382
|
-
return
|
|
1465
|
+
return { kind: "unrun", reason: "powershell_unsupported" };
|
|
1383
1466
|
}
|
|
1384
1467
|
if (entry.type === "prompt" || entry.type === "agent") {
|
|
1385
1468
|
const carrier = entry.type === "prompt" ? ctx.hookLlm : ctx.hookAgent;
|
|
@@ -1393,8 +1476,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1393
1476
|
}
|
|
1394
1477
|
}
|
|
1395
1478
|
if (entry.type === "command" && (entry.async || entry.asyncRewake)) {
|
|
1396
|
-
|
|
1397
|
-
onceFired.add(onceKey);
|
|
1479
|
+
once.handedOff(entry);
|
|
1398
1480
|
void fireAsyncCommandHook(entry, payload, ctx, event, halt.signal);
|
|
1399
1481
|
return { kind: "passed" };
|
|
1400
1482
|
}
|
|
@@ -1403,8 +1485,6 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1403
1485
|
ctx.logger.warn("hook_event_deadline_exceeded", { event, budgetSec: MAX_HOOK_EVENT_TOTAL_SECONDS });
|
|
1404
1486
|
return { kind: "unrun", reason: "budget_exhausted" };
|
|
1405
1487
|
}
|
|
1406
|
-
if (entry.once)
|
|
1407
|
-
onceFired.add(onceKey);
|
|
1408
1488
|
if (entry.type === "prompt" || entry.type === "agent")
|
|
1409
1489
|
llmEntries++;
|
|
1410
1490
|
const run = await runRunnableEntry(entry, payload, ctx, event, llmExtra, halt.signal);
|
|
@@ -1437,15 +1517,13 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1437
1517
|
return { kind: "unrun", reason: "bad_json" };
|
|
1438
1518
|
return ifOverBudget ? { kind: "ran", run, overBudget: true } : { kind: "ran", run };
|
|
1439
1519
|
};
|
|
1440
|
-
for (const
|
|
1520
|
+
for (const group of groups) {
|
|
1441
1521
|
const pending = laneSpent ? group.hooks.filter((entry) => blocksOnFailure(entry, event)) : group.hooks;
|
|
1442
1522
|
if (laneSpent && pending.length === 0)
|
|
1443
1523
|
continue;
|
|
1444
1524
|
const selected = matcherGroupSelected(ctx, event, group, matchValue, toolName, pending);
|
|
1445
1525
|
if (selected === "invalid") {
|
|
1446
1526
|
for (const entry of pending) {
|
|
1447
|
-
if (!isSyncEntry(entry))
|
|
1448
|
-
continue;
|
|
1449
1527
|
if (!laneSpent)
|
|
1450
1528
|
ledger.unrun(group.source, entry, "matcher_invalid");
|
|
1451
1529
|
if (blocksOnFailure(entry, event))
|
|
@@ -1455,12 +1533,13 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1455
1533
|
}
|
|
1456
1534
|
if (selected === false)
|
|
1457
1535
|
continue;
|
|
1458
|
-
for (const
|
|
1536
|
+
for (const entry of group.hooks) {
|
|
1459
1537
|
if (laneSpent && !blocksOnFailure(entry, event))
|
|
1460
1538
|
continue;
|
|
1461
|
-
const fate = await settle(entry
|
|
1539
|
+
const fate = await settle(entry);
|
|
1462
1540
|
switch (fate.kind) {
|
|
1463
1541
|
case "ran": {
|
|
1542
|
+
once.ran(entry);
|
|
1464
1543
|
const flaw = blocksOnFailure(entry, event) ? ranVerdictFlaw(event, fate.run) : undefined;
|
|
1465
1544
|
if (flaw !== undefined) {
|
|
1466
1545
|
noteRanVerdictFlaw(ctx, ledger, event, { entry, run: fate.run, source: group.source }, flaw, toolName);
|
|
@@ -1490,7 +1569,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1490
1569
|
case "passed":
|
|
1491
1570
|
break;
|
|
1492
1571
|
case "halted":
|
|
1493
|
-
if (
|
|
1572
|
+
if (halt.budgetSpent())
|
|
1494
1573
|
ledger.halted(group.source, entry);
|
|
1495
1574
|
return results;
|
|
1496
1575
|
default: {
|
|
@@ -1508,17 +1587,16 @@ function createEventClock() {
|
|
|
1508
1587
|
}
|
|
1509
1588
|
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";
|
|
1510
1589
|
function hookPhasesOf(groups) {
|
|
1511
|
-
|
|
1512
|
-
return HOOK_PHASES.map((phase) => ({ phase, groups: indexed.filter((g) => g.phase === phase).map(({ group, index }) => ({ group, index })) })).filter((l) => l.groups.length > 0);
|
|
1590
|
+
return HOOK_PHASES.map((phase) => ({ phase, groups: groups.filter((g) => hookPhaseOf(g.source) === phase) })).filter((l) => l.groups.length > 0);
|
|
1513
1591
|
}
|
|
1514
1592
|
function trustRank(phase) {
|
|
1515
1593
|
return HOOK_PHASES.length - 1 - HOOK_PHASES.indexOf(phase);
|
|
1516
1594
|
}
|
|
1517
|
-
async function runEventLanes(event, groups, matchValue, payload, ctx,
|
|
1595
|
+
async function runEventLanes(event, groups, matchValue, payload, ctx, once, halt, ledger, llmExtra) {
|
|
1518
1596
|
const deadline = createEventClock();
|
|
1519
1597
|
const ran = [];
|
|
1520
1598
|
for (const lane of hookPhasesOf(groups)) {
|
|
1521
|
-
for (const r of await runMatchingEntries(event, lane.groups, matchValue, payload, ctx,
|
|
1599
|
+
for (const r of await runMatchingEntries(event, lane.groups, matchValue, payload, ctx, once, halt, deadline(), ledger, llmExtra))
|
|
1522
1600
|
ran.push({ ...r, phase: lane.phase });
|
|
1523
1601
|
}
|
|
1524
1602
|
return ran.sort((a, b) => trustRank(a.phase) - trustRank(b.phase)).map(({ entry, run, source }) => ({ entry, run, source }));
|
|
@@ -1534,9 +1612,9 @@ function basePayload(ctx, permissionMode) {
|
|
|
1534
1612
|
function ignoreMatchers(groups) {
|
|
1535
1613
|
return groups.map((g) => (g.matcher === undefined ? g : { ...g, matcher: undefined }));
|
|
1536
1614
|
}
|
|
1537
|
-
async function runObserveOnlyEvent(event, groups, matchValue, payload, ctx,
|
|
1538
|
-
const ledger = createUnrunLedger(ctx, event, toolNameOf(payload));
|
|
1539
|
-
const singles = await runEventLanes(event, groups, matchValue, payload, ctx,
|
|
1615
|
+
async function runObserveOnlyEvent(event, groups, matchValue, payload, ctx, once, halt) {
|
|
1616
|
+
const ledger = createUnrunLedger(ctx, event, toolNameOf(payload), once);
|
|
1617
|
+
const singles = await runEventLanes(event, groups, matchValue, payload, ctx, once, halt, ledger);
|
|
1540
1618
|
for (const ran of singles) {
|
|
1541
1619
|
const { run } = ran;
|
|
1542
1620
|
if (run.code !== 0) {
|
|
@@ -1589,17 +1667,16 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1589
1667
|
if (!pre && !post && !postFailure && !postBatch && !promptSubmit && !stopEntries && !stopFailureEntries && !preCompactEntries && !postCompactEntries) {
|
|
1590
1668
|
return undefined;
|
|
1591
1669
|
}
|
|
1592
|
-
const
|
|
1670
|
+
const onceSpent = new Set();
|
|
1593
1671
|
const translators = {};
|
|
1594
1672
|
if (pre) {
|
|
1595
|
-
const tightenOnly =
|
|
1596
|
-
translators.PreToolUse =
|
|
1673
|
+
const tightenOnly = chainsBelowTaskOn(ctx.belowTaskChainPatterns, "classic.PreToolUse");
|
|
1674
|
+
translators.PreToolUse = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1597
1675
|
const prior = readBelowPreToolUse(below);
|
|
1598
|
-
const realApproval = prior.realApproval ? { requiresRealApproval: true } : {};
|
|
1599
1676
|
if (prior.denied)
|
|
1600
1677
|
return undefined;
|
|
1601
1678
|
const toolName = e.tool;
|
|
1602
|
-
const ledger = createUnrunLedger(ctx, "PreToolUse", toolName);
|
|
1679
|
+
const ledger = createUnrunLedger(ctx, "PreToolUse", toolName, once);
|
|
1603
1680
|
const deadline = createEventClock();
|
|
1604
1681
|
let currentInput = prior.updatedInput ?? e.input;
|
|
1605
1682
|
let rewritten = prior.updatedInput !== undefined;
|
|
@@ -1609,9 +1686,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1609
1686
|
let unknownDecision = false;
|
|
1610
1687
|
const contexts = { unmanaged: [], managedPlugin: [], managedPolicy: [] };
|
|
1611
1688
|
const contextField = () => buildHookContextField([...[...HOOK_PHASES].sort((a, b) => trustRank(a) - trustRank(b)).flatMap((p) => contexts[p]), ...(prior.additionalContext !== undefined ? [prior.additionalContext] : [])]);
|
|
1612
|
-
const
|
|
1689
|
+
const strictness = prior.realApproval === true ? { requiresRealApproval: true } : {};
|
|
1690
|
+
const runPass = async (phase, groups) => {
|
|
1613
1691
|
let rewroteBy;
|
|
1614
|
-
for (const
|
|
1692
|
+
for (const group of groups) {
|
|
1615
1693
|
const groupInput = currentInput;
|
|
1616
1694
|
const payload = {
|
|
1617
1695
|
...basePayload(ctx, e.permissionMode),
|
|
@@ -1620,7 +1698,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1620
1698
|
tool_input: groupInput,
|
|
1621
1699
|
tool_use_id: e.tool_use_id,
|
|
1622
1700
|
};
|
|
1623
|
-
const singles = await runMatchingEntries("PreToolUse", [
|
|
1701
|
+
const singles = await runMatchingEntries("PreToolUse", [group], toolName, payload, ctx, once, halt, deadline(), ledger);
|
|
1624
1702
|
for (const ran of singles) {
|
|
1625
1703
|
const { entry, run } = ran;
|
|
1626
1704
|
if (run.code === 2) {
|
|
@@ -1659,13 +1737,14 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1659
1737
|
const proposed = h.updatedInput !== null && typeof h.updatedInput === "object" ? h.updatedInput : undefined;
|
|
1660
1738
|
const proposesRewrite = proposed !== undefined && canonicalJsonStringify(proposed) !== canonicalJsonStringify(groupInput);
|
|
1661
1739
|
if (tightenOnly && ran.distrust === undefined && (decision === "allow" || (proposesRewrite && (decision === "ask" || decision === undefined)))) {
|
|
1662
|
-
return { deny: { action: "deny", message: proposesRewrite ?
|
|
1740
|
+
return { deny: { action: "deny", message: proposesRewrite ? REQUEST_HOOK_REWRITE_UNSHOWN_REASON : REQUEST_HOOK_ALLOW_UNJUDGED_REASON, ...contextField() } };
|
|
1663
1741
|
}
|
|
1664
1742
|
if (decision === "ask") {
|
|
1665
|
-
asked = alsoAsks(prior.asked ?? prior.unreadable?.message, clipDataText(typeof h.permissionDecisionReason === "string" ? h.permissionDecisionReason : "a PreToolUse hook requires approval", MAX_HOOK_FEEDBACK_CHARS));
|
|
1743
|
+
asked = alsoAsks(lane, prior.asked ?? prior.unreadable?.message, clipDataText(typeof h.permissionDecisionReason === "string" ? h.permissionDecisionReason : "a PreToolUse hook requires approval", MAX_HOOK_FEEDBACK_CHARS));
|
|
1666
1744
|
spoke = true;
|
|
1667
1745
|
}
|
|
1668
|
-
|
|
1746
|
+
const counted = decision === "allow" || decision === "ask" || decision === undefined;
|
|
1747
|
+
if (counted) {
|
|
1669
1748
|
if (ran.distrust !== undefined && hookLaneOf(ran.source) === "unmanaged" && (decision === "allow" || proposesRewrite)) {
|
|
1670
1749
|
noteVerdictUntrusted(ctx, { event: "PreToolUse", reason: ran.distrust, entry, source: ran.source, toolName });
|
|
1671
1750
|
}
|
|
@@ -1694,54 +1773,52 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1694
1773
|
};
|
|
1695
1774
|
for (const lane of hookPhasesOf(pre)) {
|
|
1696
1775
|
if (lane.phase === "unmanaged") {
|
|
1697
|
-
const pass = await runPass(lane.phase, lane.groups
|
|
1776
|
+
const pass = await runPass(lane.phase, lane.groups);
|
|
1698
1777
|
if (pass.deny !== undefined)
|
|
1699
|
-
return pass.deny;
|
|
1778
|
+
return once.refused(pass.deny);
|
|
1700
1779
|
continue;
|
|
1701
1780
|
}
|
|
1702
|
-
const
|
|
1703
|
-
const first = await runPass(lane.phase, lane.groups
|
|
1781
|
+
const rollback = once.mark();
|
|
1782
|
+
const first = await runPass(lane.phase, lane.groups);
|
|
1704
1783
|
if (first.deny !== undefined)
|
|
1705
|
-
return first.deny;
|
|
1784
|
+
return once.refused(first.deny);
|
|
1706
1785
|
if (first.rewroteBy === undefined)
|
|
1707
1786
|
continue;
|
|
1708
1787
|
contexts[lane.phase].length = 0;
|
|
1709
|
-
|
|
1710
|
-
const second = await runPass(lane.phase, lane.groups
|
|
1711
|
-
for (const key of rejudgeOnce)
|
|
1712
|
-
onceFired.add(key);
|
|
1788
|
+
rollback();
|
|
1789
|
+
const second = await runPass(lane.phase, lane.groups);
|
|
1713
1790
|
if (second.deny !== undefined)
|
|
1714
|
-
return second.deny;
|
|
1791
|
+
return once.refused(second.deny);
|
|
1715
1792
|
if (second.rewroteBy !== undefined) {
|
|
1716
1793
|
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");
|
|
1717
1794
|
}
|
|
1718
1795
|
}
|
|
1719
1796
|
const managedGap = ledger.managedVerdictGap;
|
|
1720
|
-
if (
|
|
1797
|
+
if (!spoke && managedGap === undefined)
|
|
1721
1798
|
return undefined;
|
|
1722
1799
|
if (asked !== undefined) {
|
|
1723
|
-
return { action: "ask", message: asked, questionCause: "asked", ...(rewritten ? { updatedInput: currentInput } : {}), ...
|
|
1800
|
+
return { action: "ask", message: asked, questionCause: "asked", ...strictness, ...(rewritten ? { updatedInput: currentInput } : {}), ...contextField() };
|
|
1724
1801
|
}
|
|
1725
1802
|
if (managedGap !== undefined) {
|
|
1726
1803
|
return {
|
|
1727
1804
|
action: "ask",
|
|
1728
1805
|
message: "a managed PreToolUse hook did not run to a verdict — approval required",
|
|
1729
1806
|
questionCause: managedGap,
|
|
1807
|
+
...strictness,
|
|
1730
1808
|
...(rewritten ? { updatedInput: currentInput } : {}),
|
|
1731
|
-
...realApproval,
|
|
1732
1809
|
...contextField(),
|
|
1733
1810
|
};
|
|
1734
1811
|
}
|
|
1735
1812
|
if (prior.unreadable !== undefined) {
|
|
1736
|
-
return { action: "ask", message: prior.unreadable.message, questionCause: prior.unreadable.cause, ...(rewritten ? { updatedInput: currentInput } : {}), ...
|
|
1813
|
+
return { action: "ask", message: prior.unreadable.message, questionCause: prior.unreadable.cause, ...strictness, ...(rewritten ? { updatedInput: currentInput } : {}), ...contextField() };
|
|
1737
1814
|
}
|
|
1738
1815
|
if (unknownDecision) {
|
|
1739
1816
|
return {
|
|
1740
1817
|
action: "ask",
|
|
1741
1818
|
message: "a PreToolUse hook returned an unrecognized permissionDecision — approval required",
|
|
1742
1819
|
questionCause: "verdict_unreadable",
|
|
1820
|
+
...strictness,
|
|
1743
1821
|
...(rewritten ? { updatedInput: currentInput } : {}),
|
|
1744
|
-
...realApproval,
|
|
1745
1822
|
...contextField(),
|
|
1746
1823
|
};
|
|
1747
1824
|
}
|
|
@@ -1751,10 +1828,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1751
1828
|
if (rewritten || HOOK_PHASES.some((p) => contexts[p].length > 0) || prior.additionalContext !== undefined)
|
|
1752
1829
|
return carried;
|
|
1753
1830
|
return undefined;
|
|
1754
|
-
};
|
|
1831
|
+
});
|
|
1755
1832
|
}
|
|
1756
1833
|
if (post) {
|
|
1757
|
-
translators.PostToolUse =
|
|
1834
|
+
translators.PostToolUse = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1758
1835
|
const toolName = e.tool;
|
|
1759
1836
|
const input = e.input;
|
|
1760
1837
|
const output = e.output;
|
|
@@ -1770,8 +1847,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1770
1847
|
tool_response: { isError: output.isError, text: clipDataText(responseText, MAX_TOOL_RESPONSE_CHARS) },
|
|
1771
1848
|
tool_use_id: e.tool_use_id,
|
|
1772
1849
|
};
|
|
1773
|
-
const ledger = createUnrunLedger(ctx, "PostToolUse", toolName);
|
|
1774
|
-
const singles = await runEventLanes("PostToolUse", post, toolName, payload, ctx,
|
|
1850
|
+
const ledger = createUnrunLedger(ctx, "PostToolUse", toolName, once);
|
|
1851
|
+
const singles = await runEventLanes("PostToolUse", post, toolName, payload, ctx, once, halt, ledger);
|
|
1775
1852
|
for (const ran of singles) {
|
|
1776
1853
|
const { entry, run } = ran;
|
|
1777
1854
|
if (run.code === 2) {
|
|
@@ -1807,10 +1884,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1807
1884
|
if (contexts.length === 0)
|
|
1808
1885
|
return undefined;
|
|
1809
1886
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1810
|
-
};
|
|
1887
|
+
});
|
|
1811
1888
|
}
|
|
1812
1889
|
if (postFailure) {
|
|
1813
|
-
translators.PostToolUseFailure =
|
|
1890
|
+
translators.PostToolUseFailure = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1814
1891
|
const toolName = e.tool;
|
|
1815
1892
|
const f = e.failure;
|
|
1816
1893
|
const contexts = [];
|
|
@@ -1823,8 +1900,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1823
1900
|
error: clipDataText(f.error, MAX_TOOL_RESPONSE_CHARS),
|
|
1824
1901
|
is_interrupt: f.isInterrupt,
|
|
1825
1902
|
};
|
|
1826
|
-
const ledger = createUnrunLedger(ctx, "PostToolUseFailure", toolName);
|
|
1827
|
-
const singles = await runEventLanes("PostToolUseFailure", postFailure, toolName, payload, ctx,
|
|
1903
|
+
const ledger = createUnrunLedger(ctx, "PostToolUseFailure", toolName, once);
|
|
1904
|
+
const singles = await runEventLanes("PostToolUseFailure", postFailure, toolName, payload, ctx, once, halt, ledger);
|
|
1828
1905
|
for (const ran of singles) {
|
|
1829
1906
|
const { entry, run } = ran;
|
|
1830
1907
|
if (run.code === 2) {
|
|
@@ -1856,10 +1933,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1856
1933
|
if (contexts.length === 0)
|
|
1857
1934
|
return undefined;
|
|
1858
1935
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1859
|
-
};
|
|
1936
|
+
});
|
|
1860
1937
|
}
|
|
1861
1938
|
if (postBatch) {
|
|
1862
|
-
translators.PostToolBatch =
|
|
1939
|
+
translators.PostToolBatch = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1863
1940
|
const contexts = [];
|
|
1864
1941
|
const payload = {
|
|
1865
1942
|
...basePayload(ctx, e.permissionMode),
|
|
@@ -1871,8 +1948,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1871
1948
|
tool_response: { isError: c.isError, ...(c.response !== undefined ? { text: clipDataText(c.response, MAX_TOOL_RESPONSE_CHARS) } : {}) },
|
|
1872
1949
|
})),
|
|
1873
1950
|
};
|
|
1874
|
-
const ledger = createUnrunLedger(ctx, "PostToolBatch", undefined);
|
|
1875
|
-
const singles = await runEventLanes("PostToolBatch", ignoreMatchers(postBatch), "", payload, ctx,
|
|
1951
|
+
const ledger = createUnrunLedger(ctx, "PostToolBatch", undefined, once);
|
|
1952
|
+
const singles = await runEventLanes("PostToolBatch", ignoreMatchers(postBatch), "", payload, ctx, once, halt, ledger);
|
|
1876
1953
|
for (const ran of singles) {
|
|
1877
1954
|
const { entry, run } = ran;
|
|
1878
1955
|
if (run.code === 2) {
|
|
@@ -1900,19 +1977,19 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1900
1977
|
if (contexts.length === 0)
|
|
1901
1978
|
return undefined;
|
|
1902
1979
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1903
|
-
};
|
|
1980
|
+
});
|
|
1904
1981
|
}
|
|
1905
1982
|
if (promptSubmit) {
|
|
1906
|
-
translators.UserPromptSubmit =
|
|
1983
|
+
translators.UserPromptSubmit = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1907
1984
|
const contexts = [];
|
|
1908
1985
|
const payload = { ...basePayload(ctx, e.permissionMode), hook_event_name: "UserPromptSubmit", prompt: clipDataText(e.prompt, MAX_TOOL_INPUT_CHARS) };
|
|
1909
|
-
const ledger = createUnrunLedger(ctx, "UserPromptSubmit", undefined);
|
|
1910
|
-
const singles = await runEventLanes("UserPromptSubmit", ignoreMatchers(promptSubmit), "", payload, ctx,
|
|
1986
|
+
const ledger = createUnrunLedger(ctx, "UserPromptSubmit", undefined, once);
|
|
1987
|
+
const singles = await runEventLanes("UserPromptSubmit", ignoreMatchers(promptSubmit), "", payload, ctx, once, halt, ledger);
|
|
1911
1988
|
for (const ran of singles) {
|
|
1912
1989
|
const { entry, run } = ran;
|
|
1913
1990
|
if (run.code === 2) {
|
|
1914
1991
|
const reason = clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a UserPromptSubmit hook";
|
|
1915
|
-
return { block: reason, ...buildHookContextField(contexts) };
|
|
1992
|
+
return once.refused({ block: reason, ...buildHookContextField(contexts) });
|
|
1916
1993
|
}
|
|
1917
1994
|
if (run.code !== 0) {
|
|
1918
1995
|
noteExitNonzero(ctx, ledger, "UserPromptSubmit", ran);
|
|
@@ -1925,11 +2002,11 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1925
2002
|
logHookSystemMessage(ctx, "UserPromptSubmit", out.systemMessage);
|
|
1926
2003
|
if (out.continue === false) {
|
|
1927
2004
|
const reason = clipDataText(typeof out.stopReason === "string" ? out.stopReason : "hook requested stop", MAX_HOOK_FEEDBACK_CHARS);
|
|
1928
|
-
return { block: reason, ...buildHookContextField(contexts) };
|
|
2005
|
+
return once.refused({ block: reason, ...buildHookContextField(contexts) });
|
|
1929
2006
|
}
|
|
1930
2007
|
if (out.decision === "block") {
|
|
1931
2008
|
const reason = clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a UserPromptSubmit hook", MAX_HOOK_FEEDBACK_CHARS);
|
|
1932
|
-
return { block: reason, ...buildHookContextField(contexts) };
|
|
2009
|
+
return once.refused({ block: reason, ...buildHookContextField(contexts) });
|
|
1933
2010
|
}
|
|
1934
2011
|
const hso = out.hookSpecificOutput;
|
|
1935
2012
|
if (hso !== null && typeof hso === "object" && hso.hookEventName === "UserPromptSubmit") {
|
|
@@ -1941,10 +2018,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1941
2018
|
if (contexts.length === 0)
|
|
1942
2019
|
return undefined;
|
|
1943
2020
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1944
|
-
};
|
|
2021
|
+
});
|
|
1945
2022
|
}
|
|
1946
2023
|
if (stopEntries) {
|
|
1947
|
-
translators.Stop =
|
|
2024
|
+
translators.Stop = (sctx, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1948
2025
|
const payload = { ...basePayload(ctx, sctx.permissionMode), hook_event_name: "Stop", stop_hook_active: sctx.stopHookActive };
|
|
1949
2026
|
let llmExtra;
|
|
1950
2027
|
const wantsPrompt = stopEntries.some((g) => g.hooks.some((h) => h.type === "prompt"));
|
|
@@ -1972,7 +2049,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1972
2049
|
}
|
|
1973
2050
|
}
|
|
1974
2051
|
const stopGroups = ignoreMatchers(stopEntries);
|
|
1975
|
-
const ledger = createUnrunLedger(ctx, "Stop", undefined);
|
|
2052
|
+
const ledger = createUnrunLedger(ctx, "Stop", undefined, once);
|
|
1976
2053
|
if (!llmExtra && wantsPrompt) {
|
|
1977
2054
|
for (const g of stopGroups)
|
|
1978
2055
|
for (const h of g.hooks)
|
|
@@ -1982,7 +2059,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1982
2059
|
const effectiveGroups = llmExtra || !wantsPrompt
|
|
1983
2060
|
? stopGroups
|
|
1984
2061
|
: stopGroups.map((g) => ({ ...g, hooks: g.hooks.filter((h) => h.type !== "prompt") })).filter((g) => g.hooks.length > 0);
|
|
1985
|
-
const singles = await runEventLanes("Stop", effectiveGroups, "", payload, ctx,
|
|
2062
|
+
const singles = await runEventLanes("Stop", effectiveGroups, "", payload, ctx, once, halt, ledger, llmExtra);
|
|
1986
2063
|
let block;
|
|
1987
2064
|
let sawContinueFalse = false;
|
|
1988
2065
|
const contexts = [];
|
|
@@ -2036,15 +2113,16 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
2036
2113
|
return undefined;
|
|
2037
2114
|
if (block === undefined && contexts.length === 0)
|
|
2038
2115
|
return undefined;
|
|
2039
|
-
|
|
2116
|
+
const answer = {
|
|
2040
2117
|
...belowMembers(below),
|
|
2041
2118
|
...(block !== undefined ? { block } : {}),
|
|
2042
2119
|
...buildHookContextField(withBelowContext(contexts, below)),
|
|
2043
2120
|
};
|
|
2044
|
-
|
|
2121
|
+
return block !== undefined ? once.refused(answer) : answer;
|
|
2122
|
+
});
|
|
2045
2123
|
}
|
|
2046
2124
|
if (stopFailureEntries) {
|
|
2047
|
-
translators.StopFailure =
|
|
2125
|
+
translators.StopFailure = (fctx, halt) => settleOnce(onceSpent, async (once) => {
|
|
2048
2126
|
const turnError = toAssistantTurnError(fctx.errorKind);
|
|
2049
2127
|
const payload = {
|
|
2050
2128
|
...basePayload(ctx, undefined),
|
|
@@ -2052,23 +2130,23 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
2052
2130
|
error: turnError,
|
|
2053
2131
|
...(fctx.error ? { error_details: clipDataText(redactSecrets(fctx.error), MAX_HOOK_FEEDBACK_CHARS) } : {}),
|
|
2054
2132
|
};
|
|
2055
|
-
await runObserveOnlyEvent("StopFailure", stopFailureEntries, turnError, payload, ctx,
|
|
2056
|
-
};
|
|
2133
|
+
await runObserveOnlyEvent("StopFailure", stopFailureEntries, turnError, payload, ctx, once, halt);
|
|
2134
|
+
});
|
|
2057
2135
|
}
|
|
2058
2136
|
if (preCompactEntries) {
|
|
2059
|
-
translators.PreCompact =
|
|
2137
|
+
translators.PreCompact = (pctx, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
2060
2138
|
const payload = {
|
|
2061
2139
|
...basePayload(ctx, undefined),
|
|
2062
2140
|
hook_event_name: "PreCompact",
|
|
2063
2141
|
trigger: pctx.trigger,
|
|
2064
2142
|
custom_instructions: pctx.customInstructions ?? null,
|
|
2065
2143
|
};
|
|
2066
|
-
const ledger = createUnrunLedger(ctx, "PreCompact", undefined);
|
|
2067
|
-
const singles = await runEventLanes("PreCompact", preCompactEntries, pctx.trigger, payload, ctx,
|
|
2144
|
+
const ledger = createUnrunLedger(ctx, "PreCompact", undefined, once);
|
|
2145
|
+
const singles = await runEventLanes("PreCompact", preCompactEntries, pctx.trigger, payload, ctx, once, halt, ledger);
|
|
2068
2146
|
for (const ran of singles) {
|
|
2069
2147
|
const { entry, run } = ran;
|
|
2070
2148
|
if (run.code === 2) {
|
|
2071
|
-
return { ...belowMembers(below), block: clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a PreCompact hook" };
|
|
2149
|
+
return once.refused({ ...belowMembers(below), block: clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a PreCompact hook" });
|
|
2072
2150
|
}
|
|
2073
2151
|
if (run.code !== 0) {
|
|
2074
2152
|
noteExitNonzero(ctx, ledger, "PreCompact", ran);
|
|
@@ -2083,31 +2161,31 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
2083
2161
|
ctx.logger.warn("hook_continue_false_unsupported", { event: "PreCompact" });
|
|
2084
2162
|
}
|
|
2085
2163
|
if (out.decision === "block") {
|
|
2086
|
-
return { ...belowMembers(below), block: clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a PreCompact hook", MAX_HOOK_FEEDBACK_CHARS) };
|
|
2164
|
+
return once.refused({ ...belowMembers(below), block: clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a PreCompact hook", MAX_HOOK_FEEDBACK_CHARS) });
|
|
2087
2165
|
}
|
|
2088
2166
|
}
|
|
2089
2167
|
return undefined;
|
|
2090
|
-
};
|
|
2168
|
+
});
|
|
2091
2169
|
}
|
|
2092
2170
|
if (postCompactEntries) {
|
|
2093
|
-
translators.PostCompact =
|
|
2171
|
+
translators.PostCompact = (cctx, halt) => settleOnce(onceSpent, async (once) => {
|
|
2094
2172
|
const payload = {
|
|
2095
2173
|
...basePayload(ctx, undefined),
|
|
2096
2174
|
hook_event_name: "PostCompact",
|
|
2097
2175
|
trigger: cctx.trigger,
|
|
2098
2176
|
compact_summary: clipDataText(cctx.summary, MAX_TOOL_RESPONSE_CHARS),
|
|
2099
2177
|
};
|
|
2100
|
-
await runObserveOnlyEvent("PostCompact", postCompactEntries, cctx.trigger, payload, ctx,
|
|
2101
|
-
};
|
|
2178
|
+
await runObserveOnlyEvent("PostCompact", postCompactEntries, cctx.trigger, payload, ctx, once, halt);
|
|
2179
|
+
});
|
|
2102
2180
|
}
|
|
2103
2181
|
const events = Object.keys(translators);
|
|
2104
2182
|
return {
|
|
2105
2183
|
name: SETTINGS_HOOKS_REGISTRATIONS[lane],
|
|
2106
|
-
uses: { events: events.
|
|
2184
|
+
uses: { events: events.map((event) => SETTINGS_HOOK_STATIONS[event]), calls: [] },
|
|
2107
2185
|
budgetMs,
|
|
2108
2186
|
register(on) {
|
|
2109
2187
|
for (const event of events)
|
|
2110
|
-
hangTranslator(on, event, translators
|
|
2188
|
+
hangTranslator(on, event, translators);
|
|
2111
2189
|
},
|
|
2112
2190
|
};
|
|
2113
2191
|
}
|