@sema-agent/server 7.150.0 → 7.152.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 +451 -0
- package/README.md +15 -3
- package/README.zh-CN.md +10 -2
- package/USAGE.md +144 -87
- package/deploy/sema-up/README.md +11 -4
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
- package/deploy/sema-up/chart/templates/server.yaml +5 -3
- package/deploy/sema-up/chart/values-full-single.yaml +3 -1
- package/deploy/sema-up/chart/values.yaml +8 -1
- package/deploy/sema-up/cluster-up.sh +7 -6
- package/deploy/sema-up/kube-up.sh +6 -6
- package/deploy/sema-up/lib/flagshape.sh +36 -8
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/deploy/sema-up/machines.example.yaml +3 -1
- package/deploy/sema-up/sema-up.sh +22 -16
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-audit-store.d.ts +1 -1
- package/dist/approval-ask-machine.d.ts +4 -10
- package/dist/approval-ask-retention.d.ts +1 -1
- package/dist/approval-card.d.ts +12 -14
- package/dist/approval-gate-currency.d.ts +9 -9
- package/dist/approval-gate-currency.js +3 -4
- package/dist/approval-hmac.d.ts +17 -1
- package/dist/approval-hmac.js +7 -1
- package/dist/approval-queue-kind.d.ts +1 -1
- package/dist/approval.d.ts +2 -2
- package/dist/approval.js +2 -2
- package/dist/auth-bridge.d.ts +20 -0
- package/dist/auth-bridge.js +9 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +3 -6
- package/dist/bind-host.js +4 -7
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/coordinators.d.ts +1 -1
- package/dist/boot/coordinators.js +9 -10
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +9 -14
- package/dist/boot/execution-env.js +85 -22
- package/dist/boot/execution-lane.js +32 -5
- package/dist/boot/late-binds.d.ts +8 -4
- package/dist/boot/late-binds.js +7 -1
- package/dist/boot/leader.d.ts +31 -30
- package/dist/boot/leader.js +38 -28
- package/dist/boot/leg-path-adjudication.d.ts +40 -0
- package/dist/boot/leg-path-adjudication.js +18 -0
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/parked-revive-gate.js +3 -15
- package/dist/boot/reapers.d.ts +6 -1
- package/dist/boot/reapers.js +13 -2
- package/dist/boot/resolve-spec.d.ts +3 -3
- package/dist/boot/resolve-spec.js +43 -48
- package/dist/boot/runner-deps.d.ts +46 -35
- package/dist/boot/runner-deps.js +94 -91
- package/dist/boot/session-age-out.d.ts +36 -0
- package/dist/boot/session-age-out.js +101 -0
- package/dist/boot/session-faces.d.ts +5 -14
- package/dist/boot/session-faces.js +9 -5
- package/dist/boot/shutdown.d.ts +6 -0
- package/dist/boot/shutdown.js +10 -4
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-02-web-admin-pull.js +4 -5
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +3 -2
- package/dist/boot/stage-06-runners.d.ts +9 -4
- package/dist/boot/stage-06-runners.js +24 -9
- package/dist/boot/stage-07-capability-layer.d.ts +8 -4
- package/dist/boot/stage-07-capability-layer.js +3 -2
- package/dist/boot/stage-08-reapers.d.ts +8 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +12 -5
- package/dist/boot/stage-09-leader.js +14 -5
- package/dist/boot/stage-10-http-server.d.ts +19 -5
- package/dist/boot/stage-10-http-server.js +14 -21
- package/dist/boot/stores.js +7 -4
- package/dist/boot/web-admin.js +5 -8
- package/dist/boot/workflow-orchestration.d.ts +7 -2
- package/dist/boot/workflow-orchestration.js +24 -7
- package/dist/bounded-rotation.d.ts +29 -0
- package/dist/bounded-rotation.js +24 -0
- package/dist/capabilities/approvals-push.d.ts +3 -3
- package/dist/capabilities/scenarios.d.ts +28 -13
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capability-facts.d.ts +43 -32
- package/dist/capability-facts.js +45 -51
- package/dist/card-rule-offers.d.ts +32 -0
- package/dist/card-rule-offers.js +130 -0
- package/dist/center-credential.d.ts +25 -6
- package/dist/center-credential.js +25 -5
- package/dist/config-catalog.d.ts +26 -7
- package/dist/config-catalog.js +26 -22
- package/dist/config-dir-trust.js +4 -2
- package/dist/config-invariants.d.ts +20 -8
- package/dist/config-invariants.js +55 -12
- package/dist/config-lkg.d.ts +5 -19
- package/dist/config-lkg.js +8 -62
- package/dist/config-provider.d.ts +1 -1
- package/dist/config-root-migration.d.ts +2 -2
- package/dist/config-types.d.ts +38 -42
- package/dist/config.d.ts +58 -7
- package/dist/config.js +90 -40
- package/dist/control-socket.d.ts +51 -0
- package/dist/control-socket.js +115 -0
- package/dist/deployment-governance.d.ts +2 -1
- package/dist/deployment-shape.d.ts +9 -1
- package/dist/deployment-shape.js +2 -1
- package/dist/device-protocol.d.ts +5 -4
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.d.ts +7 -0
- package/dist/device-ws-hub.js +10 -3
- package/dist/device-ws-protocol.d.ts +63 -10
- package/dist/device-ws-protocol.js +56 -25
- package/dist/elicitation.js +2 -2
- package/dist/engine-identity.d.ts +19 -7
- package/dist/engine-identity.js +10 -2
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/entry-problems.d.ts +40 -3
- package/dist/entry-problems.js +3 -1
- package/dist/execution-env-refusal.d.ts +29 -0
- package/dist/execution-env-refusal.js +8 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +1 -1
- package/dist/file-history-capture.d.ts +11 -4
- package/dist/file-history-capture.js +9 -6
- package/dist/file-history-disclosure.d.ts +7 -5
- package/dist/file-history-disclosure.js +7 -5
- package/dist/fleet/drain-entry.d.ts +4 -0
- package/dist/fleet/engine-signal.d.ts +12 -29
- package/dist/fleet/engine-signal.js +1 -7
- package/dist/fleet-client.js +2 -5
- package/dist/gate-settlement.d.ts +1 -8
- package/dist/gate-settlement.js +0 -4
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +2 -3
- package/dist/hitl-delivery.js +0 -2
- package/dist/hooks/hook-llm.js +4 -2
- package/dist/hooks/hook-runner.d.ts +3 -2
- package/dist/hooks/hook-runner.js +18 -3
- package/dist/host-decision.d.ts +11 -11
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/active-run-conflict.d.ts +35 -2
- package/dist/http/active-run-conflict.js +48 -19
- package/dist/http/admission.js +17 -2
- package/dist/http/approval-sweeps.d.ts +1 -1
- package/dist/http/approval-sweeps.js +10 -7
- package/dist/http/checkpoint-ctx.d.ts +4 -0
- package/dist/http/checkpoint-ctx.js +2 -0
- package/dist/http/dispatch.d.ts +8 -3
- package/dist/http/dispatch.js +59 -32
- package/dist/http/durable-run-leg.js +16 -17
- package/dist/http/health-reader.d.ts +16 -9
- package/dist/http/health-reader.js +2 -1
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +3 -1
- package/dist/http/owner-access.d.ts +33 -14
- package/dist/http/owner-access.js +40 -10
- package/dist/http/principal-gate.d.ts +49 -21
- package/dist/http/principal-gate.js +61 -11
- package/dist/http/request-channel.d.ts +23 -0
- package/dist/http/request-channel.js +9 -0
- package/dist/http/request-guards.js +17 -2
- package/dist/http/resume-ctx-read.js +42 -3
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +367 -117
- package/dist/http/route-ctx.d.ts +91 -15
- package/dist/http/route-ctx.js +17 -0
- package/dist/http/route-table.d.ts +5 -1
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/admin-config-refresh.js +3 -3
- package/dist/http/routes/admin-drain.d.ts +3 -0
- package/dist/http/routes/admin-drain.js +7 -7
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/admin-memory-optout.js +3 -3
- package/dist/http/routes/adoption.js +3 -5
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.d.ts +2 -1
- package/dist/http/routes/approvals-assistant.js +99 -51
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.d.ts +4 -0
- package/dist/http/routes/capabilities.js +38 -10
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +19 -7
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/images.js +10 -10
- package/dist/http/routes/memory-bundle.js +3 -3
- package/dist/http/routes/memory-compliance.js +3 -3
- package/dist/http/routes/memory-consolidation.js +2 -2
- package/dist/http/routes/memory-origin.js +3 -3
- package/dist/http/routes/memory-policy.js +2 -2
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/projects.d.ts +3 -2
- package/dist/http/routes/projects.js +4 -5
- package/dist/http/routes/retention-ops.js +3 -3
- package/dist/http/routes/rules.js +5 -5
- package/dist/http/routes/run-permission-mode.d.ts +2 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +4 -9
- package/dist/http/routes/runs.js +171 -65
- package/dist/http/routes/session-sync.d.ts +22 -9
- package/dist/http/routes/session-sync.js +204 -107
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.js +30 -15
- package/dist/http/routes/tasks.js +46 -41
- package/dist/http/routes/trace-usage.js +2 -2
- package/dist/http/routes/workflows.js +1 -1
- package/dist/http/server.d.ts +30 -30
- package/dist/http/server.js +16 -4
- package/dist/http/submit-ctx.d.ts +1 -1
- package/dist/http/submit-ctx.js +7 -4
- package/dist/http/wire-types.d.ts +14 -4
- package/dist/human-facing-args.d.ts +33 -0
- package/dist/human-facing-args.js +33 -0
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +5 -1
- package/dist/k8s-api-credentials.d.ts +29 -0
- package/dist/k8s-api-credentials.js +25 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +2 -2
- package/dist/leader/diffup.d.ts +19 -0
- package/dist/leader/diffup.js +7 -0
- package/dist/leader/leader.d.ts +116 -11
- package/dist/leader/leader.js +69 -5
- package/dist/leader/repair-wire.js +2 -2
- package/dist/leader/run-entry.d.ts +2 -1
- package/dist/leader/run-entry.js +1 -1
- package/dist/leader/wire.d.ts +42 -132
- package/dist/leader/wire.js +81 -67
- package/dist/leg-facts.d.ts +13 -5
- package/dist/leg-facts.js +2 -1
- package/dist/memory-scope.d.ts +23 -11
- package/dist/memory-scope.js +18 -6
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/model-entry-headers.d.ts +9 -10
- package/dist/model-entry-headers.js +0 -4
- package/dist/model-entry-refusal.d.ts +7 -4
- package/dist/model-entry-refusal.js +11 -5
- package/dist/model-plane-face.d.ts +1 -1
- package/dist/model-plane-face.js +3 -1
- package/dist/model-route-endpoint.d.ts +13 -7
- package/dist/model-route-endpoint.js +14 -11
- package/dist/model-select.d.ts +22 -0
- package/dist/model-select.js +9 -0
- package/dist/model-unreachable-notice.d.ts +11 -0
- package/dist/model-unreachable-notice.js +4 -4
- package/dist/object-store-buckets.d.ts +640 -6
- package/dist/object-store-buckets.js +166 -0
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +25 -17
- package/dist/observability/fail-open.js +25 -17
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -0
- package/dist/operator-roster.d.ts +68 -0
- package/dist/operator-roster.js +32 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
- package/dist/orchestration/workflow-notify-journal.js +12 -1
- package/dist/orchestration/workflow-park-decision.d.ts +70 -18
- package/dist/orchestration/workflow-park-decision.js +49 -10
- package/dist/orchestration/workflow-park-holder.d.ts +65 -0
- package/dist/orchestration/workflow-park-holder.js +98 -0
- package/dist/orchestration/workflow-record-fence.d.ts +36 -0
- package/dist/orchestration/workflow-record-fence.js +42 -0
- package/dist/outbound-dispatcher.d.ts +71 -8
- package/dist/outbound-dispatcher.js +48 -7
- package/dist/owner-faces.d.ts +2 -2
- package/dist/parked-decide.d.ts +106 -55
- package/dist/parked-decide.js +153 -117
- package/dist/peer-directory.d.ts +2 -2
- package/dist/peer-inbound-face.d.ts +2 -6
- package/dist/peer-inbound-face.js +0 -3
- package/dist/permission-mode-admission.d.ts +74 -5
- package/dist/permission-mode-admission.js +56 -3
- package/dist/plugins/adoption-log-sql.d.ts +3 -1
- package/dist/plugins/adoption-log-sql.js +7 -1
- package/dist/plugins/approval-ask-store-file.d.ts +14 -2
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
- package/dist/plugins/approval-ask-store-memory.js +35 -10
- package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
- package/dist/plugins/approval-ask-store-sql.js +45 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/blob-backend.d.ts +83 -7
- package/dist/plugins/blob-backend.js +57 -6
- package/dist/plugins/breaker-state-sql.js +2 -0
- package/dist/plugins/caching-session-store.d.ts +9 -15
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
- package/dist/plugins/checkpoint-index-columns.js +3 -6
- package/dist/plugins/checkpoint-store-face.d.ts +119 -61
- package/dist/plugins/checkpoint-store-face.js +134 -55
- package/dist/plugins/device-store-sql.js +6 -0
- package/dist/plugins/error-origin.d.ts +18 -0
- package/dist/plugins/error-origin.js +10 -0
- package/dist/plugins/execution-placement-sql.js +6 -6
- package/dist/plugins/image-bake-store-sql.js +6 -0
- package/dist/plugins/image-index-sql.js +4 -0
- package/dist/plugins/landed-attendants.d.ts +212 -0
- package/dist/plugins/landed-attendants.js +161 -0
- package/dist/plugins/leader-run-store-sql.js +4 -0
- package/dist/plugins/local-checkpoint-store.d.ts +13 -3
- package/dist/plugins/local-checkpoint-store.js +38 -49
- package/dist/plugins/local-session-live-reference.d.ts +40 -0
- package/dist/plugins/local-session-live-reference.js +39 -0
- package/dist/plugins/local-session-store.d.ts +71 -33
- package/dist/plugins/local-session-store.js +129 -27
- package/dist/plugins/memory-engine-pg.js +4 -0
- package/dist/plugins/memory-engine-sql-apply.js +5 -2
- package/dist/plugins/memory-engine-tidb.js +4 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
- package/dist/plugins/memory-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +104 -80
- package/dist/plugins/one-time-migrations.js +226 -132
- package/dist/plugins/org-delivery-quota-store.js +4 -1
- package/dist/plugins/outcome-ledger-sql.js +2 -0
- package/dist/plugins/permission-rule-store-sql.js +11 -4
- package/dist/plugins/pg-cost-quota.js +4 -0
- package/dist/plugins/pg-pool.js +35 -10
- package/dist/plugins/pg-rate-limiter.js +2 -0
- package/dist/plugins/posix-shell-fs.d.ts +6 -1
- package/dist/plugins/posix-shell-fs.js +4 -1
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +41 -15
- package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
- package/dist/plugins/remote-env-connect-seat.js +72 -0
- package/dist/plugins/remote-env-device.d.ts +22 -5
- package/dist/plugins/remote-env-device.js +106 -8
- package/dist/plugins/remote-env-e2b.d.ts +15 -6
- package/dist/plugins/remote-env-e2b.js +42 -32
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +46 -10
- package/dist/plugins/remote-env-host.js +124 -52
- package/dist/plugins/remote-env-k8s.d.ts +109 -41
- package/dist/plugins/remote-env-k8s.js +160 -54
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +34 -41
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +60 -59
- package/dist/plugins/remote-shell.d.ts +98 -1
- package/dist/plugins/remote-shell.js +218 -0
- package/dist/plugins/replica-registration.d.ts +1 -1
- package/dist/plugins/replica-registration.js +1 -1
- package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
- package/dist/plugins/resume-anchor-store-sql.js +12 -5
- package/dist/plugins/retention-lane-store-sql.js +4 -0
- package/dist/plugins/retention-sql.d.ts +20 -2
- package/dist/plugins/retention-sql.js +11 -0
- package/dist/plugins/run-store-sql.d.ts +21 -2
- package/dist/plugins/run-store-sql.js +31 -7
- package/dist/plugins/s3-presign.d.ts +23 -0
- package/dist/plugins/s3-presign.js +37 -3
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
- package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
- package/dist/plugins/scheduler-support.d.ts +2 -2
- package/dist/plugins/scheduler-support.js +0 -3
- package/dist/plugins/schema-consistency.d.ts +4 -2
- package/dist/plugins/schema-consistency.js +19 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-file-ledger.d.ts +2 -2
- package/dist/plugins/send-file-ledger.js +5 -2
- package/dist/plugins/send-user-file.d.ts +3 -4
- package/dist/plugins/send-user-file.js +56 -52
- package/dist/plugins/serving-requirement.d.ts +26 -7
- package/dist/plugins/serving-requirement.js +11 -4
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-blob-claim-token.d.ts +15 -0
- package/dist/plugins/session-blob-claim-token.js +20 -0
- package/dist/plugins/session-blob-namespace.d.ts +46 -0
- package/dist/plugins/session-blob-namespace.js +116 -0
- package/dist/plugins/session-capture-record-store-sql.js +2 -0
- package/dist/plugins/session-ext-table.d.ts +14 -1
- package/dist/plugins/session-ext-table.js +5 -1
- package/dist/plugins/session-row-sql.d.ts +49 -2
- package/dist/plugins/session-row-sql.js +56 -13
- package/dist/plugins/session-store-sql.d.ts +34 -18
- package/dist/plugins/session-store-sql.js +98 -17
- package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
- package/dist/plugins/shared-memory-store-sql.js +6 -2
- package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
- package/dist/plugins/snapshot-bucket-presence.js +8 -2
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/sql-driver.js +18 -3
- package/dist/plugins/sql-errors.d.ts +11 -6
- package/dist/plugins/sql-errors.js +5 -6
- package/dist/plugins/sql-json-column.d.ts +1 -1
- package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
- package/dist/plugins/stop-then-start-sentence.js +14 -10
- package/dist/plugins/stop-then-start.d.ts +109 -0
- package/dist/plugins/stop-then-start.js +104 -0
- package/dist/plugins/store-backend.d.ts +84 -15
- package/dist/plugins/store-backend.js +236 -72
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +17 -0
- package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
- package/dist/plugins/store-fault-sentence-m53.js +25 -0
- package/dist/plugins/store-fault.d.ts +26 -7
- package/dist/plugins/store-fault.js +18 -2
- package/dist/plugins/task-attachment-store.d.ts +2 -1
- package/dist/plugins/task-attachment-store.js +14 -1
- package/dist/plugins/task-list-store-sql.d.ts +2 -2
- package/dist/plugins/task-list-store-sql.js +10 -8
- package/dist/plugins/tidb-cost-quota.js +4 -0
- package/dist/plugins/tidb-pool.js +21 -25
- package/dist/plugins/tidb-rate-limiter.js +4 -0
- package/dist/plugins/user-input-ledger-sql.js +4 -0
- package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
- package/dist/plugins/workflow-run-store-sql.js +64 -4
- package/dist/plugins/workspace-custody.d.ts +4 -3
- package/dist/plugins/workspace-fill.d.ts +4 -7
- package/dist/plugins/workspace-fill.js +2 -1
- package/dist/plugins/write-behind-counter.js +5 -0
- package/dist/project-context.d.ts +0 -2
- package/dist/project-context.js +4 -8
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/question.d.ts +2 -1
- package/dist/question.js +5 -13
- package/dist/request-form.d.ts +6 -1
- package/dist/request-form.js +4 -1
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +4 -0
- package/dist/request-value-closure.js +10 -0
- package/dist/rule-issue-reading.d.ts +1 -1
- package/dist/rules-consent.d.ts +1 -1
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-local.js +9 -9
- package/dist/runs.d.ts +54 -16
- package/dist/runs.js +67 -13
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +30 -32
- package/dist/security.js +41 -7
- package/dist/sema-config-dir.d.ts +2 -1
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- package/dist/session-bindings.d.ts +82 -0
- package/dist/session-bindings.js +18 -0
- package/dist/session-children-retire.d.ts +2 -2
- package/dist/session-children-retire.js +2 -6
- package/dist/session-deletion.d.ts +16 -1
- package/dist/session-error-wire.d.ts +3 -3
- package/dist/session-error-wire.js +3 -3
- package/dist/session-incarnation.d.ts +10 -0
- package/dist/session-incarnation.js +10 -1
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +25 -103
- package/dist/session-sync.js +14 -76
- package/dist/session-titler.d.ts +10 -3
- package/dist/session-titler.js +19 -6
- package/dist/ssh-host-key.d.ts +5 -0
- package/dist/ssh-host-key.js +3 -0
- package/dist/stores-sql/blob-index-sql.d.ts +30 -9
- package/dist/stores-sql/blob-index-sql.js +40 -21
- package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
- package/dist/stores-sql/checkpoint-store-sql.js +70 -146
- package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
- package/dist/stores-sql/file-history-store-sql.js +205 -95
- package/dist/stores-sql/pg-session-storage.d.ts +34 -7
- package/dist/stores-sql/pg-session-storage.js +37 -13
- package/dist/stores-sql/retention-store-sql.d.ts +1 -9
- package/dist/stores-sql/retention-store-sql.js +5 -19
- package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
- package/dist/stores-sql/session-policy-store-sql.js +61 -44
- package/dist/stores-sql/session-write-hooks.d.ts +11 -0
- package/dist/stores-sql/tidb-session-store.d.ts +58 -7
- package/dist/stores-sql/tidb-session-store.js +37 -13
- package/dist/submission-exit.d.ts +3 -2
- package/dist/submission-exit.js +9 -1
- package/dist/task-cwd.d.ts +2 -2
- package/dist/task-settings.d.ts +7 -5
- package/dist/task-settings.js +3 -3
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +465 -507
- package/dist/tool-approval.js +606 -1222
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/ledger-events.d.ts +3 -3
- package/dist/trace/project.d.ts +2 -3
- package/dist/trace/redact.js +3 -2
- package/dist/trace/self-minted-wire.d.ts +571 -178
- package/dist/trace/self-minted-wire.js +189 -56
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/read-warnings.js +1 -1
- package/dist/web-admin-client/types.d.ts +1 -1
- package/dist/workspace-space.d.ts +10 -4
- package/dist/workspace-space.js +4 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
- package/package.json +7 -3
- package/scripts/embed-minimal.mjs +3 -3
- package/wire-changes/server@7.151.0.json +762 -0
- package/wire-changes/server@7.152.0.json +900 -0
- package/dist/config-d-migration.d.ts +0 -37
- package/dist/config-d-migration.js +0 -60
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
package/USAGE.md
CHANGED
|
@@ -156,7 +156,7 @@ ANTHROPIC_API_KEY=sk-ant-… # 可选:ANTHROPIC_BASE_URL / ANTHROPIC_VERSION /
|
|
|
156
156
|
- **凭据什么时候生效**:网关 key `MODEL_API_KEY`(以及 `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN`)在启动时读一次,**换值 = 重启本服务**
|
|
157
157
|
—— 没有热应用通道(以前的版本同样如此:这几把 key 只来自启动时的环境变量;引擎 7.51.0 起模型路由的构造配置也只读一次)。
|
|
158
158
|
目录条目**自己的**凭据(`apiKeyEnv` 点名的变量、`sealedApiKey`)跟着中心 / config.d 的模型面热应用走,不用重启:新起的任务与调用
|
|
159
|
-
用新的一代(
|
|
159
|
+
用新的一代(在跑的任务用它起跑时那一代;leader 车道与 agent 钩子同读 —— 跑在一只执行器上的腿用那只执行器出生时那一代)。启动时焊死模型的两只座是一条规则:降级壳焊住的目标、**记忆整理席**解到的条目,凭据**身份**随焊住的模型一起冻结
|
|
160
160
|
(`apiKeyEnv` 点名的变量名照旧每次按名现读值 —— 同名轮换不用重启;重贴 `sealedApiKey` / 换变量名 = 新身份),同名条目把端点和凭据一起换掉之后、重启之前,
|
|
161
161
|
这两只座打的仍是焊住的旧端点、带的是旧一代的凭据(绝不把新凭据发往旧端点);身份或端点变了 ⇒ `/health` 报 `restartRequired`(`degrade-route` / `memory-consolidation`)。
|
|
162
162
|
- **`agents[].model` 写成内联 Model 对象时,这一只模型的请求带哪条凭据**:本服务只验 `id` 非空,引擎对内联对象原样信任、不查目录;每次请求只发**一条**凭据 —— 凭据词头与部署钥互斥,只发赢家。
|
|
@@ -528,6 +528,13 @@ MODEL_CODE_ROLES=default,subagent # 不设=全中立;仅这些角色在「
|
|
|
528
528
|
拒句点名控制面记下的路径与现在解析到的路径,并给出两条出路:**① 把目录放回原处**;**② 在本服务的目录里跑一次重锚**:
|
|
529
529
|
`node --input-type=module -e 'import("@sema-agent/core").then(m => m.reanchorMemoryStoreRoot("<path>", { controlDir: "<controlDir>" }))'`
|
|
530
530
|
(两个坐标拒句里逐字给出),然后再起服。`MEMORY_ENGINE_BACKEND=pg|mysql` 与 `MEMORY_ENGINE=off` 的部署不经这一判。
|
|
531
|
+
- **file 记忆控制面账本的形只在开档判一次;运行中被外部写坏,本服务不检测**:起服装配(`run-local` 的装配同)在构造 file 记忆后端之前,经引擎的只读口问一次「账本是什么形」(只读、不升级、不加锁、不建文件):
|
|
532
|
+
答「引擎拒读的形」⇒ 一行 warn `memory_ledger_malformed`(`hint` 带出路),**不拒启**;读口自己抛(账本路径是目录 / 无权读 / 环路)⇒ 一行 warn `memory_ledger_check_unavailable`,照常起服。
|
|
533
|
+
**之后本服务不再判它,也没有定时复查**:账本在服务跑着时被手改、被别的进程写坏、被磁盘故障弄坏,**不会有告警** —— 跑着的服务对它的反应只取决于引擎下一次读到它的那一刻:
|
|
534
|
+
读到坏文件的记忆面答 `500 internal.memory_control_plane_corrupt`,没碰到它的读不受影响,所以症状可能只是「没有报错、读到的还是旧数据」。
|
|
535
|
+
怎么读日志:起服日志里有 `memory_ledger_malformed` ⇒ 账本的形在开档时就不对;有 `memory_ledger_check_unavailable` ⇒ 开档时没判成,**不能据此分先后**;两行都没有而之后才出 500 ⇒ 账本形在开档时判过关,坏是之后的事,或坏在账本之外的控制面文件(开档这一判只管账本的形)。
|
|
536
|
+
**出路**:修好或还原控制面账本后**重启**(重启即再开档,按上面的开档律判;账本是 5.33.0 起没被任何引擎开过的「绑定之前」旧形时,出路是「先用上一版引擎开一次再升级」—— warn 的 `hint` 逐字给出这句话,出处与细节见 MIGRATION 7.146.0 节第 23 条)。
|
|
537
|
+
不经这一判的部署形(file 记忆引擎在那里不接线、或根本没有 file 账本):`MEMORY_ENGINE_BACKEND=pg|mysql`、`MEMORY_ENGINE=off`、多租户(`REQUIRE_PRINCIPAL=true`),以及 file 记忆平面与 worker 分家而未显式放行的远端车道形。
|
|
531
538
|
- **数据根的写豁免只有一个来源(7.126.0 / 引擎 7.49.0 起)**:路径守卫对「本服务自己的数据根」的豁免,只读引擎的 `memoryEngineDir` 一处 —— 本服务把记忆引擎根
|
|
532
539
|
**恒**交给它,**`MEMORY_ENGINE=off` 的部署也交**(否则豁免根缺席,数据根下的写会被当成普通受保护路径拒)。运维零动作。
|
|
533
540
|
- **写目标的真落点读不出 ⇒ 有守卫行的面拒这次写(7.126.0 / 引擎 7.49.0 起,所有权限模式含 `bypassPermissions`)**:`Write` / `Edit` / `NotebookEdit` 的目标
|
|
@@ -580,7 +587,9 @@ MODEL_CODE_ROLES=default,subagent # 不设=全中立;仅这些角色在「
|
|
|
580
587
|
- **org 记忆准入(7.0.0 起 BREAKING)**:`org:*` 记忆 scope 分**两个来源**——部署自证
|
|
581
588
|
(env `MEMORY_SCOPE` 的 org 形 + **单用户部署**的 `projects[].defaultScopes` org 键)直通;**多租户**
|
|
582
589
|
部署里由调用方 `projectId` 选中的登记簿 org 键算 **request 来源**,必须拿到授权目录的逐 principal
|
|
583
|
-
授予才准入,拿不到一律 fail-closed
|
|
590
|
+
授予才准入,拿不到一律 fail-closed 拒。登记簿默认读层只取提交者**看得见**的登记(与 `GET /v1/projects/:id`
|
|
591
|
+
同一只判:fleet 调用方看全部,带主体的调用方只看 `registeredBy` 是自己的)—— 提交一只看不见的项目 id
|
|
592
|
+
与提交一只未登记 id 同答(没有默认读层、不拒、拒句不点名)。目录源**三态单选,
|
|
584
593
|
授权面不双源合并**:web-admin 远程腿(per-principal `orgMemory` 段)> `MEMORY_ORG_DIRECTORY_JSON`
|
|
585
594
|
静态表 > 缺席(request 来源的 org scope 恒拒)。同一个目录也是 `GET /v1/memory/export` /
|
|
586
595
|
`POST /v2/memory/sync/:scope` 的 `org:` 属主门真源(写面另需条目 `write:true`);拒绝形 = 终局
|
|
@@ -624,8 +633,8 @@ MODEL_CASCADE_LADDER=deepseek-flash,deepseek-pro # 目录里的模型名,cheap
|
|
|
624
633
|
`run-local` 声明 `host`);自建 HTTP 装配递包根导出的 `HTTP_SERVICE_LANE_ENTRY`(全部车道、不替部署声明);不走文件覆写的装配直接调同一份判据 `assertExecutionLaneInvariants(config)`。
|
|
625
634
|
`ctx` 的型 `ExecutionLaneComposeCtx` 也从包根导出(自己的装配里要写它的签名 / 抽 helper 时直接 import,不必手抄一份形)。
|
|
626
635
|
读口场景门 `scenarioGate` 是 `createHttpServer` 的必填件(7.131.0+):用包根导出的 `createScenarioGate({ config, scenarios, principalCaps, logger }, "peek")` 铸(与任务提交腿同一个工厂,型 `ScenarioGate` / `ScenarioGateLeg` / `ScenarioGateSources` 一并导出),没递就是 tsc 红;绕过类型(JS 嵌入)没递或形不对,`createHttpServer` 构造即拒并点名这一席。
|
|
627
|
-
**模型路由端点的拒启同理判在目录应用之后**:`judgeServedModelRoute(config, { envTableIsPlaceholder })`(包根导出,HTTP 服务与 `run-local` 调的就是它)只判将要服务的那张表(目录表或 env 表,句子随视图);
|
|
628
|
-
只调 `loadConfig()` 的装配不再在读配置那一拍拿到路由拒启 —— 在**自己的**配置源应用之后调它一次,有判决就拒启(`reason` 是给运维的原句)。严格名册布防(env 表是占位)传 `envTableIsPlaceholder: true`,没有名册门的装配传 `false
|
|
636
|
+
**模型路由端点的拒启同理判在目录应用之后**:`judgeServedModelRoute(config, { envTableIsPlaceholder, webAdminIsConfigSource })`(包根导出,HTTP 服务与 `run-local` 调的就是它)只判将要服务的那张表(目录表或 env 表,句子随视图);
|
|
637
|
+
只调 `loadConfig()` 的装配不再在读配置那一拍拿到路由拒启 —— 在**自己的**配置源应用之后调它一次,有判决就拒启(`reason` 是给运维的原句)。严格名册布防(env 表是占位)传 `envTableIsPlaceholder: true`,没有名册门的装配传 `false`;`webAdminIsConfigSource`(必填)= web-admin 是不是这个装配的配置源,没有配置源的装配传 `false`,只决定 env 表拒因句里「让目录缺省来服务」那条出路提不提 web-admin。
|
|
629
638
|
随包的可运行参照:`node scripts/embed-minimal.mjs`(在包目录下跑)按上面这条链装一台最小服务 —— 包根工厂、引擎的 `Runner` 与自写的一行 `resolveSpec` 凑齐 `createHttpServer` 的九个必填席,
|
|
630
639
|
host 车道、一次性数据根、内核分口的回环口,起到监听就打一行 `EMBED-MINIMAL ok port=<n>`;`--omit <席名>` 少给一席,说清 `createHttpServer` 是构造即拒(`refused`,退 2)还是照收(`accepted`,退 3)。
|
|
631
640
|
构造期判且拒句点名席名的是 `runnerFor` / `authorize` / `deploymentMods` / `peerDesk` / `scenarioGate` 五席(省掉 `config` 抛一句不点名的 `TypeError`);`runner` / `sideQuery` / `resolveSpec` 只有型是提示,绕过类型的嵌入省掉它们构造期照收。
|
|
@@ -642,15 +651,29 @@ MODEL_CASCADE_LADDER=deepseek-flash,deepseek-pro # 目录里的模型名,cheap
|
|
|
642
651
|
宿主不必、也不该替部署把档位压回 info。同一行带两格绑址,一格一个事实:`bindHost` = 本进程**请求**绑的地址(`BIND_HOST` 经无鉴权自收窄之后的那一只 —— 不设 `BIND_HOST` 而写面无鉴权时是 `127.0.0.1`,另带 `bindHostNote`;请求的是全接口时是 `"0.0.0.0/::(all interfaces)"` 这句说明),
|
|
643
652
|
`boundAddress` = 内核**实际**绑上的地址(`::` / `0.0.0.0` / `127.0.0.1` / `::1` 原样;`BIND_HOST=localhost` 时是解析出的那一只)。自起引擎的宿主要认「这个口上的是不是我起的那只」:
|
|
644
653
|
读同一行的 `boundAddress` + `port` 去连,再以 `/health` 的 `pid` / `dataRoot` 验身份;别拿配置值去推实绑地址。行上的顶层键集登记在 wire 变更清单(`selfMinted.listeningLineKey`)。
|
|
654
|
+
**监听不开端口复用**(契约 §0.4 的同名条):同一具体地址同口只有一个监听者;绑全接口时引擎不独占回环地址(macOS 上同机进程能用更具体的回环地址在同口截走回环连接,Linux 上被引擎监听范围覆盖的更具体绑定被拒、没被覆盖的异族 / 异址仍可)——
|
|
655
|
+
所以 `boundAddress` 是具体地址时只连它的逐字地址,不连 `localhost`、不换地址族;是全接口时任何回环地址上有应答都不算「是我起的那只」的证据,TCP 上证不出归属。
|
|
645
656
|
**不要**先在外面挑一个空闲口、关掉、再交给子进程去绑 —— 关与子进程真正 `listen` 之间有窗,并行负载下别的进程能抢走这个号。`configHash` 仍按**配置值**铸(配置指纹不随 OS 分的口漂)。
|
|
646
657
|
- `/health` 身份字段承诺:`pid`(= 引擎进程)、`startedAt`(**7.67.0+**,= 引擎进程起点的 epoch ms,
|
|
647
658
|
一次铸)与 `dataRoot`(= 生效数据根,解析恒回退 `~/.ai-agent`,与 DB_BACKEND 无关)**恒在**(**7.148.0+**:配了服务凭据的引擎上,
|
|
648
|
-
|
|
649
|
-
|
|
659
|
+
这些键只给出示了凭据的读者与经本机控制 socket 到达的读者 —— 宿主验身份时带起引擎用的**同一枚** `Authorization: Bearer <SERVICE_AUTH_TOKEN>` 读,或经 socket 读(7.152.0+,见下一条);
|
|
660
|
+
没出示凭据、经 TCP 到达的读者只拿 `status` / `auth` / `operator` / `center` 四键,对端是回环也一样;没配服务凭据的嵌入形照旧匿名全键,见契约 §0.4「读者分档」)——宿主用
|
|
650
661
|
它们验证「这个端口上的 /health 是不是我起的那个引擎」。`startedAt` 变了 = 这个端口后面换了一条命
|
|
651
662
|
(另一个宿主重启了共享引擎):壳据此把「引擎换代」当**一等事实**处理,不必等某个带鉴权的请求先撞一次
|
|
652
663
|
401 才发现(`/health` 无鉴权,心跳恒绿)。⚠️ 只给这一个数:service token 本体与代际计数**不上**这一面。
|
|
653
664
|
钉:`test/health-identity-contract.test.ts`。
|
|
665
|
+
- **同机附着方怎么读身份(本机控制 socket;7.152.0+;只 `DB_BACKEND=local`)**:同一台机器上的附着方(壳、桌面宿主 —— 自己起的引擎或别的进程起的引擎)读引擎身份走**控制 socket**,
|
|
666
|
+
不从引擎日志反推、也不把凭据发给一只回环 TCP 口(macOS 上全接口绑址时本机别的进程绑更具体的回环地址就能答掉回环读者;Linux 上被引擎监听范围覆盖的更具体绑定被拒、没被覆盖的异族 / 异址仍可 —— 见契约 §0.4「监听不开端口复用」)。三句:
|
|
667
|
+
① **socket 在哪**:`<数据根的绝对物理路径>/control/engine.sock`(自起者直接读引擎 `listening` 行的 `controlSocket`;没起它的附着方按绝对数据根推导 —— 用相对数据根起的引擎只有自起者能用)。
|
|
668
|
+
连之前核:`<数据根>/control` 是目录而不是符号链接、属主是你自己的 OS 用户、没有组或他人位;`engine.sock` 是 socket、属主是你自己 —— 任一不过就当这台没有 socket。
|
|
669
|
+
然后经它读 `GET /health`(例:`curl --unix-socket <数据根>/control/engine.sock http://localhost/health`),`pid` / `startedAt` / `instanceId` / `version` / `dataRoot` 全在(`port` 缺席:socket 不是 TCP 口)。
|
|
670
|
+
② **读到之后仍要比**:照样与你记下的锚点比 `pid` + `startedAt` + `instanceId` —— socket 只证「对面是本 OS 用户」,不证「是你起的那台」(同一 OS 用户的别的进程能删掉 socket 重绑)。
|
|
671
|
+
带凭据的调用也走这只 socket(凭据照带;socket 不是凭据,配了服务凭据的引擎上不带凭据的写、审批、只读口照旧 `401`);**这条路上证明的归属只算这条路**:不要拿它去放行 TCP 上的凭据出示。
|
|
672
|
+
③ **没有 socket 的宿主**:`listening` 行带 `controlSocketUnavailable`(或文件不在)时这条路不在 —— Windows(`unsupported_platform`:Windows 上不开这只口,一律走 `listening` 行)、
|
|
673
|
+
SQL / 内存后端(`data_root_not_exclusive`)、数据根路径过长(`path_too_long`:换短一点的数据根;macOS 上 socket 的绝对路径最多 104 字节)、`control/` 被放宽或属主不对(`dir_not_private`:修目录的属主与模式)、
|
|
674
|
+
路径上有一只不是本用户 socket 的东西(`path_occupied`)、绑失败(`bind_failed`)。这时读 `listening` 行(独占 `127.0.0.1` 的 `boundAddress` + `port` + `instanceId`)证归属;
|
|
675
|
+
只有引擎**精确绑在** `127.0.0.1` 且这一行证得出归属时,才向那只 TCP 口出示凭据 —— 证不出就不出示。
|
|
676
|
+
部署前提(数据根与上级不可被别的用户写、不被 ACL 放宽;socket 不得被代理)见部署前提文档「本机控制 socket 与远端读者」一节。钉:`test/control-socket.test.ts`。
|
|
654
677
|
- **数据根引擎版本高水位 marker(7.147.0+;只 `DB_BACKEND=local`)**:`<数据根>/engine-high-water.json`(`/health.dataRoot` 那只目录的顶层),
|
|
655
678
|
形 = **恰一键** `{"highWater":"x.y.z"}` —— 打开过这只数据根的最高引擎(本包)版本(引擎判过之后、往根里写第一个字节之前就抬,所以它是「可能写过这只根的最高版本」,不是服务成功的记录)。`highWater` 是纯 `x.y.z`(无前导零、无 `v` 前缀、无预发布 / 构建后缀、
|
|
656
679
|
每段是安全整数),三段按数比。宿主(壳侧判官)与引擎读**同一只文件、同一读法**,不另记第二份高水位:
|
|
@@ -691,10 +714,15 @@ MODEL_CASCADE_LADDER=deepseek-flash,deepseek-pro # 目录里的模型名,cheap
|
|
|
691
714
|
把部署回退到 ≤7.146.x、再续跑升级之后写下或改写过的会话,结果**不保证**:可能照常续到终答(一次续跑返回 200),也可能被拒 —— 两种都不在支持范围内,本服务不承诺其中任何一种,也不为它加兼容读法(一条旧版读法就是第二份读法)。
|
|
692
715
|
**出路**:回退前先排空 —— 让待续跑的停驻 run 先收完(完成或取消),再回退;随包的排空检查(`scripts/drain-check-local.mjs`〔`DB_BACKEND=local`〕/ `scripts/drain-check.mysql.sql` / `scripts/drain-check.pg.sql`,只读)是读出停驻行存量的工具;或不跨版回退。回退的唯一支持形是恢复升级前的数据根 / 库备份。
|
|
693
716
|
- **已知限制:`REMOTE_EXEC=host` 车道上请求不带 `cwd` 时,进程重起之后才被批准的停驻后台子代,续跑的命令落在已删目录**:请求不带 `cwd` 时,host 车道为这条任务铸一个一次性的工作区 `<HOST_WORKSPACE_BASE,缺省 os.tmpdir()>/sema-host-<id>-<rand>`,
|
|
694
|
-
|
|
717
|
+
由工作目录落在里面的执行环境(父 run 与委派子代)共同持有;删之前那一拍按文件系统当下的答案判「此刻谁的工作目录在里面」(经符号链接落进来的也算),有人在就交给它、最后离场的删它,判不出就留到进程退出 —— 同一进程里父 run 先收了场、停驻在审批门上的后台子代之后被批准,续跑接着在那只目录里跑,子代最后一条腿收场时目录才删(删时先在同目录改名成一只隐藏墓名再删)。
|
|
695
718
|
**进程退出时**(正常退 / 未捕获异常 / 有处理器的信号)退出兜底删掉本进程铸的全部临时目录,含仍被停驻子代持有的;重起之后再批准,续跑的命令落在已删目录上 —— 命令没有运行,引擎的拒句是 `…the task root directory no longer exists (or is no longer a directory): <路径>`,
|
|
696
719
|
而续跑提醒仍写成命令已执行(以拒句为准)。停驻中被取消 / 过期的后台子代持有的临时目录活到进程退出、由退出兜底删。
|
|
697
720
|
**出路**:提交时带 `cwd` —— 带了 `cwd` 的请求不走一次性工作区,没有这个删除(`sema` CLI 恒带;SDK 只有 launch 助手默认传 `process.cwd()`,直接调提交接口的要自己带)。
|
|
721
|
+
- **已知限制:进程被硬杀(`SIGKILL` / 内存杀手 / 容器被强停)之后,`REMOTE_EXEC=host` 车道上本服务起的前台命令的进程组不被回收 —— 它们成孤儿,活到自己退出或被外部限额拦下**:host 车道的前台命令(命令在本机跑)记在**进程内存**里的一本簿上,进程退出时由退出边界把簿上每个组整组硬杀;但这道边界挂在 `exit` 事件上,而 `exit` 事件在进程被信号**默认终止**时**不触发** ——
|
|
722
|
+
`SIGKILL`(`kill -9`、OOM killer、容器被强停)之下没有一行收尾代码会跑。那些命令的进程组于是成孤儿(父进程变 init),照常往盘上的输出暂存文件继续写,直到它们自己退出、或被外部限额(磁盘配额 / `ulimit` / cgroup)拦下。
|
|
723
|
+
**覆盖与不覆盖**:**覆盖** —— 正常退出、未捕获异常的崩溃出口、装了处理器的信号(HTTP 车道的 `SIGTERM` / `SIGINT` / `SIGHUP` 收尾;`run-local` 的 `SIGINT` / `SIGTERM`,退出码取 128 + 信号号):退出前对簿上每个组硬杀。**不覆盖** —— 被硬杀的那一代留下的组:簿只在进程内存里、不落盘,**重起之后的新进程不知道前代起过哪些组,也不接管**;起服时的孤儿回收(`DB_BACKEND=local`:把前代孤立的在跑 run 翻成 `failed`、放掉会话占用)作用在 run 行与会话占用上,不作用于进程。远端车道(沙箱 / ssh / adb / device)里的命令跑在远端环境,不在这一条射程内。
|
|
724
|
+
**影响**:被硬杀过的 host 部署上,机器上可能留着父进程为 init 的长跑命令(构建 / 监听 / 不退出的脚本之类),持续写盘、占 CPU,本服务不再跟踪它们。
|
|
725
|
+
**出路**:本服务**不提供**起服回收,也不登记前代的进程组。运维侧:① 把服务放进容器或 cgroup,让「服务被杀 ⇒ 整树被收」由容器运行时 / 进程管理器兜底,并设磁盘配额 / `ulimit` 之类外部限额;② 硬杀之后手工清:找父进程为 init、工作目录或输出路径对得上本服务数据根 / 工作区的进程组,核对后整组 `kill`;③ 要停服务走 `SIGTERM` 或排空口(`POST /v1/admin/drain`),让退出边界跑得起来,不用 `SIGKILL`。
|
|
698
726
|
- `/health` 活体 store 探测(5.14.0,SQL 后端专属 additive):后台探针(`STORE_PROBE_INTERVAL_MS`,
|
|
699
727
|
默认 15000;0=关;负/非数启动响亮拒)缓存一份 DB 真往返结果,`storeProbe:{live,ageMs,error?}` 在
|
|
700
728
|
探针接线时恒在,顶层告警键 `storeLive:false` 只在死时出现。**status 保持 "ok"**(liveness≠readiness
|
|
@@ -711,19 +739,19 @@ MODEL_CASCADE_LADDER=deepseek-flash,deepseek-pro # 目录里的模型名,cheap
|
|
|
711
739
|
逐字同一份),`/readyz` 503 `{"ready":false,"reasons":[…]}` + `Retry-After: 5`(体只这两键,不带身份字段)。
|
|
712
740
|
⚠️ 7.102.0 起 **draining 也是未就绪**:此前 draining 形的 `/health` 只有 `draining:true`、不带 `ready` 键(读成
|
|
713
741
|
「就绪」),与同一刻计费提交的 503 自相矛盾。`storeLive:false` **不进**就绪判(见上一条:披露不代裁)。fleet 心跳的
|
|
714
|
-
`ready` 同一只判(
|
|
715
|
-
|
|
742
|
+
`engineSignal.ready` 同一只判(名册未落时 `ready:false`,落地当刻即再报一次)。fleet 心跳的 `engineSignal.restart`(**7.102.0+**;7.152.0 起只在
|
|
743
|
+
`engineSignal` 里):与 `/health.restart` 同一只取值口、逐字同一个对象(形 = settings-schema `RestartSignal`:`reasons` / `version` / `since`;
|
|
716
744
|
在场即「须重启才能应用配置」,缺席即不需要 —— 中心整行替换);重启信号出现 / 消失 / 变化的当刻即再报一次,不等下一拍心跳。
|
|
717
745
|
**7.106.0+**:候选**部分应用**(某组被整组拒、其余组已提交)的拍也照同一律算这一信号 —— 修前那一拍不签;被拒的是审批组 / 模型面组时
|
|
718
746
|
(新进程 boot 重判可能拒启)信号扣下、只出 warn `restart_signal_withheld_boot_may_refuse`(点名组与差异)。
|
|
719
747
|
钉:`test/health-readyz.test.ts` / `test/health-readiness-single-source.test.ts`。
|
|
720
748
|
- **引擎信号 `engineSignal`(7.123.0+,`/health` 与 fleet 心跳都带,恒在场)**:引擎态整只,型 = settings-schema `EngineSignal`
|
|
721
|
-
(`@sema-agent/settings-schema/fleet`;字段以契约包为准)。不带 `instanceId`(身份只在体顶层)
|
|
722
|
-
`engineSignal.draining`(排空事实 `{actionId, since, deadlineAt}`)在场
|
|
723
|
-
`
|
|
749
|
+
(`@sema-agent/settings-schema/fleet`;字段以契约包为准)。不带 `instanceId`(身份只在体顶层)。**一次读数**:
|
|
750
|
+
`engineSignal.draining`(排空事实 `{actionId, since, deadlineAt}`)在场 = 排空中,`since` = 排空起点;
|
|
751
|
+
`/health` 顶层的就绪键 / `restart` / 成员三键 / 世代账两版本与嵌套里的同名键同值(心跳体顶层不带任何引擎态键)。缺席 = 更早的引擎。⚠️ `/health` 无鉴权而排空中
|
|
724
752
|
`engineSignal.draining.actionId` 是本次排空的动作号:引擎自起的排空是引擎的闭集词,经 `POST /v1/admin/drain` 进的是调用方自取的幂等键原样
|
|
725
|
-
—— 用不透明 id(推荐 `manual:<uuid>`)
|
|
726
|
-
|
|
753
|
+
—— 用不透明 id(推荐 `manual:<uuid>`),别放秘密或人名。8.0 扁平方言(心跳体顶层 `ready` / `draining` / `restart` / 成员三键,
|
|
754
|
+
`/health` 的布尔 `draining` + `drainingSince`)随 settings-schema 26.0.0 退役,本引擎 **7.152.0** 起停发 —— 读它们的编排脚本 / 壳改读 `engineSignal`。
|
|
727
755
|
- **配置接力位 `configHandoff`(7.121.0+,只在 `/health`,不上心跳)**:`{ state: "missing", version, since }`,**在场 ⇔ 部署声明了耐久接力(`CONFIG_LKG_DURABLE=true`
|
|
728
756
|
∧ LKG 启用)∧ 应用着的那一代没在下一次起服将用的凭证身份的 LKG 桶里确认耐久落盘** —— 中心断着时重启按**此刻的凭证身份**选 LKG 桶,那只桶里没有这一代就回到
|
|
729
757
|
别的配置。三种形:LKG 发布失败(保留候选、启动期技能债)、部分应用(某组被整拒、其余组已热应用,LKG 停在上一个完整世代)、凭据换了人(凭证文件换成别的身份,
|
|
@@ -771,6 +799,13 @@ MODEL_CASCADE_LADDER=deepseek-flash,deepseek-pro # 目录里的模型名,cheap
|
|
|
771
799
|
分区会话不进会话列表(`GET /v1/sessions`、`/resume`);属主按帧上的 `transcriptId` 读 `GET /v1/sessions/<transcriptId>`(体上带 `agent` 键)。记录被收割时转录一并删除(`BG_AGENT_RETENTION_MS`,缺省 7 天;
|
|
772
800
|
记录已不在的分区会话由分区孤儿腿按同一视界收);删根会话不连带删子代转录。会话同步往子代 id 上写 ⇒ `409 conflict.session_placed`。
|
|
773
801
|
本机形升级前停驻时被拷进宿主店的旧子代转录是普通会话(进列表、不随记录删),要清就 `DELETE /v1/sessions/<id>`。
|
|
802
|
+
- **客户端放置的子代会话(会话种类 `sessionKind`,server ≥7.151.0;能力位 `sessionKinds`)**:壳自己起的子代对话(Agent 子代、serve 每次对话一只新会话)在**建这只会话的那一笔提交**里带
|
|
803
|
+
`sessionKind: "sidechain"`。这种会话不进 `GET /v1/sessions` 的缺省视图与 `ListAgents`(`GET /v1/sessions?sessionKind=sidechain` 单列它们;列表行与 `GET /v1/sessions/:id` 体上带 `sessionKind`),
|
|
804
|
+
不能作 `SendMessage` 的跨会话收件人;按 id 的读写(视图 / 头 / 事件流 / 改名 / 删除 / fork / 同步)与普通会话相同。种类终身不改:带键提交到种类不同的既有会话 ⇒ `409 conflict.session_kind_mismatch`;
|
|
805
|
+
续轮不带键照常。fork / 同步导入建的会话无种类(「先在本地建 sidechain 再同步上云」到云上是普通会话)。**老化**:最后活动(run / 追加 / 收场推它;**读不是活动**)之后过
|
|
806
|
+
`BG_AGENT_RETENTION_MS`(缺省 7 天,与后台子代行同一根旋钮)、且没有在跑的 run / 待决的审批 / 在跑的子代或 workflow 挂着它、所在域不在托管留存的保全中 ⇒ 维护拍(`REAP_INTERVAL_SEC`)经删除协调器删除
|
|
807
|
+
(每拍至多 64 只 / 5 s,跨拍轮转;每删一只一行 `session_aged_out`,计数 `sidechain_sessions_aged_out_total`,跳过按理由计 `sidechain_age_out_skipped_total{reason}`)。之后按 id 读 404。
|
|
808
|
+
`DB_BACKEND=memory` 记不了种类:能力位 `[]`,带键提交 `400 request.precondition_unmet`。⚠️ SQL 两后端的活引用判(老化与托管留存同一句)读 `workflow_run` 表:显式 `WORKFLOW_RUN_STORE=file` / `memory` 的 SQL 部署上,workflow 记录不在那张表里,会话发起的在跑 workflow 护不住它(缺省 `auto` 用 SQL 孪生,不受影响)。
|
|
774
809
|
- **任务清单(TaskCreate/TaskList 家族)的持久边界**:清单按**会话**分区,同一会话
|
|
775
810
|
跨 turn/跨 resume 连续,跨会话互不可见。配了 SQL 后端(`SESSION_BACKEND=mysql` / `DB_BACKEND=pg`)
|
|
776
811
|
时落 `task_list_meta`/`task_list_item` 两表 ⇒ **跨副本、跨重启都续得上**;**没有 SQL 后端的形态
|
|
@@ -940,7 +975,7 @@ MODEL_CASCADE_LADDER=deepseek-flash,deepseek-pro # 目录里的模型名,cheap
|
|
|
940
975
|
- `WORKSPACE_FILE_MAX_BYTES` 随面转 INERT(值仍收下并校验,center 推送兼容;不再有任何效果)。
|
|
941
976
|
- rewind 的新姿势:提交带 `resumeAt` + `restoreFiles: true`(或 code-only 的 `rewindFilesTo`)⇒
|
|
942
977
|
引擎把**本会话跟踪集**收敛到该消息时刻的边界;`acceptPartialRestore: true` 容忍部分恢复
|
|
943
|
-
(缺省=响亮失败带逐文件账本)
|
|
978
|
+
(缺省=响亮失败带逐文件账本)。`rewindFilesTo` 不与 `cascade: true` 同体(梯级每一级在现铸的会话里跑、没有这只会话的历史)⇒ 受理时 400 `request.field_conflict`,梯子一级都不起;去掉其一重提。旧键 `rewindFiles` 已不在提交面上:fresh 提交带它 ⇒ 400 `request.body_shape`
|
|
944
979
|
(`unknownKeys` 点名它;捕获不需要请求,还原写 `resumeAt` + `restoreFiles: true`);盘上旧任务体里的它零读者。
|
|
945
980
|
- rewind 与设备车道(`REMOTE_EXEC=device`):带 `resumeAt` 的那一发是**根提交**(不是续跑一族),`deviceId` 照收、按根提交的规矩判 —— 已绑:缺席 = 沿用 / 同 = 幂等 /
|
|
946
981
|
异 = 403 `device.identity_mismatch`(rewind 不换设备,换设备走显式换绑);未绑:携 = 首绑、缺席 = 409 `device.not_bound`;非 device 车道携它 = 400 `request.precondition_unmet`。
|
|
@@ -960,7 +995,7 @@ MINIO_ACCESS_KEY=… MINIO_SECRET_KEY=… # 可选 MINIO_REGION;外接 S3
|
|
|
960
995
|
S3_PUBLIC_ENDPOINT=https://files.example.com # 用户可达的 S3/MinIO 公网 base(反代必须透传 Host——SigV4 绑定 Host)
|
|
961
996
|
S3_PUBLIC_BUCKET=sema-public # 永久轨匿名 GET 桶(默认 sema-public)
|
|
962
997
|
SESSION_SNAPSHOT_BUCKET=session-snapshots # 限时轨私桶(与 snapshot 面共用;sendfile/ 前缀内隔离)
|
|
963
|
-
SEND_USER_FILE_URL_TTL=0 # 缺省 ttl 秒:0=永久(默认);1..604800
|
|
998
|
+
SEND_USER_FILE_URL_TTL=0 # 缺省 ttl 秒:0=永久(默认);1..604800=限时签名链接;其余(超限 / 不是十进制整数:1h、-5、3600.5、1e3)起服拒
|
|
964
999
|
SEND_USER_FILE_SANDBOX_PUT_ENDPOINT=… # 可选:沙箱直传 PUT 的端点(默认=S3_PUBLIC_ENDPOINT;
|
|
965
1000
|
# k8s 集群内 pod 可指内网 MinIO 省公网带宽)
|
|
966
1001
|
```
|
|
@@ -968,6 +1003,7 @@ SEND_USER_FILE_SANDBOX_PUT_ENDPOINT=… # 可选:沙箱直传 PUT 的端
|
|
|
968
1003
|
- **🔴 云形(`DB_BACKEND=mysql|pg`)快照 blob 强制对象存储(1.295+,clay 拍)**:缺 MinIO 三键 ⇒ **boot 拒启**——单行 SQL blob 写会撞 TiDB `txn-entry-size-limit`(默认 6MiB,真库实测矮墙)/ mysql 协议 `max_allowed_packet`,大字节归对象存储(与 D-1 附件面同裁定)。单机/测试台显式逃生:`SNAPSHOT_BLOB_ALLOW_SQL_BYTES=true`(SQL 店此时带 per-blob 帽,MySQL 协议(InnoDB 与 TiDB)默认 = **写入那条数据库连接**报的两堵已知墙取最小:单行上限减 1 KiB(blob 行自己的余量:哈希键 + 长度 + 时间戳;TiDB 才有)与包墙 `max_allowed_packet` 扣 1 KiB 语句余量后折半(⌊(包墙 − 1 KiB) ÷ 2⌋:文本协议把 blob 写成十六进制,语句至少是它的 2 倍);任一读数读不出时按该库族文档缺省并留一行运维日志 `fail_open`(tag `server.sql.packet-cap-unread` / `server.sql.tidb-row-cap-unread`),超限 PUT 413 `blob_too_large_for_sql`,句子按帽的出处分三形(运维旋钮 / 库报的墙 / 读不出而按文档缺省假定的墙),机读位 `wallSource` 同词 `operator` / `reported` / `assumed`。包墙是每条连接自己的会话值(7.133.0 起按连接判):DBA 调大 `max_allowed_packet` 之后,池里的旧连接在它第一次按包墙拒 blob 时自换(运维日志一行 `sql_connection_packet_wall_stale`,那一笔在新连接上重判),不必重启副本;`GET /v1/diagnostics/wiring` 的 `sqlEngine.maxRowBytes` / `sqlEngine.maxPacketBytes` 是最近一次初始化的那条连接的读数;帽可用 `SNAPSHOT_BLOB_SQL_MAX_BYTES` 按部署真实限值覆写,两方言生效;pg 默认无帽)。
|
|
969
1004
|
- **per-file rewind 历史的边界上限**(与 workspace 浏览面同一个整树快照纪元退役批留下的保留条款):`FILE_HISTORY_RETENTION_KEEP` —— 每个 scope(会话)存活的**最新** boundary 数,**每次 boundary 提交后自剪**(最旧者先亡,刚提交者恒存活;失引用的版本行级联删,blob 字节走异步 grace 窗 GC;v1 基线永存)。未设=core 缺省 **100**(由 core 的 `resolveFileHistoryRetention` 兑现,server 不复制那个数);`unbounded` 是**唯一**的「不剪」拼法(整店自剪关闭,GC 归部署自排 `reap`);`0`/负数/小数/非数 ⇒ **boot 拒启**(码 `config.retention_policy_invalid`,与 core 内置后端同码同判——**省略这个键不等于不剪**,它选的是缺省 100)。三条车道(TiDB / PG / local 文件店)同旋钮同判。⚠️ 升级即生效:存量超 100 boundary 的 scope 在下一次提交时被剪到 100;要保全量先写 `unbounded`。被剪 entry 的键**已花掉**(再次 snapshot 同 entry 典型拒,不复铸)。排序=DB 分配的 per-scope 发布序号 `file_history_boundary.publish_seq`(不是墙钟):**自 7.50.x 有存量 `file_history_boundary` 的部署升级本版会在 boot 期被 `assertFileHistorySchema` 拒启,拒因打印这张表缺的列的 `ALTER TABLE … ADD COLUMN …`,由部署者自己执行**(列集对账与拒启句只打印语句、永不改库;per-file rewind 历史照留,会话与其他持久面不动)。⚠️ `publish_seq` 是 `NOT NULL` 且无缺省的列(要值列:已有行的值只有部署者知道),拒启句对它打印**三步配方**而不是一句 ADD COLUMN:先 `ADD COLUMN publish_seq BIGINT;`(可空加列),再一行 `-- ` 注释(回填 `UPDATE file_history_boundary SET publish_seq = … WHERE publish_seq IS NULL;`,值由部署者按 per-scope 的发布顺序补;注释行不会被误执行),最后收紧(PostgreSQL `ALTER COLUMN … SET NOT NULL`;MySQL 协议先开 `STRICT_ALL_TABLES` 再 `MODIFY COLUMN`)。打印的语句全部生效之前起服一直拒 —— 只执行了第一句(列已在、仍可空)同样拒,并只再给后两步;空表上打印的语句逐字全部可执行。
|
|
970
1005
|
- **会话同步重推(同图)要读 blob**(7.136.0 起):`POST /v1/sessions/:id/sync/import` 的 identical 重推臂,对云端「已握着同一张文件历史图」的目标,也先把信封引用的每一枚 blob 经云端自己的店读一遍、核哈希(不回写),再答成功 —— 对象存储里的对象若在图发布之后丢了,这一腿答 `422 missing_blob`(`PUT` 缺的 blob 再推;图不动),不再答 `200 identical`。代价:无变化会话的频繁重推多付对象存储读流量(每枚引用的对象一次下载,正比于引用的 blob 字节);没有旋钮。
|
|
1006
|
+
- **会话同步的文件历史 blob 按落点可见**(7.152.0 起;SQL 后端):一枚 blob 只对「这只会话的历史图引用它(会话在时)」或「在这只会话 id、同一调用方身份下 `PUT …/sync/blobs/:hash` 传过它」的推送 / 拉取可见 —— 别的主体 / 别的会话传过的同一份字节不让你的推送过预检(`422 missing_blob`,与谁都没传过同答),也读不出来(`404 not_found.blob`)。字节仍全局去重一份;「谁传过」记在 `file_history_blob_grant`(起服自建,随会话删除清,收割腿在 blob 孤儿回收的 1 h 宽限之后清掉没导入的上传,还记着的上传不当孤儿回收)。客户端照契约在第一阶段之前逐枚 `PUT` 即不受影响;上传与导入身份不同、或相隔超过 1 h,会多一轮 422 → 补 `PUT`。升级之前已写进图的引用维持原样,核查跨属主共享的 blob 用 MIGRATION 7.152.0 节那一句只读查询。
|
|
971
1007
|
- **文件历史捕获总开关**(7.97.0 立,7.104.0 改语义):`FILE_HISTORY_CAPTURE`(缺省 `true`;布尔词表 true/false/1/0/yes/no/on/off,未知词 ⇒ boot 拒启;TiDB / PG / local 三条车道同义)。`false` ⇒ **只关捕获**:历史店照接,引擎拿到部署捕获位 `RunnerDeps.fileHistoryCapture: "off"`,改动文件的首次快照**一个都不捕获**、不铸回合边界(`wiring_manifest.fileHistory` 报 `"disabled"`);**已存历史照常可用** —— `resumeAt`+`restoreFiles` / `rewindFilesTo` 照常还原、2c session-sync 照常导出 / 导入。`GET /v1/capabilities` 的 `fileHistoryCapture` 报 `"off"`,而 `restoreFiles` / `rewindFilesTo` / `sessionSync` 仍为 `true`(缺省部署报 `"on-optional"` = 捕获中且请求可按 run 关掉,见上一段)。🔴 **7.97.0–7.103.x 的旧语义**:`false` = 不把店交给引擎,连已存历史也读不了(还原走 `rewind.store_unconfigured`、sync 501)—— 把本旋钮当成「整个文件历史功能关掉」来用的部署,升级后已存历史**重新可以被还原 / 同步**。要让已存历史也不可用,今天的出路只有**逐会话** `DELETE /v1/sessions/:id`(擦除面不受本旋钮管)与 SQL 后端的留存清扫(`RETENTION_MODE=enforce` + `RETENTION_MAX_AGE_DAYS` + `RETENTION_SWEEP_INTERVAL_SEC`,按会话年龄删,local 车道没有留存车道);**没有**「整库历史一键不可用」的旋钮。⚠️ **关掉 ≠ 删掉**:翻旋钮不批量删除存量历史;删会话照删已捕获的历史(三条车道同读:local 车道自 7.146.0 / 引擎 7.64.0 起也走整会话清理动词 —— 边界、版本记录、v1 基线与只被这只会话引用的 blob 一起删;此前 local 走 `reap`,v1 基线留存)。关着时 `FILE_HISTORY_RETENTION_KEEP` 没有效果(不再有边界提交,自剪不会触发),值仍照常校验。没有存储后端的部署(env-only worker)本来就没有历史店,旋钮在那里无事可关、不下发捕获位(引擎对「off 但没店」拒 prepare)。
|
|
972
1008
|
- **🔴 公桶策略必须 GetObject-only**:`mc anonymous set download` 会**连带打开 ListBucket**——匿名 `GET /<bucket>/?list-type=2` 能枚举全部不可猜 key,能力链接设计即告失效。正确姿势=`mc anonymous set-json`,policy 只含 `Action:["s3:GetObject"]` on `arn:aws:s3:::<bucket>/*`(验证:对象 GET 200、桶 LIST 403)。
|
|
973
1009
|
- **两条轨**:ttl=0(默认)→ 匿名 GET 公桶下 `uuidv7/<name>` 不可猜 key,链接永久、可回收(删对象);0<ttl≤7 天 → 私桶 + SigV4 限时签名链接(7 天是 SigV4 物理上限,更久用 ttl=0)。
|
|
@@ -993,6 +1029,9 @@ SEMA_WEB_ADMIN_TOKEN=<SERVICE_PULL_TOKEN 的值> # 取自配置控制面主机
|
|
|
993
1029
|
# 🔴 拒启两形:内容读不成([config.center_credential_malformed]:`{` 开头坏 JSON / 信封多键缺键 /
|
|
994
1030
|
# issuer 非 http(s) / 裸行不是令牌)、多租户(REQUIRE_PRINCIPAL=true)读到信封
|
|
995
1031
|
# ([config.center_credential_user_session_multi_tenant])。运行期同形 = 该次取值 fail-closed + 一次 warn。
|
|
1032
|
+
# SEMA_WEB_ADMIN_ASSERTION_TOKEN=<wat_…> # 7.151.0:web-admin 断言令牌(编排器给配了凭据库的受管引擎注入;手接引擎改用 SEMA_WEB_ADMIN_ASSERTION_TOKEN_FILE,
|
|
1033
|
+
# 两键二选一、都设=拒启,与上面那一对同一只判官)。本版只读声明:GET /health 的 center.assertionToken 答 declared / absent,
|
|
1034
|
+
# 起服一行 center_assertion_token;不读文件内容、不向中心出示。它是本服务自有凭据,宿主子进程环境里扣掉。
|
|
996
1035
|
# CENTER_CREDENTIAL_RENEW_LEAD_MS=300000 # 续签提前量(ms;缺省 5 min)。0 = 关续签、只读信封(壳负责续);其余须为 [8000, 1800000] 内整数,
|
|
997
1036
|
# 坏值拒启。续签成功 info center_credential_renewed;真失效(refresh token 已作废)warn
|
|
998
1037
|
# center_credential_renew_failed 一次 + /health.centerCredential.renewal.state=failed,到期后中心请求
|
|
@@ -1046,8 +1085,9 @@ FLEET_ADVERTISE_ADDRESS=http://<本机可达IP>:8090 # 可选:设了才启公
|
|
|
1046
1085
|
# warn fleet_announce_reply_unreadable)。只有显式的 capabilities 对象是中心的声明。
|
|
1047
1086
|
# FLEET_SCOPE=acme # 7.121.0:本引擎所在的**租户 scope**(配置渲染器对每台受管引擎写,缺省 scope 也写 = 它的 per-worker 令牌绑的 scope)。缺席 =
|
|
1048
1087
|
# 缺省 scope global;在场必须是 scope id 形(小写字母 / 数字 / 内部连字符,1–64;空串拒启
|
|
1049
|
-
# config.fleet_scope_invalid)。与 FLEET_GENERATION
|
|
1050
|
-
# 请求不带 scope 读成 global
|
|
1088
|
+
# config.fleet_scope_invalid)。与 FLEET_GENERATION 不联动。两处读同一个值:① 排空口的身份比对(请求的 scope 与它比,
|
|
1089
|
+
# 请求不带 scope 读成 global);② 7.151.0 起 fleet 成员(设了 FLEET_GENERATION)上的登录令牌准入 —— 令牌验过签而
|
|
1090
|
+
# scope 不等于它 ⇒ 整次请求 403 auth.scope_mismatch(/health 不拒;非成员不比对;没有旋钮)。续租体与心跳不带它(scope 由中心凭证绑定)。
|
|
1051
1091
|
# FLEET_LEASE_OUTAGE_MAX_MS=86400000 # 7.121.0:一台实例**活着而不服务的最长时长**(缺省 24 h;< 60000 / 0 / 非整数拒启)。两处读它:
|
|
1052
1092
|
# ① 服务租约中心不可达的容忍上限 —— 租约过期(中心不可达 / 答 unknown)后照常服务,过期满这么久 ⇒
|
|
1053
1093
|
# 新工作 503 state.lease_expired(Retry-After 60;取消 / HITL 应答 / 续跑 / 读面照放行,在飞不动,
|
|
@@ -1138,32 +1178,27 @@ QUESTION_TTL_MS=300000
|
|
|
1138
1178
|
要在活流腿上保留旧的自答续跑行为,目前的办法是把该请求改走 `/v1/tasks`(非流)或 `/v1/runs`,
|
|
1139
1179
|
或带上 `x-detach-on-disconnect: true`。
|
|
1140
1180
|
|
|
1141
|
-
**流内审批协议(`approval_request` 帧族)——
|
|
1181
|
+
**流内审批协议(`approval_request` 帧族)—— 十个调优钮(没有总开关)**
|
|
1142
1182
|
|
|
1143
|
-
> 🔴
|
|
1144
|
-
>
|
|
1145
|
-
>
|
|
1146
|
-
>
|
|
1147
|
-
>
|
|
1148
|
-
> `streamApproval` 为真)只发 `approval_request` / `approval_complete` / `approval_revoke
|
|
1149
|
-
>
|
|
1183
|
+
> 🔴 **7.152.0 起没有总开关**:协议上不上场只看这台 worker 的装配 —— **审批席(`TOOL_APPROVAL_ENABLED`)∧ store backend ∧ park 设施在场**
|
|
1184
|
+
> (`DURABLE_APPROVAL=true` + checkpoint 能力的 backend)。三项任一不成立 ⇒ 起服不装审批席:零帧、零卡(审批席开着而后两项缺一 ⇒ 启动一行 warn
|
|
1185
|
+
> `approval_cards_unavailable` 说出缺哪项),受门调用的终局归引擎(有 park 设施 ⇒ 停驻;否则当场拒)。旧总开关 `STREAM_APPROVAL_ENABLED` 已退役:部署 env 里留着它(任何值)⇒ **拒启**
|
|
1186
|
+
> (契约包墓碑,拒句带 `config.env_key_retired`、点名这一键,不回显值),出路 = 删掉这一键 —— 它的「关」是回退发旧族卡,旧族已经没有了。
|
|
1187
|
+
> 壳/SDK 不实现呈卡族的消费就等于用户看不到审批卡。🔴 **只有一个帧族**:呈卡的 worker(`GET /v1/capabilities` 的
|
|
1188
|
+
> `streamApproval` 为真)只发 `approval_request` / `approval_complete` / `approval_revoke`;旧族 `tool_approval` / `tool_approval_complete`
|
|
1189
|
+
> 不再出现在任何流上。帧格式、消费端契约、五合取全表在
|
|
1150
1190
|
> 契约 §4a-quint(内部记录;错误码 `feature.approval_ask_disabled` 在契约附录 A)。
|
|
1151
|
-
> 🔴 **7.134.0 起卡只发给声明认得这一族的客户端**:提交体 `settings.approvalFrameFamilies:
|
|
1152
|
-
>
|
|
1191
|
+
> 🔴 **7.134.0 起卡只发给声明认得这一族的客户端**:提交体 `settings.approvalFrameFamilies: "approval_request"[]` 声明这条 run 的客户端
|
|
1192
|
+
> 渲染得了这一族(7.152.0 起写 `"tool_approval"` ⇒ `400 request.field_invalid`);一条 run 只在声明含 `GET /v1/capabilities` 顶层 `approvalFrameFamilies` 那个词时收到活卡。缺席 / 不含 ⇒ 这条 run 不呈卡(不换族、不双发)、
|
|
1153
1193
|
> 开流不重放挂着的卡,每只审批问(会话里已记住的放行照旧先兑现)当场收场,结局看这台 worker 有没有耐久店(`DURABLE_APPROVAL` 开着):在场 ⇒ 交 `UNATTENDED_APPROVAL_POLICY`:`park`(缺省)⇒ 任务停驻、`/v1/approvals/:sessionId/decide` 作答;`deny` ⇒ 当场拒,拒因句点名缺的族与出路;
|
|
1154
1194
|
> 不在场(`DURABLE_APPROVAL=false`,含 helm 图表关持久的形)⇒ 受门工具当场拒(缺省 `park` 政策下是引擎按 `approver_unavailable` 拒,结算当事方是「无人」,不是 `deny` 政策的结算,拒因句不点名缺的族与声明键;`deny` 政策下是部署政策拒)、run 跑完、无卡无 `/decide`(对 7.133.x 是有意的行为收窄:那类 worker 原本出活的 `tool_approval` 卡);两形都不出任何一个族的卡。
|
|
1155
|
-
> 运维日志 `approver_unavailable` 的 `arm` 是 `frame_family_undeclared
|
|
1195
|
+
> 运维日志 `approver_unavailable` 的 `arm` 是 `frame_family_undeclared`。
|
|
1156
1196
|
> 续跑读持久化的提交体(声明随体重放);耐久事件流 `GET /v1/runs/:id/events` 的开流重放只列这条 run 名下的卡,声明由卡作证(没有通道的腿一张卡都不落;7.135.0 起不读落盘的声明,run 跑完之后名下仍在窗内的卡照样重放);与同步流开流共读同一只判据函数,入参不全对称:关窗臂里「贴 deadline ⇒ `window_zero`」由 sync 腿判,事件流只按窗判。坏形(非数组 / 词表外 / 重复)⇒ `400 request.field_invalid`(`field` / `reason: "bad_entry"` / `index`)。
|
|
1157
1197
|
> 受理位 `taskSettings.approvalFrameFamilies`(恒真;老 server 对这个键 `400 request.body_shape` —— 见位才发)。读法全文在契约 §0.58。
|
|
1158
1198
|
|
|
1159
1199
|
```bash
|
|
1160
|
-
#
|
|
1161
|
-
#
|
|
1162
|
-
# 回滚键是下面的 UNATTENDED_APPROVAL_POLICY=deny(两根旋钮正交,别当一根用);它也**不**再回滚窗长
|
|
1163
|
-
# (窗是活卡件不是协议件,见下一键——缺省值与旧硬编码窗同为 300000,没配过就仍然字节不变)
|
|
1164
|
-
STREAM_APPROVAL_ENABLED=true
|
|
1165
|
-
# 活卡窗(毫秒)。**辖域=所有腿**:协议上不上场都按它计窗——无 checkpoint 店 / 关了协议的部署同样
|
|
1166
|
-
# 生效(此前那几形上本键一个字节都不生效、窗恒 5min,且没有任何一行说出来)。
|
|
1200
|
+
# (协议总开关 STREAM_APPROVAL_ENABLED 已退役:设了任何值即拒启,删掉它。要回到「窗满即拒」配 UNATTENDED_APPROVAL_POLICY=deny。)
|
|
1201
|
+
# 活卡窗(毫秒)。**辖域=呈卡的每一条腿**(窗是活卡件,缺省值与旧硬编码窗同为 300000,没配过就仍然字节不变)。
|
|
1167
1202
|
# 🔴 **缺省值是 posture 派生的,不是一个数**:单机 turnkey(`REQUIRE_PRINCIPAL` 未设)=
|
|
1168
1203
|
# **86400000(24 小时)**,多租户形 = 300000(5min)。**7.81.0 起这根旋钮在单机上是要读的那一根**:
|
|
1169
1204
|
# local 后端自此有持久 ask 账、流内协议上场,受门 ask 先发一张活卡、**窗满才转 park**(升级前是铸造
|
|
@@ -1216,10 +1251,10 @@ UNREACHED_ASK_TTL_MS=3600000
|
|
|
1216
1251
|
**同一条不变量对悬挂窗再判一次**(7.52.0 案A):`UNREACHED_ASK_TTL_MS + STREAM_APPROVAL_ADHOC_GRACE_MS`
|
|
1217
1252
|
同样必须严格小于 `STREAM_APPROVAL_ORPHAN_TTL_MS`(悬挂行的 `expiresAtMs ≈ 创建 + 悬挂窗)。两条分开判
|
|
1218
1253
|
是为了让拒启文案点得出**是哪一个键**破了不等式;默认值(1h + 60s vs 7d)自然满足。
|
|
1219
|
-
⚠️
|
|
1220
|
-
`
|
|
1254
|
+
⚠️ 悬挂窗这一条**不是无条件**:门挂在「这台部署会不会铸出悬挂行」上,两形豁免(配置期可知)——
|
|
1255
|
+
`TOOL_APPROVAL_ENABLED=false`(协调器不构造,
|
|
1221
1256
|
core 走 headless 缺省,零 ask 行)、`UNATTENDED_APPROVAL_POLICY=deny`(零活流的 ask 铸造时刻即拒,
|
|
1222
|
-
悬挂路径结构上不可达)
|
|
1257
|
+
悬挂路径结构上不可达)。两形下该键即使与短 orphan TTL 组合也照常起服 —— 一批从未选择本能力的既有
|
|
1223
1258
|
部署不因升级引入的 1h 缺省当场拒启。上一条(`STREAM_ASK_WINDOW_MS` 版)保持**无条件**,与既有行为逐字一致。
|
|
1224
1259
|
- **断连时活卡怎么办**:客户端**优雅断开**(server 收到 socket close)时,流内未决 ask
|
|
1225
1260
|
立即强转 durable park(7.16.0 起),恢复后 attach 重放会重呈卡。客户端**网络中断**(TCP half-open,
|
|
@@ -1227,26 +1262,18 @@ UNREACHED_ASK_TTL_MS=3600000
|
|
|
1227
1262
|
耗尽(十几分钟量级)才感知——这段时间内真正的兜底是**活卡窗到期转 park**(`STREAM_ASK_WINDOW_MS`,
|
|
1228
1263
|
默认 5min),所以把窗改大等于把断连场景的最坏无人区拉长,改小前先看上面的跨旋钮不变量。half-open 的
|
|
1229
1264
|
主动探测(写水位判死)在攻关排期。
|
|
1230
|
-
- **无 durable 前置的部署(
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
(启动一行 `
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
「此刻无人可答」,见上面的 `UNATTENDED_APPROVAL_POLICY`;结局不变,拒绝理由的文案更准确。)要「断连也不丢决策」的语义,配齐 durable 前置(持久 store + `DURABLE_APPROVAL=true`)。
|
|
1237
|
-
⚠️ **这条腿上的窗照样是 `STREAM_ASK_WINDOW_MS`**:此前它被硬编码成 5min、旋钮在这些部署上
|
|
1238
|
-
静默无效(慢组场景只能真等满 5 分钟);现在调它就是调这条腿。另:这类部署上**迟到决议**
|
|
1239
|
-
(卡挂过窗、人才按 Yes)不能走 `POST /v1/tool-approvals/:id/respond`(没有持久 ask 行 ⇒ 恒 404
|
|
1240
|
-
`not_found.ask`;7.147.x 及以前 `tool_approval.not_pending`、不带 `cause`),要走 `POST /v1/approvals/:sessionId/decide`
|
|
1241
|
-
——前提是配了 `DURABLE_APPROVAL=true`(local 车道有文件形 checkpoint 店),否则窗到期即 fail-closed 拒。
|
|
1242
|
-
⚠️ **上面这段「没有持久 ask 行 ⇒ 恒 404」自 7.81.0 起不再适用于 `DB_BACKEND=local` 本身**:local 的
|
|
1243
|
-
ask 账已是文件形,配齐 park 设施的单机部署上迟到决议走 `respond` 的赎回席是通的;本段现在只说
|
|
1244
|
-
那几条**真的**不上场的部署形(无 backend / 无 checkpoint 能力 / 显式关协议)。
|
|
1265
|
+
- **无 durable 前置的部署(三项任一不成立:审批席 / store backend / park 设施;`local` backend 有文件形 ask 账,配齐
|
|
1266
|
+
`DURABLE_APPROVAL=true` + checkpoint 店的单机部署上协议照常上场)**:7.152.0 起不装审批席 —— 没有卡、没有活登记,
|
|
1267
|
+
受门调用的终局归引擎:审批席关而有 park 设施 ⇒ 照常 durable park(经 `POST /v1/approvals/:sessionId/decide` 作答);审批席开而无
|
|
1268
|
+
store backend / 无 park 设施 ⇒ 引擎的无审批席臂当场拒(启动一行 warn `approval_cards_unavailable`),有问行的卡的两扇口
|
|
1269
|
+
(决断口 `POST /v1/tasks/:taskId/asks/:askId/decision` / 按问读口 `GET /v1/tasks/:taskId/asks/:askId`)答 `501 feature.approval_ask_disabled`。要「断连也不丢决策」,
|
|
1270
|
+
配齐 durable 前置(持久 store + `DURABLE_APPROVAL=true`)。(7.151.x 及以前这类部署呈旧族活卡、窗满 fail-closed 拒;旧族已退役。)
|
|
1245
1271
|
默认值(300s + 60s vs 7d)自然满足,只有显式改坏才会撞上。
|
|
1246
1272
|
- **调参方向**:想让人有更长时间点审批卡 → 调大 `STREAM_ASK_WINDOW_MS`;卡太多刷屏 → 调小两个 `ADMIT_MAX_*`
|
|
1247
1273
|
(代价是超限的 ask 走 park,要有人去审批队列捞);库压大 → 调小 `STREAM_APPROVAL_RECONCILE_BATCH`
|
|
1248
1274
|
(代价是收敛变慢,靠队列轮转保证下轮接着扫)。
|
|
1249
1275
|
- **停驻行最长活多久(local 文件后端与 SQL 店同一公式)**:一张 pending 的 checkpoint 行在 `max(createdAt + APPROVAL_TERMINAL_BACKSTOP_MS, deadline + 1h)` 到点后由后台 reaper(每 `REAP_INTERVAL_SEC`,缺省 60 s 一拍)expire;`deadline` 只在配了审批 SLA / TTL 时有,没配就是 `createdAt + 后备上限`。旋钮缺省 30 天、下钳 60 s、非有限值落缺省。到点的行先 expire,挂起的 run 行随后由 reaper 翻成 `failed`(`errorCode: approval.expired`)。所以「老停驻行在 local 后端最长活多久」= 后备上限(缺省 30 天)+ 最多一拍;要缩短就调 `APPROVAL_TERMINAL_BACKSTOP_MS`(两店同辖)。
|
|
1276
|
+
- **workflow 停驻卡在多副本上的决断(7.151.0 起;`REAP_INTERVAL_SEC` 是它的跨副本生效延迟)**:持有这张卡的 run 读作 `running` 期间,任一副本上的 `/decide` 先把决定落成一条耐久决定行(落在那条 run 的记录行锁里,同一张卡先受理的决定立住,另一个决定答 409 `decide.claim_lost`),答 200 `{taskId: <workflow run id>, status: "resuming"}`,不起宿主一跑;跑那条 run 的进程恰是受理的那一只 ⇒ 当场交给引擎,否则跑它的进程在下一个维护拍(每 `REAP_INTERVAL_SEC`,缺省 60 s;每拍至多 64 条、墙钟预算 5 s,超出的轮到下一拍)把行交给 run。run 先收场 ⇒ run 的完成送达把行交给宿主会话的下一跑(服务端起的一跑:以卡属主为主体,宿主停在 `task_done` 卡上时那张卡的属主必须是同一个,付费方两门照判、拒即不起(中心不可达 ⇒ 下一拍重投);一行 `workflow_park_handoff_refused` + `workflow_park_handoff_total{result}` 计数,行留着、卡可再决)。没有新旋钮:要更短的跨副本生效延迟就调低 `REAP_INTERVAL_SEC`(同一拍的其余各腿一起变快,库读一起变多)。持有进程死掉而记录仍读作 `running` ⇒ 要等孤儿窗(`WORKFLOW_ORPHAN_GRACE_MS`,缺省 24 h)翻 `failed` 后才交出;记录收场了而终态记录没写进去同等(完成留着待恢复扫);`WORKFLOW_RUN_STORE=memory` 没有完成日志 —— 要重投的转交不重投,一行 `workflow_park_handoff_not_redelivered`,决定由宿主会话的下一跑带或再决。
|
|
1250
1277
|
- **SQL 店写停驻行的预判与 SLA 拒扫的取行序(7.136.0 起)**:`put` 先看这份检查点放不放得进索引列 —— 没有 `gate` / `pendingAction` 对象,或门上卡词的 UTF-8 **字节**数超过 `approval_card` 列的容量(MySQL 协议 `TEXT` 65,535 字节;PG 无上限),抛 `CheckpointIndexRefusedError`(`err.refusal.kind` 为 `unreadable` / `card_too_long`),一句 SQL 都不发 —— 严格与非严格 sql_mode 的库都一样,不会落成半只卡词;引擎自己铸的检查点不会触发。SLA 拒扫每拍至多取一页(100 行),取行序是到期时刻(同刻按行键);拒扫按页**轮转**走全部到期审批 —— 每拍从上一拍取到的最后一行之后接着取,一页取不满就回到队首(local 文件后端同律)。所以一页每拍都被拒的行(引擎认领前拒、停驻子代、本版不重放的存量体、混跑窗里旧副本停驻的问答行……)挡不住排在后面的到期审批:到期审批数为 N 时一圈走 ⌊N/100⌋ + 1 拍(最后一拍取到的不满一页),每一张每圈被试一次;一行的存体读法抛出只让这一行这一拍不续(运维日志 `deny_sweep_row_failed`)。
|
|
1251
1278
|
- **审批账本保留多久(`APPROVAL_ASK_RETENTION_MS`,缺省 `2592000000` = 30 天;local 文件后端与 SQL 店同一条律)**:审批在盘上有三本账 —— 问账(SQL 的 `approval_ask` / `approval_batch`,local 的
|
|
1252
1279
|
`<数据根>/approval-asks/asks.jsonl`)与 local 审计账(`<数据根>/approval-ask-audit/ledger.jsonl`,`GET /v1/approvals` 的 `crashConverged` 读它)。一问**结了**且它最后一次动静早于
|
|
@@ -1299,10 +1326,8 @@ UNATTENDED_APPROVAL_POLICY=park
|
|
|
1299
1326
|
- 纯部署级:**不看**客户端的任何表态/权限模式。协调器整体关掉(`TOOL_APPROVAL_ENABLED` 关)时这个旋钮
|
|
1300
1327
|
没有施加对象。`APPROVAL_REQUIRE` 名单只决定「这只工具要不要审批」,与本旋钮无关;协调器在场时,名单工具的
|
|
1301
1328
|
审批与其余 ask 走同一条路、同一个政策(`deny` 部署上同样当场拒)。
|
|
1302
|
-
- 🔴
|
|
1303
|
-
|
|
1304
|
-
不是 server 的 ask 行,「有 durable 设施但没开协议」正是「窗到期走 park」要救的那类部署)。要回到旧的「窗满即拒」
|
|
1305
|
-
就配 `UNATTENDED_APPROVAL_POLICY=deny`。
|
|
1329
|
+
- 🔴 **回到旧的「窗满即拒」只有这一根旋钮**:配 `UNATTENDED_APPROVAL_POLICY=deny`(曾经的协议总开关 `STREAM_APPROVAL_ENABLED` 已退役,
|
|
1330
|
+
设了即拒启;它从来不回滚「窗到期走 park」—— park 的承载是引擎的 checkpoint,不是 server 的 ask 行)。
|
|
1306
1331
|
|
|
1307
1332
|
**「本会话不再询问」对引擎的问也生效(7.106.0 起)**
|
|
1308
1333
|
|
|
@@ -1943,7 +1968,8 @@ invalid_using_default` 警告 + 退回缺省值」这条臂随词表放宽一并
|
|
|
1943
1968
|
所以它只在「worker 盘就是调用方的盘」时挂 —— host 车道、未设 `REQUIRE_PRINCIPAL=true`(多主的 host 部署本来就拒启)。PATH 上有对应的
|
|
1944
1969
|
language server 就用,没有就优雅退回 grep / read;`LSP_HOST_ENABLED=false` 关掉。**其余车道没有 LSP**:e2b / k8s / local-docker / ssh / adb /
|
|
1945
1970
|
device / none 一律不挂,模型名册里没有 LSP 工具、`wiring_manifest` 上没有 `lsp` 段,代码导航用 grep / read。服务入口与 `run-local` 同一条律。
|
|
1946
|
-
沙箱车道的 LSP 桥已删除(7.127.0
|
|
1971
|
+
沙箱车道的 LSP 桥已删除(7.127.0 起它本来就挂不上:引擎只读执行环境「绑定」的那只文件,当时沙箱车道不实现绑定读;今天沙箱车道的绑定读是逐答重绑,
|
|
1972
|
+
LSP 挂不挂照旧只看上面那一条律,沙箱里的语言服务器要另一条传输);它的开关 `LSP_ENABLED`
|
|
1947
1973
|
是墓碑(上表),设了任一值都拒启,空串按未设。e2b 模板里烤的语言服务器只是工具链内容(模板的月检只验它们在不在,不验有没有谁在驱动它们)。
|
|
1948
1974
|
|
|
1949
1975
|
**host 腿语言服务器拿到的环境 + 点名放行 `LSP_ENV_ALLOW`(7.101.0 起)**:host 腿的语言服务器是本机子进程,它拿到的环境
|
|
@@ -1980,9 +2006,9 @@ device / none 一律不挂,模型名册里没有 LSP 工具、`wiring_manifest`
|
|
|
1980
2006
|
|
|
1981
2007
|
**请求级 `inheritEnv`(7.106.0 起)—— 调用方声明,不是部署旋钮**:提交体顶层键 `inheritEnv:"all"` 让**这一条请求**的模型驱动 host shell
|
|
1982
2008
|
继承整份用户环境(CC 交互形,用户自己的凭据形变量在内)—— 🔴 **但不含本服务自己的凭据**(7.129.0 起,引擎 7.51.1):配置目录全部 `type:"secret"` 名
|
|
1983
|
-
(`SERVICE_AUTH_TOKEN(S)` / `APPROVAL_HMAC_KEYS` / `MODEL_API_KEY` …)与名单型旋钮名起服已向引擎声明为本进程自有凭据,生效配置里每条模型条目的 `apiKeyEnv` 也在名单里
|
|
2009
|
+
(`SERVICE_AUTH_TOKEN(S)` / `APPROVAL_HMAC_KEYS` / `MODEL_API_KEY` …)、bake-runner 的 bearer `BAKE_RUNNER_TOKEN`(7.151.0 起;runner 进程自己的凭据,不是配置目录行,三个进程同一份声明)与名单型旋钮名起服已向引擎声明为本进程自有凭据,生效配置里每条模型条目的 `apiKeyEnv` 也在名单里
|
|
1984
2010
|
(中心热应用新增 / 改名条目时在模型目录换代前重声明,名单只随落地的世代增长 —— 改名后旧名照扣到重启,没落地的候选不留痕;条目的 `apiKeyEnv` 是引擎扣不住的名,或它点到的名正被某只名单型旋钮交给沙箱 / 语言服务器(见下文沙箱名单段)⇒ 该候选整拒),`"all"` = 整份环境**减**它们,任何继承词都不把它们
|
|
1985
|
-
交给模型 shell(能力位 `inherit_env.own_credentials_withheld` = 最近一次声明 ⊇ 当前生效配置应声明的集合;真要让模型 shell 持某枚令牌 ⇒ 放在引擎进程环境里一个不在配置目录、也不是任何模型条目 `apiKeyEnv` 的名下,配 `inheritEnv:"all"`;7.146.0 起请求 `settings.env` 不收凭据,见 9.5j);这些变量此刻装着的**每一枚凭据**也交给引擎按值扣 —— 整值,列表形另加每一枚:`SERVICE_AUTH_TOKENS` 表里的每一枚令牌、`APPROVAL_HMAC_KEYS` 里的每一把钥(7.149.0 起;此前只交整张表的原文,表里一枚令牌换个变量名放着照进模型 shell)——
|
|
2011
|
+
交给模型 shell(能力位 `inherit_env.own_credentials_withheld` = 最近一次声明 ⊇ 当前生效配置应声明的集合;真要让模型 shell 持某枚令牌 ⇒ 放在引擎进程环境里一个不在配置目录、也不是任何模型条目 `apiKeyEnv` 的名下,配 `inheritEnv:"all"`;7.146.0 起请求 `settings.env` 不收凭据,见 9.5j);这些变量此刻装着的**每一枚凭据**也交给引擎按值扣(名单型旋钮除外:它们的原文是一张变量名单,不是凭据,只按名扣、原文不交引擎比值 —— 7.151.0 起;此前名单原文也被当一枚凭据比值,`LSP_ENV_ALLOW=GOPATH` 这类短名单因此冒下面那行告警、把值能力位翻 false)—— 整值,列表形另加每一枚:`SERVICE_AUTH_TOKENS` 表里的每一枚令牌、`APPROVAL_HMAC_KEYS` 里的每一把钥(7.149.0 起;此前只交整张表的原文,表里一枚令牌换个变量名放着照进模型 shell)——
|
|
1986
2012
|
同值换名的副本同样进不了模型 shell(整串比:`Bearer <令牌>`、令牌多一个字符 / 少一个字符、只是系统名的值都不是副本,照交),引擎判某一枚「不是凭据值」(空白 / 占位词 / 一个字符重复 / 不足 8 字符)⇒
|
|
1987
2013
|
那一枚不按值扣(同一变量的其余几枚照扣,名照扣、不拒启,能力位 `inherit_env.own_credential_values_withheld` 答 false),起服与模型目录换代时每个这样的变量出**一条** warn 结构化行 `own_credential_value_not_withheld { name, reason }`
|
|
1988
2014
|
(`reason` 是引擎的拒句原文,从不回显值;起服第一步 logger 还没建时,这一行当拍以同一行形写 stderr,不缓冲;logger 接上之后——模型目录换代并进的条目的值被拒——这一行受 `LOG_LEVEL` 约束,`error` 级读不到,机读事实读上面那个能力位)—— 按事件名告警,给该变量一个真值即可。值是**网关密钥**(`MODEL_API_KEY` / `ANTHROPIC_API_KEY`,起服交给模型适配器的那一个)时也只有这一行:引擎在适配器构造口收下同一个值,声明口拒过的值它不再说第二遍(此前这里写的「另有引擎自己的一行裸文本」已不成立);给密钥一个真值这一行消失。`"scrub"` / 缺席 = 上面的缺省剥除。🔴 **`"all"` 只在单用户部署兑现**:`REQUIRE_PRINCIPAL=true`
|
|
@@ -2075,6 +2101,10 @@ bake-runner 要用 ⇒ `LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW` 点名放回。
|
|
|
2075
2101
|
> **装了中心鉴权桥(`SEMA_WEB_ADMIN_URL` 在位即默认开,或 `AUTH_BRIDGE_ISSUER`)就不是 dev-open**(7.132.0 起;此前这一形被读成 dev-open):带登录令牌的调用方按令牌里的身份钉人,
|
|
2076
2102
|
> 不带任何凭据的列表 `401 auth.unauthorized`、`/metrics` 族 `401`(要 `METRICS_TOKEN`)。仍成立的边界:没配 service token 的部署上,不带登录令牌的请求自报的主体头仍按身份读
|
|
2077
2103
|
> (与 `REQUIRE_PRINCIPAL` 无 token 形同读)—— 要让「没令牌就没有身份」成立,配 `SERVICE_AUTH_TOKEN`(全局凭据门:每个请求要么带 service token、要么带登录令牌)。
|
|
2104
|
+
>
|
|
2105
|
+
> **写门问请求(7.151.0+;契约 §0.13)**:计费提交、改写门、破坏性会话写只收带**过门凭据**的请求 —— service token,或鉴权桥验过的登录令牌(直连门的审批令牌不算);
|
|
2106
|
+
> 都没带 ⇒ 503 `auth.service_token_required`(`ALLOW_UNAUTHED_WRITES=true` 照旧放行;配了 service token 的部署上这样的请求先吃全局凭据门的 401)。所以只装了鉴权桥、没配 service token 的部署上,带登录令牌的用户提交得了任务
|
|
2107
|
+
> (≤ 7.150.x 一律 503),不带的照旧 503;只开 `REQUIRE_PRINCIPAL` / 只配 `TRACE_TOKEN` 的部署上谁都过不了这道门。
|
|
2078
2108
|
|
|
2079
2109
|
> **不报主体的 service token 是谁(`SERVICE_TOKEN_ACTS_FOR_DEPLOYMENT`,7.146.0+)**:出示这台部署的 service token 而**不带主体头**的请求,缺省(不设 = `true`)代部署本人说话 ——
|
|
2080
2110
|
> fleet 读面(舰队流 / 会话列表 / 发件链接 / 名册 / trace / 用量)看全舰队、运维聚合口(`/metrics*`、`GET /v1/tasks/source-summary`)照放、删除 / fork / 同步对任何会话照开。
|
|
@@ -2120,9 +2150,15 @@ PostgreSQL 仍只有 8 MiB。这一窗的 413 句子说是假定(`the database's
|
|
|
2120
2150
|
事实在场、但这一堵墙读失败退了文档缺省(TiDB < 7.6 又无 `CONFIG` 权限读不到单行上限;`max_allowed_packet` 读不出)的不会自己变真,请运维让库账号读得到那个上限(`GET /v1/diagnostics/wiring` 的 `sqlEngine.wallSources` 逐堵说出处)。
|
|
2121
2151
|
`PUT /v1/sessions/:id/sync/blobs/:hash` 超 SQL 快照 blob 帽的 `413 blob_too_large_for_sql` 同样带 `wallSource`,词多一个 `"operator"`(帽是你设的 `SNAPSHOT_BLOB_SQL_MAX_BYTES`),句子按三形分:旋钮 / 库报的墙 / 没读到的假定墙。
|
|
2122
2152
|
受理口放行、写续跑输入那一笔被库以「一行装不下」拒时(开了 durable 审批的部署)答同一个 413,出路按拒它的那堵墙给(TiDB 单行墙 ⇒ 抬 `txn-entry-size-limit`;语句墙 ⇒ 抬 `max_allowed_packet`;
|
|
2123
|
-
PostgreSQL 硬上限 ⇒
|
|
2153
|
+
PostgreSQL 硬上限 ⇒ 只有缩小;7.151.0 起 413 句与错误本身不再括号带库的原句,库的那句在店边界那一行 `at=store` 里),运维日志一行 `submit_ctx_row_too_large`(`wall` 点名那堵墙);刚认领的 run 当场撤掉,撤认领的库写自己也失败时一行 `submit_ctx_run_release_failed`(带步名)
|
|
2124
2154
|
并计 `submit_ctx_run_release_failed_total{step}`,会话到 `REAP_RUN_STALE_SEC` 才放。
|
|
2125
2155
|
|
|
2156
|
+
**SQL 店失败时库的原话在哪(7.151.0 起)**:任何一只 SQL 店的失败越过店边界时只带驱动的原码与一句对外句(类别句 + `[original code: <码>]`)—— run 终局、子代结算卡、后台子代通告、
|
|
2157
|
+
`GET /v1/runs/:id/subagents/:handle/output`、文件历史与记忆补丁的失败句都是这一句。要库的原话读 worker 日志的店边界那一行:
|
|
2158
|
+
`[terminal] outward_failure_code_folded original=<码 | <uncoded>> outward=<internal.store_error | -> messageBytes=<n> at=store site=<店>.<方法> class=<类别> message=<JSON 串>`
|
|
2159
|
+
(`message=` 是原错与其 `cause` 链各层的句子,经出口座:凭据形换记号、剥控制字符、有界;`class` 是店故障判官的词:`connection` / `deployment` / `corrupt` / `defect` / `unclassified`),
|
|
2160
|
+
计数 `store_boundary_fault_total{site,class}`。run 终局离开引擎时的 `at=exit` 那一行照旧出,`message=` 已是对外句;按 `original=` 与时间对两行(与 `request_error` 行同)。
|
|
2161
|
+
|
|
2126
2162
|
**请求体字段(常用;受理**闭集**以契约 §1 为准(内部记录)—— 本表不再重抄一份):**
|
|
2127
2163
|
| 字段 | 必填 | 说明 |
|
|
2128
2164
|
|---|---|---|
|
|
@@ -2170,6 +2206,16 @@ PostgreSQL 硬上限 ⇒ 只有缩小),运维日志一行 `submit_ctx_row_too_la
|
|
|
2170
2206
|
> `terminal.kind:"failed"`+`code`);`POST /v1/runs` 202=已受理(执行期结局落在终态 run 记录/`done` 帧)。执行期
|
|
2171
2207
|
> 错误结构上无法用 HTTP 状态码承载——流的响应头在 run 开跑前就发完了。
|
|
2172
2208
|
|
|
2209
|
+
**同一把 `Idempotency-Key` 重投(`POST /v1/tasks` · `POST /v1/tasks/stream` · `POST /v1/runs`;契约 §0.7,内部记录)**:同一调用方、同一把键、**同一份体**才算同一次提交;体不同 ⇒ `409 conflict.idempotency_payload_mismatch`(要重试就重发同一份体,要发不同的请求换新键)。首发**已落定**之后的重投读行作答:同步腿 `200` + 与首答同一只结果信封的体(读行重放不带只属于首答那次请求的 `wiringManifest` / `notice` / `warnings`)+ `replay: true`,流式腿终帧 `done.result` 同体(`done.replay` 同位),`POST /v1/runs` 照首答的 `202 { taskId, sessionId, status }`。
|
|
2210
|
+
**首发还在跑的时候重投,同步 / 流式腿的回执有两形,取决于重投落在哪个进程**(这是现行行为,不是两个版本的差别):
|
|
2211
|
+
|
|
2212
|
+
| 重投落在哪 | 你拿到什么 | 等多久 |
|
|
2213
|
+
|---|---|---|
|
|
2214
|
+
| 首发所在的**同一个进程**(那条在飞的提交还挂在本进程的在飞表里) | **等**首发落定,拿同一份结局(与首答同体)+ `replay: true`;流式腿是终帧 `done.result` 同体;首发被拒则拿同样的拒 | 本层没有第二只超时,等到首发落定为止。**只有在飞表条目有期限**:缺省 15 分钟(不可配);首发 15 分钟后仍未落定,**之后才到的**同键重投不再合流、改读行(下一行) |
|
|
2215
|
+
| **另一个副本**、**服务重启之后**、或在飞表条目已过 15 分钟 | 读行:行上**还没有结果可交** ⇒ **立刻**答 `200` 轮询回执 `{ taskId, sessionId, status, replay: true }`(`status` 是那一行此刻的词,在跑 ⇒ `running`);行上已有结果 ⇒ 与首答同一只结果信封的体(同上,不含首答那次请求独有的三键)+ `replay: true` | 立刻返回,不等 |
|
|
2216
|
+
|
|
2217
|
+
所以:带短超时的重试方,落在同一进程的重投看起来像「卡住」(它在等首发),落在别的副本的重投立刻拿到一份**没有结局**的回执。判别:体里**没有 `terminal` 键**、只有 `taskId` / `sessionId` / `status` / `replay` 的是轮询回执,**不是**结局,不要当终局读 —— 去 `GET /v1/runs/:taskId`(或 `GET /v1/runs?idempotencyKey=<原始键>`)轮询。`POST /v1/runs` 腿没有这两形:它的首答与重投恒是 `202` 回执,结局本来就要轮询。
|
|
2218
|
+
|
|
2173
2219
|
---
|
|
2174
2220
|
|
|
2175
2221
|
## 2. Hello world——同步发一个任务,拿到答案(最简单)
|
|
@@ -2289,14 +2335,14 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
|
|
|
2289
2335
|
| 端点 | 用途 |
|
|
2290
2336
|
|---|---|
|
|
2291
2337
|
| `GET /v1/sessions/<id>` | 审计回溯:当前上下文 + 摘要(owner 校验);消息里模型 / 工具产出的文本与 live 帧、账本帧同一只脱敏(密钥形换占位,其余字节不变);Read 图像 / PDF 的媒体卡(工具结果消息的 `details`)的 `file.base64` 是字节编码,逐字。**委派子代的转录**也走这一口:`<id>` = 子代帧 / fleet 子代行上的 `transcriptId`(未压缩过的子代首条用户消息是委派 prompt;子代跑过的工具是 assistant 消息里的 `toolCall` 段 + 同 `toolCallId` 的 `toolResult` 行;整段逐字条目走 `…/sync/entries`)。体顶层加性键 `agent: { id?, parentSessionId?, rootSessionId? }`(**7.133.0+**)说这是哪只子代:只投影会话行上存下来的委派元组,`id` 与 fleet 行的 `id`、`GET /v1/agents/roster` 的 `handle` 同一个串;键缺席 = 普通会话 / 老 server(`DB_BACKEND=local` 到 7.140.x 也是)/ 会话店不存元组(`DB_BACKEND=memory`;嵌入方自建、不声明委派分区的店),读作「没存」、回落 fleet 行 / 名册上的 id。子代会话的属主是引擎判的委派树属主(**7.144.0+**:没人派生的 run 读自己那一行的属主、按化身绑一次,原样带给每一层子代;三只持久会话店〔MySQL 协议 / PostgreSQL / local〕建行那一笔原样记引擎交来的属主,`null` = 根匿名;停驻挂点只比对宿主行属主与引擎交来的属主,不认领、不推断。**7.133.0–7.143.x** 是本服务在建行那一笔按根 / 父推断:根会话的行在 ⇒ 它的属主,根行已不在 ⇒ 它记录的父会话的,都不在 ⇒ 哨兵 `_orphan:<id>`;7.132.x 及更早的 SQL 后端上子代会话无主、谁都读得到)⇒ 用发起子代的那位主体读;别的主体与不存在的 id 同一个 `404 not_found.session`。属主为空的委派子代行(根会话本就无主,或升级前写下、还没回填)只有 fleet 调用方读得到(出示 service 凭据、不带主体头;dev-open 部署不钉人),任何具名主体、没有 service 凭据的无身份调用方同样 404(存量无主会话互认臂 —— 单用户形下 `default` 主对无主的普通会话放行,fork / 删除 / `/sync/*`(同步族自 7.134.0 起)同走这一只 —— 对这些 placed 行同样不放行,审批豁免、notify 同样不放行;fork / 删除 / `/sync/*` 的 fleet 调用方与此处同一个判据:出示 service 凭据、不带主体头,带主体头的 service 凭据请求是那位主体,7.134.0 起);SQL 后端两店每次起服由一次性迁移 M23 在它的窗内回填升级前写下的无主 placed 行(按 7.133.0 起的读法:根的属主,根行不在取记录的父的,都不在写 `_orphan:<id>`;起服读数行 `placedSessionOwnersRemaining` 非零 = 还有没定下的,再起直到为 0),local 后端没有回填臂(**7.145.0+** local 后端建子代行先记属主、再建转录存档,进程崩在两笔之间留下的是一只没有转录的属主格 —— 不是子代行,不再新生无主子代行;更早版本崩在两笔之间留下的无主子代行照旧无主、不回填,出路是取消 / 删掉那只后台子代)。属主 `_orphan:<id>` 由 7.133.0–7.143.x 的建行推断与 M23 回填写下(7.144.0 起本服务不再推哨兵,建行原样记引擎交来的属主 —— 已有的哨兵属主随引擎的树属主原样带到它下面新建的子代行上):任何主体都不匹配,只有 fleet-wide / operator 读得到,前缀永久保留。停驻时宿主行属主与引擎交来的不等 ⇒ 停驻否决(那张待批卡作废、那一只子代以失败收尾) |
|
|
2292
|
-
| `GET /v1/approvals?owner=user:42` | 高危写审批(durable,需 `DURABLE_APPROVAL=true`):**operator** 看待办队列(可按 owner 过滤);非 operator 只看自己的。队列里某一行的存储体读不出来、重试不会好时,答 `500` + `errorCode:"approvals.read_corrupt"`(**7.134.0+**;与订阅流同码、同一只判官;运维处置那一行后再读,别原样重试);此刻读不出队列(连接 / 超时 / 店抖动)⇒ `503` + `errorCode:"approvals.read_unavailable"`(**7.135.0+**,此前 500 `internal.error`;稍后重发,这一答不表示队列为空);本服务自己的程序错(代码缺陷 / 读腿漂移)⇒ `500` + `errorCode:"internal.error"`(**7.148.0+**,此前同落 503;重发不会好,看运维行 `request_error`)。`GET /v1/assistant/inbox` / `GET /v1/assistant/tasks` 读同一个队列,两种读失败同码同状态(**7.135.0+**)。一张停驻行的存储体读不出摘要(手改成 `{}`、整段缺 `state` 等)只坏它自己那一行(**7.145.0+**,MySQL 协议 / PostgreSQL 后端):收件箱与运维队列照列它、带引擎判官的 `rowVerdict`(只缺 `pendingAction` 的行判官答 `ok`,引擎侧已知缺口),任务视图照列那条 run,三个面都不再整张答 500 / 503;别的卡的决断照常,这张卡自己的决断答 409 带码拒,`error` 以行上 `rowVerdict.sentence` 开头(**7.146.0+**;此前存储体 `{}` 的卡被指向 plan_review 的口、存储体读不成检查点的卡只有店的诊断);`DB_BACKEND=local` 上列表面本版仍整张 503(决断已逐行)。开了工具审批时响应另带 `livePending[]`(本副本上的活卡,决议走 `POST /v1/
|
|
2338
|
+
| `GET /v1/approvals?owner=user:42` | 高危写审批(durable,需 `DURABLE_APPROVAL=true`):**operator** 看待办队列(可按 owner 过滤);非 operator 只看自己的。队列里某一行的存储体读不出来、重试不会好时,答 `500` + `errorCode:"approvals.read_corrupt"`(**7.134.0+**;与订阅流同码、同一只判官;运维处置那一行后再读,别原样重试);此刻读不出队列(连接 / 超时 / 店抖动)⇒ `503` + `errorCode:"approvals.read_unavailable"`(**7.135.0+**,此前 500 `internal.error`;稍后重发,这一答不表示队列为空);本服务自己的程序错(代码缺陷 / 读腿漂移)⇒ `500` + `errorCode:"internal.error"`(**7.148.0+**,此前同落 503;重发不会好,看运维行 `request_error`)。`GET /v1/assistant/inbox` / `GET /v1/assistant/tasks` 读同一个队列,两种读失败同码同状态(**7.135.0+**)。一张停驻行的存储体读不出摘要(手改成 `{}`、整段缺 `state` 等)只坏它自己那一行(**7.145.0+**,MySQL 协议 / PostgreSQL 后端):收件箱与运维队列照列它、带引擎判官的 `rowVerdict`(只缺 `pendingAction` 的行判官答 `ok`,引擎侧已知缺口),任务视图照列那条 run,三个面都不再整张答 500 / 503;别的卡的决断照常,这张卡自己的决断答 409 带码拒,`error` 以行上 `rowVerdict.sentence` 开头(**7.146.0+**;此前存储体 `{}` 的卡被指向 plan_review 的口、存储体读不成检查点的卡只有店的诊断);`DB_BACKEND=local` 上列表面本版仍整张 503(决断已逐行)。开了工具审批时响应另带 `livePending[]`(本副本上的活卡,决议走 `POST /v1/tasks/<taskId>/asks/<askId>/decision`;7.151.x 及以前另有已删的活卡应答口):**7.149.0+** 它与下面的按问读口同一只读法 —— 列出的每一张,读口对同一调用方都答 `pending`(反过来不然:具名主体的列表不含无主的卡,运维列表含读口不放行的卡),店读不出某张卡的行 ⇒ 这张不列(读口同时答 404 `not_found.ask`;`livePending` 为空不等于没有待批,可能是此刻读不出),行已被别处收走 ⇒ 不列,属主取行上当下的那一位(此前按本副本登记列,店抖动期照列而读口 404);店恢复后重列即回,每次列表对每个有行的不同 ask 多一次按 id 的点读。停驻的**技能卡**(对引擎 `Skill` 工具的调用)的行带 `boundGrantDigest` / `boundGrants`(批准它还授予的东西:技能名 + 两只工具清单;清单只在哈希等于摘要时才有,是部署文本,渲染要按上下文转义),分类器没给判词的卡带 `classifierNoRuling`(`error` / `timeout` / `parse_error`)—— **7.136.0+**,与 `GET /v1/assistant/inbox` 行逐字同值(此前只有收件箱行与活卡帧带);普通卡三位都缺席。`GET /v1/assistant/inbox` 行的 `objective` 是门所属 run 的**目标预览**(写入时已脱敏、截到约 120 字符,与 `GET /v1/assistant/tasks` 读同一列;委派子代的门读派它的那条 run;没有 run 账本 ⇒ `null`;**7.136.0+**,此前原样回显存着的任务目标,运维 `?owner=` 跨看也是原文)。停驻行带 `agent`(**7.145.0+**):行的会话在委派树里的位置 `{ id?, parentSessionId?, rootSessionId? }`,与 `GET /v1/sessions/<sessionId>` 体顶层的 `agent` 同一只读口、逐值同答 —— 后台委派子代停驻的行(`taskId` 为 `null`、`sessionId` 是子代自己的会话)凭它连回发起委派的会话(`rootSessionId` / `parentSessionId` = 本端会话 ⇒ 本端的卡);缺席 = 这台 server 没有说(宿主会话自己的停驻、同步委派的子代、`subagent_type: "fork"` 的后台子代、不存委派元组的店、那一读没读成 —— 只这一行缺键、列表照出),按原读法判,不读作「不是子代」 |
|
|
2293
2339
|
| `GET /v1/approvals/stream` | 同一队列的 SSE 推送(范围同上):首拍快照 → `pending` / `resolved` 增量(开了工具审批时另有 `live_pending` / `live_resolved`),空闲时心跳,15 分钟上限(`STREAM_MAX_DURATION` 帧后重连)。**心跳只表示流活着,不表示这一拍读过队列**:队列读不出时每次读失败发一帧 `error`(`approvals.read_unavailable`,流留着、下一拍再读,恢复后同一条流继续);某一行的存储体读不出来、重试不会好时发 `approvals.read_corrupt` 并收流(运维处置那一行后再重连);本服务自己的程序错发 `internal.error` 并收流(**7.148.0+**,此前同落 `approvals.read_unavailable`、流不收)。15 分钟上限对读失败的拍同样算数。`live_pending` / `live_resolved` 与 `GET /v1/approvals` 的 `livePending[]` 同一只读函数(**7.149.0+** 同按问读口读行:读不出行 ⇒ 这一拍离场、店恢复后再入场一帧,推流每拍对每个有行的不同 ask 多一次点读;问账读不出而队列读得出的拍才发这一对帧)。`pending` 帧带的行与 `GET /v1/approvals` 同一只投影(含上面的技能卡三位,**7.136.0+**;含 `agent`,新订阅首拍补给的帧与之后推出的帧同值,**7.145.0+**) |
|
|
2294
2340
|
| `POST /v1/approvals/<sessionId>/decide` `{"decision":"approve"|"deny","reason":"…"}` | 批/否并恢复挂起任务(CAS,重复决议 409);**仅 operator**(非 operator → 403)。5.0.0 起旧轮询腿 `POST /v1/approvals/<id>` 已退役。停驻的后台子代**复活不了**(行上没有根会话锚;未起名的后台子代不在此列 —— 引擎 7.57.0 起每只子代都有名字,升级前的无名行读作派生名,照常复活)⇒ `deny` 作废这张卡:`200 {taskId, status:"failed", decision:"deny"}`,卡离开待决队列、子代终局 `failed`;`approve` 答 `409 decide.row_unrevivable`、拒句指路 deny(**7.136.0+**;此前两个决定都 409,卡处理不掉)。有根会话锚的停驻子代卡上,`decide` 与删根会话 / 卡作废并发:写口放行之后卡已被作废 ⇒ `422 parked_resume.startup_failed`(卡已作废、什么都没复活;与 `409 decide.gate_moved` 并列为并发终局码,调用方须同时处理 409 / 422) |
|
|
2295
|
-
| `GET /v1/
|
|
2341
|
+
| `GET /v1/tasks/<taskId>/asks/<askId>` | 按问读口(**7.152.0+** 在这一根,与耐久决断口 `POST /v1/tasks/<taskId>/asks/<askId>/decision` 同根同门同身份;**7.133.0–7.151.x** 在 `GET /v1/tool-approvals/<approvalId>`,它与活卡应答口 `POST /v1/tool-approvals/<approvalId>/respond` 一起 7.152.0 起已删,迁移对照见 MIGRATION)。不是你的 ask 与查无同形 404 —— **7.148.0+** 与耐久决断口同码 `not_found.ask`、不带状态位,`tool_approval.not_pending` 只对属主出;**7.136.0+** 决断口与本口同一只属主判据:有行的问读行上当下的属主,收编之后新属主两口都认、前属主两口都 404;此前本副本上的活卡读的是铸卡那一刻记下的属主;**7.149.0+** 本口在店读不出时看不见这只问,答 404 `not_found.ask`(与查无同体;活卡与起服接管的登记同答 —— 7.136.0–7.148.x 对本副本自己铸的活卡回落登记,登记属主认你 ⇒ `pending`),店恢复后重读即回):一只审批问此刻在哪一态,`state` ∈ `pending` / `decided` / `parked` / `void`(闭集)。停驻卡被答过 ⇒ `decided`、停驻 run 被取消 ⇒ `void`(**7.134.0+**;7.133.x 恒答 `parked`);停驻行的门已结算却读不出可用的决议(含坏行:状态词 / 种类 / 当事方不在闭集、结算记录过不了引擎的不变量筛、缺必填成员、时刻 / 方向读不出)⇒ 404 `tool_approval.not_pending`,运维日志一行 error(`defect` 首条缺陷句 · `defectCount`)。停驻行的 `decided` 可回到 `parked`:续跑腿在被批准的动作开跑前失败时,引擎重开同一张门 —— 读口答 `parked` + `decidePath` 并另带 `reopened`(**7.135.0+**):`reason` 是引擎的重开因由词(`env_failed` 按原决议再交一次 —— 经 `decidePath` 或决断口;`tool_unavailable` / `constraint_rejected` 重新决;`config_refused` 改好配置再交或重新决),`decision` / `decidedAtMs` / `decisionNote?` 是重开之前的那次决议(读不出 ⇒ 只带 `reason`);再决之后回到 `decided`。续跑被取消 ⇒ 重开的门被收掉,读作 `void`。全文见契约 §4a-bis-read |
|
|
2296
2342
|
| `GET /v1/agents/roster` | 后台 agent **名册**(7.29 起,需 durable background-agent store,否则 501 `capability.background_agent_store_required`):调用方自己 scope 的 `a…` 行,新→旧。行只带 `handle`/`name`/`agentType`/`status`/`spawnedAt`/`updatedAt`/`settledAt`(content-free;子代产物正文走 `GET /v1/runs/<id>/subagents/<handle>/output`)。查询:`?limit=`(1..100,默认 20)、`?before=`(上一页的 `nextBefore` 游标)、`?status=`(running\|parked\|completed\|failed\|killed)、`?session=`(按会话树窄化)、`?scope=`(**仅** fleet 调用方:不带主体头的 service 凭据 / 只读 `TRACE_TOKEN`(只在没配 service 凭据的部署上够得着这一口)/ dev-open;带主体头的调用方 —— 含带 service 凭据的 —— 锁定自己)。回体 `{agents,total,nextBefore?,truncated?}`;`truncated:true` = 租户行数超过名册窗(500),`total` 此时是窗内数。非属主的行**不出现也不计数**(无存在性 oracle) |
|
|
2297
2343
|
| `GET /v1/capabilities/scenarios/<name>` | 单个场景的只读详情:工具面、提示词概览、**本部署现在跑不跑得动**、附件供给、**技能清单**(见下) |
|
|
2298
2344
|
| `GET /v1/capabilities/mcp[?scenario=<场景名>]` | **无需先跑 run 的逐台 MCP 状态**(现连、列工具、关掉;按调用方限速 + 30 秒复用)。答的是**某个场景**会挂哪些中心声明的 MCP 服务器:不带参数 = 这位主体 run 时的场景(**7.131.0+**:中心按主体指派的场景胜出,否则部署缺省场景;此前恒读部署缺省场景;指派悬空 ⇒ `503 state.scenario_assignment_unknown`,与提交任务时同一句;**7.147.0+** 部署接了中心而中心答不出这位主体的裁定(不可达 / 超时 / 答复读不出 / 指派两键形不对)⇒ 点名与不点名同答 `503 state.scenario_assignment_unavailable`(体无 `detail`、带 `permanence: "transient"`),与提交任务时同一句,不再按「无治理」读部署缺省场景;`GET /v1/sessions/:id/mcp` 与 `…/a2a` 两张会话面板同读这位主体 run 时的场景:a2a 面板悬空时同样整面 503,而 mcp 面板另有「这个会话上一次真挂上了什么」那一半(`lastLegMcp`),悬空时答 `200`、`lastLegMcp` 照答、`servers` 缺席、拒因在 `scenarioRefusal: { errorCode, error, scenario, source }`(与状态面整面 503 的体是同一份成员,`scenario` · `source` 是门拒的机读事实、与 `errorCode` / `error` 同层 —— 7.148.0 起,此前嵌在 `detail` 里;`servers` 缺席 = 场景这一半没答,`servers: []` = 该场景没配 MCP));`?scenario=<名>`(**7.130.0+**)= 点名场景,可见集与同场景任务 run 时是同一只解析、过同一只场景门 —— 不在册 `400 scenario_unknown`(附在册词表;空串 `?scenario=` 同此,与提交 `scenario: ""` 同答)、这位 principal 的场景白名单集外 `400 scenario_not_allowed`(附 allowlist),两者的体与提交任务时的拒逐字同形;重复给出参数 `400 request.field_invalid`(提交腿没有这一形)。场景门接缝 `scenarioGate` 是 `createHttpServer` 的必填件:自建 `ServiceDeps` 的嵌入方用包根导出的 `createScenarioGate` 铸它(`"peek"` 腿给读面),没递就是 tsc 红。老 server 忽略这个参数、回缺省场景那一份,按 `GET /v1/capabilities` 的 `version` 判。`REQUIRE_PRINCIPAL` 下无身份 `401`(先于场景门)。每一行(两条口同形)在 §G.7 的行形之外多两个可选键(**7.133.0+**):`toolNames`(这台会挂上的工具名,引擎命名空间形 `mcp__<server>__<tool>`,读数序)+ `toolNamesTruncated: true`(名单超过 200 只时只截表,`toolCount` 仍是真数;读数用 `toolCount`,别用 `toolNames.length`);该台读数里没有名单 ⇒ 两键缺席(不编 `[]`),没连上的台是在场的 `[]`;老 server 没有这两键,按缺席读。中心声明里有两台归一后挂在同一个工具命名空间前缀下(`my.srv` / `my_srv` 同挂 `mcp__my_srv__`)⇒ **7.143.0+** `409 config.mcp_server_name_collision` + 引擎原句(点名两个原拼写;此前无码 `500`),与同一份声明集在 `POST /v1/tasks` 上的答复同码、同状态、同句 —— 出路 = 改配置里的名字。自带 `.mcp.json` 的探测口是 `POST /v1/capabilities/mcp/probe` |
|
|
2299
|
-
| `POST /v1/admin/drain` `{"actionId":"…","worker":"…","deadlineAt":…}` | **排空口**(7.121.0 起体 = settings-schema `DrainRequest
|
|
2345
|
+
| `POST /v1/admin/drain` `{"actionId":"…","worker":"…","deadlineAt":…}` | **排空口**(7.121.0 起体 = settings-schema `DrainRequest`;持排空权力者 —— principal 须在 `OPERATOR_PRINCIPALS`(全运维)或 `OPERATOR_DRAIN_PRINCIPALS`(排空档:只持排空一权的服务主体,7.152.0+;它的身份在其余每条路由上 403 `auth.principal_confined`)内,或单用户部署声明了 `OPERATOR_SINGLE_USER=true`;三条出路都没有〔两档名单都空且没声明〕⇒ 501)。体 `{ actionId, worker, deadlineAt, scope?, expectedGeneration?, instanceId?, term? }`:`actionId` 幂等键(人手形自取,如 `manual:<uuid>`)、`worker` 本引擎的 worker 名(`SEMA_WEB_ADMIN_WORKER`)、`deadlineAt` 到期自停的 epoch ms、`scope` 本引擎的租户 scope(`FLEET_SCOPE`;不带 = 缺省 scope `global`,与没设 `FLEET_SCOPE` 的引擎相符 —— 多租引擎要带它自己的)、`expectedGeneration` fleet 成员的代际(`FLEET_GENERATION`;非成员不带)、`instanceId` 本进程身份(`GET /health` 读;不带则不比)。身份逐字段比(`worker` / `expectedGeneration` 缺席对缺席),不符 ⇒ `409 conflict.fleet_identity`(什么都不变);首次 ⇒ `200 {actionId, since, deadlineAt, state:"draining"}` 并**进入排空**(拒新提交、本副本可抢占的在飞腿当拍让出、活的审批卡改路耐久停驻、在飞归零或到期限即停);再来 ⇒ `200 … state:"already_draining"` 回显第一次的 `since` / `deadlineAt`,不重置。体坏 ⇒ `400 request.field_invalid`;`deadlineAt` 离本引擎此刻超过 `FLEET_LEASE_OUTAGE_MAX_MS`(缺省 24 h,一台实例活着而不服务的最长时长;7.122.0 起)⇒ 同码 400(什么都不变;拒句点名字段与上界的值;只在这一发会进入排空时判 —— 已在排空或硬停已在进行时任何重发都回 `already_draining`),已过的期限照收(进入即到期);嵌入宿主(无收尾链)⇒ `501 capability.drain_state_required`。没有 worker 身份的引擎(没配 `SEMA_WEB_ADMIN_WORKER`)恒 409 —— 用 SIGTERM。经本口进的排空之后,平台随后发的第一发 SIGTERM 被吸收、不缩短期限(第二发判据见「排空期的第二发信号」)。7.120.x 的 `{"reason":"…"}` 声明形与 `/health.drainReason` 已退役。 |
|
|
2300
2346
|
| `GET /v1/config/catalog` | **配置目录自描述**(operator-only —— `explicitOperatorOk`:没有运维名册〔`OPERATOR_PRINCIPALS` 为空且没有单用户声明 `OPERATOR_SINGLE_USER=true`〕⇒ 501 `capability.operator_principals_required`,有名册而调用方不是运维 ⇒ 403)。逐 env 键一行:`{name, domain, type, semantics, writeLanes, effectiveLane, envHeld, envTiming, staticDefault?/derivedDefaultNote?, effectiveValue, valueClass, danger, center?{domain,path,precedence,timing,restartSlice?,managedNow,effectiveNow}}`(🔴 7.106.0 起 `center.domainExists` 删除:座位在加载期对契约 `DOMAIN_SCHEMAS` 核过域 + 路径,核不过即拒启 ⇒ 有 `center` 块 ⇔ 中心可写;readFace 四键 / `PERMISSIONS_DISABLE_AUTO_MODE` / `MODEL_DEGRADE_ON` / `_REACTIVE` 七行的座位随之删除);顶层带 `restartSlices`(重启片闭集)与 `centerDomains`(settings-schema 现行域表)。**两轴不混**:`writeLanes`=谁能写,`effectiveLane`=现在谁在生效(env-wins 族 env 占位 ⇒ center 腿 `effectiveNow:false`)。secret 类值**永不回传**(只回在场位;opaque 回在场位+长度;URL 剥 userinfo)。完备性由仓内 AST 双向对账门执法(分母=全 `src/` 生产 env 读取点)。旋钮 `CONFIG_CATALOG_ENABLED=false`(合规部署)⇒ 501 `feature.config_catalog_disabled`(路径恒挂载)+ 能力位 `configCatalog:false`。响应 `Cache-Control: no-store`。**7.57.0 起**:`enum` 行的 `effectiveValue` **恒落在该行自己的 `enumValues` 闭集内**(仓内机器门执法)——此前 `SESSION_BACKEND` 回的是**内部标签** `tidb`(自 5.0.0 起是**退役公名**,写回去 boot 拒),现归一成公名 `mysql`;`MODEL_DEFAULT_THINKING` 补上一直被解析器接受、却漏在目录闭集外的 `xhigh`,并改为回**实算值**(未设 ⇒ `null`;7.147.x 及以前 `off` 也回 `null`,**7.148.0 起** `off` 是真档、回 `"off"`)而不是 env 原文。 |
|
|
2301
2347
|
| `POST /v1/admin/config/refresh` | **配置手动刷新**(operator-only,与上一行同门:没有运维名册〔`OPERATOR_PRINCIPALS` 为空且没有单用户声明 `OPERATOR_SINGLE_USER=true`〕⇒ 501;名单非空而调用方不在名单上 ⇒ 403)。改完中心配置 / `config.d` 之后不想等 60s 轮询就调它:触发**一次既有**的 refresh 拍(在飞则汇入那一拍,绝不并发双拍),返回时该拍已落地。200 体 `{triggered:true,targetVersion,appliedVersion}` —— 两个世代号与 `/health` 的 `configTargetVersion`/`configAppliedVersion` 同源。候选被判官整拒(坏域 / 坏 prompts / 带事实的退役域 —— 7.126.0 起 / 本机 `config.d` 里读不出的文档,门控域在内)是这一拍的结论,不是失败:照样 200,`targetVersion ≠ appliedVersion`,拒因在 `config_candidate_rejected` 日志行;拍真的失败(配置源不可达 / 读不了 / 应用抛错)⇒ `502 internal.config_refresh_failed`。本部署没有配置管道(纯 env worker:既没配 `CONFIG_CENTER`、也不是 `CONFIG_PROVIDER=local`)⇒ 409 `config.refresh_unavailable` 指路,不会回一个「触发了但什么都没发生」的 200。 |
|
|
2302
2348
|
| `POST /v1/adoption/<adoptionId>/sessions` `{"sessions":[{"clientSessionId":"…","entries":[…]}]}` | **收编批量导入**(**7.146.0+**;能力位 `adoptionImport`,按调用方):收编的**源主体本人**把本机会话导进那条收编的目的主体名下(operator 不能代,请求体不能点名目的地);导进来的是只读镜像,在云端接着跑先 fork。`adoptionId` 从 `GET /v1/capabilities` 的 `adoptionImport.adoptionId` 读(只对源主体本人在场,另带两只帽 `maxSessions` / `maxSessionBytes`)。云端会话 id 由 `(adoptionId, clientSessionId)` 确定性派生 ⇒ 重投安全。200 + 逐元素结局 `imported` / `already_imported` / `rejected{code: too_large \| invalid_envelope \| duplicate_client_session_id}`;信封恰好两键,多一个键(如 `cwd`)⇒ 这个元素 `invalid_envelope`。整请求拒:401 / 501 `capability.adoption_store_required` / 404 `not_found.adoption` / 403 `auth.adoption_source_only` / 409 `adoption.not_adopted` / 400(体形、元素数超帽)。帽 = `ADOPTION_IMPORT_MAX_SESSIONS`(缺省 100)/ `ADOPTION_IMPORT_MAX_SESSION_BYTES`(缺省 6 MiB)。契约 §26 |
|
|
@@ -2324,7 +2370,8 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
|
|
|
2324
2370
|
|
|
2325
2371
|
> **operator 鉴权(审批队列与全部运维面,一条读法)**:`OPERATOR_PRINCIPALS=ops:alice,ops:bob`(CSV)= 谁能当 operator —— 列任意 owner 待办 + 决议(批/否)。非名单 principal 列待办只看自己的、且**不能决议**(防「请求方批自己的高危操作」跳过 F4 闸);
|
|
2326
2372
|
> **名单为空 = 没有人是 operator**(每个调用方只看自己的待批 —— 不带主体的调用方看到的是匿名卡〔不带主体提交的任务停下的那几张,即决断口对它开放的那几张〕,`?owner=` 不生效;7.133.0 之前审批四个读面在名单为空时把每个调用方当 operator,那条读法已删)。
|
|
2327
|
-
>
|
|
2373
|
+
> **排空档(7.152.0+)**:`OPERATOR_DRAIN_PRINCIPALS=svc:drain`(CSV)= 只持排空一权的服务主体 —— 名单里的验过主体只能调 `POST /v1/admin/drain`,其余每条路由整次请求 403 `auth.principal_confined`(不提交任务、不建会话、不碰运维口),`GET /health` 只拿匿名档四键;它名下登记过的设备在 `GET /v1/device/ws` 的 hello 被拒 `auth_failed`(执行器退避重试、不删钥匙;属主回到人档的那次重启后自己连上);不算运维声明;与 `OPERATOR_PRINCIPALS` 同名、或列了不是主体名的条目 ⇒ 拒启(`operator-roster-well-formed`)。
|
|
2374
|
+
> **单用户部署当自己的 operator**:`OPERATOR_SINGLE_USER=true` = 「这台部署的每个调用方都是 operator」,对全部运维面生效;只在 `REQUIRE_PRINCIPAL` 未开且 `OPERATOR_PRINCIPALS` 与 `OPERATOR_DRAIN_PRINCIPALS` 都为空时成立(与任一同在 ⇒ 拒启);
|
|
2328
2375
|
> 声明要有一道身份边界:没配服务凭据(`SERVICE_AUTH_TOKEN` / `SERVICE_AUTH_TOKENS`)的部署上能连上端口的都是 operator,所以**声明 ∧ 没配凭据 ∧ 监听地址不只在本机回环**(缺省全接口 / `0.0.0.0` / 局域网地址 / 主机名)⇒ 服务进程起服拒
|
|
2329
2376
|
> (不变量 `operator-single-user-boundary`;拒句一行给三条出路:配凭据 / `BIND_HOST=127.0.0.1` 只听本机回环 —— 端口要发布给别的主机的容器改配凭据 / 撤声明换具名 `OPERATOR_PRINCIPALS`);
|
|
2330
2377
|
> `ALLOW_UNAUTHED_WRITES=true` 且没配凭据时监听地址本来就收窄到 127.0.0.1,照起。不监听的 `run-local` 不判这一条。
|
|
@@ -2332,7 +2379,7 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
|
|
|
2332
2379
|
> 部署形不是输入:单用户部署上 `GET /v1/diagnostics/wiring` 与 `GET /v1/outcomes` 也只认运维,具名名单在单用户部署上同样生效。
|
|
2333
2380
|
> 🔴 **单用户部署必须声明谁是运维**:`REQUIRE_PRINCIPAL` 未开、`OPERATOR_PRINCIPALS` 为空、`OPERATOR_SINGLE_USER` 不是 `true` ⇒ 装配运维面时拒(服务进程起服拒;直接调 `createHttpServer` 的嵌入方同拒;不变量 `operator-declaration-required`),
|
|
2334
2381
|
> stderr 一行拒句点名两条出路 —— `OPERATOR_SINGLE_USER=true`(每个调用方都是运维)或 `OPERATOR_PRINCIPALS=<主体,…>`(只有点名的主体);不止一个人调用的 worker 是多租,设 `REQUIRE_PRINCIPAL=true`。
|
|
2335
|
-
> 没有旋钮、没有宽限、没有缺省;`OPERATOR_SINGLE_USER=false` 与没写同判。`sema-up
|
|
2382
|
+
> 没有旋钮、没有宽限、没有缺省;`OPERATOR_SINGLE_USER=false` 与没写同判。`sema-up` 的 `--users` 必填、没有缺省(脚本不替部署选「几个人用」:缺了拒并给 `--users=single` / `--users=multi` 两条出路;重跑沿用 `.env` 里上一次落下的事实),`--users=single` 按租户词渲 `OPERATOR_SINGLE_USER=true`(kube 两条 helm 路径写进 values 的 `server.operatorSingleUser`);直接 `helm` 的部署由你写显式 values 键 `server.operatorSingleUser=true`(单人)或 `server.requirePrincipal=true`(多人),图表不从租户词派生它,两键都没设渲染即拒。
|
|
2336
2383
|
> 不挂 HTTP 面的 `run-local` 不判这一条;运维面 501 `capability.operator_principals_required` 从此只出现在「多租 + 空名单」上。
|
|
2337
2384
|
> ⚠️ **多租户形拒启**:`DURABLE_APPROVAL=true` + `REQUIRE_PRINCIPAL=true` 而 `OPERATOR_PRINCIPALS` 空 ⇒ 进程启动失败并点名修法(空名单下没人能当这台多租 worker 审批队列的 operator)。设名单,或确属单租户则不设 `REQUIRE_PRINCIPAL`。
|
|
2338
2385
|
> 🔒 **停驻任务续跑上下文里的凭据是密封的(7.134.0 起)**:任务停驻时存下的提交体里,请求自带的凭据(`mcpServers[].transport.headers` / `.env` 的值、`a2aPeers[].headers` 的值、`settings.env` 的值、
|
|
@@ -2488,8 +2535,8 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
|
|
|
2488
2535
|
> ⚠️ **分钟级持久作业**:客户端超时后**原样重发**是安全的 —— 同副本上在飞的那一轮会被并入(单飞),
|
|
2489
2536
|
> 落定之后的重发走 core 的 durable run 行续跑(零新 mint)。**跨副本**仍是 at-least-once,别从两个地方
|
|
2490
2537
|
> 同时打同一个 scope。
|
|
2491
|
-
> ⚠️ 它**真的烧模型** ⇒ 与 `/v1/tasks` 同吃三道 503 门(drain / roster 未落 /
|
|
2492
|
-
> 🔴 因此:**没配 `SERVICE_AUTH_TOKEN
|
|
2538
|
+
> ⚠️ 它**真的烧模型** ⇒ 与 `/v1/tasks` 同吃三道 503 门(drain / roster 未落 / 请求没带过门凭据)。
|
|
2539
|
+
> 🔴 因此:**没配 `SERVICE_AUTH_TOKEN`、也没装鉴权桥且未开 `ALLOW_UNAUTHED_WRITES` 的 worker 上这一口恒 503**(装了鉴权桥的只收带登录令牌的请求),
|
|
2493
2540
|
> 而能力位仍报 true(本族共有缺口,附录 B.1 已如实登记)。启动日志为此打一条
|
|
2494
2541
|
> `memory_consolidation_run_credential_gated`;状态读那一口不受影响(它不烧模型)。
|
|
2495
2542
|
> 谁是运维:阀门开得起来的只有单用户 + file 记忆后端的部署,而单用户部署起服就得声明运维(`OPERATOR_SINGLE_USER=true` 或具名 `OPERATOR_PRINCIPALS`,
|
|
@@ -2584,7 +2631,7 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
|
|
|
2584
2631
|
> 与主张(`REMOTE_EXEC_HOME_DIR`,或 host 的本进程家目录 / e2b 的 `/home/user`)不一致(去掉尾斜杠后逐字比)或问不出 ⇒ 那只执行环境不开,拒句点名两个值与改法
|
|
2585
2632
|
> (把 `REMOTE_EXEC_HOME_DIR` 设成实测值、删掉错的声明,或让环境的 `HOME` 读主张那个值)。host 车道的读数在铸环境时就到手 ⇒ 环境不铸,run 在开跑前失败
|
|
2586
2633
|
> (码 `env.home_unconfirmed`,同步腿 409;一条命令没跑、模型一次没调,命令带不带路径都是这一句;7.144.0 起,此前拒句落在工具结果里);远端五车道的环境也在开跑前打开、拒在那一拍判出,但 run 照样开跑 ⇒
|
|
2587
|
-
> 拒句落在工具结果里(带路径的命令可能先撞读边界、ssh / adb 上带附件的会话开跑前就失败、从快照恢复的续跑腿答 `resume.env_failed`,逐形见 §9 的 `env.home_unconfirmed` 行),环境答了的不一致记在那只环境上(
|
|
2634
|
+
> 拒句落在工具结果里(带路径的命令可能先撞读边界、ssh / adb 上带附件的会话开跑前就失败、从快照恢复的续跑腿答 `resume.env_failed`,逐形见 §9 的 `env.home_unconfirmed` 行),环境答了的不一致记在那只环境上(码 `env.home_unconfirmed`,与 host 车道同一码;此后每次回同一句,不再起容器 / pod / 沙箱、不再问),问不出的那一次不记(`connect_failed`)、下一次重问。e2b 恢复出来的沙箱对不上时尝试重新挂起(挂起成功快照留着;挂起失败只记一行 warn,沙箱按自己的寿命到期),不杀。
|
|
2588
2635
|
> e2b 的出厂答案 `/home/user` 已于 2026-10-29 在真沙箱上实测一致(缺省模板:用户 `user`、`$HOME` = `/home/user`);自定义模板换了用户的,`$HOME` 若不是它,没声明 `REMOTE_EXEC_HOME_DIR` 的 e2b 部署的每只沙箱建起来就拒,把声明设成沙箱里 `echo $HOME` 的结果(声明同样被对证)。
|
|
2589
2636
|
> device 车道读不了家目录:声明即座,起服响一行 `execution_lane_home_unmeasured`(点名声明值与「未实测」)。
|
|
2590
2637
|
>
|
|
@@ -2877,13 +2924,13 @@ k8s 车道每条 run 一只新 pod(pod 寿命 = 泄漏护栏,不跨 run 复用)
|
|
|
2877
2924
|
|
|
2878
2925
|
- **没配快照存储**(`MINIO_ENDPOINT` / `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY` 缺任一)⇒ 工作区每轮为空,`GET /v1/capabilities` 不带 `workspaceSync`;起服一行 `workspace_persist_unavailable`(`missing` 点名缺的键;缺省 `space` 也出,设 `WORKSPACE_PERSIST=off` 即不出)。
|
|
2879
2926
|
- **没有存储后端**(`DB_BACKEND=memory`;配了 SQL 的 `DB_BACKEND` 却显式 `SESSION_BACKEND=memory` 时库不开,同一形)× `space`(含缺省,且配了快照存储)⇒ **拒启**,拒句一行点名 `WORKSPACE_PERSIST=space`、缺的存储后端、会话店种类(与 `/health.sessionBackend` 同一读法)与可用的后端。出路:`DB_BACKEND=local`,或 SQL(`DB_BACKEND=mysql|pg`,`SESSION_BACKEND` 不设 `memory`),或设 `WORKSPACE_PERSIST=off`。`SESSION_BACKEND=memory` 配 `DB_BACKEND=local` 不在此列:被收编成 local 店,照起。拒启而不是降级:否则能力位报 `space`、每条 run 却一份都不存。
|
|
2880
|
-
- **快照桶不存在**(`WORKSPACE_SNAPSHOT_BUCKET` 指的桶没建):**起服拒启**(k8s 车道配了快照存储时,server 在打开任何店之前核这只桶;拒句点名桶名、`MINIO_ENDPOINT` 的显示安全形与出路 —— 建桶,或把 `WORKSPACE_SNAPSHOT_BUCKET` 指向已有的桶;建桶晚于 server 起是编排里的常态,所以缺桶在 `STORE_LOCK_WAIT_MS` 窗内重试、到窗才拒);连不上 / 403 / 5xx 这些证明不了桶缺的答复不拒启,走 fail-open 兜底口 `server.snapshot-bucket.presence-unproven`。起服之后桶才没的(被删),或起服核证明不了的部署:读 `latest` 得 `404 NoSuchBucket` ⇒ 这条 run **连沙箱失败**(`
|
|
2881
|
-
- **读 `latest` 失败**(非 404 的 HTTP 错、网络错)、**读或弃提交围栏那一行失败**或**读会话住客失败**(会话店报错、答出的不是住客令牌,或没在 `rpcTimeoutMs`〔30 秒,与读围栏行、读 `latest` 同一只墙〕内答 —— 挂住的会话店不再让 run 的起步永挂)⇒ 这条 run 连沙箱失败(`connect_failed`,工具调用报沙箱不可用;停驻 run
|
|
2927
|
+
- **快照桶不存在**(`WORKSPACE_SNAPSHOT_BUCKET` 指的桶没建):**起服拒启**(k8s 车道配了快照存储时,server 在打开任何店之前核这只桶;拒句点名桶名、`MINIO_ENDPOINT` 的显示安全形与出路 —— 建桶,或把 `WORKSPACE_SNAPSHOT_BUCKET` 指向已有的桶;建桶晚于 server 起是编排里的常态,所以缺桶在 `STORE_LOCK_WAIT_MS` 窗内重试、到窗才拒);连不上 / 403 / 5xx 这些证明不了桶缺的答复不拒启,走 fail-open 兜底口 `server.snapshot-bucket.presence-unproven`。起服之后桶才没的(被删),或起服核证明不了的部署:读 `latest` 得 `404 NoSuchBucket` ⇒ 这条 run **连沙箱失败**(`env.snapshot_bucket_missing`,句子带 `snapshot_bucket_missing`、桶名与出路;码在引擎的可重试表之外 —— 再问也是同一个答),一只 pod 都不建,另有一行 `workspace_snapshot_bucket_missing`(`space` / `bucket` / `code` / `effect`),每只执行环境至多一次;**不再**读成「空间第一条 run」而给一个空目录、每轮只留下一条不点名桶的存失败。无 `NoSuchBucket` 的 404(桶在、键不在;代理的 404)仍是「空间第一条 run」。**恢复归档那一发**(停驻续跑;或 `latest` 读之后、取归档之前桶没了)得 `404 NoSuchBucket` 同一读法:pod 把存储的答复原样交回、由 worker 用同一只判据读 ⇒ 同拒(句子带 `snapshot_bucket_missing`、桶名与出路)、同一行(停驻车道带 `sessionId`,不带 `space`)、刚建的 pod 释放,这只执行环境此后每次连接答同一拒;此前读成悬空恢复点(`workspace_latest_dangling`),续跑在空目录上照跑。无 `NoSuchBucket` 的 404 仍是悬空恢复点。
|
|
2928
|
+
- **读 `latest` 失败**(非 404 的 HTTP 错、网络错)、**读或弃提交围栏那一行失败**或**读会话住客失败**(会话店报错、答出的不是住客令牌,或没在 `rpcTimeoutMs`〔30 秒,与读围栏行、读 `latest` 同一只墙〕内答 —— 挂住的会话店不再让 run 的起步永挂)⇒ 这条 run 连沙箱失败(`connect_failed`,工具调用报沙箱不可用;停驻 run 续跑时的恢复同样失败;会话行在而**不带住客令牌**那一形是存储数据缺陷、再读也是同一个答 ⇒ `env.occupant_missing`,出路给行补令牌或删会话),**不会**悄悄给一个空目录、也不猜「没有提交在飞」—— 「以为恢复了其实没有」比失败更坏。读住客失败时一只 pod 都不建,另有一行 `workspace_space_unreadable_occupant`(`sessionId` / `code`:会话店错误的码,不带正文;读超时的码是 `incarnation_read_timeout`),每条 run 至多一次。修好存储 / 数据库后重跑,或设 `WORKSPACE_PERSIST=off` 即恢复。
|
|
2882
2929
|
- **`latest` 指向的快照对象不在了**(被删 / 被只盖 `.tar.gz` 的生命周期规则清掉)⇒ 沙箱**照常起**:一行 `workspace_latest_dangling`(`lane: "space"` / `space` / `key` / `deleted`),删掉悬空的 `latest`,这条 run 从空目录开始,它的 run 末快照成为新的 `latest`(数据已被运维规则清走:响亮、可继续)。指针删不掉 ⇒ 同一行 `deleted: false` + `error`,下一条 run 再说一次。**打包过的停驻快照对象不在了**(`kata-…` 形,同样被清走)⇒ 同一条规则、同一行名:续跑**照常起**,一行 `workspace_latest_dangling`(`lane: "park"` / `key` / `sessionId`),这条腿从空目录开始(停驻车道没有指针可删;空间开着时它的 run 末快照成为新的 `latest`)。7.142.x 及以前这一形不出任何行。
|
|
2883
|
-
- **`latest` 指向的快照在、却拿不回来**(桶答了却不是 200 / 解压失败 / 超过快照时限 / 传输中断)⇒ 这条 run **仍然连沙箱失败**(`
|
|
2930
|
+
- **`latest` 指向的快照在、却拿不回来**(桶答了却不是 200 / 解压失败 / 超过快照时限 / 传输中断)⇒ 这条 run **仍然连沙箱失败**(`env.sandbox_refused`:这只执行环境记住的拒)、**不**退到空目录 —— 用户的改动还在桶里,静默空目录 = 让人以为丢了。**一条 run 只恢复一次**(同一只执行环境上并发的连沙箱 —— 显式 `connect()` 与首个工具调用的懒连接 —— 共用同一次建连:一只 pod、一次恢复、一个终局,被拒也是同一个拒;恢复还没完成时才到的工具调用和 `reconnect` 也等这一次建连 —— pod 先于它的工作区存在,不在半恢复的 `/workspace` 上先跑):瞬时类(`timeout` 超过快照时限 / `transport` 传输中断:执行通道断了,或 pod 取包的 GET 没拿到完整应答 —— 连不上、被重置、传到一半被截)在恢复这一步里换一只新 pod 再试一次(约 1 秒后),再试成了 ⇒ 照常起、不出行;`store_busy`(桶答 `408` / `429` / `500` / `502` / `503` / `504` —— 「现在不行」,同一请求再发可能换答案)同属瞬时类;非瞬时类(`download` 桶答了、答的是其余非 200 —— 如 `401` / `403` / `501`;`untar` 包完整下来了却解不开)不重试。每次没成的尝试,新起的 pod 当场删掉(残缺目录既不给工具用,也不会在 run 末被快照回去覆盖 `latest`)。恢复终局是拒 ⇒ **恰一行** `workspace_restore_failed`(`space` / `snapshotId` / `class` = `store_busy` \| `download` \| `untar` \| `timeout` \| `transport` / `attempts` = 这次恢复的尝试次数(`1` 或 `2`)/ `boundMs` = 每次尝试的时限 / `error`,预签 URL 已脱敏),这条 run 之后的每次沙箱操作都答**同一句**拒(不再建 pod、不再读 `latest`、不再出行);建 pod 本身失败不是恢复的结局(不出这行,下一次操作重来)。拒句写明类别与尝试次数,点名两条出路:**调大 `WORKSPACE_SNAPSHOT_TIMEOUT_MS`**(大工作区撞上界),或 **`WORKSPACE_PERSIST=off` 跑一轮**(空目录起,不删任何快照;改回 `space` 后下一条 run 照常恢复那一份)。没有「删指针」的接口:丢弃这份快照 = 丢弃用户数据,要做就由运维在对象存储侧有意识地删 `<前缀>/<化身>/space/latest`(下一条 run 从空目录起)。与上一条「悬空」分开:那是对象**不在**(没东西可恢复 ⇒ 空目录 + 响亮),这是对象**在**而拿不回来(⇒ 拒)。
|
|
2884
2931
|
- **run 末提交围栏失守、上传失败或 `latest` 写失败** ⇒ 一行 `workspace_snapshot_failed`(`space` / `stage` = `fence` \| `upload` \| `pointer` / `code` / `error`,预签 URL 已脱敏),这条 run 在 `GET /v1/fleet/stream` 上的终态 task 帧带 `workspaceSnapshot: "failed"`;pod 照删;`latest` 不动 ⇒ 下一条 run 恢复的是**上一份**。`latest` 只指向真写出的对象:run 末保存走到上传那一步时沙箱 pod 已不在(它在提交围栏认领期间消失)也按上传失败处理(`stage: upload`、`code: connect_failed`),不铸一个没有对象的 snapshotId 去改指针。**上传成没成只看 worker 对那只对象的回读**(预签 `HEAD`,2xx = 在;两条车道同一判据,停驻挂起也只在回读之后才把 snapshotId 交给引擎):pod 里 curl 报的退出码与 HTTP 状态只用来解释失败 —— curl 拿到 3xx(不跟随)退出 0 而对象不在 ⇒ 上传失败(`error` 里点名回读结果与 pod 报的状态);对象已经落下、curl 才丢了应答(非零退出)⇒ 算存成。`latest` 在回读之后才动。**`latest` 写(以及悬空恢复点删 `latest`)的应答没回到 worker**(请求抛出:连接重置、时限到点、被拒的重定向)⇒ 回读一次指针定结局:指着这一份(删:已不在)⇒ 算成;否则 / 回读失败 ⇒ 失败(`stage: pointer`)。回读只在那一写的期限之内作数(run 末那一写的期限 = 提交围栏的期限;过了期限才答 / 来不及回读 ⇒ 失败,`error` 写「deadline passed」,不删旧份)。存储答了非 2xx ⇒ 照旧直接算失败。上传与对象回读共用这次保存的数据界(`WORKSPACE_SNAPSHOT_TIMEOUT_MS` 减去提交前等待的时长),回读不另开一只时限。
|
|
2885
2932
|
- **run 末快照保存前一律先停 pod 里的进程并确认**(与那一刻有没有命令在飞无关)。命令「结束」(自己退出、被取消、超时)不等于它起的进程结束(断开 exec 套接字不会让 pod 里的进程停),在飞登记里已经没有命令也不能证明 pod 静了,所以保存前都先杀掉 pod 里除 init 与容器保活进程外的全部进程并确认;没连过沙箱的 run 没有可存的工作区,不走这一步。**run 结束时还有命令在跑**(取消 / 超时结束的 run 的命令没来得及停)⇒ 杀之前**先等**它们结束:最长一只 `rpcTimeoutMs` 墙(缺省 30 秒;等待算在这次提交的快照时限里,上传拿到的是剩下的);等不到的还要断开仍开着的 exec 套接字(那条命令的调用方读到 `aborted`),**照样保存**,并出一行 `workspace_snapshot_commands_cut`(`space` / `inFlight` / `waitedMs` / `killed`)。**没能确认进程停下**(杀进程那一步失败,或几次复查后仍有活进程;有没有命令在飞、等到与否都一样)⇒ **不保存**:一行 `workspace_snapshot_failed`(`stage: upload`、`code: command_in_flight`),`latest` 不动 —— 可能还在变的工作区不当 `latest`。**确认不了的四种形**(工作区不存,下一轮恢复的是上一份 —— 本轮的工作在下一轮看不到;7.131.x 在「run 结束时没有命令在飞」时照存):镜像里经 `sudo` / setuid 程序起的、以别的 uid 跑的进程(`kill -9` 没有权限,例如 `sudo -u postgres` 起的库进程)· 不可中断睡眠(D 态)的进程 · `podSpecPatch` 打开了 `shareProcessNamespace`(同 pod 别的容器的进程也在 `/proc` 里)· 镜像里没有 `tr`、而容器保活进程不是 1 号进程(pod 起动先跑包源钩子的那一形:认不出保活进程、把它杀掉,容器随之结束)。**出路**:k8s 车道镜像以一个非 root 用户跑、不经 sudo / setuid 起常驻进程,带 `tr`,不开 `shareProcessNamespace`;按 `workspace_snapshot_failed{stage: upload, code: command_in_flight}` 告警;不需要跨轮保留的部署设 `WORKSPACE_PERSIST=off`。杀进程脚本只在「该杀的都不活了」时退出 0(僵尸进程算死:容器保活进程不收尸)。从 destroy 开始起这只执行环境不再收新命令(工具调用报沙箱已销毁)。`command_in_flight` 的拒只留给停驻挂起(run 还活着,撕裂的归档才是真风险)。此前 run 结束时只要还有命令在飞,快照就整份被拒(`workspace_snapshot_failed`,`stage: upload`),`latest` 不动,下一轮恢复上一份 —— 取消 = 丢掉这一轮的工作。
|
|
2886
|
-
- **pod 被集群在准入时拒**(pod 建出来后、跑起来之前就到了 `Failed`:如 `K8S_SANDBOX_IPV6=disabled` 而 kubelet 没放开那两只 sysctl 时的 `SysctlForbidden`、节点亲和不符、节点放不下)⇒ 这只执行环境**记住这次拒**直到销毁:这条 run
|
|
2933
|
+
- **pod 被集群在准入时拒**(pod 建出来后、跑起来之前就到了 `Failed`:如 `K8S_SANDBOX_IPV6=disabled` 而 kubelet 没放开那两只 sysctl 时的 `SysctlForbidden`、节点亲和不符、节点放不下)⇒ 这只执行环境**记住这次拒**直到销毁:这条 run 的每次操作答同一句,码 `env.sandbox_refused`(沙箱不可用;句子点名 pod 的阶段与 kubelet 的原因),**不再每次操作重建 pod**(此前一条 run 里可建出几十只 `Failed` pod),与「恢复被拒」同一只记住的槽、同一个写口;一行 `sandbox_pod_refused`(`pod` / `phase` / `reason` / `detail`:kubelet 的原话,截断 / `sessionId`),每只执行环境至多一次。重跑这条 run 是一只新的执行环境,重新问集群。API 拒建 pod(HTTP 非 2xx)不在此列,仍是那一次尝试的失败:命名空间配额(403 `exceeded quota`)⇒ `connect_failed`(别的 pod 结束就有额度,车道在自己的重试界内再建),其余 401 / 403 ⇒ `auth_failed`(沙箱 Role 不许)。
|
|
2887
2934
|
- **删最老的失败** ⇒ 一行 `workspace_snapshot_prune_failed`,不影响本轮(空间里只是多留几份)。
|
|
2888
2935
|
- **空间结束时回收快照对象失败**(列举失败、列举被截断〔分区里超过 1000 个对象〕、某个对象删失败)⇒ 会话照删,每个失败的分区 / 阶段一行 `workspace_space_reclaim_failed`(`space` 前缀 / `sessionId` / `lane` = `space` \| `park` / `stage` = `list` \| `delete` \| `budget` \| `seat_threw`(回收座违约抛了,响亮接住、不炸进程)/ `count` / `error`,预签 URL 不进行;**一次调用里同类(分区 × 阶段)的失败合成一行**:`count` = 撞上它的空间数,`space` / `sessionId` / `error` 是调用里排第一的那个 —— sweep 一拍几百个空间遇上同一个 RBAC 漂移只出一行;卷那一行 `workspace_cache_reclaim_failed` 同形)+ 计数 `server.workspace-space.reclaim-failed`(仍逐空间计);
|
|
2889
2936
|
`budget` = 回收座这一次调用的绝对截止(= 快照时限;会话删除 = 一个空间,托管留存 sweep = 每个域每拍一次;卷回收也在内)到点,这个空间余下的列举与删除没做 —— 截止在轮到这个空间之前就过了 ⇒ 它一个请求都没发,同样记进 `budget` 那一类(配了缓存卷的,它的卷记进 `workspace_cache_reclaim_failed{reason: "budget"}` 那一类)—— `budget` 类行里的 `count` 就是被截止留下的空间数。截止之前的失败互不牵连(另一个分区、构建缓存卷照收)。对象留在桶里,按行里的空间前缀 / 会话 id 去桶里手清,或等桶的生命周期规则;到期会话已删、不会被下一拍重新列出;一拍最长 = 有结束空间的域数 × 快照时限,超过 sweep 间隔时中间的拍被跳过(防重入守卫照旧);**快照时限 ≥ 2 × sweep 间隔(= 租约 TTL)时,一个域内的回收可把本副本的租约耗过期 ⇒ 这一拍余下的域不跑、下一拍再起(一行 `retention_sweep_lease_lost`)—— 配法:快照时限要明显小于租约 TTL,即 `WORKSPACE_SNAPSHOT_TIMEOUT_MS`(毫秒)< 2 × `RETENTION_SWEEP_INTERVAL_SEC` × 1000 再留出该域 SQL 步骤的余量;缺省时限 300 000 ms 对 sweep 间隔 ≥ 300 s 的部署成立,间隔更短的部署调大间隔或调小时限(时限下限 30 000 ms)**。
|
|
@@ -2943,7 +2990,7 @@ k8s 车道每条 run 一只新 pod(pod 寿命 = 泄漏护栏,不跨 run 复用)
|
|
|
2943
2990
|
供给器不在,`claim_unbound`)、卷绑上了而挂着它的 pod 起不来(挂载失败 / 卷所在节点没了,`claim_unmountable`)—— 后两种把等它的那只 pod 删掉、换一只不挂卷的 —— 、没有这只会话(会话店答「没有」,`incarnation_unknown`)⇒ run **照常起**:不挂卷、不注入缓存 env,
|
|
2944
2991
|
计数 `server.workspace-cache.unavailable`(fail-open 登记表第 129 行)+ 一行 `workspace_cache_unavailable`(`space` / `claim` / `reason` / `error`),每条 run 至多一次。
|
|
2945
2992
|
**没绑上 / 没挂上(`claim_unbound` / `claim_unmountable`)按空间记一个快照时限**:这个空间的后续 run 在窗内直接不挂卷 —— 不发 claim 请求、不起等卷的 pod(此前每条 run 都等满一个快照时限、删掉第一只 pod 再起第二只),照样计数 + 一行(`error` 点名「记着的」);窗过了再问一次(运维补上缺省 StorageClass 后,窗后第一条 run 就挂上)。记忆放在部署的 per-run 绑定里(进程内、不跨副本、不落盘)。
|
|
2946
|
-
- **读住客失败 ⇒ 拒这一轮**:会话店报错(或答出的不是住客令牌)不是「没有空间」—— 与 9.3b
|
|
2993
|
+
- **读住客失败 ⇒ 拒这一轮**:会话店报错(或答出的不是住客令牌)不是「没有空间」—— 与 9.3b 同一只拒(店报错 / 读超时 `connect_failed`;会话行不带住客令牌 `env.occupant_missing`)(一只 pod 都不建,一行 `workspace_space_unreadable_occupant`,不计数);拒句点名开着的旋钮
|
|
2947
2994
|
(只开卷时是 `WORKSPACE_CACHE=off`)。重跑即重新读。
|
|
2948
2995
|
- **委派子代 / 后台代理不挂卷**(与不开空间同一条法:它们与父并发,不共享父的空间)—— 不计数、不出行。
|
|
2949
2996
|
- **卷的寿命 = 空间的寿命**:pod 删卷留;**空间结束时随之回收** —— `DELETE /v1/sessions/:id` 的删除协调器与托管留存 sweep 删掉会话树之后,都按标签
|
|
@@ -2987,6 +3034,9 @@ k8s 车道每条 run 一只新 pod(pod 寿命 = 泄漏护栏,不跨 run 复用)
|
|
|
2987
3034
|
Kata 运行时把 namespaced sysctl 设在客体内核里,作用在客体的网卡上。
|
|
2988
3035
|
- **pod 的 sysctl 只有这一个属主**:嵌入方的 pod-spec 补丁带 `podSecurityContext.sysctls` ⇒ 拒(补丁是浅合并,会把这里的关闭项整只换掉)。
|
|
2989
3036
|
|
|
3037
|
+
**集群 API 凭据**(`REMOTE_EXEC=k8s` 的起服前提):显式 `K8S_API_URL` + `K8S_TOKEN` + `K8S_CA_CERT_B64`(实验室 `K8S_INSECURE_TLS=true`)优先、in-cluster 服务账号补缺,逐件判(不读 kubeconfig)。缺哪一件 ⇒ **起服拒**
|
|
3038
|
+
`config.k8s_api_credentials_missing`,拒句点名缺的那一件与两条出路(给凭据 / 改车道 `REMOTE_EXEC=none` 或别的车道);凭据缺时下面的起服自检不发。起服之后令牌失效:每条 run 铸环境之前探一次,集群答 401 ⇒ run `failed` 带 `env.sandbox_refused`(模型零调用、零 pod;同步腿 409);403 / 5xx / 探问没答不拦。
|
|
3039
|
+
|
|
2990
3040
|
**起服自检**(`REMOTE_EXEC=k8s`,起服一次、不挡起服):服务用自己的 k8s 账号读节点表(`nodes` get / list,集群级)与沙箱 ns 的 NetworkPolicy(`networkpolicies` get / list),
|
|
2991
3041
|
按「选中沙箱 pod 的 Egress 策略的放行规则并集」判每个节点的每个 InternalIP / ExternalIP。读出的缺口每个一行 warn `sandbox_egress_policy_gap`(带 `effect` 后果句)并计数
|
|
2992
3042
|
`server.sandbox-egress.policy-gap`(fail-open 登记表第 135 行,记债);零缺口一行 info `sandbox_egress_policy_checked`;自检本身半途抛了一行 error `sandbox_egress_policy_check_crashed`。
|
|
@@ -3218,6 +3268,7 @@ GET /v1/capabilities?permissionMode=auto (AUTONOMY=plan 的部署)
|
|
|
3218
3268
|
`{ requested, effective:"default", foldedBy:"operator_deny" }`。auto 的两键任一为 `false` 即拒,另一键的 `true` 翻不回;`true` / 缺席 = 不拒。
|
|
3219
3269
|
两键的值不是布尔 ⇒ 当作契约破损,这个 principal 的放大面整份 fail-closed。center 取数硬失败的降级窗(最长约 10 秒,之后整份重抓)里
|
|
3220
3270
|
bypass 与 auto 同样折回。7.132.x 及更早这两键被服务端丢掉:组织关了 bypass,引擎照放。
|
|
3271
|
+
委派子代腿(同步 / 后台 / fork / 复活;主体从父腿继承)按同一个主体同样执行,父腿跑着时中心才收回的也落在此后派的子代上(7.151.0 起;此前子腿不问,只靠父腿出生那一刻的模式天花板)。
|
|
3221
3272
|
部署级的 `TASK_WRITE_FACE_ESCALATION` 管「这台部署给不给任务层掀写围栏」,本条管「组织给不给这个人」—— 两道都过才是 bypass;
|
|
3222
3273
|
能力位 `taskWriteFaceOpen` 只答前一道(部署级,看不到 per-principal 的拒),实际模式读回执。
|
|
3223
3274
|
|
|
@@ -3231,9 +3282,12 @@ bypass 与 auto 同样折回。7.132.x 及更早这两键被服务端丢掉:组
|
|
|
3231
3282
|
|
|
3232
3283
|
**plan 只有一个判官 —— 引擎的 plan 模式(7.122.0 起)**:请求顶层 `permissionMode:"plan"`、`settings.permissions.defaultMode:"plan"`、
|
|
3233
3284
|
运维 `AUTONOMY=plan` 与模型自己调 `EnterPlanMode`,落到的都是同一个模式词。提交之后,一条 run 的模式词只有一个源 —— 存储的提交体顶层
|
|
3234
|
-
`permissionMode
|
|
3235
|
-
(请求不带模式词 ⇒ `plan`;带任何词 ⇒ 钳成 `plan`;bundle 的 `defaultMode` 不动,顶层赢)
|
|
3236
|
-
|
|
3285
|
+
`permissionMode`;写它的是提交入口、在飞切档(`POST /v1/runs/:id/permission-mode`)、下面的 `plan_review` 写回与续跑重放。运维 `AUTONOMY=plan` 是**提交入口的模式词地板**:受理时盖进提交体
|
|
3286
|
+
(请求不带模式词 ⇒ `plan`;带任何词 ⇒ 钳成 `plan`;bundle 的 `defaultMode` 不动,顶层赢);不按段续跑重钳 —— 停驻的 run 被续跑之前(`/decide` · `/resume` · `/wake` · `plan_review`)
|
|
3287
|
+
体上的词过一次**现**地板(与受理同一步、读此刻的配置):事后(热改或重启时)改成 `AUTONOMY=plan`,停驻 run 体上的 `bypassPermissions` / `auto` / `dontAsk` / 无词在下一次续跑
|
|
3288
|
+
钳成 `plan`(钳过的词随续跑写回,之后照它读;人批了它的计划再出 plan),`plan_review` 批准写在体顶层的 `default` / `acceptEdits` 原样 —— 服务端在写下那一格的同一笔里记下是谁写的(7.152.0 起),
|
|
3289
|
+
所以提交或在飞切档带来的同字词照钳,只在 bundle `defaultMode` 里的照钳,7.152.0 之前写下的停驻行(没有这条记录)也照钳(已批过计划的要再批一次);
|
|
3290
|
+
那一腿的生效词看 `wiring_manifest.permissionMode`(钳制通告 `permission.entry_mode_clamped` 只在受理门发)。请求的词真被折了(带了比 `plan` 松的词)⇒ 7.129.0 起这条会话的流(`POST /v1/tasks/stream` / `POST /v1/runs` 的事件账)
|
|
3237
3291
|
在开口那一拍多一帧 `engine_notice` `permission.entry_mode_clamped`,`detail: { requested, effective, ceiling, sessionId }`;没带词、带的就是 `plan` ⇒ 不发。工具表与 `default` 同面(写手、委派工具 `Agent` 都在),
|
|
3238
3292
|
写与非只读调用在**调用时**由引擎的 plan 门问(有人可答)/ 拒(无人可答)—— 问是一张审批卡,人批了就写,
|
|
3239
3293
|
**射程是写面根围栏之内**(任务 `cwd`、引擎宣告的可写目录〔记忆目录、会话 scratchpad〕、请求的 `additionalDirectories`):批准只清模式门,引擎文件工具自己的根围栏不受批准影响,
|
|
@@ -3750,7 +3804,7 @@ WebSearch 工具的 `tool_result` 错误文本,回到模型的对话里,**不是
|
|
|
3750
3804
|
| env | 缺省 | 说明 |
|
|
3751
3805
|
|---|---|---|
|
|
3752
3806
|
| `IMAGE_API_BASE` | 必填 | image-api 根(尾斜杠去掉) |
|
|
3753
|
-
| `BAKE_RUNNER_TOKEN` | 必填 | claim / heartbeat 的运维主体 bearer
|
|
3807
|
+
| `BAKE_RUNNER_TOKEN` | 必填 | claim / heartbeat 的运维主体 bearer。不进日志、不进任何子进程:7.151.0 起它是本包的自有凭据(起服第一步按名与按值向引擎声明,与服务进程同一份)⇒ `BAKE_ENV_ALLOW` 点到它 ⇒ 拒启;同值换名的副本同样不交给配方脚本与主机命令,`BAKE_ENV_ALLOW` 点到副本也拒启(此前只靠形状剥:点名放回与换名副本照交)。按值那一半只对引擎收作凭据的值成立:令牌不足 8 字符 / 是占位词 / 一个字符重复 ⇒ 起服一行 `own_credential_value_not_withheld { name: "BAKE_RUNNER_TOKEN" }`,只按名扣,副本照交 —— 给它一个真随机串 |
|
|
3754
3808
|
| `BAKE_RUNNER_ID` | `bake-runner-<HOSTNAME>` | 认领时报给 image-api 的 runner 名 |
|
|
3755
3809
|
| `RECIPE_REF` | `HEAD` | 配方 checkout 的 ref(`HEAD` = 用现成 checkout,不 fetch) |
|
|
3756
3810
|
| `RECIPE_DIR` | `/opt/recipes` | 配方仓 checkout 根(build.sh 的 cwd) |
|
|
@@ -3762,7 +3816,7 @@ WebSearch 工具的 `tool_result` 错误文本,回到模型的对话里,**不是
|
|
|
3762
3816
|
|
|
3763
3817
|
**子进程 env(7.103.0,剥密收口的残余面)。** runner 起的每一只子进程组 —— `build.sh`,以及主机命令 `git fetch` / `docker push` /
|
|
3764
3818
|
`docker image inspect` / `df` —— 拿到的 env = 本进程 env **剥密**:core 的一变量一判(7.106.0 起 = core 7.35.0,参照实现 CC 2.1.280 的形:
|
|
3765
|
-
凭据名表 / `OTEL_*` 前缀 / `SEMA_` 命名空间 / 名字形状 / 值里带凭据,动作恒为整只删)∘ 服务配置目录里的 secret 名 ∘ 名单型旋钮原文。runner 自己的
|
|
3819
|
+
凭据名表 / `OTEL_*` 前缀 / `SEMA_` 命名空间 / 名字形状 / 值里带凭据,动作恒为整只删)∘ 本包自有凭据(服务配置目录里的 secret 名 ∪ runner 自己的 `BAKE_RUNNER_TOKEN`,按名,并按值扣同值换名的副本)∘ 名单型旋钮原文。runner 自己的
|
|
3766
3820
|
`BAKE_RUNNER_TOKEN` 在内。剥了什么在第一次起组时记一行 `secret_env_scrubbed`(warn,site = `server.bake-runner.spawn-env`,带 `allowed` 与出路句;只键名,
|
|
3767
3821
|
不带值)。`PATH` / `HOME` / `NO_PROXY` / `DOCKER_CONFIG` / `BAKE_IMAGE_REGISTRY` / `RECIPE_GITSHA` 这类非密钥键照常传。
|
|
3768
3822
|
docker 推送的鉴权走构建宿主上的 docker 凭据存储(`docker login`),不走 env,不受影响。
|
|
@@ -3774,7 +3828,7 @@ docker 推送的鉴权走构建宿主上的 docker 凭据存储(`docker login`),
|
|
|
3774
3828
|
**`BAKE_ENV_ALLOW=NAME,NAME`。** 配方真要一枚密钥形 env(例如 build.sh 里自己做 registry 登录要 `REGISTRY_PASSWORD`,或
|
|
3775
3829
|
`git fetch` 的 askpass 读 `GIT_TOKEN`)⇒ 点名它,runner 把该键从本进程 env **原样**放回给每一只子进程组(部署方显式承担)。
|
|
3776
3830
|
与服务侧 `LSP_ENV_ALLOW` 同一只解析器、同一只放行谓词:
|
|
3777
|
-
- 形错(空段 / 尾逗号 / 非变量名形,如 `$NPM_TOKEN`、`a b`、`NAME=value` 整段贴入 / 点名任一只名单型旋钮 / 点名本服务自有凭据名,7.132.0 起;点名值是本服务某一枚凭据的另一个变量,7.149.0 起)⇒ runner **拒启**,
|
|
3831
|
+
- 形错(空段 / 尾逗号 / 非变量名形,如 `$NPM_TOKEN`、`a b`、`NAME=value` 整段贴入 / 点名任一只名单型旋钮 / 点名本服务自有凭据名,7.132.0 起;点名值是本服务某一枚凭据的另一个变量,7.149.0 起;点名 runner 自己的 `BAKE_RUNNER_TOKEN` 或装着同一个值的另一个变量,7.151.0 起)⇒ runner **拒启**,
|
|
3778
3832
|
`bake_runner_fatal` 那一行点名旋钮与第几段(`entry #k of n`,一句话只有这一套序号),**不回显值**(自有凭据那一形与服务侧同一句:说明这是本部署自己的凭据、给出路,并说明引擎拒它进任何名单);
|
|
3779
3833
|
- 本进程环境里没有的名 ⇒ 起服一行 `config_env_entry_rejected`(只报序号)、不放行;
|
|
3780
3834
|
- 旋钮原文本身按凭据类对待,不进子进程;
|
|
@@ -3845,15 +3899,18 @@ web-admin 拉取 / fleet 公告 / 凭证续签、WebSearch、对象存储、OTLP
|
|
|
3845
3899
|
① **运维日志** 一行 `outbound_connect_failed { targetHost, code, proxyInUse, proxyHop?, proxyReadAtMs, sinceBootMs, hint }` —— `proxyInUse` = 这一跳走的代理
|
|
3846
3900
|
**变量名**(`HTTP_PROXY` / `HTTPS_PROXY`,不打值;直连 ⇒ `null`),`proxyHop` = 只在这一跳走了代理时在场的**原句**(上游错误原文,含代理 host:port,凭据位已脱敏;
|
|
3847
3901
|
这是代理地址在运行时失败里唯一的去处,wire 上没有),`proxyReadAtMs` = 代理变量被读进来的时刻(= 起服那一拍),`sinceBootMs` = 进程已跑多久
|
|
3848
|
-
—— 两者一对照就知道「起服之后 VPN /
|
|
3902
|
+
—— 两者一对照就知道「起服之后 VPN / 代理是不是换过」;`hint` 的出路句 = ③ 那张表的 `remedy`(属一次模型调用的直连一跳按失败类,其余是通用句);全进程的出网都算(模型、中心、工具 …),每条失败的请求一行(重试各算一次)。
|
|
3849
3903
|
② **诊断面** `GET /v1/diagnostics/wiring` 的 `outbound` 段:`{ proxy: { http, https }, noProxy, loopbackDirect, proxyReadAtMs, lastConnectFailure }` ——
|
|
3850
3904
|
代理只报**名字**(哪只变量供的;`https` 在 `HTTPS_PROXY` 缺席时回落 `HTTP_PROXY`)、`NO_PROXY` 只报在不在,地址一个字节都不上本段;
|
|
3851
3905
|
`lastConnectFailure` = 本进程最近一次建连失败 `{ targetHost, code, proxyInUse, atMs }`(没有过 ⇒ `null`)。
|
|
3852
3906
|
③ **用户面**:一次**模型调用**因建连失败而终态(它的最后一条请求在建连时失败;5xx / 中途断流 / 取消都不算;腿里的辅助调用 ——
|
|
3853
3907
|
WebFetch 摘要、压实、提示建议、分类器 —— 同判:说的是端点够不着,不是 run 失败了)⇒ 这条 run 的流 / 账本上一帧
|
|
3854
|
-
`engine_notice` `server.model_unreachable`,`detail = { code, targetHost, proxyInUse?, remedy
|
|
3855
|
-
(契约附录 D.3;每腿每目标一次;流式 / 后台 / 续跑三条腿有,同步非流式腿没有投递口 ⇒ 只有 ① ②)
|
|
3856
|
-
|
|
3908
|
+
`engine_notice` `server.model_unreachable`,`detail = { code, targetHost, proxyInUse?, remedy, sessionId }`
|
|
3909
|
+
(契约附录 D.3;每腿每目标一次;流式 / 后台 / 续跑三条腿有,同步非流式腿没有投递口 ⇒ 只有 ① ②)。**出路按失败类分(7.152.0 起;此前对所有失败类说同一句)**:`remedy` 与正文末句取自一张闭表的同一行,按 `code` 的失败类选,**走了代理的一跳(`proxyInUse` 在场)一律说通用句**:
|
|
3910
|
+
· 拒连(`ECONNREFUSED`,直连)⇒ 查那个地址上有没有服务在听(本机模型服务起了没有)、模型网关地址(`MODEL_GATEWAY_BASEURL` 或该模型条目的 `baseUrl`)配得对不对 —— `remedy` = `check that a service is listening at the model endpoint address; check the model gateway address configuration`,不提 VPN;
|
|
3911
|
+
· 主机名解析不了(`ENOTFOUND` / `EAI_AGAIN`,直连)⇒ 地址写错,或 DNS / VPN 不通 —— `remedy` = `check the model gateway address configuration; check DNS / VPN`;
|
|
3912
|
+
· 建连超时 / 无路由 / 网络不可达(`UND_ERR_CONNECT_TIMEOUT` / `EHOSTUNREACH` / `ENETUNREACH`)与任何走了代理的一跳 ⇒ 通用句,逐字同 7.151.x:`remedy` = `check VPN / proxy; restart if the proxy changed since boot` —— 查 VPN / 代理;代理或 VPN 在起服之后变过 ⇒ 重启 server(代理变量只在启动时读)。
|
|
3913
|
+
建议句(正文末句与 `remedy`)里没有配置值、代理地址、凭据(模型端点的 `host:port` 只在正文前半句与 `detail.targetHost`,部署自己声明的端点,与 7.151.x 同;代理只以变量名在 `detail.proxyInUse`)。按通告码与 `detail.code` / `detail.proxyInUse` 判,不要按整句匹配 `remedy` 或正文。没有旋钮。**会被它打扰的部署形**:辅助端点(auto 分类器 / WebFetch 摘要 / 提示建议 / 压实)单独部署且挂掉、
|
|
3857
3914
|
主模型正常 —— 用户每腿每目标会看到一帧、出路句是泛化的;读 `detail.targetHost` 分清是哪一个端点(它是部署自己声明的模型端点,对用户是新披露的事实;
|
|
3858
3915
|
代理地址不上),运维按同一目标对 `outbound_connect_failed` 对账。Bun 运行时三件都没有(它的原生 fetch 不经 undici 诊断通道)。
|
|
3859
3916
|
- **Bun 运行时(发布镜像 `CMD ["bun", …]` 与 `bun build --compile` 二进制)**:Bun 的 fetch 不读 undici 的全局 dispatcher,它**自己**读这三只变量
|
|
@@ -4008,7 +4065,7 @@ web-admin 拉取 / fleet 公告 / 凭证续签、WebSearch、对象存储、OTLP
|
|
|
4008
4065
|
(`GATE_INNODB_TEST_URL=""` 想关掉那条腿)⇒ `REMOTE_GATE_DSN_EMPTY` 红停;**缺席** ⇒ `REMOTE_GATE_DSN_ABSENT` 红停。脚本不再有共享库缺省
|
|
4009
4066
|
(旧形把空串 / 缺席回落到共享的 `sema_server_test` 等库,车QC 的锁形套在共享库上整表 DELETE 了别车的行)。要关一条腿:别在 `--dsn` 里点它;
|
|
4010
4067
|
要用:给按车库(`eval "$(node scripts/db-lane.mjs <车>)"` 建 `aiagent_test_<车>` / `sema_server_test_<车>`;起它时 shell 里已有的
|
|
4011
|
-
`GATE_*_TEST_URL` 跟着换成同一只车道库,没有就自己显式 export 三条指 k3s8 上那几只库)
|
|
4068
|
+
`GATE_*_TEST_URL` 跟着换成同一只车道库,没有就自己显式 export 三条指 k3s8 上那几只库);发车链的三台引擎坐标由起链者经环境交给启动器 `scripts/chain-launch.sh`(六个变量,缺席 / 为空 ⇒ 启动器退出码 11),
|
|
4012
4069
|
门 2 的真库组进组时各自换成自己的车道库(下一条)。
|
|
4013
4070
|
值**不进任何 argv**:经 ssh 的 stdin 送到远端 shell,再以 `docker run -e <名>`(只有名字)交给容器 —— 本机与 k3s8 的 `ps` 都看不见口令,
|
|
4014
4071
|
值里带 `&` / 空格也不会切断远端命令;值里有换行 ⇒ 红停。远端先 unset 点了名的每一条、只收点了名的名,核每一条都收到且解得开才起容器
|
|
@@ -4312,7 +4369,7 @@ docker run -d --name sema-server -p 8090:8090 \
|
|
|
4312
4369
|
-e MODEL_GATEWAY_BASEURL=https://<your-gateway>/v1 -e MODEL_ID=<your-model-name> -e MODEL_API_KEY=… \
|
|
4313
4370
|
-e SERVICE_AUTH_TOKEN=<随机长串> \
|
|
4314
4371
|
sema-server:<版本>
|
|
4315
|
-
# SERVICE_AUTH_TOKEN 不是起服必需,但没有它(
|
|
4372
|
+
# SERVICE_AUTH_TOKEN 不是起服必需,但没有它(也没接鉴权桥、没开 ALLOW_UNAUTHED_WRITES)提交任务一律 503 auth.service_token_required —— 第 5 步只验就绪,交任务前先配它。另一形是显式 ALLOW_UNAUTHED_WRITES=1:那时没有 service 令牌的 worker 只绑 127.0.0.1(自收窄),容器外经 -p 访问不到;7.148.0 起单用户部署(没设 REQUIRE_PRINCIPAL)上再写 BIND_HOST=0.0.0.0 把无鉴权写面暴露出去 ⇒ 起服拒(不变量 single-user-anonymous-boundary;进程看不见宿主把端口只发布到回环)—— 容器形一律配 SERVICE_AUTH_TOKEN。两形的取舍见 §0「监听绑址」段。
|
|
4316
4373
|
# 5. 验收 —— 就绪 + 版本
|
|
4317
4374
|
curl -fsS http://127.0.0.1:8090/readyz # {"ready":true}
|
|
4318
4375
|
curl -s -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>" http://127.0.0.1:8090/health # "version" 应等于你构建的 <版本>
|