@sema-agent/server 7.147.0 → 7.148.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +1039 -24
- package/README.md +20 -7
- package/README.zh-CN.md +14 -8
- package/USAGE.md +380 -163
- 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/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +28 -30
- package/dist/approval-gate-currency.js +3 -2
- package/dist/approval-reconciler.d.ts +4 -13
- package/dist/approval-reconciler.js +2 -2
- package/dist/approval.d.ts +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 +0 -14
- package/dist/auth-bridge.js +0 -7
- package/dist/auto-mode-face.d.ts +10 -7
- package/dist/auto-mode-face.js +7 -4
- package/dist/background-agent-name.d.ts +19 -1
- package/dist/background-agent-name.js +12 -2
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.js +9 -6
- package/dist/bench/s1/arms.js +6 -5
- package/dist/bench/s1/live-deps.js +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 +37 -31
- 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-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 +55 -67
- 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 +11 -4
- package/dist/boot/runtime-caps.d.ts +2 -2
- package/dist/boot/runtime-caps.js +16 -2
- package/dist/boot/session-faces.d.ts +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.js +9 -1
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
- package/dist/boot/stage-02-web-admin-pull.js +6 -1
- package/dist/boot/stage-03-store-backend.d.ts +3 -0
- package/dist/boot/stage-03-store-backend.js +4 -3
- package/dist/boot/stage-04-stores.d.ts +2 -0
- package/dist/boot/stage-04-stores.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +7 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +10 -12
- package/dist/boot/stage-06-runners.js +23 -15
- package/dist/boot/stage-07-capability-layer.d.ts +11 -8
- package/dist/boot/stage-07-capability-layer.js +5 -3
- package/dist/boot/stage-08-reapers.d.ts +11 -8
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +12 -15
- package/dist/boot/stage-09-leader.js +12 -4
- package/dist/boot/stage-10-http-server.d.ts +12 -15
- 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 +3 -0
- package/dist/boot/stores.js +21 -10
- 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 +38 -11
- package/dist/capability-facts.js +47 -8
- package/dist/card-void.d.ts +4 -4
- package/dist/card-void.js +1 -1
- package/dist/center-credential-renewer.d.ts +6 -2
- package/dist/center-credential-renewer.js +7 -3
- package/dist/config-catalog.d.ts +16 -1
- package/dist/config-catalog.js +62 -56
- package/dist/config-dir-trust.d.ts +37 -4
- package/dist/config-dir-trust.js +88 -44
- package/dist/config-invariants.d.ts +42 -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 +26 -17
- package/dist/config.d.ts +8 -16
- package/dist/config.js +113 -47
- 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 +30 -4
- package/dist/deployment-shape.js +7 -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-witness.d.ts +7 -0
- package/dist/env-witness.js +16 -0
- package/dist/execution-lane-caps.d.ts +5 -18
- package/dist/execution-lane-caps.js +0 -22
- 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/hook-llm.d.ts +5 -1
- package/dist/hooks/hook-llm.js +24 -15
- package/dist/hooks/hook-runner.d.ts +67 -57
- package/dist/hooks/hook-runner.js +260 -186
- package/dist/host-lsp-manager.d.ts +22 -8
- package/dist/host-lsp-manager.js +4 -1
- package/dist/http/active-run-conflict.d.ts +2 -43
- package/dist/http/active-run-conflict.js +3 -7
- package/dist/http/admission.d.ts +4 -18
- package/dist/http/admission.js +75 -78
- package/dist/http/approval-sweeps.d.ts +3 -3
- package/dist/http/approval-sweeps.js +54 -30
- 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 +4 -3
- package/dist/http/dispatch.d.ts +8 -1
- package/dist/http/dispatch.js +76 -30
- package/dist/http/durable-run-leg.d.ts +3 -3
- package/dist/http/durable-run-leg.js +17 -12
- package/dist/http/execution-context.d.ts +17 -43
- package/dist/http/execution-context.js +7 -5
- package/dist/http/health-reader.d.ts +36 -0
- package/dist/http/health-reader.js +21 -0
- package/dist/http/health-self-report.d.ts +9 -9
- package/dist/http/health-self-report.js +4 -4
- package/dist/http/idempotency.d.ts +9 -5
- package/dist/http/idempotency.js +4 -4
- package/dist/http/memory-compliance-failure-reply.d.ts +15 -16
- package/dist/http/memory-compliance-failure-reply.js +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 +391 -67
- package/dist/http/owner-access.js +371 -35
- package/dist/http/principal-gate.d.ts +24 -81
- package/dist/http/principal-gate.js +24 -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 +35 -12
- package/dist/http/resume-ctx-read.js +25 -6
- package/dist/http/resume-legs.d.ts +21 -18
- package/dist/http/resume-legs.js +189 -129
- package/dist/http/retired-skill-manifest.d.ts +1 -1
- package/dist/http/route-ctx.d.ts +25 -32
- package/dist/http/routes/a2a-serve.d.ts +43 -5
- package/dist/http/routes/a2a-serve.js +58 -37
- package/dist/http/routes/admin-config-refresh.js +2 -2
- package/dist/http/routes/admin-drain.js +2 -2
- package/dist/http/routes/admin-memory-optout.js +4 -3
- package/dist/http/routes/adoption.d.ts +3 -0
- package/dist/http/routes/adoption.js +17 -10
- package/dist/http/routes/agents-roster.js +13 -7
- package/dist/http/routes/approvals-assistant.js +70 -65
- 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 +15 -18
- 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 +27 -3
- package/dist/http/routes/diagnostics.js +27 -21
- package/dist/http/routes/engine.js +2 -2
- package/dist/http/routes/fleet.js +5 -3
- package/dist/http/routes/images.js +10 -6
- package/dist/http/routes/leader.d.ts +7 -2
- package/dist/http/routes/leader.js +12 -3
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +7 -15
- package/dist/http/routes/memory-bundle.js +4 -7
- package/dist/http/routes/memory-compliance.js +4 -4
- package/dist/http/routes/memory-consolidation.js +6 -9
- package/dist/http/routes/memory-origin.d.ts +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 +1 -1
- package/dist/http/routes/principal-inbox.js +2 -2
- 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 +146 -231
- package/dist/http/routes/session-memory-sync.d.ts +2 -2
- package/dist/http/routes/session-memory-sync.js +7 -13
- package/dist/http/routes/session-sync.d.ts +4 -2
- package/dist/http/routes/session-sync.js +21 -20
- 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 +136 -120
- 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 +39 -40
- package/dist/http/server.js +36 -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 +16 -8
- package/dist/http/submit-ctx.js +6 -2
- package/dist/http/submit-replay.d.ts +19 -6
- package/dist/http/submit-replay.js +18 -6
- package/dist/http/sync-submit-body.d.ts +3 -4
- package/dist/http/sync-submit-body.js +4 -5
- package/dist/http/wire-types.d.ts +4 -3
- package/dist/identity-source.d.ts +36 -5
- package/dist/identity-source.js +27 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -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/lsp-evict.d.ts +6 -4
- package/dist/lsp-evict.js +2 -3
- package/dist/memory-operator-faces.d.ts +5 -4
- package/dist/memory-operator-faces.js +1 -1
- package/dist/memory-scope.d.ts +29 -2
- package/dist/memory-scope.js +64 -15
- package/dist/memory-store-refusal.d.ts +5 -2
- package/dist/memory-sync-client.d.ts +3 -2
- package/dist/memory-sync-client.js +6 -3
- package/dist/model-compat.d.ts +17 -8
- package/dist/model-compat.js +6 -2
- package/dist/model-context-window.d.ts +18 -0
- package/dist/model-context-window.js +2 -0
- package/dist/model-entry-headers.d.ts +46 -4
- package/dist/model-entry-headers.js +2 -2
- package/dist/model-entry-refusal.d.ts +35 -16
- package/dist/model-entry-refusal.js +40 -27
- package/dist/model-plane-face.d.ts +19 -11
- package/dist/model-plane-face.js +9 -1
- package/dist/model-plane-probe.d.ts +2 -0
- package/dist/model-plane-probe.js +17 -0
- package/dist/model-provider.d.ts +3 -3
- package/dist/model-route-endpoint.d.ts +9 -5
- package/dist/model-route-endpoint.js +29 -7
- package/dist/model-select.d.ts +16 -0
- package/dist/model-select.js +4 -0
- package/dist/mountinfo.d.ts +37 -0
- package/dist/mountinfo.js +47 -0
- package/dist/namespaced-rule-name.d.ts +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 +58 -38
- package/dist/observability/fail-open.js +60 -38
- package/dist/observability/logger.d.ts +22 -1
- package/dist/observability/logger.js +89 -12
- package/dist/observability/metrics.js +3 -4
- package/dist/observability/otel-exporter.js +2 -1
- package/dist/observability/principal-context.d.ts +14 -7
- package/dist/observability/principal-context.js +8 -3
- package/dist/observability/run-terminal.d.ts +7 -1
- package/dist/observability/run-terminal.js +5 -2
- package/dist/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 +5 -4
- package/dist/org-delivery-gate.js +7 -6
- package/dist/outbound-dispatcher.d.ts +1 -1
- package/dist/outbound-dispatcher.js +6 -12
- package/dist/owner-brands.d.ts +81 -0
- package/dist/owner-brands.js +42 -0
- package/dist/owner-faces.d.ts +531 -0
- package/dist/owner-faces.js +126 -0
- package/dist/parked-decide.d.ts +67 -5
- package/dist/parked-decide.js +127 -5
- package/dist/parked-revive-surface.d.ts +14 -4
- package/dist/parked-revive-surface.js +5 -4
- package/dist/peer-directory.d.ts +6 -8
- package/dist/peer-directory.js +3 -2
- package/dist/permission-rule-vocab.d.ts +53 -8
- package/dist/permission-rule-vocab.js +30 -2
- package/dist/plugins/adoption-log-sql.d.ts +0 -22
- package/dist/plugins/adoption-log-sql.js +5 -3
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.d.ts +7 -0
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.js +17 -0
- package/dist/plugins/approval-ask-store-file.d.ts +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 +39 -20
- package/dist/plugins/approval-ask-store-sql.js +41 -10
- package/dist/plugins/approval-exemption-skill-m46.d.ts +20 -0
- package/dist/plugins/approval-exemption-skill-m46.js +25 -0
- package/dist/plugins/approval-exemption-store.d.ts +6 -1
- package/dist/plugins/approval-exemption-store.js +14 -0
- package/dist/plugins/approval-nonce-store.d.ts +39 -12
- package/dist/plugins/approval-nonce-store.js +72 -23
- package/dist/plugins/blob-backend.d.ts +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 +0 -15
- package/dist/plugins/ensure-schema-lock-policy.js +3 -2
- package/dist/plugins/file-run-store.d.ts +63 -23
- package/dist/plugins/file-run-store.js +138 -83
- 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 +58 -23
- package/dist/plugins/local-checkpoint-store.js +195 -76
- package/dist/plugins/local-data-dir-modes-m39.js +2 -1
- 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 +4 -2
- package/dist/plugins/local-engine-high-water.js +4 -1
- package/dist/plugins/local-session-store.d.ts +358 -125
- package/dist/plugins/local-session-store.js +824 -251
- 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 +39 -27
- package/dist/plugins/memory-run-store.js +72 -70
- package/dist/plugins/one-time-migration-marker.d.ts +10 -0
- package/dist/plugins/one-time-migration-marker.js +7 -0
- package/dist/plugins/one-time-migrations.d.ts +186 -45
- package/dist/plugins/one-time-migrations.js +442 -119
- package/dist/plugins/org-delivery-quota-store.js +2 -1
- package/dist/plugins/permission-rule-store-file.d.ts +3 -3
- package/dist/plugins/permission-rule-store-sql.d.ts +4 -63
- package/dist/plugins/permission-rule-store-sql.js +6 -86
- package/dist/plugins/pg-pool.d.ts +1 -31
- package/dist/plugins/pg-pool.js +16 -7
- package/dist/plugins/remote-env-e2b.d.ts +7 -25
- package/dist/plugins/remote-env-e2b.js +34 -25
- package/dist/plugins/remote-env-host.d.ts +2 -9
- package/dist/plugins/remote-env-host.js +34 -22
- package/dist/plugins/remote-env-k8s.d.ts +40 -45
- package/dist/plugins/remote-env-k8s.js +107 -58
- package/dist/plugins/remote-env-local-docker.d.ts +148 -14
- package/dist/plugins/remote-env-local-docker.js +367 -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 +56 -68
- package/dist/plugins/run-store-sql.js +127 -116
- package/dist/plugins/s3-answer.d.ts +2 -1
- package/dist/plugins/sandbox-reaper.d.ts +26 -0
- package/dist/plugins/sandbox-reaper.js +2 -0
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +54 -0
- package/dist/plugins/scenario-prefix-switch-m42.js +55 -0
- package/dist/plugins/scheduler-support.d.ts +16 -1
- package/dist/plugins/scheduler-support.js +22 -2
- package/dist/plugins/schema-consistency.d.ts +42 -9
- package/dist/plugins/schema-consistency.js +212 -11
- package/dist/plugins/schema-drift-sentence.d.ts +4 -1
- package/dist/plugins/schema-drift-sentence.js +4 -4
- package/dist/plugins/schema-ensure-legs.d.ts +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 +22 -16
- 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 +20 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +3 -0
- package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
- package/dist/plugins/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/store-backend.d.ts +84 -15
- package/dist/plugins/store-backend.js +186 -55
- package/dist/plugins/store-contracts.d.ts +90 -30
- package/dist/plugins/store-contracts.js +22 -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.js +23 -8
- package/dist/plugins/web-search.js +5 -3
- package/dist/plugins/workflow-run-store-sql.d.ts +6 -1
- package/dist/plugins/workflow-run-store-sql.js +11 -5
- package/dist/principal-jwt.d.ts +4 -4
- package/dist/principal-jwt.js +20 -5
- package/dist/principal-shape.d.ts +41 -0
- package/dist/principal-shape.js +19 -0
- package/dist/question.d.ts +13 -23
- package/dist/question.js +21 -39
- package/dist/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-local.d.ts +14 -6
- package/dist/run-local.js +92 -80
- package/dist/run-stale-default.d.ts +7 -0
- package/dist/run-stale-default.js +2 -0
- package/dist/runs.d.ts +26 -15
- package/dist/runs.js +39 -27
- 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 +21 -5
- package/dist/server-secret-env.js +14 -4
- package/dist/session-children-retire.d.ts +7 -5
- package/dist/session-children-retire.js +7 -2
- package/dist/session-deletion.d.ts +88 -0
- package/dist/session-deletion.js +8 -0
- package/dist/session-erase.d.ts +145 -0
- package/dist/session-erase.js +115 -0
- package/dist/session-error-wire.d.ts +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/spec-fields.d.ts +57 -3
- package/dist/spec-fields.js +72 -51
- package/dist/store-posture.d.ts +136 -20
- package/dist/store-posture.js +188 -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 +33 -28
- package/dist/stores-sql/checkpoint-store-sql.js +75 -44
- 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/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 +1 -1
- package/dist/task-a2a.js +3 -3
- package/dist/task-cwd.d.ts +20 -0
- package/dist/task-cwd.js +8 -0
- package/dist/task-mcp.d.ts +1 -1
- package/dist/task-mcp.js +3 -3
- package/dist/task-settings.d.ts +14 -10
- package/dist/task-settings.js +18 -7
- package/dist/terminal.d.ts +25 -43
- package/dist/terminal.js +31 -11
- package/dist/tool-approval.d.ts +131 -129
- package/dist/tool-approval.js +189 -193
- 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/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 +1 -30
- package/dist/trace/ledger-sink.js +0 -11
- package/dist/trace/model-segment.d.ts +5 -5
- package/dist/trace/model-segment.js +5 -5
- package/dist/trace/project.d.ts +55 -42
- package/dist/trace/project.js +52 -19
- package/dist/trace/redact.d.ts +123 -27
- package/dist/trace/redact.js +880 -260
- package/dist/trace/self-minted-wire.d.ts +487 -19
- package/dist/trace/self-minted-wire.js +172 -23
- 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 +13 -16
- 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/package.json +6 -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/wire-changes/server@7.148.0.json +1517 -0
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +0 -25
- package/dist/http/memory-control-plane-corrupt-reply.js +0 -19
- package/dist/http/memory-layer-reply.d.ts +0 -30
- package/dist/http/memory-layer-reply.js +0 -24
- package/dist/lsp/e2b-bridge.d.ts +0 -57
- package/dist/lsp/e2b-bridge.js +0 -139
- package/dist/lsp/e2b-manager.d.ts +0 -93
- package/dist/lsp/e2b-manager.js +0 -178
- package/dist/lsp/lsp-frames.d.ts +0 -14
- package/dist/lsp/lsp-frames.js +0 -25
- package/dist/lsp/manager.d.ts +0 -129
- package/dist/lsp/manager.js +0 -127
- package/dist/lsp/types.d.ts +0 -12
- package/dist/lsp/types.js +0 -2
- package/dist/lsp/ws-transport.d.ts +0 -40
- package/dist/lsp/ws-transport.js +0 -210
|
@@ -1,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";
|
|
@@ -42,31 +44,26 @@ function hookEnv(ctx) {
|
|
|
42
44
|
return hookChildEnv(composeHookEnvLayer(ctx.shellEnv, ctx.cwd, undefined), false);
|
|
43
45
|
}
|
|
44
46
|
export const SETTINGS_HOOK_STATIONS = {
|
|
45
|
-
PreToolUse:
|
|
46
|
-
PostToolUse:
|
|
47
|
-
PostToolUseFailure:
|
|
48
|
-
PostToolBatch:
|
|
49
|
-
UserPromptSubmit:
|
|
50
|
-
Stop:
|
|
51
|
-
StopFailure:
|
|
52
|
-
PreCompact:
|
|
53
|
-
PostCompact:
|
|
47
|
+
PreToolUse: "classic.PreToolUse",
|
|
48
|
+
PostToolUse: "classic.PostToolUse",
|
|
49
|
+
PostToolUseFailure: "classic.PostToolUseFailure",
|
|
50
|
+
PostToolBatch: "classic.PostToolBatch",
|
|
51
|
+
UserPromptSubmit: "classic.UserPromptSubmit",
|
|
52
|
+
Stop: "classic.Stop",
|
|
53
|
+
StopFailure: "classic.StopFailure",
|
|
54
|
+
PreCompact: "classic.PreCompact",
|
|
55
|
+
PostCompact: "classic.PostCompact",
|
|
54
56
|
};
|
|
55
57
|
function chainsBelowTaskOn(patterns, station) {
|
|
56
58
|
return patterns.some((p) => p === station || (p.endsWith(".*") && station.startsWith(p.slice(0, -1))));
|
|
57
59
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const MANAGED_REWRITE_UNSHOWN_REASON = "a managed PreToolUse hook rewrote this call's input, but this deployment runs its own handler for this call after the request's hooks and that handler never sees a rewrite made above it, so the rewrite cannot be honored and the call was not executed";
|
|
62
|
-
const MANAGED_ALLOW_UNJUDGED_REASON = "a managed PreToolUse hook allowed this call, but this deployment runs its own handler for this call after the request's hooks, and a request hook's allow does not stand in for that handler's judgment, so the call was not executed (the same outcome as the same hook without a managed source)";
|
|
63
|
-
function hangTranslator(on, event, translators, lane) {
|
|
60
|
+
const REQUEST_HOOK_REWRITE_UNSHOWN_REASON = "a request PreToolUse hook rewrote this call's input, but this deployment runs its own handler for this call after the request's hooks and that handler never sees a rewrite made above it, so the rewrite cannot be honored and the call was not executed";
|
|
61
|
+
const REQUEST_HOOK_ALLOW_UNJUDGED_REASON = "a request PreToolUse hook allowed this call, but this deployment runs its own handler for this call after the request's hooks, and a request hook's allow does not stand in for that handler's judgment, so the call was not executed";
|
|
62
|
+
function hangTranslator(on, event, translators) {
|
|
64
63
|
const translate = translators[event];
|
|
65
64
|
if (translate === undefined)
|
|
66
65
|
return;
|
|
67
|
-
|
|
68
|
-
for (const station of SETTINGS_HOOK_STATIONS[event])
|
|
69
|
-
hang(on, station, translate);
|
|
66
|
+
hangClassic(on, SETTINGS_HOOK_STATIONS[event], translate);
|
|
70
67
|
}
|
|
71
68
|
export const SETTINGS_HOOKS_REGISTRATIONS = {
|
|
72
69
|
managed: "settings.hooks.managed",
|
|
@@ -242,54 +239,61 @@ function hooksCapIssue(limit, event, path, count) {
|
|
|
242
239
|
}
|
|
243
240
|
const matcherPath = (event, groupIndex) => ["hooks", event, groupIndex, "matcher"];
|
|
244
241
|
export function buildHooksRefusal(issue) {
|
|
245
|
-
const field = "settings.hooks";
|
|
246
242
|
switch (issue.reason) {
|
|
247
|
-
case "dead_alias":
|
|
243
|
+
case "dead_alias": {
|
|
244
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
248
245
|
return {
|
|
249
246
|
message: `settings.hooks.${issue.event}: matcher "${issue.alias}" is an alias; tool-event matchers match the tool's wire name (PostToolUse / PostToolUseFailure since 7.107.0) — use "${issue.canonical}"`,
|
|
250
|
-
field,
|
|
251
|
-
detail: { reason: issue.reason, event: issue.event, alias: issue.alias, canonical: issue.canonical, path: matcherPath(issue.event, issue.groupIndex) },
|
|
247
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, alias: issue.alias, canonical: issue.canonical },
|
|
252
248
|
};
|
|
253
|
-
|
|
249
|
+
}
|
|
250
|
+
case "over_budget": {
|
|
251
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
254
252
|
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) },
|
|
253
|
+
message: `${field}: evaluating the pattern did not finish within ${issue.budgetMs} ms (catastrophic regex backtracking) — rewrite it as a tool-name list or a pattern without nested repetition`,
|
|
254
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, budgetMs: issue.budgetMs },
|
|
258
255
|
};
|
|
259
|
-
|
|
256
|
+
}
|
|
257
|
+
case "budget_exceeded": {
|
|
258
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
260
259
|
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) },
|
|
260
|
+
message: `${field}: evaluating this configuration's regular-expression matchers took longer than ${issue.totalMs} ms in total (very slow patterns) — write tool names as a list such as "Read|Edit", or simplify the patterns`,
|
|
261
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, totalMs: issue.totalMs },
|
|
264
262
|
};
|
|
265
|
-
|
|
263
|
+
}
|
|
264
|
+
case "invalid_regex": {
|
|
265
|
+
const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
|
|
266
266
|
return {
|
|
267
|
-
message:
|
|
268
|
-
field,
|
|
269
|
-
detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, path: matcherPath(issue.event, issue.groupIndex) },
|
|
267
|
+
message: `${field}: ${JSON.stringify(issue.matcher)} is not a valid regular expression (${issue.compileError}) — fix the pattern, or write the tool names as a list such as "Read|Edit"`,
|
|
268
|
+
facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex },
|
|
270
269
|
};
|
|
271
|
-
|
|
270
|
+
}
|
|
271
|
+
case "unsupported_entry_type": {
|
|
272
|
+
const field = hooksFieldCoordinate(issue.path);
|
|
272
273
|
return {
|
|
273
|
-
message: `${
|
|
274
|
-
field,
|
|
275
|
-
detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path), type: issue.type },
|
|
274
|
+
message: `${field}: this server does not run hook entries of type ${issue.type}; supported: ${SUPPORTED_HOOK_ENTRY_TYPES.join(" / ")}`,
|
|
275
|
+
facts: { field, reason: issue.reason, type: issue.type },
|
|
276
276
|
};
|
|
277
|
+
}
|
|
277
278
|
case "over_cap":
|
|
278
279
|
case "too_long": {
|
|
279
280
|
const cap = issue;
|
|
280
|
-
return { message: HOOKS_CAPS[cap.limit].sentence(cap.event, cap.count),
|
|
281
|
+
return { message: HOOKS_CAPS[cap.limit].sentence(cap.event, cap.count), facts: { ...limitFacts(hooksFieldCoordinate(cap.path), HOOKS_CAPS[cap.limit].measure, cap.count, cap.cap), reason: cap.reason } };
|
|
282
|
+
}
|
|
283
|
+
case "unnamed_refusal": {
|
|
284
|
+
const field = hooksFieldCoordinate(issue.path);
|
|
285
|
+
return { message: `${field}: the hooks reader refused this configuration without naming a piece`, facts: { field, reason: issue.reason } };
|
|
286
|
+
}
|
|
287
|
+
case "wire_key_invalid": {
|
|
288
|
+
const field = hooksFieldCoordinate(issue.path);
|
|
289
|
+
return { message: `${field}: ${HOOKS_WIRE_KEY_SHAPE[issue.key]}`, facts: { field, reason: issue.reason, key: issue.key } };
|
|
281
290
|
}
|
|
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
291
|
default: {
|
|
287
292
|
const piece = issue;
|
|
288
293
|
const key = piece.key !== undefined ? hooksOutgoingKey(piece.key) : undefined;
|
|
289
294
|
return {
|
|
290
295
|
message: hooksPieceRefusal(piece),
|
|
291
|
-
field,
|
|
292
|
-
detail: { reason: piece.reason, path: hooksOutgoingPath(piece.path), ...(key !== undefined ? { key } : {}) },
|
|
296
|
+
facts: { field: hooksFieldCoordinate(piece.path), reason: piece.reason, ...(key !== undefined ? { key } : {}) },
|
|
293
297
|
};
|
|
294
298
|
}
|
|
295
299
|
}
|
|
@@ -352,8 +356,8 @@ export function hooksUrlCredentialIssue(config) {
|
|
|
352
356
|
return undefined;
|
|
353
357
|
}
|
|
354
358
|
export function buildHooksUrlCredentialRefusal(issue) {
|
|
355
|
-
const entry =
|
|
356
|
-
return buildRequestUrlCredentialRefusal(
|
|
359
|
+
const entry = ["hooks", issue.event, issue.groupIndex, "hooks", issue.entryIndex];
|
|
360
|
+
return buildRequestUrlCredentialRefusal(hooksFieldCoordinate([...entry, "url"]), issue.credential, urlCredentialHeaderExit(hooksFieldCoordinate([...entry, "headers"])));
|
|
357
361
|
}
|
|
358
362
|
const HOOKS_PIECE_MEANING = {
|
|
359
363
|
"hooks-not-object": "`hooks` must be an object keyed by hook event name",
|
|
@@ -371,8 +375,8 @@ const HOOKS_PIECE_MEANING = {
|
|
|
371
375
|
export function hooksOutgoingPath(path) {
|
|
372
376
|
return outgoingPath(path).map((seg) => (typeof seg === "string" ? echoCallerText(seg) : seg));
|
|
373
377
|
}
|
|
374
|
-
export function
|
|
375
|
-
return
|
|
378
|
+
export function hooksFieldCoordinate(path) {
|
|
379
|
+
return fieldCoordinate("settings", hooksOutgoingPath(path));
|
|
376
380
|
}
|
|
377
381
|
function hooksOutgoingKey(key) {
|
|
378
382
|
return echoCallerText(String(outgoingPath([key])[0] ?? ""));
|
|
@@ -382,7 +386,7 @@ function hooksPieceIssue(piece) {
|
|
|
382
386
|
}
|
|
383
387
|
function hooksPieceRefusal(piece) {
|
|
384
388
|
const field = piece.key !== undefined ? ` (field: ${hooksOutgoingKey(piece.key)})` : "";
|
|
385
|
-
return `${
|
|
389
|
+
return `${hooksFieldCoordinate(piece.path)}: ${piece.reason} — ${HOOKS_PIECE_MEANING[piece.reason]}${field}`;
|
|
386
390
|
}
|
|
387
391
|
function hooksRefused(issue, pieces) {
|
|
388
392
|
const error = buildHooksRefusal(issue).message;
|
|
@@ -733,24 +737,26 @@ const VERDICT_GAP_CAUSE = {
|
|
|
733
737
|
input_truncated: "verdict_unreadable",
|
|
734
738
|
matcher_over_budget: "verdict_unreadable",
|
|
735
739
|
};
|
|
736
|
-
function createUnrunLedger(ctx, event, toolName) {
|
|
740
|
+
function createUnrunLedger(ctx, event, toolName, once) {
|
|
737
741
|
let managedVerdictGap;
|
|
738
742
|
let haltNoted = false;
|
|
739
743
|
const ledger = {
|
|
740
744
|
halted(source, entry) {
|
|
741
|
-
if (haltNoted)
|
|
745
|
+
if (haltNoted || !isSyncEntry(entry))
|
|
742
746
|
return;
|
|
743
747
|
haltNoted = true;
|
|
744
748
|
ledger.unrun(source, entry, "budget_exhausted", ENGINE_BUDGET_SPENT_DETAIL);
|
|
745
749
|
},
|
|
746
750
|
untrusted(source, entry, reason) {
|
|
751
|
+
once.unsettled(entry);
|
|
747
752
|
if (hookLaneOf(source) === "unmanaged")
|
|
748
753
|
return;
|
|
749
754
|
managedVerdictGap ??= VERDICT_GAP_CAUSE[reason];
|
|
750
755
|
noteVerdictUntrusted(ctx, { event, reason, entry, source, toolName });
|
|
751
756
|
},
|
|
752
757
|
unrun(source, entry, reason, detail) {
|
|
753
|
-
|
|
758
|
+
once.unsettled(entry);
|
|
759
|
+
if (source === undefined || hookLaneOf(source) === "unmanaged" || !isSyncEntry(entry))
|
|
754
760
|
return;
|
|
755
761
|
managedVerdictGap ??= VERDICT_GAP_CAUSE[reason];
|
|
756
762
|
ctx.logger.warn("hook_managed_unrun", { event, reason, source: echoCallerText(source), type: entry.type, ...(toolName !== undefined ? { tool: toolName } : {}) });
|
|
@@ -830,8 +836,12 @@ function withBelowContext(parts, below) {
|
|
|
830
836
|
const tail = belowString(below, "additionalContext");
|
|
831
837
|
return tail === undefined ? [...parts] : [...parts, tail];
|
|
832
838
|
}
|
|
833
|
-
|
|
834
|
-
|
|
839
|
+
const ALSO_ASKS_SPEAKER = {
|
|
840
|
+
managed: "a managed PreToolUse hook",
|
|
841
|
+
unmanaged: "a PreToolUse hook",
|
|
842
|
+
};
|
|
843
|
+
function alsoAsks(lane, below, own) {
|
|
844
|
+
return below === undefined || below === own ? own : `${below} (${ALSO_ASKS_SPEAKER[lane]} also asks: ${own})`;
|
|
835
845
|
}
|
|
836
846
|
function readBelowPreToolUse(below) {
|
|
837
847
|
const action = belowString(below, "action");
|
|
@@ -845,7 +855,7 @@ function readBelowPreToolUse(below) {
|
|
|
845
855
|
allowed: action === "allow",
|
|
846
856
|
...(action === "ask" && (cause === undefined || cause === "asked") ? { asked: message } : {}),
|
|
847
857
|
...(action === "ask" && cause !== undefined && cause !== "asked" ? { unreadable: { message, cause: unreadableCause } } : {}),
|
|
848
|
-
|
|
858
|
+
...(action === "ask" && typeof below === "object" && below !== null && Object.hasOwn(below, "requiresRealApproval") && Reflect.get(below, "requiresRealApproval") === true ? { realApproval: true } : {}),
|
|
849
859
|
...(rewrite !== null && typeof rewrite === "object" ? { updatedInput: rewrite } : {}),
|
|
850
860
|
...(additionalContext !== undefined ? { additionalContext } : {}),
|
|
851
861
|
};
|
|
@@ -857,7 +867,65 @@ function spawnPlannedCommand(plan, ctx, stdio) {
|
|
|
857
867
|
const sh = hostShell();
|
|
858
868
|
return spawn(sh.shell, [...sh.args, plan.command], { cwd: ctx.cwd, env, stdio, detached: true });
|
|
859
869
|
}
|
|
860
|
-
|
|
870
|
+
function createHookTreeLadder(child, ctx, event) {
|
|
871
|
+
const leaderOurs = () => child.pid !== undefined && child.exitCode === null && child.signalCode === null;
|
|
872
|
+
const alive = () => leaderOurs() || (child.pid !== undefined && reapedLeaderGroupAlive(child.pid));
|
|
873
|
+
const shoot = (sig) => {
|
|
874
|
+
const pid = child.pid;
|
|
875
|
+
if (pid === undefined) {
|
|
876
|
+
child.kill(sig);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
if (leaderOurs()) {
|
|
880
|
+
signalProcessTree(pid, sig);
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
if (!reapedLeaderGroupAlive(pid))
|
|
884
|
+
return;
|
|
885
|
+
try {
|
|
886
|
+
(sig === "SIGTERM" ? killTreeSoft : killTreeHard)(pid);
|
|
887
|
+
}
|
|
888
|
+
catch {
|
|
889
|
+
child.kill(sig);
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
let hardFired = false;
|
|
893
|
+
const hard = (end) => {
|
|
894
|
+
if (hardFired)
|
|
895
|
+
return;
|
|
896
|
+
hardFired = true;
|
|
897
|
+
shoot("SIGKILL");
|
|
898
|
+
const recheck = setTimeout(() => {
|
|
899
|
+
const clean = !alive();
|
|
900
|
+
if (!clean)
|
|
901
|
+
shoot("SIGKILL");
|
|
902
|
+
const fields = { event, type: "command", end, shots: clean ? 1 : 2, clean };
|
|
903
|
+
if (clean)
|
|
904
|
+
ctx.logger.info("hook_command_tree_swept", fields);
|
|
905
|
+
else
|
|
906
|
+
ctx.logger.warn("hook_command_tree_swept", fields);
|
|
907
|
+
}, HOOK_KILL_GRACE_MS);
|
|
908
|
+
recheck.unref();
|
|
909
|
+
};
|
|
910
|
+
return {
|
|
911
|
+
halt(onEscalate) {
|
|
912
|
+
shoot("SIGTERM");
|
|
913
|
+
const escalate = setTimeout(() => {
|
|
914
|
+
if (hardFired || !alive())
|
|
915
|
+
return;
|
|
916
|
+
onEscalate();
|
|
917
|
+
hard("halt");
|
|
918
|
+
}, HOOK_KILL_GRACE_MS);
|
|
919
|
+
escalate.unref();
|
|
920
|
+
},
|
|
921
|
+
kill: hard,
|
|
922
|
+
ended() {
|
|
923
|
+
if (alive())
|
|
924
|
+
hard("exit");
|
|
925
|
+
},
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
async function runCommandHook(entry, payload, ctx, halt, event) {
|
|
861
929
|
const plan = await planCommandSpawn(entry, ctx.cwd, ctx.shellEnv);
|
|
862
930
|
if (plan.kind === "refused")
|
|
863
931
|
return { code: null, stdout: "", stderr: "", timedOut: false, spawnError: plan.error };
|
|
@@ -882,6 +950,7 @@ async function runCommandHook(entry, payload, ctx, halt) {
|
|
|
882
950
|
return;
|
|
883
951
|
}
|
|
884
952
|
const ticket = adoptHostForegroundChild(child);
|
|
953
|
+
const tree = createHookTreeLadder(child, ctx, event);
|
|
885
954
|
let stdout = "";
|
|
886
955
|
let stderr = "";
|
|
887
956
|
let timedOut = false;
|
|
@@ -900,40 +969,16 @@ async function runCommandHook(entry, payload, ctx, halt) {
|
|
|
900
969
|
timedOut = true;
|
|
901
970
|
if (sent !== undefined)
|
|
902
971
|
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
972
|
settle(null);
|
|
973
|
+
tree.kill("timeout");
|
|
913
974
|
}, 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
975
|
const onHalt = () => {
|
|
926
976
|
if (settled)
|
|
927
977
|
return;
|
|
928
978
|
sent = "SIGTERM";
|
|
929
|
-
|
|
930
|
-
const escalate = setTimeout(() => {
|
|
931
|
-
if (child.exitCode !== null || child.signalCode !== null)
|
|
932
|
-
return;
|
|
979
|
+
tree.halt(() => {
|
|
933
980
|
sent = "SIGKILL";
|
|
934
|
-
|
|
935
|
-
}, HOOK_KILL_GRACE_MS);
|
|
936
|
-
escalate.unref();
|
|
981
|
+
});
|
|
937
982
|
};
|
|
938
983
|
halt.addEventListener("abort", onHalt, { once: true });
|
|
939
984
|
child.stdout?.on("data", (d) => {
|
|
@@ -952,7 +997,12 @@ async function runCommandHook(entry, payload, ctx, halt) {
|
|
|
952
997
|
resolve({ code: null, stdout, stderr, timedOut, spawnError: String(e) });
|
|
953
998
|
}
|
|
954
999
|
});
|
|
955
|
-
child.on("close", (code) =>
|
|
1000
|
+
child.on("close", (code) => {
|
|
1001
|
+
const natural = !settled && sent === undefined;
|
|
1002
|
+
settle(code);
|
|
1003
|
+
if (natural)
|
|
1004
|
+
tree.ended();
|
|
1005
|
+
});
|
|
956
1006
|
child.stdin?.on("error", () => { });
|
|
957
1007
|
child.stdin?.end(`${JSON.stringify(boundedToolInputPayload(payload))}\n`);
|
|
958
1008
|
});
|
|
@@ -970,18 +1020,11 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
|
|
|
970
1020
|
return;
|
|
971
1021
|
const child = spawnPlannedCommand(plan, ctx, ["pipe", "ignore", rewake ? "pipe" : "ignore"]);
|
|
972
1022
|
const ticket = adoptHostForegroundChild(child);
|
|
1023
|
+
const tree = createHookTreeLadder(child, ctx, event);
|
|
973
1024
|
let killedByTimeout = false;
|
|
974
1025
|
const timer = setTimeout(() => {
|
|
975
1026
|
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
|
-
}
|
|
1027
|
+
tree.kill("timeout");
|
|
985
1028
|
}, timeoutMs);
|
|
986
1029
|
timer.unref?.();
|
|
987
1030
|
let stderr = "";
|
|
@@ -1000,6 +1043,8 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
|
|
|
1000
1043
|
child.on("close", (code) => {
|
|
1001
1044
|
clearTimeout(timer);
|
|
1002
1045
|
ticket?.release();
|
|
1046
|
+
if (!killedByTimeout)
|
|
1047
|
+
tree.ended();
|
|
1003
1048
|
noteAsyncOutcome(entry, ctx, event, payload, { code, rewake, killedByTimeout });
|
|
1004
1049
|
if (!rewake || code !== 2)
|
|
1005
1050
|
return;
|
|
@@ -1119,6 +1164,7 @@ function httpHookWithheldSentence(event, block) {
|
|
|
1119
1164
|
return `settings.hooks.${event}: http hook not sent — ${why} (rule: ${block.rule}); ${exit}`;
|
|
1120
1165
|
}
|
|
1121
1166
|
const MAX_BLANKED_REFERENCES_LOGGED = 16;
|
|
1167
|
+
const httpHookFetch = createEgressFetch("declare the final address as this hook entry's url");
|
|
1122
1168
|
async function runHttpHook(entry, payload, ctx, event) {
|
|
1123
1169
|
const block = httpHookUrlVerdict(entry.url, ctx.httpHookAllowlistLayers, SERVER_WORKSPACE_TRUST);
|
|
1124
1170
|
if (block !== undefined)
|
|
@@ -1146,12 +1192,11 @@ async function runHttpHook(entry, payload, ctx, event) {
|
|
|
1146
1192
|
const ac = new AbortController();
|
|
1147
1193
|
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
1148
1194
|
try {
|
|
1149
|
-
const res = await
|
|
1195
|
+
const res = await httpHookFetch(entry.url, {
|
|
1150
1196
|
method: "POST",
|
|
1151
1197
|
headers,
|
|
1152
1198
|
body: `${JSON.stringify(boundedToolInputPayload(payload))}\n`,
|
|
1153
1199
|
signal: ac.signal,
|
|
1154
|
-
redirect: "error",
|
|
1155
1200
|
});
|
|
1156
1201
|
let body = "";
|
|
1157
1202
|
const reader = res.body?.getReader();
|
|
@@ -1277,7 +1322,7 @@ function runRunnableEntry(entry, payload, ctx, event, llmExtra, halt) {
|
|
|
1277
1322
|
case "agent":
|
|
1278
1323
|
return runLlmHook(entry, payload, ctx, { system: ccAgentHookSystemFor(event), event });
|
|
1279
1324
|
case "command":
|
|
1280
|
-
return runCommandHook(entry, payload, ctx, halt);
|
|
1325
|
+
return runCommandHook(entry, payload, ctx, halt, event);
|
|
1281
1326
|
default: {
|
|
1282
1327
|
const unreachable = entry;
|
|
1283
1328
|
void unreachable;
|
|
@@ -1285,6 +1330,41 @@ function runRunnableEntry(entry, payload, ctx, event, llmExtra, halt) {
|
|
|
1285
1330
|
}
|
|
1286
1331
|
}
|
|
1287
1332
|
}
|
|
1333
|
+
async function settleOnce(spentOf, body) {
|
|
1334
|
+
const candidates = new Set();
|
|
1335
|
+
let refused = false;
|
|
1336
|
+
const once = {
|
|
1337
|
+
spent: (entry) => spentOf.has(entry),
|
|
1338
|
+
ran: (entry) => {
|
|
1339
|
+
if (entry.once)
|
|
1340
|
+
candidates.add(entry);
|
|
1341
|
+
},
|
|
1342
|
+
handedOff: (entry) => {
|
|
1343
|
+
if (entry.once)
|
|
1344
|
+
spentOf.add(entry);
|
|
1345
|
+
},
|
|
1346
|
+
unsettled: (entry) => {
|
|
1347
|
+
candidates.delete(entry);
|
|
1348
|
+
},
|
|
1349
|
+
refused: (answer) => {
|
|
1350
|
+
refused = true;
|
|
1351
|
+
return answer;
|
|
1352
|
+
},
|
|
1353
|
+
mark: () => {
|
|
1354
|
+
const at = new Set(candidates);
|
|
1355
|
+
return () => {
|
|
1356
|
+
candidates.clear();
|
|
1357
|
+
for (const entry of at)
|
|
1358
|
+
candidates.add(entry);
|
|
1359
|
+
};
|
|
1360
|
+
},
|
|
1361
|
+
};
|
|
1362
|
+
const answer = await body(once);
|
|
1363
|
+
if (!refused)
|
|
1364
|
+
for (const entry of candidates)
|
|
1365
|
+
spentOf.add(entry);
|
|
1366
|
+
return answer;
|
|
1367
|
+
}
|
|
1288
1368
|
function isSyncEntry(entry) {
|
|
1289
1369
|
return !(entry.type === "command" && (entry.async === true || entry.asyncRewake === true));
|
|
1290
1370
|
}
|
|
@@ -1342,7 +1422,7 @@ function noteRanVerdictFlaw(ctx, ledger, event, ran, flaw, toolName) {
|
|
|
1342
1422
|
}
|
|
1343
1423
|
}
|
|
1344
1424
|
}
|
|
1345
|
-
async function runMatchingEntries(event, groups, matchValue, payload, ctx,
|
|
1425
|
+
async function runMatchingEntries(event, groups, matchValue, payload, ctx, once, halt, deadlineAt, ledger, llmExtra) {
|
|
1346
1426
|
const results = [];
|
|
1347
1427
|
let llmEntries = 0;
|
|
1348
1428
|
const toolName = toolNameOf(payload);
|
|
@@ -1350,10 +1430,10 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1350
1430
|
const truncatedFor = (entry) => (entry.type === "prompt" || entry.type === "agent" ? llmHookArguments(payload).truncated : inputTruncated);
|
|
1351
1431
|
const blockedBy = (entry, source, cause) => ({ entry, run: blockingFailureRun(event, cause), source });
|
|
1352
1432
|
let laneSpent = false;
|
|
1353
|
-
const settle = async (entry
|
|
1433
|
+
const settle = async (entry) => {
|
|
1354
1434
|
if (halt.signal.aborted)
|
|
1355
1435
|
return { kind: "halted" };
|
|
1356
|
-
if (entry.once &&
|
|
1436
|
+
if (entry.once && once.spent(entry))
|
|
1357
1437
|
return { kind: "passed" };
|
|
1358
1438
|
let ifOverBudget = false;
|
|
1359
1439
|
if (entry.if !== undefined) {
|
|
@@ -1379,7 +1459,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1379
1459
|
}
|
|
1380
1460
|
if (entry.type === "command" && entry.shell === "powershell") {
|
|
1381
1461
|
ctx.logger.warn("hook_entries_skipped", { event, type: entry.type, reason: "powershell_not_supported" });
|
|
1382
|
-
return
|
|
1462
|
+
return { kind: "unrun", reason: "powershell_unsupported" };
|
|
1383
1463
|
}
|
|
1384
1464
|
if (entry.type === "prompt" || entry.type === "agent") {
|
|
1385
1465
|
const carrier = entry.type === "prompt" ? ctx.hookLlm : ctx.hookAgent;
|
|
@@ -1393,8 +1473,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1393
1473
|
}
|
|
1394
1474
|
}
|
|
1395
1475
|
if (entry.type === "command" && (entry.async || entry.asyncRewake)) {
|
|
1396
|
-
|
|
1397
|
-
onceFired.add(onceKey);
|
|
1476
|
+
once.handedOff(entry);
|
|
1398
1477
|
void fireAsyncCommandHook(entry, payload, ctx, event, halt.signal);
|
|
1399
1478
|
return { kind: "passed" };
|
|
1400
1479
|
}
|
|
@@ -1403,8 +1482,6 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1403
1482
|
ctx.logger.warn("hook_event_deadline_exceeded", { event, budgetSec: MAX_HOOK_EVENT_TOTAL_SECONDS });
|
|
1404
1483
|
return { kind: "unrun", reason: "budget_exhausted" };
|
|
1405
1484
|
}
|
|
1406
|
-
if (entry.once)
|
|
1407
|
-
onceFired.add(onceKey);
|
|
1408
1485
|
if (entry.type === "prompt" || entry.type === "agent")
|
|
1409
1486
|
llmEntries++;
|
|
1410
1487
|
const run = await runRunnableEntry(entry, payload, ctx, event, llmExtra, halt.signal);
|
|
@@ -1437,15 +1514,13 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1437
1514
|
return { kind: "unrun", reason: "bad_json" };
|
|
1438
1515
|
return ifOverBudget ? { kind: "ran", run, overBudget: true } : { kind: "ran", run };
|
|
1439
1516
|
};
|
|
1440
|
-
for (const
|
|
1517
|
+
for (const group of groups) {
|
|
1441
1518
|
const pending = laneSpent ? group.hooks.filter((entry) => blocksOnFailure(entry, event)) : group.hooks;
|
|
1442
1519
|
if (laneSpent && pending.length === 0)
|
|
1443
1520
|
continue;
|
|
1444
1521
|
const selected = matcherGroupSelected(ctx, event, group, matchValue, toolName, pending);
|
|
1445
1522
|
if (selected === "invalid") {
|
|
1446
1523
|
for (const entry of pending) {
|
|
1447
|
-
if (!isSyncEntry(entry))
|
|
1448
|
-
continue;
|
|
1449
1524
|
if (!laneSpent)
|
|
1450
1525
|
ledger.unrun(group.source, entry, "matcher_invalid");
|
|
1451
1526
|
if (blocksOnFailure(entry, event))
|
|
@@ -1455,12 +1530,13 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1455
1530
|
}
|
|
1456
1531
|
if (selected === false)
|
|
1457
1532
|
continue;
|
|
1458
|
-
for (const
|
|
1533
|
+
for (const entry of group.hooks) {
|
|
1459
1534
|
if (laneSpent && !blocksOnFailure(entry, event))
|
|
1460
1535
|
continue;
|
|
1461
|
-
const fate = await settle(entry
|
|
1536
|
+
const fate = await settle(entry);
|
|
1462
1537
|
switch (fate.kind) {
|
|
1463
1538
|
case "ran": {
|
|
1539
|
+
once.ran(entry);
|
|
1464
1540
|
const flaw = blocksOnFailure(entry, event) ? ranVerdictFlaw(event, fate.run) : undefined;
|
|
1465
1541
|
if (flaw !== undefined) {
|
|
1466
1542
|
noteRanVerdictFlaw(ctx, ledger, event, { entry, run: fate.run, source: group.source }, flaw, toolName);
|
|
@@ -1490,7 +1566,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
1490
1566
|
case "passed":
|
|
1491
1567
|
break;
|
|
1492
1568
|
case "halted":
|
|
1493
|
-
if (
|
|
1569
|
+
if (halt.budgetSpent())
|
|
1494
1570
|
ledger.halted(group.source, entry);
|
|
1495
1571
|
return results;
|
|
1496
1572
|
default: {
|
|
@@ -1508,17 +1584,16 @@ function createEventClock() {
|
|
|
1508
1584
|
}
|
|
1509
1585
|
const ENGINE_BUDGET_SPENT_DETAIL = "the managed lane's handler ran past its engine budget (HOOKS_TIMEOUT_MS); the managed entries after this one did not run on this event";
|
|
1510
1586
|
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);
|
|
1587
|
+
return HOOK_PHASES.map((phase) => ({ phase, groups: groups.filter((g) => hookPhaseOf(g.source) === phase) })).filter((l) => l.groups.length > 0);
|
|
1513
1588
|
}
|
|
1514
1589
|
function trustRank(phase) {
|
|
1515
1590
|
return HOOK_PHASES.length - 1 - HOOK_PHASES.indexOf(phase);
|
|
1516
1591
|
}
|
|
1517
|
-
async function runEventLanes(event, groups, matchValue, payload, ctx,
|
|
1592
|
+
async function runEventLanes(event, groups, matchValue, payload, ctx, once, halt, ledger, llmExtra) {
|
|
1518
1593
|
const deadline = createEventClock();
|
|
1519
1594
|
const ran = [];
|
|
1520
1595
|
for (const lane of hookPhasesOf(groups)) {
|
|
1521
|
-
for (const r of await runMatchingEntries(event, lane.groups, matchValue, payload, ctx,
|
|
1596
|
+
for (const r of await runMatchingEntries(event, lane.groups, matchValue, payload, ctx, once, halt, deadline(), ledger, llmExtra))
|
|
1522
1597
|
ran.push({ ...r, phase: lane.phase });
|
|
1523
1598
|
}
|
|
1524
1599
|
return ran.sort((a, b) => trustRank(a.phase) - trustRank(b.phase)).map(({ entry, run, source }) => ({ entry, run, source }));
|
|
@@ -1534,9 +1609,9 @@ function basePayload(ctx, permissionMode) {
|
|
|
1534
1609
|
function ignoreMatchers(groups) {
|
|
1535
1610
|
return groups.map((g) => (g.matcher === undefined ? g : { ...g, matcher: undefined }));
|
|
1536
1611
|
}
|
|
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,
|
|
1612
|
+
async function runObserveOnlyEvent(event, groups, matchValue, payload, ctx, once, halt) {
|
|
1613
|
+
const ledger = createUnrunLedger(ctx, event, toolNameOf(payload), once);
|
|
1614
|
+
const singles = await runEventLanes(event, groups, matchValue, payload, ctx, once, halt, ledger);
|
|
1540
1615
|
for (const ran of singles) {
|
|
1541
1616
|
const { run } = ran;
|
|
1542
1617
|
if (run.code !== 0) {
|
|
@@ -1589,17 +1664,16 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1589
1664
|
if (!pre && !post && !postFailure && !postBatch && !promptSubmit && !stopEntries && !stopFailureEntries && !preCompactEntries && !postCompactEntries) {
|
|
1590
1665
|
return undefined;
|
|
1591
1666
|
}
|
|
1592
|
-
const
|
|
1667
|
+
const onceSpent = new Set();
|
|
1593
1668
|
const translators = {};
|
|
1594
1669
|
if (pre) {
|
|
1595
|
-
const tightenOnly =
|
|
1596
|
-
translators.PreToolUse =
|
|
1670
|
+
const tightenOnly = chainsBelowTaskOn(ctx.belowTaskChainPatterns, "classic.PreToolUse");
|
|
1671
|
+
translators.PreToolUse = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1597
1672
|
const prior = readBelowPreToolUse(below);
|
|
1598
|
-
const realApproval = prior.realApproval ? { requiresRealApproval: true } : {};
|
|
1599
1673
|
if (prior.denied)
|
|
1600
1674
|
return undefined;
|
|
1601
1675
|
const toolName = e.tool;
|
|
1602
|
-
const ledger = createUnrunLedger(ctx, "PreToolUse", toolName);
|
|
1676
|
+
const ledger = createUnrunLedger(ctx, "PreToolUse", toolName, once);
|
|
1603
1677
|
const deadline = createEventClock();
|
|
1604
1678
|
let currentInput = prior.updatedInput ?? e.input;
|
|
1605
1679
|
let rewritten = prior.updatedInput !== undefined;
|
|
@@ -1609,9 +1683,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1609
1683
|
let unknownDecision = false;
|
|
1610
1684
|
const contexts = { unmanaged: [], managedPlugin: [], managedPolicy: [] };
|
|
1611
1685
|
const contextField = () => buildHookContextField([...[...HOOK_PHASES].sort((a, b) => trustRank(a) - trustRank(b)).flatMap((p) => contexts[p]), ...(prior.additionalContext !== undefined ? [prior.additionalContext] : [])]);
|
|
1612
|
-
const
|
|
1686
|
+
const strictness = prior.realApproval === true ? { requiresRealApproval: true } : {};
|
|
1687
|
+
const runPass = async (phase, groups) => {
|
|
1613
1688
|
let rewroteBy;
|
|
1614
|
-
for (const
|
|
1689
|
+
for (const group of groups) {
|
|
1615
1690
|
const groupInput = currentInput;
|
|
1616
1691
|
const payload = {
|
|
1617
1692
|
...basePayload(ctx, e.permissionMode),
|
|
@@ -1620,7 +1695,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1620
1695
|
tool_input: groupInput,
|
|
1621
1696
|
tool_use_id: e.tool_use_id,
|
|
1622
1697
|
};
|
|
1623
|
-
const singles = await runMatchingEntries("PreToolUse", [
|
|
1698
|
+
const singles = await runMatchingEntries("PreToolUse", [group], toolName, payload, ctx, once, halt, deadline(), ledger);
|
|
1624
1699
|
for (const ran of singles) {
|
|
1625
1700
|
const { entry, run } = ran;
|
|
1626
1701
|
if (run.code === 2) {
|
|
@@ -1659,10 +1734,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1659
1734
|
const proposed = h.updatedInput !== null && typeof h.updatedInput === "object" ? h.updatedInput : undefined;
|
|
1660
1735
|
const proposesRewrite = proposed !== undefined && canonicalJsonStringify(proposed) !== canonicalJsonStringify(groupInput);
|
|
1661
1736
|
if (tightenOnly && ran.distrust === undefined && (decision === "allow" || (proposesRewrite && (decision === "ask" || decision === undefined)))) {
|
|
1662
|
-
return { deny: { action: "deny", message: proposesRewrite ?
|
|
1737
|
+
return { deny: { action: "deny", message: proposesRewrite ? REQUEST_HOOK_REWRITE_UNSHOWN_REASON : REQUEST_HOOK_ALLOW_UNJUDGED_REASON, ...contextField() } };
|
|
1663
1738
|
}
|
|
1664
1739
|
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));
|
|
1740
|
+
asked = alsoAsks(lane, prior.asked ?? prior.unreadable?.message, clipDataText(typeof h.permissionDecisionReason === "string" ? h.permissionDecisionReason : "a PreToolUse hook requires approval", MAX_HOOK_FEEDBACK_CHARS));
|
|
1666
1741
|
spoke = true;
|
|
1667
1742
|
}
|
|
1668
1743
|
if (decision === "allow" || decision === undefined) {
|
|
@@ -1694,54 +1769,52 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1694
1769
|
};
|
|
1695
1770
|
for (const lane of hookPhasesOf(pre)) {
|
|
1696
1771
|
if (lane.phase === "unmanaged") {
|
|
1697
|
-
const pass = await runPass(lane.phase, lane.groups
|
|
1772
|
+
const pass = await runPass(lane.phase, lane.groups);
|
|
1698
1773
|
if (pass.deny !== undefined)
|
|
1699
|
-
return pass.deny;
|
|
1774
|
+
return once.refused(pass.deny);
|
|
1700
1775
|
continue;
|
|
1701
1776
|
}
|
|
1702
|
-
const
|
|
1703
|
-
const first = await runPass(lane.phase, lane.groups
|
|
1777
|
+
const rollback = once.mark();
|
|
1778
|
+
const first = await runPass(lane.phase, lane.groups);
|
|
1704
1779
|
if (first.deny !== undefined)
|
|
1705
|
-
return first.deny;
|
|
1780
|
+
return once.refused(first.deny);
|
|
1706
1781
|
if (first.rewroteBy === undefined)
|
|
1707
1782
|
continue;
|
|
1708
1783
|
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);
|
|
1784
|
+
rollback();
|
|
1785
|
+
const second = await runPass(lane.phase, lane.groups);
|
|
1713
1786
|
if (second.deny !== undefined)
|
|
1714
|
-
return second.deny;
|
|
1787
|
+
return once.refused(second.deny);
|
|
1715
1788
|
if (second.rewroteBy !== undefined) {
|
|
1716
1789
|
ledger.unrun(second.rewroteBy.source, second.rewroteBy.entry, "rewrite_unsettled", "the managed hooks of this phase rewrote the tool input again after being re-run on their own rewrite; approval required");
|
|
1717
1790
|
}
|
|
1718
1791
|
}
|
|
1719
1792
|
const managedGap = ledger.managedVerdictGap;
|
|
1720
|
-
if (
|
|
1793
|
+
if (!spoke && managedGap === undefined)
|
|
1721
1794
|
return undefined;
|
|
1722
1795
|
if (asked !== undefined) {
|
|
1723
|
-
return { action: "ask", message: asked, questionCause: "asked", ...(rewritten ? { updatedInput: currentInput } : {}), ...
|
|
1796
|
+
return { action: "ask", message: asked, questionCause: "asked", ...strictness, ...(rewritten ? { updatedInput: currentInput } : {}), ...contextField() };
|
|
1724
1797
|
}
|
|
1725
1798
|
if (managedGap !== undefined) {
|
|
1726
1799
|
return {
|
|
1727
1800
|
action: "ask",
|
|
1728
1801
|
message: "a managed PreToolUse hook did not run to a verdict — approval required",
|
|
1729
1802
|
questionCause: managedGap,
|
|
1803
|
+
...strictness,
|
|
1730
1804
|
...(rewritten ? { updatedInput: currentInput } : {}),
|
|
1731
|
-
...realApproval,
|
|
1732
1805
|
...contextField(),
|
|
1733
1806
|
};
|
|
1734
1807
|
}
|
|
1735
1808
|
if (prior.unreadable !== undefined) {
|
|
1736
|
-
return { action: "ask", message: prior.unreadable.message, questionCause: prior.unreadable.cause, ...(rewritten ? { updatedInput: currentInput } : {}), ...
|
|
1809
|
+
return { action: "ask", message: prior.unreadable.message, questionCause: prior.unreadable.cause, ...strictness, ...(rewritten ? { updatedInput: currentInput } : {}), ...contextField() };
|
|
1737
1810
|
}
|
|
1738
1811
|
if (unknownDecision) {
|
|
1739
1812
|
return {
|
|
1740
1813
|
action: "ask",
|
|
1741
1814
|
message: "a PreToolUse hook returned an unrecognized permissionDecision — approval required",
|
|
1742
1815
|
questionCause: "verdict_unreadable",
|
|
1816
|
+
...strictness,
|
|
1743
1817
|
...(rewritten ? { updatedInput: currentInput } : {}),
|
|
1744
|
-
...realApproval,
|
|
1745
1818
|
...contextField(),
|
|
1746
1819
|
};
|
|
1747
1820
|
}
|
|
@@ -1751,10 +1824,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1751
1824
|
if (rewritten || HOOK_PHASES.some((p) => contexts[p].length > 0) || prior.additionalContext !== undefined)
|
|
1752
1825
|
return carried;
|
|
1753
1826
|
return undefined;
|
|
1754
|
-
};
|
|
1827
|
+
});
|
|
1755
1828
|
}
|
|
1756
1829
|
if (post) {
|
|
1757
|
-
translators.PostToolUse =
|
|
1830
|
+
translators.PostToolUse = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1758
1831
|
const toolName = e.tool;
|
|
1759
1832
|
const input = e.input;
|
|
1760
1833
|
const output = e.output;
|
|
@@ -1770,8 +1843,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1770
1843
|
tool_response: { isError: output.isError, text: clipDataText(responseText, MAX_TOOL_RESPONSE_CHARS) },
|
|
1771
1844
|
tool_use_id: e.tool_use_id,
|
|
1772
1845
|
};
|
|
1773
|
-
const ledger = createUnrunLedger(ctx, "PostToolUse", toolName);
|
|
1774
|
-
const singles = await runEventLanes("PostToolUse", post, toolName, payload, ctx,
|
|
1846
|
+
const ledger = createUnrunLedger(ctx, "PostToolUse", toolName, once);
|
|
1847
|
+
const singles = await runEventLanes("PostToolUse", post, toolName, payload, ctx, once, halt, ledger);
|
|
1775
1848
|
for (const ran of singles) {
|
|
1776
1849
|
const { entry, run } = ran;
|
|
1777
1850
|
if (run.code === 2) {
|
|
@@ -1807,10 +1880,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1807
1880
|
if (contexts.length === 0)
|
|
1808
1881
|
return undefined;
|
|
1809
1882
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1810
|
-
};
|
|
1883
|
+
});
|
|
1811
1884
|
}
|
|
1812
1885
|
if (postFailure) {
|
|
1813
|
-
translators.PostToolUseFailure =
|
|
1886
|
+
translators.PostToolUseFailure = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1814
1887
|
const toolName = e.tool;
|
|
1815
1888
|
const f = e.failure;
|
|
1816
1889
|
const contexts = [];
|
|
@@ -1823,8 +1896,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1823
1896
|
error: clipDataText(f.error, MAX_TOOL_RESPONSE_CHARS),
|
|
1824
1897
|
is_interrupt: f.isInterrupt,
|
|
1825
1898
|
};
|
|
1826
|
-
const ledger = createUnrunLedger(ctx, "PostToolUseFailure", toolName);
|
|
1827
|
-
const singles = await runEventLanes("PostToolUseFailure", postFailure, toolName, payload, ctx,
|
|
1899
|
+
const ledger = createUnrunLedger(ctx, "PostToolUseFailure", toolName, once);
|
|
1900
|
+
const singles = await runEventLanes("PostToolUseFailure", postFailure, toolName, payload, ctx, once, halt, ledger);
|
|
1828
1901
|
for (const ran of singles) {
|
|
1829
1902
|
const { entry, run } = ran;
|
|
1830
1903
|
if (run.code === 2) {
|
|
@@ -1856,10 +1929,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1856
1929
|
if (contexts.length === 0)
|
|
1857
1930
|
return undefined;
|
|
1858
1931
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1859
|
-
};
|
|
1932
|
+
});
|
|
1860
1933
|
}
|
|
1861
1934
|
if (postBatch) {
|
|
1862
|
-
translators.PostToolBatch =
|
|
1935
|
+
translators.PostToolBatch = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1863
1936
|
const contexts = [];
|
|
1864
1937
|
const payload = {
|
|
1865
1938
|
...basePayload(ctx, e.permissionMode),
|
|
@@ -1871,8 +1944,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1871
1944
|
tool_response: { isError: c.isError, ...(c.response !== undefined ? { text: clipDataText(c.response, MAX_TOOL_RESPONSE_CHARS) } : {}) },
|
|
1872
1945
|
})),
|
|
1873
1946
|
};
|
|
1874
|
-
const ledger = createUnrunLedger(ctx, "PostToolBatch", undefined);
|
|
1875
|
-
const singles = await runEventLanes("PostToolBatch", ignoreMatchers(postBatch), "", payload, ctx,
|
|
1947
|
+
const ledger = createUnrunLedger(ctx, "PostToolBatch", undefined, once);
|
|
1948
|
+
const singles = await runEventLanes("PostToolBatch", ignoreMatchers(postBatch), "", payload, ctx, once, halt, ledger);
|
|
1876
1949
|
for (const ran of singles) {
|
|
1877
1950
|
const { entry, run } = ran;
|
|
1878
1951
|
if (run.code === 2) {
|
|
@@ -1900,19 +1973,19 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1900
1973
|
if (contexts.length === 0)
|
|
1901
1974
|
return undefined;
|
|
1902
1975
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1903
|
-
};
|
|
1976
|
+
});
|
|
1904
1977
|
}
|
|
1905
1978
|
if (promptSubmit) {
|
|
1906
|
-
translators.UserPromptSubmit =
|
|
1979
|
+
translators.UserPromptSubmit = (e, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1907
1980
|
const contexts = [];
|
|
1908
1981
|
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,
|
|
1982
|
+
const ledger = createUnrunLedger(ctx, "UserPromptSubmit", undefined, once);
|
|
1983
|
+
const singles = await runEventLanes("UserPromptSubmit", ignoreMatchers(promptSubmit), "", payload, ctx, once, halt, ledger);
|
|
1911
1984
|
for (const ran of singles) {
|
|
1912
1985
|
const { entry, run } = ran;
|
|
1913
1986
|
if (run.code === 2) {
|
|
1914
1987
|
const reason = clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a UserPromptSubmit hook";
|
|
1915
|
-
return { block: reason, ...buildHookContextField(contexts) };
|
|
1988
|
+
return once.refused({ block: reason, ...buildHookContextField(contexts) });
|
|
1916
1989
|
}
|
|
1917
1990
|
if (run.code !== 0) {
|
|
1918
1991
|
noteExitNonzero(ctx, ledger, "UserPromptSubmit", ran);
|
|
@@ -1925,11 +1998,11 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1925
1998
|
logHookSystemMessage(ctx, "UserPromptSubmit", out.systemMessage);
|
|
1926
1999
|
if (out.continue === false) {
|
|
1927
2000
|
const reason = clipDataText(typeof out.stopReason === "string" ? out.stopReason : "hook requested stop", MAX_HOOK_FEEDBACK_CHARS);
|
|
1928
|
-
return { block: reason, ...buildHookContextField(contexts) };
|
|
2001
|
+
return once.refused({ block: reason, ...buildHookContextField(contexts) });
|
|
1929
2002
|
}
|
|
1930
2003
|
if (out.decision === "block") {
|
|
1931
2004
|
const reason = clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a UserPromptSubmit hook", MAX_HOOK_FEEDBACK_CHARS);
|
|
1932
|
-
return { block: reason, ...buildHookContextField(contexts) };
|
|
2005
|
+
return once.refused({ block: reason, ...buildHookContextField(contexts) });
|
|
1933
2006
|
}
|
|
1934
2007
|
const hso = out.hookSpecificOutput;
|
|
1935
2008
|
if (hso !== null && typeof hso === "object" && hso.hookEventName === "UserPromptSubmit") {
|
|
@@ -1941,10 +2014,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1941
2014
|
if (contexts.length === 0)
|
|
1942
2015
|
return undefined;
|
|
1943
2016
|
return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
|
|
1944
|
-
};
|
|
2017
|
+
});
|
|
1945
2018
|
}
|
|
1946
2019
|
if (stopEntries) {
|
|
1947
|
-
translators.Stop =
|
|
2020
|
+
translators.Stop = (sctx, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
1948
2021
|
const payload = { ...basePayload(ctx, sctx.permissionMode), hook_event_name: "Stop", stop_hook_active: sctx.stopHookActive };
|
|
1949
2022
|
let llmExtra;
|
|
1950
2023
|
const wantsPrompt = stopEntries.some((g) => g.hooks.some((h) => h.type === "prompt"));
|
|
@@ -1972,7 +2045,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1972
2045
|
}
|
|
1973
2046
|
}
|
|
1974
2047
|
const stopGroups = ignoreMatchers(stopEntries);
|
|
1975
|
-
const ledger = createUnrunLedger(ctx, "Stop", undefined);
|
|
2048
|
+
const ledger = createUnrunLedger(ctx, "Stop", undefined, once);
|
|
1976
2049
|
if (!llmExtra && wantsPrompt) {
|
|
1977
2050
|
for (const g of stopGroups)
|
|
1978
2051
|
for (const h of g.hooks)
|
|
@@ -1982,7 +2055,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
1982
2055
|
const effectiveGroups = llmExtra || !wantsPrompt
|
|
1983
2056
|
? stopGroups
|
|
1984
2057
|
: 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,
|
|
2058
|
+
const singles = await runEventLanes("Stop", effectiveGroups, "", payload, ctx, once, halt, ledger, llmExtra);
|
|
1986
2059
|
let block;
|
|
1987
2060
|
let sawContinueFalse = false;
|
|
1988
2061
|
const contexts = [];
|
|
@@ -2036,15 +2109,16 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
2036
2109
|
return undefined;
|
|
2037
2110
|
if (block === undefined && contexts.length === 0)
|
|
2038
2111
|
return undefined;
|
|
2039
|
-
|
|
2112
|
+
const answer = {
|
|
2040
2113
|
...belowMembers(below),
|
|
2041
2114
|
...(block !== undefined ? { block } : {}),
|
|
2042
2115
|
...buildHookContextField(withBelowContext(contexts, below)),
|
|
2043
2116
|
};
|
|
2044
|
-
|
|
2117
|
+
return block !== undefined ? once.refused(answer) : answer;
|
|
2118
|
+
});
|
|
2045
2119
|
}
|
|
2046
2120
|
if (stopFailureEntries) {
|
|
2047
|
-
translators.StopFailure =
|
|
2121
|
+
translators.StopFailure = (fctx, halt) => settleOnce(onceSpent, async (once) => {
|
|
2048
2122
|
const turnError = toAssistantTurnError(fctx.errorKind);
|
|
2049
2123
|
const payload = {
|
|
2050
2124
|
...basePayload(ctx, undefined),
|
|
@@ -2052,23 +2126,23 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
2052
2126
|
error: turnError,
|
|
2053
2127
|
...(fctx.error ? { error_details: clipDataText(redactSecrets(fctx.error), MAX_HOOK_FEEDBACK_CHARS) } : {}),
|
|
2054
2128
|
};
|
|
2055
|
-
await runObserveOnlyEvent("StopFailure", stopFailureEntries, turnError, payload, ctx,
|
|
2056
|
-
};
|
|
2129
|
+
await runObserveOnlyEvent("StopFailure", stopFailureEntries, turnError, payload, ctx, once, halt);
|
|
2130
|
+
});
|
|
2057
2131
|
}
|
|
2058
2132
|
if (preCompactEntries) {
|
|
2059
|
-
translators.PreCompact =
|
|
2133
|
+
translators.PreCompact = (pctx, halt, below) => settleOnce(onceSpent, async (once) => {
|
|
2060
2134
|
const payload = {
|
|
2061
2135
|
...basePayload(ctx, undefined),
|
|
2062
2136
|
hook_event_name: "PreCompact",
|
|
2063
2137
|
trigger: pctx.trigger,
|
|
2064
2138
|
custom_instructions: pctx.customInstructions ?? null,
|
|
2065
2139
|
};
|
|
2066
|
-
const ledger = createUnrunLedger(ctx, "PreCompact", undefined);
|
|
2067
|
-
const singles = await runEventLanes("PreCompact", preCompactEntries, pctx.trigger, payload, ctx,
|
|
2140
|
+
const ledger = createUnrunLedger(ctx, "PreCompact", undefined, once);
|
|
2141
|
+
const singles = await runEventLanes("PreCompact", preCompactEntries, pctx.trigger, payload, ctx, once, halt, ledger);
|
|
2068
2142
|
for (const ran of singles) {
|
|
2069
2143
|
const { entry, run } = ran;
|
|
2070
2144
|
if (run.code === 2) {
|
|
2071
|
-
return { ...belowMembers(below), block: clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a PreCompact hook" };
|
|
2145
|
+
return once.refused({ ...belowMembers(below), block: clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a PreCompact hook" });
|
|
2072
2146
|
}
|
|
2073
2147
|
if (run.code !== 0) {
|
|
2074
2148
|
noteExitNonzero(ctx, ledger, "PreCompact", ran);
|
|
@@ -2083,31 +2157,31 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
|
|
|
2083
2157
|
ctx.logger.warn("hook_continue_false_unsupported", { event: "PreCompact" });
|
|
2084
2158
|
}
|
|
2085
2159
|
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) };
|
|
2160
|
+
return once.refused({ ...belowMembers(below), block: clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a PreCompact hook", MAX_HOOK_FEEDBACK_CHARS) });
|
|
2087
2161
|
}
|
|
2088
2162
|
}
|
|
2089
2163
|
return undefined;
|
|
2090
|
-
};
|
|
2164
|
+
});
|
|
2091
2165
|
}
|
|
2092
2166
|
if (postCompactEntries) {
|
|
2093
|
-
translators.PostCompact =
|
|
2167
|
+
translators.PostCompact = (cctx, halt) => settleOnce(onceSpent, async (once) => {
|
|
2094
2168
|
const payload = {
|
|
2095
2169
|
...basePayload(ctx, undefined),
|
|
2096
2170
|
hook_event_name: "PostCompact",
|
|
2097
2171
|
trigger: cctx.trigger,
|
|
2098
2172
|
compact_summary: clipDataText(cctx.summary, MAX_TOOL_RESPONSE_CHARS),
|
|
2099
2173
|
};
|
|
2100
|
-
await runObserveOnlyEvent("PostCompact", postCompactEntries, cctx.trigger, payload, ctx,
|
|
2101
|
-
};
|
|
2174
|
+
await runObserveOnlyEvent("PostCompact", postCompactEntries, cctx.trigger, payload, ctx, once, halt);
|
|
2175
|
+
});
|
|
2102
2176
|
}
|
|
2103
2177
|
const events = Object.keys(translators);
|
|
2104
2178
|
return {
|
|
2105
2179
|
name: SETTINGS_HOOKS_REGISTRATIONS[lane],
|
|
2106
|
-
uses: { events: events.
|
|
2180
|
+
uses: { events: events.map((event) => SETTINGS_HOOK_STATIONS[event]), calls: [] },
|
|
2107
2181
|
budgetMs,
|
|
2108
2182
|
register(on) {
|
|
2109
2183
|
for (const event of events)
|
|
2110
|
-
hangTranslator(on, event, translators
|
|
2184
|
+
hangTranslator(on, event, translators);
|
|
2111
2185
|
},
|
|
2112
2186
|
};
|
|
2113
2187
|
}
|