@sema-agent/server 7.132.0 → 7.133.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 +266 -0
- package/README.md +8 -9
- package/README.zh-CN.md +7 -6
- package/USAGE.md +174 -55
- package/deploy/sema-up/README.md +19 -1
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
- package/deploy/sema-up/chart/templates/server.yaml +5 -2
- package/deploy/sema-up/stack/compose.yaml +3 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
- package/dist/adoption/plan.d.ts +3 -2
- package/dist/adoption/plan.js +7 -5
- package/dist/adoption/runner.js +3 -10
- package/dist/adoption/sql.d.ts +3 -2
- package/dist/adoption/sql.js +3 -5
- package/dist/adoption/wire.d.ts +4 -1
- package/dist/adoption/wire.js +1 -0
- package/dist/approval-ask-audit-store.d.ts +31 -13
- package/dist/approval-ask-audit-store.js +272 -74
- package/dist/approval-ask-machine.d.ts +15 -0
- package/dist/approval-ask-machine.js +6 -0
- package/dist/approval-ask-retention.d.ts +136 -0
- package/dist/approval-ask-retention.js +102 -0
- package/dist/approval-card.d.ts +79 -19
- package/dist/approval-card.js +44 -13
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval.d.ts +9 -0
- package/dist/approval.js +24 -3
- package/dist/audit.d.ts +27 -10
- package/dist/audit.js +12 -16
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/execution-env.js +9 -7
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.js +2 -0
- package/dist/boot/memory-boundary.js +2 -2
- package/dist/boot/memory-consolidation.d.ts +5 -4
- package/dist/boot/memory-consolidation.js +7 -6
- package/dist/boot/org-delivery.d.ts +28 -0
- package/dist/boot/org-delivery.js +20 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +3 -0
- package/dist/boot/resolve-spec.js +60 -81
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-06-runners.d.ts +2 -0
- package/dist/boot/stage-06-runners.js +6 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -0
- package/dist/boot/stage-07-capability-layer.js +24 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -0
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +3 -0
- package/dist/boot/stage-10-http-server.d.ts +3 -0
- package/dist/boot/stage-10-http-server.js +5 -6
- package/dist/boot/stores.js +2 -2
- package/dist/boot/web-admin.d.ts +4 -0
- package/dist/boot/web-admin.js +151 -63
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +8 -3
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/caller-text-echo.d.ts +9 -6
- package/dist/caller-text-echo.js +8 -11
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +21 -0
- package/dist/capabilities/hands-lane.js +10 -0
- package/dist/capabilities/mcp-probe.d.ts +36 -4
- package/dist/capabilities/mcp-probe.js +27 -4
- package/dist/capabilities/scenarios.d.ts +63 -7
- package/dist/capabilities/scenarios.js +39 -7
- package/dist/capability-facts.d.ts +34 -4
- package/dist/capability-facts.js +28 -2
- package/dist/center-config-tier.d.ts +69 -0
- package/dist/center-config-tier.js +42 -0
- package/dist/checkpoint-identity.d.ts +16 -0
- package/dist/checkpoint-identity.js +19 -0
- package/dist/config-catalog.d.ts +17 -10
- package/dist/config-catalog.js +43 -28
- package/dist/config-d-migration.d.ts +3 -1
- package/dist/config-d-migration.js +2 -2
- package/dist/config-dir-trust.d.ts +114 -0
- package/dist/config-dir-trust.js +388 -0
- package/dist/config-invariants.d.ts +18 -5
- package/dist/config-invariants.js +35 -3
- package/dist/config-provider.d.ts +6 -1
- package/dist/config-provider.js +6 -2
- package/dist/config-types.d.ts +71 -14
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +121 -59
- package/dist/delegated-session-owner.d.ts +185 -0
- package/dist/delegated-session-owner.js +119 -0
- package/dist/device-protocol.d.ts +5 -3
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +21 -2
- package/dist/device-ws-protocol.d.ts +70 -6
- package/dist/device-ws-protocol.js +50 -23
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/execution-lane-caps.d.ts +49 -10
- package/dist/execution-lane-caps.js +43 -4
- package/dist/field-conflict.d.ts +43 -0
- package/dist/field-conflict.js +20 -0
- package/dist/fleet/fleet-bus.d.ts +80 -6
- package/dist/fleet/fleet-bus.js +41 -9
- package/dist/hooks/classic-stations.d.ts +10 -5
- package/dist/hooks/classic-stations.js +4 -4
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.js +2 -2
- package/dist/hooks/hook-runner.d.ts +127 -25
- package/dist/hooks/hook-runner.js +668 -287
- package/dist/hooks/hook-source.d.ts +44 -0
- package/dist/hooks/hook-source.js +40 -0
- package/dist/http/active-run-conflict.d.ts +5 -13
- package/dist/http/active-run-conflict.js +17 -27
- package/dist/http/admission.js +103 -60
- package/dist/http/approval-sweeps.js +55 -18
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +16 -16
- package/dist/http/checkpoint-ctx.js +13 -10
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +2 -1
- package/dist/http/dispatch.js +10 -4
- package/dist/http/durable-run-leg.d.ts +4 -32
- package/dist/http/durable-run-leg.js +34 -10
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +48 -23
- package/dist/http/principal-gate.js +39 -12
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/request-guards.d.ts +16 -23
- package/dist/http/request-guards.js +30 -15
- package/dist/http/resume-ctx-read.d.ts +2 -5
- package/dist/http/resume-ctx-read.js +7 -4
- package/dist/http/resume-legs.d.ts +3 -4
- package/dist/http/resume-legs.js +126 -69
- package/dist/http/retired-service-deps.d.ts +43 -0
- package/dist/http/retired-service-deps.js +18 -0
- package/dist/http/route-ctx.d.ts +44 -28
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.js +3 -4
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.js +1 -1
- package/dist/http/routes/admin-memory-optout.js +5 -1
- package/dist/http/routes/adoption.js +2 -9
- package/dist/http/routes/approvals-assistant.js +49 -48
- package/dist/http/routes/background.js +3 -2
- package/dist/http/routes/capabilities.js +20 -4
- package/dist/http/routes/config-catalog.d.ts +3 -3
- package/dist/http/routes/config-catalog.js +1 -1
- package/dist/http/routes/devices.js +3 -17
- package/dist/http/routes/diagnostics.js +5 -1
- package/dist/http/routes/images.js +6 -7
- package/dist/http/routes/leader.js +1 -8
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +3 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/memory-policy.d.ts +1 -1
- package/dist/http/routes/memory-policy.js +3 -2
- package/dist/http/routes/notify-wake.js +8 -21
- package/dist/http/routes/observability.js +2 -2
- package/dist/http/routes/principal-inbox.d.ts +39 -0
- package/dist/http/routes/principal-inbox.js +76 -0
- package/dist/http/routes/retention-ops.js +2 -9
- package/dist/http/routes/rules.js +5 -18
- package/dist/http/routes/runs.d.ts +5 -0
- package/dist/http/routes/runs.js +33 -106
- package/dist/http/routes/session-sync.js +15 -28
- package/dist/http/routes/sessions.js +30 -40
- package/dist/http/routes/side-query.js +6 -4
- package/dist/http/routes/tasks.js +50 -14
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/send.d.ts +24 -3
- package/dist/http/send.js +14 -2
- package/dist/http/server.d.ts +17 -18
- package/dist/http/server.js +15 -13
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.js +4 -3
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +10 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -1
- package/dist/lane-home-probe.d.ts +78 -9
- package/dist/lane-home-probe.js +78 -12
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/limit-refusal.d.ts +17 -5
- package/dist/limit-refusal.js +4 -1
- package/dist/mcp-assertion-header.d.ts +31 -10
- package/dist/mcp-assertion-header.js +10 -3
- package/dist/mcp-tool-faces.js +1 -3
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +23 -16
- package/dist/memory-scope.js +24 -8
- package/dist/memory-sync-client.d.ts +27 -13
- package/dist/memory-sync-client.js +107 -18
- package/dist/model-entry-refusal.d.ts +9 -1
- package/dist/model-entry-refusal.js +6 -1
- package/dist/model-plane-face.d.ts +51 -0
- package/dist/model-plane-face.js +24 -0
- package/dist/model-provider.d.ts +5 -0
- package/dist/model-provider.js +4 -2
- package/dist/model-route-endpoint.d.ts +8 -11
- package/dist/model-route-endpoint.js +4 -7
- package/dist/model-route-env.d.ts +22 -0
- package/dist/model-route-env.js +2 -0
- package/dist/model-route-gap.d.ts +60 -30
- package/dist/model-route-gap.js +21 -15
- package/dist/observability/corrupt-read-seat.d.ts +7 -0
- package/dist/observability/corrupt-read-seat.js +9 -0
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +35 -9
- package/dist/observability/fail-open.js +35 -9
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/prompt-manifest.d.ts +3 -17
- package/dist/observability/prompt-manifest.js +45 -42
- package/dist/observability/tool-trace.js +9 -9
- package/dist/operator-ask.d.ts +10 -0
- package/dist/operator-ask.js +3 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
- package/dist/orchestration/workflow-agent-session-index.js +9 -13
- package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
- package/dist/orchestration/workflow-completion-inbox.js +13 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
- package/dist/orchestration/workflow-notify-journal.js +27 -34
- package/dist/orchestration/workflow-park-decision.d.ts +89 -0
- package/dist/orchestration/workflow-park-decision.js +118 -0
- package/dist/org-delivery-gate.d.ts +81 -0
- package/dist/org-delivery-gate.js +59 -0
- package/dist/panel-tool-names.d.ts +23 -0
- package/dist/panel-tool-names.js +8 -0
- package/dist/parked-decide.d.ts +39 -6
- package/dist/parked-decide.js +98 -51
- package/dist/parked-revive-surface.d.ts +9 -2
- package/dist/parked-revive-surface.js +11 -8
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/plugins/approval-ask-store-file.d.ts +16 -1
- package/dist/plugins/approval-ask-store-file.js +21 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
- package/dist/plugins/approval-ask-store-memory.js +34 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
- package/dist/plugins/approval-ask-store-sql.js +37 -1
- package/dist/plugins/blob-backend.d.ts +38 -25
- package/dist/plugins/blob-backend.js +29 -19
- package/dist/plugins/breaker-state-sql.d.ts +2 -2
- package/dist/plugins/breaker-state-sql.js +4 -4
- package/dist/plugins/caching-session-store.d.ts +3 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +14 -0
- package/dist/plugins/checkpoint-store-sql.js +20 -2
- package/dist/plugins/file-history-store-sql.d.ts +5 -2
- package/dist/plugins/file-history-store-sql.js +3 -1
- package/dist/plugins/file-run-store.d.ts +5 -13
- package/dist/plugins/file-run-store.js +9 -0
- package/dist/plugins/fork-routing-session-store.d.ts +9 -1
- package/dist/plugins/fork-routing-session-store.js +12 -1
- package/dist/plugins/host-platform.d.ts +2 -0
- package/dist/plugins/host-platform.js +2 -1
- package/dist/plugins/local-checkpoint-store.d.ts +2 -0
- package/dist/plugins/local-checkpoint-store.js +6 -1
- package/dist/plugins/local-session-store.d.ts +1 -1
- package/dist/plugins/local-session-window.d.ts +39 -0
- package/dist/plugins/local-session-window.js +54 -0
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
- package/dist/plugins/mailbox-store-sql.d.ts +30 -48
- package/dist/plugins/mailbox-store-sql.js +77 -52
- package/dist/plugins/memory-embedder-fingerprint.js +2 -1
- package/dist/plugins/memory-run-store.d.ts +5 -13
- package/dist/plugins/memory-run-store.js +8 -0
- package/dist/plugins/one-time-migrations.d.ts +110 -5
- package/dist/plugins/one-time-migrations.js +320 -8
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +17 -4
- package/dist/plugins/pg-session-storage.js +29 -6
- package/dist/plugins/remote-env-adb.d.ts +6 -12
- package/dist/plugins/remote-env-adb.js +12 -2
- package/dist/plugins/remote-env-k8s.d.ts +8 -12
- package/dist/plugins/remote-env-k8s.js +23 -5
- package/dist/plugins/remote-env-local-docker.d.ts +10 -15
- package/dist/plugins/remote-env-local-docker.js +12 -9
- package/dist/plugins/remote-env-ssh.d.ts +10 -16
- package/dist/plugins/remote-env-ssh.js +17 -11
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-user-file.js +2 -2
- package/dist/plugins/session-epoch-anchor.d.ts +32 -6
- package/dist/plugins/session-epoch-anchor.js +2 -3
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/sql-driver.d.ts +74 -11
- package/dist/plugins/sql-driver.js +210 -12
- package/dist/plugins/sql-errors.d.ts +23 -0
- package/dist/plugins/sql-errors.js +21 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +40 -14
- package/dist/plugins/store-contracts.d.ts +42 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.d.ts +6 -1
- package/dist/plugins/tidb-pool.js +44 -10
- package/dist/plugins/tidb-session-storage.d.ts +3 -2
- package/dist/plugins/tidb-session-storage.js +2 -2
- package/dist/plugins/tidb-session-store.d.ts +24 -4
- package/dist/plugins/tidb-session-store.js +28 -4
- package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
- package/dist/plugins/workflow-journal-store-sql.js +19 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
- package/dist/plugins/workflow-run-store-sql.js +50 -9
- package/dist/posture-source.d.ts +18 -10
- package/dist/posture-source.js +4 -1
- package/dist/project-identity.d.ts +45 -6
- package/dist/project-identity.js +162 -8
- package/dist/project-layer-key.d.ts +28 -0
- package/dist/project-layer-key.js +29 -0
- package/dist/question.js +3 -2
- package/dist/read-deny-entry.d.ts +25 -0
- package/dist/read-deny-entry.js +12 -0
- package/dist/read-face-posture.d.ts +37 -11
- package/dist/read-face-posture.js +32 -3
- package/dist/request-key-closure.d.ts +7 -0
- package/dist/request-key-closure.js +9 -1
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +26 -2
- package/dist/rule-entry-list.js +72 -12
- package/dist/rules-consent.js +3 -4
- package/dist/run-acceptance.d.ts +19 -3
- package/dist/run-acceptance.js +13 -1
- package/dist/run-local.js +36 -6
- package/dist/runs.d.ts +10 -9
- package/dist/runs.js +21 -3
- package/dist/runtime-caps-resolver.d.ts +16 -6
- package/dist/runtime-caps-resolver.js +18 -5
- package/dist/sandbox-pkg-source.d.ts +19 -1
- package/dist/sandbox-pkg-source.js +29 -7
- package/dist/security.d.ts +87 -9
- package/dist/security.js +52 -9
- package/dist/session-error-wire.d.ts +19 -2
- package/dist/session-error-wire.js +5 -1
- package/dist/session-titled-frame.d.ts +33 -0
- package/dist/session-titled-frame.js +4 -0
- package/dist/session-titler.d.ts +9 -1
- package/dist/session-titler.js +15 -4
- package/dist/spec-fields.js +21 -2
- package/dist/sql-engine-posture.d.ts +3 -1
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +7 -66
- package/dist/task-settings.d.ts +89 -88
- package/dist/task-settings.js +71 -63
- package/dist/text-bidi.d.ts +0 -4
- package/dist/text-bidi.js +1 -3
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +303 -87
- package/dist/tool-approval.js +623 -239
- package/dist/trace/core-keyset-guard.d.ts +104 -22
- package/dist/trace/exit-seat.d.ts +28 -0
- package/dist/trace/exit-seat.js +76 -0
- package/dist/trace/ledger-events.d.ts +3 -2
- package/dist/trace/project.d.ts +80 -12
- package/dist/trace/project.js +41 -28
- package/dist/trace/projection-table.d.ts +100 -0
- package/dist/trace/projection-table.js +130 -0
- package/dist/trace/redact.d.ts +54 -0
- package/dist/trace/redact.js +778 -152
- package/dist/trace/self-minted-wire.d.ts +345 -1
- package/dist/trace/self-minted-wire.js +117 -1
- package/dist/trace/wire-projection-faces.d.ts +298 -2
- package/dist/trace/wire-projection-faces.js +154 -13
- package/dist/url-refusal.js +2 -0
- package/dist/web-admin-client/apply-effective.d.ts +12 -0
- package/dist/web-admin-client/apply-effective.js +56 -5
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/skills-mcp.js +4 -5
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
- package/package.json +7 -3
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { RUN_STATUS_CLASS } from "./plugins/store-contracts.js";
|
|
2
|
+
export const APPROVAL_ASK_RETENTION_DEFAULT_MS = 30 * 86_400_000;
|
|
3
|
+
export const APPROVAL_ASK_RETENTION_FLOOR_MS = 86_400_000;
|
|
4
|
+
export const APPROVAL_ASK_RETENTION_PASS_MS = 3_600_000;
|
|
5
|
+
export const APPROVAL_ASK_REAP_BATCH = 500;
|
|
6
|
+
export const MOVABLE_RUN_STATUSES = [
|
|
7
|
+
...Object.entries(RUN_STATUS_CLASS).filter(([, cls]) => cls === "parked"),
|
|
8
|
+
...Object.entries(RUN_STATUS_CLASS).filter(([, cls]) => cls === "live"),
|
|
9
|
+
...Object.entries(RUN_STATUS_CLASS).filter(([, cls]) => cls === "parked"),
|
|
10
|
+
].map(([status]) => status);
|
|
11
|
+
const BACKGROUND_AGENT_MOVABLE = {
|
|
12
|
+
running: true,
|
|
13
|
+
parked: true,
|
|
14
|
+
completed: false,
|
|
15
|
+
failed: false,
|
|
16
|
+
killed: false,
|
|
17
|
+
};
|
|
18
|
+
export async function collectMovableAnchors(input) {
|
|
19
|
+
const anchors = new Set();
|
|
20
|
+
for (const status of MOVABLE_RUN_STATUSES) {
|
|
21
|
+
let cursor;
|
|
22
|
+
for (;;) {
|
|
23
|
+
const page = await input.runs.listRuns({ status, limit: APPROVAL_ASK_REAP_BATCH, ...(cursor !== undefined ? { cursor } : {}) });
|
|
24
|
+
for (const r of page) {
|
|
25
|
+
anchors.add(r.taskId);
|
|
26
|
+
anchors.add(r.sessionId);
|
|
27
|
+
}
|
|
28
|
+
const last = page[page.length - 1];
|
|
29
|
+
if (page.length < APPROVAL_ASK_REAP_BATCH || last === undefined)
|
|
30
|
+
break;
|
|
31
|
+
cursor = { createdAt: last.createdAt, taskId: last.taskId };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const agents = input.backgroundAgents;
|
|
35
|
+
if (agents !== undefined) {
|
|
36
|
+
if (agents.listScopes === undefined) {
|
|
37
|
+
throw new Error("approval ledger retention: the background-agent store cannot enumerate its scopes (no listScopes) — cannot prove which delegated children can no longer move, so nothing is aged out this pass");
|
|
38
|
+
}
|
|
39
|
+
for (const scope of await agents.listScopes()) {
|
|
40
|
+
for (const row of await agents.listByScope(scope)) {
|
|
41
|
+
if (!BACKGROUND_AGENT_MOVABLE[row.status])
|
|
42
|
+
continue;
|
|
43
|
+
for (const anchor of [row.owner, row.sessionId, row.parentSessionId, row.rootSessionId])
|
|
44
|
+
if (anchor !== undefined)
|
|
45
|
+
anchors.add(anchor);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (input.checkpoints !== undefined)
|
|
50
|
+
for (const sessionId of await input.checkpoints.listPendingSessionIds())
|
|
51
|
+
anchors.add(sessionId);
|
|
52
|
+
return anchors;
|
|
53
|
+
}
|
|
54
|
+
export async function runApprovalAskRetentionPass(input) {
|
|
55
|
+
const { askStore, audit, runs, backgroundAgents, checkpoints, cutoffMs, logger, metrics } = input;
|
|
56
|
+
const reading = { cutoffMs, asks: 0, batches: 0, auditAsks: 0, auditRecords: 0 };
|
|
57
|
+
const count = (ledger, n) => {
|
|
58
|
+
if (n > 0)
|
|
59
|
+
metrics.inc("approval_ask_retention_rows_deleted_total", { ledger }, n);
|
|
60
|
+
};
|
|
61
|
+
const report = (incomplete) => {
|
|
62
|
+
if (reading.asks === 0 && reading.batches === 0 && reading.auditRecords === 0)
|
|
63
|
+
return;
|
|
64
|
+
logger.info("approval_ask_retention_swept", {
|
|
65
|
+
...reading,
|
|
66
|
+
...(incomplete ? { incomplete: true } : {}),
|
|
67
|
+
note: "settled approval asks quiet for longer than APPROVAL_ASK_RETENTION_MS, with nothing they hang off (their run, host session or asking leg's session) still able to move, were deleted whole from the approval ledgers (ask rows, emptied batches, and their audit-ledger records); records that remain are byte-for-byte unchanged. Set APPROVAL_ASK_RETENTION_MS=0 to keep everything.",
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
try {
|
|
71
|
+
const movable = await collectMovableAnchors({ runs, backgroundAgents, checkpoints });
|
|
72
|
+
if (askStore !== undefined) {
|
|
73
|
+
for (;;) {
|
|
74
|
+
const n = await askStore.reapSettledAsks(cutoffMs, APPROVAL_ASK_REAP_BATCH, movable);
|
|
75
|
+
reading.asks += n;
|
|
76
|
+
count("asks", n);
|
|
77
|
+
if (n < APPROVAL_ASK_REAP_BATCH)
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
for (;;) {
|
|
81
|
+
const n = await askStore.reapEmptyBatches(cutoffMs, APPROVAL_ASK_REAP_BATCH);
|
|
82
|
+
reading.batches += n;
|
|
83
|
+
count("batches", n);
|
|
84
|
+
if (n < APPROVAL_ASK_REAP_BATCH)
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (audit !== undefined) {
|
|
89
|
+
const rotated = audit.rotateOlderThan(cutoffMs, movable);
|
|
90
|
+
reading.auditAsks += rotated.droppedAsks;
|
|
91
|
+
reading.auditRecords += rotated.droppedRecords;
|
|
92
|
+
count("audit", rotated.droppedRecords);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
report(true);
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
report(false);
|
|
100
|
+
return reading;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=approval-ask-retention.js.map
|
package/dist/approval-card.d.ts
CHANGED
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
import { z } from "zod";
|
|
24
24
|
import { ALLOW_RULE_MEMBERS, READ_ROOT_CANDIDATE_DIR_MAX, type AskClass, type AskEvidenceAbsence, type PendingAction as CorePendingAction, type ReadRootGrantCandidate, type ResumeStartupCause, type RuleOffer, type RuleOffersAbsence as CoreRuleOffersAbsence, type SteerReplayFacet } from "@sema-agent/core";
|
|
25
25
|
import type { AskRow } from "./plugins/approval-ask-store-sql.js";
|
|
26
|
+
import type { SettleCause, SettleOutcome } from "./approval-deny-reasons.js";
|
|
27
|
+
import type { ToolApprovalFrame } from "./tool-approval.js";
|
|
26
28
|
/** 模型自由文本(`sourceAgentName` / `delegation.agentName`)的限长(设计稿 §6.2)。设计 §3.1 把
|
|
27
29
|
* 「限长 + 脱敏」写成 **server 新增责任**(引擎无此层):spawning model 挑的名字是自由文本,
|
|
28
30
|
* 不能指望壳去截——一条 100KB 的 agentName 在 server 侧就该被拒,而不是变成一张撑爆呈卡面的卡。 */
|
|
@@ -82,8 +84,8 @@ export declare const RuleOfferSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
82
84
|
rule: z.ZodString;
|
|
83
85
|
match: z.ZodEnum<{
|
|
84
86
|
name: "name";
|
|
85
|
-
path: "path";
|
|
86
87
|
host: "host";
|
|
88
|
+
path: "path";
|
|
87
89
|
exact: "exact";
|
|
88
90
|
prefix: "prefix";
|
|
89
91
|
wildcard: "wildcard";
|
|
@@ -99,8 +101,8 @@ export declare const RuleOfferSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
99
101
|
rule: z.ZodString;
|
|
100
102
|
match: z.ZodEnum<{
|
|
101
103
|
name: "name";
|
|
102
|
-
path: "path";
|
|
103
104
|
host: "host";
|
|
105
|
+
path: "path";
|
|
104
106
|
exact: "exact";
|
|
105
107
|
prefix: "prefix";
|
|
106
108
|
wildcard: "wildcard";
|
|
@@ -167,8 +169,8 @@ export declare const RuleOfferRawSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
167
169
|
rule: z.ZodString;
|
|
168
170
|
match: z.ZodEnum<{
|
|
169
171
|
name: "name";
|
|
170
|
-
path: "path";
|
|
171
172
|
host: "host";
|
|
173
|
+
path: "path";
|
|
172
174
|
exact: "exact";
|
|
173
175
|
prefix: "prefix";
|
|
174
176
|
wildcard: "wildcard";
|
|
@@ -184,8 +186,8 @@ export declare const RuleOfferRawSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
184
186
|
rule: z.ZodString;
|
|
185
187
|
match: z.ZodEnum<{
|
|
186
188
|
name: "name";
|
|
187
|
-
path: "path";
|
|
188
189
|
host: "host";
|
|
190
|
+
path: "path";
|
|
189
191
|
exact: "exact";
|
|
190
192
|
prefix: "prefix";
|
|
191
193
|
wildcard: "wildcard";
|
|
@@ -631,8 +633,8 @@ export declare const ApprovalCardSchema: z.ZodObject<{
|
|
|
631
633
|
rule: z.ZodString;
|
|
632
634
|
match: z.ZodEnum<{
|
|
633
635
|
name: "name";
|
|
634
|
-
path: "path";
|
|
635
636
|
host: "host";
|
|
637
|
+
path: "path";
|
|
636
638
|
exact: "exact";
|
|
637
639
|
prefix: "prefix";
|
|
638
640
|
wildcard: "wildcard";
|
|
@@ -648,8 +650,8 @@ export declare const ApprovalCardSchema: z.ZodObject<{
|
|
|
648
650
|
rule: z.ZodString;
|
|
649
651
|
match: z.ZodEnum<{
|
|
650
652
|
name: "name";
|
|
651
|
-
path: "path";
|
|
652
653
|
host: "host";
|
|
654
|
+
path: "path";
|
|
653
655
|
exact: "exact";
|
|
654
656
|
prefix: "prefix";
|
|
655
657
|
wildcard: "wildcard";
|
|
@@ -728,10 +730,13 @@ export declare const ApprovalCardSchema: z.ZodObject<{
|
|
|
728
730
|
}, z.core.$strict>;
|
|
729
731
|
export type ApprovalCard = z.infer<typeof ApprovalCardSchema>;
|
|
730
732
|
/**
|
|
731
|
-
* `approval_ask.card_json` 里真正存的东西(设计稿 §6.2)
|
|
732
|
-
* 车2 铸的 `approvalId`(wire 面的回决通道桥 + 消费端与并行 `tool_approval` 帧的去重键),而它不属于
|
|
733
|
-
* 「卡的内容」——放进卡里会让 schema 的语义边界糊掉。`schemaVersion` 是形的版本闩(与行上的
|
|
733
|
+
* `approval_ask.card_json` 里真正存的东西(设计稿 §6.2)。`schemaVersion` 是形的版本闩(与行上的
|
|
734
734
|
* `schema_version` 列同值,列供 SQL 侧过滤,信封里这份供读面在解出内容**之前**判形)。
|
|
735
|
+
*
|
|
736
|
+
* `approvalId` = 这张卡**呈出时**的 wire 身份。7.133.0 起它恒等于行的键 `askId`(一只 ask 一只 wire 身份),本服务的活读者(重放帧 /
|
|
737
|
+
* 应答口 / 读口)一律读行的键、不读这一格;写它是给滚动升级窗里上一版的副本(它们的 strict 信封 schema 要求这一格并照它重放)。
|
|
738
|
+
* 唯一读这一格的是 local 车道的启动收敛 —— 拿它去审计账里查前世这只 ask 的成因:审计行记的就是当时呈出的那个 id
|
|
739
|
+
* (更早写下的行上是当年的登记本地 id)。
|
|
735
740
|
*/
|
|
736
741
|
export declare const ApprovalCardEnvelopeSchema: z.ZodObject<{
|
|
737
742
|
schemaVersion: z.ZodLiteral<1>;
|
|
@@ -766,8 +771,8 @@ export declare const ApprovalCardEnvelopeSchema: z.ZodObject<{
|
|
|
766
771
|
rule: z.ZodString;
|
|
767
772
|
match: z.ZodEnum<{
|
|
768
773
|
name: "name";
|
|
769
|
-
path: "path";
|
|
770
774
|
host: "host";
|
|
775
|
+
path: "path";
|
|
771
776
|
exact: "exact";
|
|
772
777
|
prefix: "prefix";
|
|
773
778
|
wildcard: "wildcard";
|
|
@@ -783,8 +788,8 @@ export declare const ApprovalCardEnvelopeSchema: z.ZodObject<{
|
|
|
783
788
|
rule: z.ZodString;
|
|
784
789
|
match: z.ZodEnum<{
|
|
785
790
|
name: "name";
|
|
786
|
-
path: "path";
|
|
787
791
|
host: "host";
|
|
792
|
+
path: "path";
|
|
788
793
|
exact: "exact";
|
|
789
794
|
prefix: "prefix";
|
|
790
795
|
wildcard: "wildcard";
|
|
@@ -958,16 +963,33 @@ export declare function buildApprovalRequestFrame(input: {
|
|
|
958
963
|
card: ApprovalCard;
|
|
959
964
|
expiresAtMs: number;
|
|
960
965
|
nowMs: number;
|
|
966
|
+
live: ApprovalRequestLiveFacts;
|
|
961
967
|
}): ApprovalRequestFrame;
|
|
962
968
|
/**
|
|
963
|
-
*
|
|
969
|
+
* 🔴 **呈卡帧的活面事实座**(呈卡腿上旧族退役之后,开卡帧的全部事实都由本族承载)。
|
|
970
|
+
*
|
|
971
|
+
* 这十个座是活卡帧 `tool_approval` 上有、而卡(`ApprovalCardSchema`,`card_json` 的耐久信封)上**没有**的那几位:
|
|
972
|
+
* 卡外的事实此前只骑活卡帧,呈卡腿的消费方靠「两帧按 approvalId 合读」拿到它们。呈卡腿自此只发本族帧 ⇒ 它们挪到**活铸**的
|
|
973
|
+
* 呈卡帧顶层,同名同型同值 —— 值取自同一只帧对象(活卡帧的那一次铸定,`tool-approval.ts` 的 `askBroadcast`),本仓不另算一遍。
|
|
964
974
|
*
|
|
965
|
-
*
|
|
966
|
-
* `
|
|
975
|
+
* 在场面与它们在活卡帧上的在场面**逐字相同**:只在活铸的帧上,断连重放帧({@link buildReplayFrame},从 `card_json` 回读)上恒缺席 ——
|
|
976
|
+
* 活卡帧从来不重放,卡外事实也从来不在重放面上;是否把其中某几位收进卡(耐久、随重放)是另一件事,各自要过 `.strict()` 信封的回滚窗判断
|
|
977
|
+
* (`readRootCandidate` 有不进卡的硬理由:耐久面兑现不了它,见活卡帧该座顶注)。
|
|
967
978
|
*
|
|
968
|
-
*
|
|
979
|
+
* `requiresRealApproval` 不在表里:卡上 `risk.requiresRealApproval` 是同一个事实(铸卡第三参就是它),一个事实一个读法。
|
|
969
980
|
*/
|
|
970
|
-
export
|
|
981
|
+
export declare const APPROVAL_REQUEST_LIVE_FACT_KEYS: readonly ["mandated", "mandate", "origin", "boundGrantDigest", "boundGrants", "classifierNoRuling", "boundGrantAbsence", "approvalCard", "readRootCandidate", "probeReason"];
|
|
982
|
+
/** 呈卡帧活面事实座的类型面 = 活卡帧同名座的 `Pick`(同型由构造保证,不手抄)。 */
|
|
983
|
+
export type ApprovalRequestLiveFacts = Pick<ToolApprovalFrame, (typeof APPROVAL_REQUEST_LIVE_FACT_KEYS)[number]>;
|
|
984
|
+
/**
|
|
985
|
+
* [ref] §3.1 的呈卡帧(设计稿 §4.1 逐字)。
|
|
986
|
+
*
|
|
987
|
+
* 🔴 **一条腿一个帧族**:呈卡协议在一条腿上场(腿的审批上下文接了 `emitCard`)⇒ 这条腿上一只 ask 的开卡 / 消卡 / 撤卡只走本族
|
|
988
|
+
* (`approval_request` / {@link ApprovalCompleteFrame} / {@link ApprovalRevokeFrame}),旧族 `tool_approval` / `tool_approval_complete`
|
|
989
|
+
* 一帧都不发;协议未上场的腿只发旧族。同一只 ask 在同一条腿上不再有两种开卡帧,消费方不再按 `approvalId` 去重。
|
|
990
|
+
* 开卡的全部事实因此在本帧上:卡(`card`,耐久信封)+ 活面事实座({@link ApprovalRequestLiveFacts},只在活铸的帧上)。
|
|
991
|
+
*/
|
|
992
|
+
export interface ApprovalRequestFrame extends ApprovalRequestLiveFacts {
|
|
971
993
|
/** = SSE 具名事件名(与 `tool_approval` 同约定)。 */
|
|
972
994
|
type: "approval_request";
|
|
973
995
|
schemaVersion: 1;
|
|
@@ -984,12 +1006,50 @@ export interface ApprovalRequestFrame {
|
|
|
984
1006
|
expiresAtMs: number;
|
|
985
1007
|
serverNowMs: number;
|
|
986
1008
|
/**
|
|
987
|
-
* server 扩(不在设计字面)
|
|
988
|
-
*
|
|
989
|
-
* 车4 上线后仍保留(旧壳过渡窗)。
|
|
1009
|
+
* server 扩(不在设计字面):`POST /v1/tool-approvals/:id/respond` / `GET /v1/tool-approvals/:id` 的 id —— **恒等于 `askId`**(行的键就是这只 ask
|
|
1010
|
+
* 唯一的 wire 身份;本族的消卡帧({@link ApprovalCompleteFrame})同带它)。
|
|
990
1011
|
*/
|
|
991
1012
|
approvalId: string;
|
|
992
1013
|
}
|
|
1014
|
+
/**
|
|
1015
|
+
* 呈卡族的**单卡消卡帧**(`approval_complete`)—— 一只 ask 落定时发给每一条**收到过它的呈卡帧**的呈卡腿连接。
|
|
1016
|
+
*
|
|
1017
|
+
* 语义与旧族 `tool_approval_complete` 逐字同一件事(同一次 settle 的同一份判决:`outcome` 三词、非人结局的 `cause`、park 路由的
|
|
1018
|
+
* `parked`),只是它属于本族:键与开卡帧对位(`askId` / `taskId` / `approvalId`,开卡帧上有的身份这里都有),消卡按开卡那一帧的键。
|
|
1019
|
+
* 与 {@link ApprovalRevokeFrame} 的分工:撤卡帧是**批级**的(兄弟被赢家连坐成 `VOID` 的那一批,名单 = 那一次原子事务的行集,
|
|
1020
|
+
* 不带逐卡终局);本帧是**单卡**的终局(人答 / 窗到期 / park 路由 / 取消 …)。同一只 ask 两帧都可能收到(被撤的兄弟自己的
|
|
1021
|
+
* 登记也按 settle 收场)—— 按 `askId` 清卡即可,两帧不冲突。
|
|
1022
|
+
*
|
|
1023
|
+
* 投递口 = 开卡帧的同一只口(`ToolApprovalRunContext.emitCard`):卡帧在哪,消卡帧就在哪(sync 腿 live + detach 账本,bg / resume 腿账本)。
|
|
1024
|
+
* 门 = 这条连接的**开卡帧真的送达过**(没见过开卡帧的连接收到消卡帧就是孤儿 close,与旧族同一条门)。
|
|
1025
|
+
*/
|
|
1026
|
+
export interface ApprovalCompleteFrame {
|
|
1027
|
+
/** = SSE 具名事件名(同 `approval_request` 约定)。 */
|
|
1028
|
+
type: "approval_complete";
|
|
1029
|
+
schemaVersion: 1;
|
|
1030
|
+
askId: string;
|
|
1031
|
+
taskId: string;
|
|
1032
|
+
approvalId: string;
|
|
1033
|
+
/** 这只 ask 怎么落定 —— 与审计 settle 行 `outcome` 同三词(`allowed` / `denied` = 一次决议;`expired` = 非人结局)。 */
|
|
1034
|
+
outcome: SettleOutcome;
|
|
1035
|
+
/** 非人结局的成因(与审计 settle 行 `cause` 同一个词);人答缺席。缺席不是证据。 */
|
|
1036
|
+
cause?: SettleCause;
|
|
1037
|
+
/** 这只 ask 按 park 路由收尾(行已转 PARKING / PARKED、迟到回决可达)。缺席 = 无证据,禁读作真拒。 */
|
|
1038
|
+
parked?: true;
|
|
1039
|
+
serverNowMs: number;
|
|
1040
|
+
}
|
|
1041
|
+
/** 单卡消卡帧的纯构造(`build*`:纯数据)。可选座只在有值时写键。 */
|
|
1042
|
+
export declare function buildApprovalCompleteFrame(input: {
|
|
1043
|
+
askId: string;
|
|
1044
|
+
taskId: string;
|
|
1045
|
+
approvalId: string;
|
|
1046
|
+
outcome: SettleOutcome;
|
|
1047
|
+
cause?: SettleCause;
|
|
1048
|
+
parked: boolean;
|
|
1049
|
+
nowMs: number;
|
|
1050
|
+
}): ApprovalCompleteFrame;
|
|
1051
|
+
/** 呈卡腿的单卡帧(开卡 / 消卡)—— `ToolApprovalRunContext.emitCard` 的入参形。 */
|
|
1052
|
+
export type ApprovalCardLegFrame = ApprovalRequestFrame | ApprovalCompleteFrame;
|
|
993
1053
|
/**
|
|
994
1054
|
* [ref] §3.3 的**批级撤卡帧**(车6;设计稿 §3 逐字)。
|
|
995
1055
|
*
|
package/dist/approval-card.js
CHANGED
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { ALLOW_RULE_MEMBERS, ASK_EVIDENCE_ABSENCE_VALUES, BOUND_GRANT_ABSENCES, MAX_RULE_TEXT_CHARS, READ_ROOT_CANDIDATE_DIR_MAX, RESUME_STARTUP_CAUSES, RULE_OFFERS_ABSENCES, STEER_REPLAY_FACETS, isAskClass, isAskOrigin, isAutoModeFallbackCause, isMintableProbeReason, isPersistedRuleMandate, screenAskClassMembers } from "@sema-agent/core";
|
|
3
3
|
import { redactSecrets } from "./trace/redact.js";
|
|
4
4
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
5
|
+
import { capText } from "./caller-text-echo.js";
|
|
5
6
|
import { retireParkArmWords, retireStoredCardWords } from "./retired-card-words.js";
|
|
6
7
|
import { PERSISTED_RULE_MATCHES, UNCOVERED_SEGMENT_REASONS } from "./permission-rule-vocab.js";
|
|
7
8
|
export const MAX_AGENT_NAME = 200;
|
|
@@ -450,11 +451,6 @@ const RiskAxesEnvelopeSchema = z.object({
|
|
|
450
451
|
})
|
|
451
452
|
.optional(),
|
|
452
453
|
});
|
|
453
|
-
function clip(s, max) {
|
|
454
|
-
if (s === undefined)
|
|
455
|
-
return undefined;
|
|
456
|
-
return s.length > max ? s.slice(0, max) : s;
|
|
457
|
-
}
|
|
458
454
|
export function buildApprovalCard(source, req, requiresRealApproval) {
|
|
459
455
|
const axes = RiskAxesEnvelopeSchema.safeParse(req);
|
|
460
456
|
const riskAxes = axes.success ? axes.data.riskAxes : undefined;
|
|
@@ -463,13 +459,13 @@ export function buildApprovalCard(source, req, requiresRealApproval) {
|
|
|
463
459
|
const ruleOffersAbsence = readRuleOffersAbsence(req);
|
|
464
460
|
const denialLimitFallback = readDenialLimitFallback(req);
|
|
465
461
|
const askClassPair = readAskClassPair(source);
|
|
466
|
-
const toolCallId =
|
|
467
|
-
const sourceTaskId =
|
|
468
|
-
const sourceAgentName =
|
|
462
|
+
const toolCallId = capText(source.toolCallId, MAX_IDENT);
|
|
463
|
+
const sourceTaskId = capText(source.sourceTaskId, MAX_IDENT);
|
|
464
|
+
const sourceAgentName = capText(source.sourceAgentName, MAX_AGENT_NAME);
|
|
469
465
|
const allowRuleShadowed = readAllowRuleShadowed(req);
|
|
470
466
|
return {
|
|
471
|
-
toolName:
|
|
472
|
-
message:
|
|
467
|
+
toolName: capText(source.toolName, MAX_IDENT) ?? "",
|
|
468
|
+
message: capText(source.message, MAX_MESSAGE) ?? "",
|
|
473
469
|
...(source.argsOmitted === true ? { argsOmitted: true } : source.args !== undefined ? { args: source.args } : {}),
|
|
474
470
|
...(toolCallId !== undefined ? { toolCallId } : {}),
|
|
475
471
|
risk: {
|
|
@@ -493,9 +489,9 @@ export function buildApprovalCard(source, req, requiresRealApproval) {
|
|
|
493
489
|
...(source.delegation
|
|
494
490
|
? {
|
|
495
491
|
delegation: {
|
|
496
|
-
parentToolCallId:
|
|
492
|
+
parentToolCallId: capText(source.delegation.parentToolCallId, MAX_IDENT) ?? "",
|
|
497
493
|
depth: source.delegation.depth,
|
|
498
|
-
...(source.delegation.agentName !== undefined ? { agentName:
|
|
494
|
+
...(source.delegation.agentName !== undefined ? { agentName: capText(source.delegation.agentName, MAX_AGENT_NAME) ?? "" } : {}),
|
|
499
495
|
},
|
|
500
496
|
}
|
|
501
497
|
: {}),
|
|
@@ -532,6 +528,41 @@ export function buildApprovalRequestFrame(input) {
|
|
|
532
528
|
expiresInMs: Math.max(0, input.expiresAtMs - input.nowMs),
|
|
533
529
|
serverNowMs: input.nowMs,
|
|
534
530
|
approvalId: input.approvalId,
|
|
531
|
+
...pickApprovalRequestLiveFacts(input.live),
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
export const APPROVAL_REQUEST_LIVE_FACT_KEYS = [
|
|
535
|
+
"mandated",
|
|
536
|
+
"mandate",
|
|
537
|
+
"origin",
|
|
538
|
+
"boundGrantDigest",
|
|
539
|
+
"boundGrants",
|
|
540
|
+
"classifierNoRuling",
|
|
541
|
+
"boundGrantAbsence",
|
|
542
|
+
"approvalCard",
|
|
543
|
+
"readRootCandidate",
|
|
544
|
+
"probeReason",
|
|
545
|
+
];
|
|
546
|
+
function pickApprovalRequestLiveFacts(src) {
|
|
547
|
+
const out = {};
|
|
548
|
+
for (const key of APPROVAL_REQUEST_LIVE_FACT_KEYS) {
|
|
549
|
+
const v = src[key];
|
|
550
|
+
if (v !== undefined)
|
|
551
|
+
out[key] = v;
|
|
552
|
+
}
|
|
553
|
+
return out;
|
|
554
|
+
}
|
|
555
|
+
export function buildApprovalCompleteFrame(input) {
|
|
556
|
+
return {
|
|
557
|
+
type: "approval_complete",
|
|
558
|
+
schemaVersion: 1,
|
|
559
|
+
askId: input.askId,
|
|
560
|
+
taskId: input.taskId,
|
|
561
|
+
approvalId: input.approvalId,
|
|
562
|
+
outcome: input.outcome,
|
|
563
|
+
...(input.cause !== undefined ? { cause: input.cause } : {}),
|
|
564
|
+
...(input.parked ? { parked: true } : {}),
|
|
565
|
+
serverNowMs: input.nowMs,
|
|
535
566
|
};
|
|
536
567
|
}
|
|
537
568
|
export function buildRevokeFrame(batchId, askIds, reason, serverNowMs, originTaskId) {
|
|
@@ -551,7 +582,7 @@ export function buildReplayFrame(row, nowMs) {
|
|
|
551
582
|
expiresAtMs: row.expiresAtMs,
|
|
552
583
|
expiresInMs: Math.max(0, row.expiresAtMs - nowMs),
|
|
553
584
|
serverNowMs: nowMs,
|
|
554
|
-
approvalId:
|
|
585
|
+
approvalId: row.askId,
|
|
555
586
|
};
|
|
556
587
|
}
|
|
557
588
|
export function storedCardDemandsAPerson(cardJson) {
|
|
@@ -46,7 +46,7 @@ export declare const APPROVAL_ENDING_CAUSES: {
|
|
|
46
46
|
/** 承载这张卡的流没了:断连强转 park(`parkOpenAsksForTask`,断连臂的事实 = 这个 wire run 的承载流断了;卡曾送达过,只是不会再有人从那条流上答它)。 */
|
|
47
47
|
readonly STREAM_DISCONNECTED: "stream_disconnected";
|
|
48
48
|
/**
|
|
49
|
-
* 这张卡呈不出去:兜底臂(行不可用 / 身份不定 /
|
|
49
|
+
* 这张卡呈不出去:兜底臂(行不可用 / 身份不定 / 无行且无旧族腿可呈,`unattendedOutcome` 的 `persisted_row_unusable` / `ensure_indeterminate` / `no_row_no_presenter`)—— 持久行证不出属主或读不成,
|
|
50
50
|
* 本次登记根本没把卡呈到任何投递面;同 askId 的其余本地登记按这个词随行收场。与 `broadcast_lost`(emit 零接收)是两个事实。
|
|
51
51
|
*/
|
|
52
52
|
readonly UNDELIVERABLE: "undeliverable";
|
package/dist/approval.d.ts
CHANGED
|
@@ -184,5 +184,14 @@ export declare function createDeploymentListExemption(store: Pick<ApprovalExempt
|
|
|
184
184
|
info(event: string, fields?: Record<string, unknown>): void;
|
|
185
185
|
warn(event: string, fields?: Record<string, unknown>): void;
|
|
186
186
|
}, leg?: "parked_revive"): DeploymentListExemption;
|
|
187
|
+
/**
|
|
188
|
+
* **请求叶策略:`settings.permissions.neverAuto`**(S-1351)—— 命中名单的工具恒问真人;名单外「本层没有意见」(裸 allow)。叶只管请求自己写的那张表,部署的 `APPROVAL_NEVER_AUTO`
|
|
189
|
+
* 在基线里({@link createDurableAskPolicy}),两者经 `tightenGoverned` 的 deny-wins 折叠取并:请求叶只会**多**问,删不掉基线里的任何一行。
|
|
190
|
+
*
|
|
191
|
+
* 名字读法与部署名单是**同一只**({@link createApprovalListVerdict} → 精确 ∪ covering,收紧臂读调用答得上的全部名字):一条规则只有一种读法。问的铸点是
|
|
192
|
+
* {@link requestAlwaysHumanAsk}(要真人位 + 请求出处),不是部署的 {@link operatorAlwaysHumanAsk}(那一个盖部署出身,请求里的声明冒不得)。
|
|
193
|
+
* `source` = 这张表在请求体里的坐标(出处进 `matchedAskRule`,审计 / 卡面据它说清是哪张表问的)。
|
|
194
|
+
*/
|
|
195
|
+
export declare function createRequestNeverAutoPolicy(names: readonly string[], source: string): ToolPolicy;
|
|
187
196
|
export declare function createDurableAskPolicy(opts: DurableAskOptions): ToolPolicy;
|
|
188
197
|
//# sourceMappingURL=approval.d.ts.map
|
package/dist/approval.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "@sema-agent/core";
|
|
2
|
-
import { operatorAlwaysHumanAsk, operatorAsk } from "./operator-ask.js";
|
|
2
|
+
import { operatorAlwaysHumanAsk, operatorAsk, requestAlwaysHumanAsk } from "./operator-ask.js";
|
|
3
3
|
import { ASK_USER_QUESTION_TOOL_NAME } from "./approval-content-kind.js";
|
|
4
4
|
import { isExplicitPosture } from "./posture-source.js";
|
|
5
5
|
import { handsOnWorkerFilePlane } from "./execution-lane-caps.js";
|
|
@@ -37,7 +37,7 @@ export function buildNoResponderBootWarns(input) {
|
|
|
37
37
|
out.push({
|
|
38
38
|
event: "fs_write_gate_no_responder",
|
|
39
39
|
fields: {
|
|
40
|
-
hint: "host-semantics lane with no approval face: permissionMode default/auto
|
|
40
|
+
hint: "host-semantics lane with no approval face: the engine's write-gate asks (permissionMode default/auto, absent reads as default; acceptEdits outside the write roots) will auto-deny (fail-closed); wire TOOL_APPROVAL_ENABLED=true or DURABLE_APPROVAL=true to answer them",
|
|
41
41
|
},
|
|
42
42
|
});
|
|
43
43
|
}
|
|
@@ -45,7 +45,7 @@ export function buildNoResponderBootWarns(input) {
|
|
|
45
45
|
out.push({
|
|
46
46
|
event: "workflow_gate_no_responder",
|
|
47
47
|
fields: {
|
|
48
|
-
hint: "self-orchestration with no approval face:
|
|
48
|
+
hint: "self-orchestration with no approval face: run_workflow asks (every permission mode but bypassPermissions, which releases them, and dontAsk, which refuses them; absent reads as default) will auto-deny (fail-closed); wire TOOL_APPROVAL_ENABLED=true or DURABLE_APPROVAL=true to answer them",
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
51
|
}
|
|
@@ -122,6 +122,27 @@ function createNameSetMatcher(names) {
|
|
|
122
122
|
function grantedByRule() {
|
|
123
123
|
return { action: "allow", decisionReason: "rule" };
|
|
124
124
|
}
|
|
125
|
+
export function createRequestNeverAutoPolicy(names, source) {
|
|
126
|
+
const verdictOf = createApprovalListVerdict({ requireApproval: [], neverAuto: names });
|
|
127
|
+
return {
|
|
128
|
+
check: (req) => {
|
|
129
|
+
const verdict = verdictOf(req);
|
|
130
|
+
switch (verdict.list) {
|
|
131
|
+
case "never_auto":
|
|
132
|
+
return requestAlwaysHumanAsk(`${source}(${verdict.hit})`, `human approval required to run "${req.toolName}"`);
|
|
133
|
+
case "none":
|
|
134
|
+
return { action: "allow" };
|
|
135
|
+
case "deny":
|
|
136
|
+
case "require":
|
|
137
|
+
throw new Error(`request never-auto leaf reached a "${verdict.list}" verdict with empty deny / require lists`);
|
|
138
|
+
default: {
|
|
139
|
+
const unreachable = verdict;
|
|
140
|
+
throw new Error(`unhandled approval-list verdict: ${JSON.stringify(unreachable)}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
125
146
|
export function createDurableAskPolicy(opts) {
|
|
126
147
|
const verdictOf = createApprovalListVerdict(opts);
|
|
127
148
|
const budget = Math.max(0, Math.floor(opts.autoBudget ?? 0));
|
package/dist/audit.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type StoredPromptEpoch } from "@sema-agent/core";
|
|
1
|
+
import { type SessionPlacementRecord, type StoredPromptEpoch } from "@sema-agent/core";
|
|
2
2
|
import type { Pool } from "mysql2/promise";
|
|
3
3
|
import type { Pool as PgPool } from "pg";
|
|
4
4
|
/**
|
|
@@ -29,12 +29,32 @@ export interface SessionAudit {
|
|
|
29
29
|
* the key entirely (undefined). */
|
|
30
30
|
promptEpoch?: StoredPromptEpoch;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* 会话视图体顶层 additive 键 `agent` —— **这只会话是哪只委派子代的转录**(`GET /v1/sessions/:id`;读法:终端侧链投影方按 fleet 帧的 `transcriptId`
|
|
34
|
+
* 读同一只会话读面,从体上拿到子代身份,不必再回头翻 fleet 行 —— 行一离场就没有了)。
|
|
35
|
+
*
|
|
36
|
+
* 只投影**存下来的 placement 元组**(`session_meta` 的 `placement_*` 列,首写不可变;店的 `placementOf` 一行 PK 探针),**不另铸**:
|
|
37
|
+
* · `id` = 元组里的 `handle` —— 耐久 agent 行的 `a…` 键,与 fleet 行的 `id`、`GET /v1/agents/roster` 的 `handle` 是同一个串(core 铸元组时 `handle: taskId`);
|
|
38
|
+
* · `parentSessionId` / `rootSessionId` = 元组里的同名格(派它的会话 / 委派树的根会话);
|
|
39
|
+
* · 元组缺哪一格这里就缺哪一格(present-iff;不铸空串);元组的 `scope`(租户键)/ `placedAt` / `kind` 不上 wire。
|
|
40
|
+
* 键在场 = 这是一只委派子代的转录(哪怕元组只存了 `kind`,那时 `agent` 是 `{}`);键缺席 = 普通会话,**或这台部署的店不存 placement 元组**
|
|
41
|
+
* (local 后端:子代转录停驻前住私有短 TTL 店、停驻时拷进来的那一份是普通会话行 —— 事实没存就不报,消费方在 fleet 行 / `GET /v1/agents/roster` 上本就有 `id`)。
|
|
42
|
+
* 元组由引擎在**后台**委派子代(带耐久 agent 行、店声明了 placements)建会话时铸;同步委派的子代转录不落宿主店,没有元组。
|
|
43
|
+
*/
|
|
44
|
+
export interface SessionAgent {
|
|
45
|
+
id?: string;
|
|
46
|
+
parentSessionId?: string;
|
|
47
|
+
rootSessionId?: string;
|
|
48
|
+
}
|
|
49
|
+
/** {@link SessionAgent} 的唯一投影:店答出的 placement 元组 → 体上的 `agent` 值;`undefined`(普通会话 / 店没有这一面)⇒ 调用方不铸键。 */
|
|
50
|
+
export declare function sessionAgentOf(placement: SessionPlacementRecord | undefined): SessionAgent | undefined;
|
|
32
51
|
/**
|
|
33
52
|
* 用户消息行的**回退手柄**表:用户条目 id → 回退时交给 `resumeAt` 的那个 `event_id`(R8 用户消息锚按 run 的 taskId 键入)。
|
|
34
53
|
* 真源 = `resume_anchor`(锚店 `listBySession` 的读数),本表只是它对**一位读者**的一次投影。
|
|
35
54
|
*/
|
|
36
55
|
export type RewindHandles = ReadonlyMap<string, string>;
|
|
37
|
-
/** 会话视图读口(`ServiceDeps.sessionAudit`)的读者参数:`reader` = 读这张视图的**已验身份**(无身份 = `null`)。给了 ⇒
|
|
56
|
+
/** 会话视图读口(`ServiceDeps.sessionAudit`)的读者参数:`reader` = 读这张视图的**已验身份**(无身份 = `null`)。给了 ⇒ 这是一次**视图读**:用户消息行投回退手柄、体顶层投 `agent`({@link sessionAgentOf});
|
|
57
|
+
* 不给(只要归属的调用方:memory-status / 自助抹除)⇒ 两样投影的读都不付。 */
|
|
38
58
|
export interface SessionAuditReadOpts {
|
|
39
59
|
readonly reader: string | null;
|
|
40
60
|
}
|
|
@@ -53,15 +73,12 @@ export declare function buildRewindHandles(anchors: ReadonlyArray<{
|
|
|
53
73
|
* rewind-handle projection ({@link buildRewindHandles}); absent ⇒ no `taskId` keys. */
|
|
54
74
|
export declare function buildSessionAudit(pool: Pool, sessionId: string, handles?: RewindHandles): Promise<SessionAudit | undefined>;
|
|
55
75
|
/** The PG twin — same view over PgSessionStorage.wake. Until this, the
|
|
56
|
-
* audit face was TiDB-only and a PG/local deployment 404'd the whole web session area.
|
|
57
|
-
* (its storage seam has no wake-equivalent yet — may turn out to be a core gap). */
|
|
76
|
+
* audit face was TiDB-only and a PG/local deployment 404'd the whole web session area. */
|
|
58
77
|
export declare function buildSessionAuditPg(pool: PgPool, sessionId: string, handles?: RewindHandles): Promise<SessionAudit | undefined>;
|
|
59
|
-
/** The LOCAL (File) leg — web session area on DB_BACKEND=local.
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* `boundedTail`(纯函数切 floor)→ InMemorySessionStorage → 同一 auditFromStorage 内核。零写面、
|
|
64
|
-
* 零新 seam;createdAt 从 repo.list() 的 metadata 取(File 形态 meta 与 entries 分储)。 */
|
|
78
|
+
/** The LOCAL (File) leg — web session area on DB_BACKEND=local: the same view over `LocalSessionWindow.wake`
|
|
79
|
+
* (`plugins/local-session-window.ts`). All three legs read one way — a bounded window that carries the epoch anchor below its
|
|
80
|
+
* floor — and on every backend that is what the run reads: the SQL twins' run wakes the same window; the local run wakes the whole
|
|
81
|
+
* tree, and the local window is cut from that tree's branch, with the anchor walking the branch below the floor. */
|
|
65
82
|
export declare function buildSessionAuditLocal(root: string, sessionId: string, handles?: RewindHandles): Promise<SessionAudit | undefined>;
|
|
66
83
|
/**
|
|
67
84
|
* 🔴 **会话视图的读面口 —— `GET /v1/sessions/:id` 的全部取法(整读 / `?tail` / `?before` / `?blobCap` / `?message=N`)共用这一只**。
|
package/dist/audit.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import { StoredSession
|
|
1
|
+
import { StoredSession } from "@sema-agent/core";
|
|
2
2
|
import { TiDBSessionStorage } from "./plugins/tidb-session-storage.js";
|
|
3
3
|
import { PgSessionStorage } from "./plugins/pg-session-storage.js";
|
|
4
|
-
import {
|
|
4
|
+
import { LocalSessionWindow } from "./plugins/local-session-window.js";
|
|
5
5
|
import { redactModelText } from "./observability/run-terminal.js";
|
|
6
6
|
import { redactDeepWith } from "./trace/redact.js";
|
|
7
7
|
import { projectToolStructured } from "./trace/tool-output-media.js";
|
|
8
8
|
import { INJECTED_BLOCK_RE, isAttachmentFrame } from "./user-authored-text.js";
|
|
9
|
+
export function sessionAgentOf(placement) {
|
|
10
|
+
if (placement === undefined)
|
|
11
|
+
return undefined;
|
|
12
|
+
return {
|
|
13
|
+
...(placement.handle !== undefined ? { id: placement.handle } : {}),
|
|
14
|
+
...(placement.parentSessionId !== undefined ? { parentSessionId: placement.parentSessionId } : {}),
|
|
15
|
+
...(placement.rootSessionId !== undefined ? { rootSessionId: placement.rootSessionId } : {}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
9
18
|
export function buildRewindHandles(anchors, reader) {
|
|
10
19
|
const byEntry = new Map();
|
|
11
20
|
for (const a of anchors) {
|
|
@@ -26,20 +35,7 @@ export async function buildSessionAuditPg(pool, sessionId, handles) {
|
|
|
26
35
|
return auditFromStorage(await PgSessionStorage.wake(pool, sessionId), sessionId, handles);
|
|
27
36
|
}
|
|
28
37
|
export async function buildSessionAuditLocal(root, sessionId, handles) {
|
|
29
|
-
|
|
30
|
-
let entries;
|
|
31
|
-
try {
|
|
32
|
-
entries = await repo.exportEntries(sessionId);
|
|
33
|
-
}
|
|
34
|
-
catch (e) {
|
|
35
|
-
if (e.code === "not_found")
|
|
36
|
-
return undefined;
|
|
37
|
-
throw e;
|
|
38
|
-
}
|
|
39
|
-
const meta = (await repo.list()).find((m) => m.id === sessionId);
|
|
40
|
-
const { tail, floorEntryId } = boundedTail(entries);
|
|
41
|
-
const storage = new InMemorySessionStorage({ entries: tail, floorEntryId, ...(meta ? { metadata: meta } : {}) });
|
|
42
|
-
return auditFromStorage(storage, sessionId, handles);
|
|
38
|
+
return auditFromStorage(await LocalSessionWindow.wake(root, sessionId), sessionId, handles);
|
|
43
39
|
}
|
|
44
40
|
async function auditFromStorage(storage, sessionId, handles) {
|
|
45
41
|
if (!storage)
|
package/dist/bake-runner/main.js
CHANGED
|
@@ -5,6 +5,7 @@ import { logConfigDiagnostics, parseEnvNameAllowlist, parseNumOrFailNonNegative
|
|
|
5
5
|
import { installSecretEnvScrubRecorder } from "../observability/secret-env-scrub.js";
|
|
6
6
|
import { declareServerWithheldEnv, hostSubprocessEnv } from "../server-secret-env.js";
|
|
7
7
|
import { shellQuote as shellSafe } from "../plugins/remote-shell.js";
|
|
8
|
+
import { echoCallerText } from "../caller-text-echo.js";
|
|
8
9
|
import { BakeRunner, } from "./runner.js";
|
|
9
10
|
const BAKE_CLAIM_INGEST_FETCH_TIMEOUT_MS = 30_000;
|
|
10
11
|
const BAKE_HEARTBEAT_FETCH_TIMEOUT_MS = 10_000;
|
|
@@ -181,9 +182,9 @@ export async function execGroup(cmd, timeoutMs, envAllow) {
|
|
|
181
182
|
try {
|
|
182
183
|
const { code, signal } = await child.exited;
|
|
183
184
|
if (timedOut)
|
|
184
|
-
throw new Error(`host exec timed out after ${timeoutMs}ms (group killed): ${cmd
|
|
185
|
+
throw new Error(`host exec timed out after ${timeoutMs}ms (group killed): ${echoCallerText(cmd, { maxChars: 120 })}`);
|
|
185
186
|
if (code !== 0)
|
|
186
|
-
throw new Error(`host exec exited ${code ?? signal}: ${cmd
|
|
187
|
+
throw new Error(`host exec exited ${code ?? signal}: ${echoCallerText(cmd, { maxChars: 120 })}${stderr.trim() ? ` — ${stderr.trim().slice(-400)}` : ""}`);
|
|
187
188
|
return { stdout };
|
|
188
189
|
}
|
|
189
190
|
finally {
|
|
@@ -118,7 +118,7 @@ export class DeferredSandboxPathEnv extends StubExecutionEnv {
|
|
|
118
118
|
reason: found.reason,
|
|
119
119
|
face,
|
|
120
120
|
sessionId: this.sessionId ?? null,
|
|
121
|
-
note: "the sandbox
|
|
121
|
+
note: "the sandbox path adjudication has no task environment to read — the sensitive-path guard fails closed (deny) on every write target until one is bound",
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
124
|
return {
|