@sema-agent/server 7.140.0 → 7.142.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 +505 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +142 -25
- package/dist/approval-ask-audit-store.d.ts +54 -38
- package/dist/approval-ask-audit-store.js +58 -39
- package/dist/approval-batch-census.d.ts +27 -0
- package/dist/approval-batch-census.js +27 -0
- package/dist/approval-card.d.ts +39 -24
- package/dist/approval-card.js +6 -3
- package/dist/approval-crash-convergence.d.ts +17 -7
- package/dist/approval-crash-convergence.js +94 -22
- package/dist/approval-deny-reasons.d.ts +34 -30
- package/dist/approval-deny-reasons.js +21 -6
- package/dist/approval-policy-settlement.d.ts +1 -1
- package/dist/approval-reconciler.d.ts +33 -1
- package/dist/approval-reconciler.js +43 -40
- package/dist/approval.d.ts +15 -0
- package/dist/approval.js +10 -0
- package/dist/audit.d.ts +4 -2
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +9 -6
- package/dist/auth-bridge.js +9 -3
- package/dist/boot/adoption.js +2 -1
- package/dist/boot/budget-tracing.d.ts +16 -0
- package/dist/boot/budget-tracing.js +10 -6
- package/dist/boot/device-lane.d.ts +11 -0
- package/dist/boot/device-lane.js +16 -0
- package/dist/boot/engine-lease.d.ts +24 -3
- package/dist/boot/engine-lease.js +9 -2
- package/dist/boot/execution-env.d.ts +24 -4
- package/dist/boot/execution-env.js +34 -27
- package/dist/boot/execution-lane.js +2 -1
- package/dist/boot/exit-boundary.js +5 -4
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/memory-consolidation.d.ts +1 -1
- package/dist/boot/memory-consolidation.js +3 -2
- package/dist/boot/parked-revive-gate.js +2 -1
- package/dist/boot/permission-rules-audit.d.ts +0 -28
- package/dist/boot/permission-rules-audit.js +2 -1
- package/dist/boot/read-deny-anchor-audit.js +2 -1
- package/dist/boot/reapers.d.ts +2 -2
- package/dist/boot/reapers.js +4 -3
- package/dist/boot/resolve-spec.js +18 -6
- package/dist/boot/retention-lane.js +5 -3
- package/dist/boot/runner-deps.js +16 -13
- package/dist/boot/runtime-caps.js +3 -2
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +8 -6
- package/dist/boot/shutdown.js +8 -2
- package/dist/boot/stage-04-stores.js +3 -2
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.js +11 -7
- package/dist/boot/stage-06-runners.d.ts +1 -3
- package/dist/boot/stage-06-runners.js +3 -2
- package/dist/boot/stage-07-capability-layer.d.ts +1 -2
- package/dist/boot/stage-07-capability-layer.js +10 -11
- package/dist/boot/stage-08-reapers.d.ts +1 -2
- package/dist/boot/stage-08-reapers.js +3 -2
- package/dist/boot/stage-09-leader.d.ts +1 -2
- package/dist/boot/stage-10-http-server.d.ts +1 -2
- package/dist/boot/stage-10-http-server.js +6 -4
- package/dist/boot/stores.js +13 -6
- package/dist/boot/web-admin.js +18 -17
- package/dist/boot/webfetch-summarize-lane.js +2 -1
- package/dist/boot/workflow-orchestration.js +3 -2
- package/dist/capabilities/builtin-tools.d.ts +2 -1
- package/dist/capabilities/builtin-tools.js +2 -4
- package/dist/capabilities/composite-members.d.ts +2 -1
- package/dist/capabilities/composite-members.js +2 -1
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +33 -0
- package/dist/capability-facts.js +32 -0
- package/dist/card-void.d.ts +38 -0
- package/dist/card-void.js +23 -0
- package/dist/config-catalog.js +12 -8
- package/dist/config-provider.d.ts +13 -13
- package/dist/config-provider.js +19 -33
- package/dist/config-types.d.ts +39 -10
- package/dist/config.d.ts +6 -0
- package/dist/config.js +72 -49
- package/dist/delegated-session-owner.d.ts +21 -19
- package/dist/delegated-session-owner.js +1 -1
- package/dist/device-store.d.ts +7 -0
- package/dist/device-store.js +3 -0
- package/dist/execution-config-root.d.ts +22 -0
- package/dist/execution-config-root.js +35 -0
- package/dist/execution-lane-caps.d.ts +50 -2
- package/dist/execution-lane-caps.js +90 -13
- package/dist/execution-placement.d.ts +3 -0
- package/dist/execution-placement.js +7 -0
- package/dist/fleet/drain-entry.d.ts +3 -0
- package/dist/fleet/fleet-bus.d.ts +6 -3
- package/dist/hooks/hook-runner.d.ts +6 -0
- package/dist/hooks/hook-runner.js +30 -1
- package/dist/hosted-posture.d.ts +8 -0
- package/dist/hosted-posture.js +4 -0
- package/dist/http/admission.js +3 -3
- package/dist/http/caller-trust.d.ts +3 -2
- package/dist/http/caller-trust.js +2 -1
- package/dist/http/dispatch.js +8 -2
- package/dist/http/execution-context.d.ts +2 -2
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/live-frame.d.ts +24 -0
- package/dist/http/live-frame.js +16 -0
- package/dist/http/principal-gate.d.ts +3 -1
- package/dist/http/principal-gate.js +17 -8
- package/dist/http/resume-legs.js +42 -29
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/approvals-assistant.js +1 -0
- package/dist/http/routes/attachments.js +18 -0
- package/dist/http/routes/capabilities.js +10 -6
- package/dist/http/routes/diagnostics.d.ts +0 -19
- package/dist/http/routes/diagnostics.js +16 -2
- package/dist/http/routes/memory-bundle.d.ts +2 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-policy.js +27 -7
- package/dist/http/routes/run-permission-mode.d.ts +75 -0
- package/dist/http/routes/run-permission-mode.js +170 -0
- package/dist/http/routes/runs.js +3 -3
- package/dist/http/routes/session-memory-sync.d.ts +63 -0
- package/dist/http/routes/session-memory-sync.js +157 -0
- package/dist/http/routes/session-sync.d.ts +3 -6
- package/dist/http/routes/session-sync.js +7 -2
- package/dist/http/routes/sessions-list.d.ts +2 -1
- package/dist/http/routes/sessions.js +5 -4
- package/dist/http/routes/tasks.js +70 -71
- package/dist/http/run-read-face.d.ts +7 -0
- package/dist/http/run-read-face.js +10 -4
- package/dist/http/send.d.ts +6 -1
- package/dist/http/send.js +10 -3
- package/dist/http/server.d.ts +20 -7
- package/dist/http/server.js +2 -4
- package/dist/http/sse-log.d.ts +3 -8
- package/dist/http/stored-body-replay.d.ts +3 -3
- package/dist/http/stored-body-replay.js +3 -1
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +2 -2
- package/dist/http/sync-submit-body.d.ts +21 -4
- package/dist/http/sync-submit-body.js +13 -0
- package/dist/identity-source.d.ts +21 -2
- package/dist/identity-source.js +6 -0
- package/dist/instruction-source-notice.d.ts +7 -0
- package/dist/instruction-source-notice.js +6 -6
- package/dist/mcp-assertion-header.d.ts +4 -0
- package/dist/mcp-assertion-header.js +5 -0
- package/dist/memory-incident-sink.d.ts +19 -6
- package/dist/memory-incident-sink.js +8 -4
- package/dist/memory-posture.d.ts +1 -1
- package/dist/memory-scope.d.ts +4 -4
- package/dist/memory-scope.js +1 -1
- package/dist/memory-sync-client.d.ts +35 -23
- package/dist/memory-sync-client.js +122 -52
- package/dist/memory-sync-identity.d.ts +24 -0
- package/dist/memory-sync-identity.js +57 -0
- package/dist/memory-sync.d.ts +7 -1
- package/dist/memory-sync.js +6 -3
- package/dist/observability/fail-open.d.ts +57 -12
- package/dist/observability/fail-open.js +50 -9
- package/dist/observability/metrics.js +0 -1
- package/dist/observability/run-terminal.d.ts +93 -31
- package/dist/observability/run-terminal.js +175 -171
- package/dist/observability/secret-env-scrub.d.ts +20 -1
- package/dist/observability/secret-env-scrub.js +14 -0
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
- package/dist/orchestration/workflow-completion-inbox.js +13 -5
- package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
- package/dist/orchestration/workflow-notify-journal.js +2 -1
- package/dist/permission-mode-admission.d.ts +68 -0
- package/dist/permission-mode-admission.js +23 -0
- package/dist/permission-rule-list.d.ts +55 -6
- package/dist/permission-rule-list.js +52 -5
- package/dist/plugins/approval-ask-store-file.d.ts +14 -4
- package/dist/plugins/approval-ask-store-file.js +48 -7
- package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
- package/dist/plugins/approval-ask-store-memory.js +9 -8
- package/dist/plugins/approval-ask-store-sql.d.ts +42 -10
- package/dist/plugins/approval-ask-store-sql.js +49 -19
- package/dist/plugins/caching-session-store.d.ts +6 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
- package/dist/plugins/checkpoint-store-sql.js +74 -3
- package/dist/plugins/device-store-sql.d.ts +5 -2
- package/dist/plugins/device-store-sql.js +4 -1
- package/dist/plugins/execution-placement-sql.d.ts +11 -1
- package/dist/plugins/execution-placement-sql.js +12 -1
- package/dist/plugins/file-run-store.d.ts +7 -2
- package/dist/plugins/file-run-store.js +12 -2
- package/dist/plugins/fork-routing-session-store.d.ts +10 -32
- package/dist/plugins/fork-routing-session-store.js +2 -61
- package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
- package/dist/plugins/k8s-exec-protocol.js +6 -1
- package/dist/plugins/local-checkpoint-store.d.ts +10 -1
- package/dist/plugins/local-checkpoint-store.js +22 -0
- package/dist/plugins/local-session-store.d.ts +260 -39
- package/dist/plugins/local-session-store.js +582 -57
- package/dist/plugins/local-session-window.d.ts +17 -3
- package/dist/plugins/local-session-window.js +7 -13
- package/dist/plugins/local-task-attachment-store.d.ts +12 -2
- package/dist/plugins/local-task-attachment-store.js +67 -43
- package/dist/plugins/memory-key-guards.d.ts +3 -3
- package/dist/plugins/memory-run-store.d.ts +7 -2
- package/dist/plugins/memory-run-store.js +12 -2
- package/dist/plugins/one-time-migrations.d.ts +68 -2
- package/dist/plugins/one-time-migrations.js +120 -4
- package/dist/plugins/pg-pool.js +3 -2
- package/dist/plugins/pg-session-storage.d.ts +2 -0
- package/dist/plugins/pg-session-storage.js +3 -2
- package/dist/plugins/remote-env-e2b.d.ts +47 -7
- package/dist/plugins/remote-env-e2b.js +242 -46
- package/dist/plugins/remote-env-k8s.d.ts +51 -6
- package/dist/plugins/remote-env-k8s.js +234 -44
- package/dist/plugins/remote-env-local-docker.d.ts +40 -14
- package/dist/plugins/remote-env-local-docker.js +127 -33
- package/dist/plugins/run-store-sql.d.ts +11 -3
- package/dist/plugins/run-store-sql.js +13 -4
- package/dist/plugins/sandbox-read-floor.d.ts +273 -0
- package/dist/plugins/sandbox-read-floor.js +608 -0
- package/dist/plugins/session-ownership.d.ts +2 -1
- package/dist/plugins/session-placement.d.ts +17 -4
- package/dist/plugins/session-placement.js +2 -1
- package/dist/plugins/session-store.d.ts +18 -20
- package/dist/plugins/session-store.js +4 -12
- package/dist/plugins/store-backend.d.ts +41 -7
- package/dist/plugins/store-backend.js +22 -4
- package/dist/plugins/store-contracts.d.ts +35 -3
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/task-attachment-store.d.ts +112 -14
- package/dist/plugins/task-attachment-store.js +221 -28
- package/dist/plugins/tidb-pool.js +2 -1
- package/dist/plugins/tidb-session-store.d.ts +4 -1
- package/dist/plugins/tidb-session-store.js +3 -2
- package/dist/plugins/workspace-fill.d.ts +60 -0
- package/dist/plugins/workspace-fill.js +106 -0
- package/dist/project-bundle.d.ts +38 -0
- package/dist/project-bundle.js +609 -0
- package/dist/run-cancel-context.d.ts +34 -0
- package/dist/run-cancel-context.js +7 -0
- package/dist/run-local.js +2 -8
- package/dist/runs.d.ts +39 -12
- package/dist/runs.js +69 -55
- package/dist/sandbox-egress-policy.d.ts +4 -1
- package/dist/sandbox-egress-policy.js +3 -1
- package/dist/sandbox-git-plane.d.ts +31 -12
- package/dist/sandbox-git-plane.js +24 -4
- package/dist/security.d.ts +11 -2
- package/dist/security.js +8 -0
- package/dist/server-secret-env.d.ts +2 -1
- package/dist/server-secret-env.js +2 -4
- package/dist/session-error-wire.d.ts +46 -4
- package/dist/session-error-wire.js +23 -0
- package/dist/session-incarnation.d.ts +9 -3
- package/dist/session-sync-kernel.d.ts +42 -1
- package/dist/session-sync-kernel.js +17 -0
- package/dist/session-sync.js +16 -4
- package/dist/sql-engine-coordinates.d.ts +49 -0
- package/dist/sql-engine-coordinates.js +27 -0
- package/dist/standing-answer-grant.d.ts +31 -2
- package/dist/standing-answer-grant.js +14 -2
- package/dist/store-posture.d.ts +1 -1
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-mcp.d.ts +1 -1
- package/dist/task-settings.d.ts +62 -27
- package/dist/task-settings.js +105 -29
- package/dist/terminal.d.ts +97 -20
- package/dist/terminal.js +107 -18
- package/dist/tool-approval.d.ts +4 -3
- package/dist/tool-approval.js +12 -14
- package/dist/trace/core-keyset-guard.d.ts +196 -2
- package/dist/trace/engine-notice-wire.d.ts +8 -2
- package/dist/trace/engine-notice-wire.js +4 -2
- package/dist/trace/exit-seat.d.ts +9 -1
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/ledger-sink.d.ts +8 -4
- package/dist/trace/ledger-sink.js +2 -2
- package/dist/trace/model-segment.d.ts +2 -2
- package/dist/trace/project.d.ts +18 -1
- package/dist/trace/project.js +16 -0
- package/dist/trace/redact.js +323 -90
- package/dist/trace/self-minted-wire.d.ts +419 -4
- package/dist/trace/self-minted-wire.js +145 -0
- package/dist/trace/wire-projection-faces.d.ts +1 -1
- package/dist/trace/wire-projection-faces.js +1 -1
- package/dist/verifier-pause-card.d.ts +8 -0
- package/dist/verifier-pause-card.js +19 -0
- package/dist/web-admin-client/apply-effective.d.ts +5 -7
- package/dist/web-admin-client/apply-effective.js +22 -2
- package/dist/web-admin-client/candidate-gate.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.js +2 -0
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/types.d.ts +4 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
- package/package.json +2 -2
- package/wire-changes/server@7.141.0.json +367 -0
- package/wire-changes/server@7.142.0.json +639 -0
package/README.md
CHANGED
|
@@ -206,7 +206,7 @@ The server is configured entirely through environment variables. The most import
|
|
|
206
206
|
| `CONFIG_PROVIDER` | unset | Config source: `local` (file-backed `config.d/`, single machine) / `remote` (registry control plane at `SEMA_WEB_ADMIN_URL` — `remote` without that URL refuses to boot). Unset = the center if `SEMA_WEB_ADMIN_URL` is set, else env only. Closed set, matched exactly (7.104.0+): any other value (wrong case, surrounding spaces) refuses to boot; empty = unset |
|
|
207
207
|
| `DEFAULT_SCENARIO` | `code` | Default scenario when the request body names none; must be a scenario this deployment has (boot refuses otherwise) |
|
|
208
208
|
| `SANDBOX_PKG_SOURCE` | `global` | Package sources inside sandboxes: `global` (official upstreams) / `cn` (China mirrors) / `custom` / `none` |
|
|
209
|
-
| `SENSITIVE_WRITE_PATTERNS` | core's recommended set | Sensitive-path write deny list; comma-separated value replaces the set, `off` **or an empty value** disables. Applied unconditionally at the governance layer (independent of client permission mode, lane or settings presence) — including on the `run-local` leg. A value that cannot compile into a guard set (e.g. `/`, a pattern with no path segment) refuses to start |
|
|
209
|
+
| `SENSITIVE_WRITE_PATTERNS` | core's recommended set | Sensitive-path write deny list; comma-separated value replaces the set, `off` **or an empty value** disables. Applied unconditionally at the governance layer (independent of client permission mode, lane or settings presence) — including on the `run-local` leg. Scope: it refuses the **file tools** (Write / Edit / NotebookEdit, by path); a shell command that writes the same path (redirection, `tee`, `cp` …) is not refused by this set — it is an ordinary approval ask, answered like any other shell write (a person, or the classifier under `auto`). A value that cannot compile into a guard set (e.g. `/`, a pattern with no path segment) refuses to start |
|
|
210
210
|
| `WRITE_PROTECTED_EXTRA` | unset (engine default table) | **Adds** rows to core's write-protection table (the literal-name table whose hit demotes a surviving `allow` to `ask` on Write/Edit/NotebookEdit). Comma-separated bare names (a bare name matches ANY path segment; a name containing `/` matches a consecutive segment run) or a JSON array of `"name"` strings / `{name, kind}` rows (`kind`: `basename` \| `segment` \| `segment-run`). The value is composed as `[...WRITE_PROTECTED_DEFAULT_TABLE, …]`, so **no default row can be lost**. Unset = no seat is wired = the engine's default table is in force (this server never copies that table). Form discrimination is by content, not by first character: a value containing any JSON structural character (`[ ] { } "`) is parsed as JSON and **must** be a top-level array (a missing pair of brackets refuses to start instead of being split into junk bare names). An empty value, a malformed entry (glob metacharacter, unknown kind, kind/name mismatch) or setting this together with `WRITE_PROTECTED_TABLE_REPLACE` **refuses to start**. Read faces: `GET /v1/capabilities` → `writeProtection.{armed,rows,replaced}`; `GET /v1/diagnostics/wiring` → `writeProtection.{rows,source,droppedDefaultRows}` (operator-only) |
|
|
211
211
|
| `WRITE_PROTECTED_TABLE_REPLACE` | unset (engine default table) | **Replaces the whole** write-protection table (core's seat is whole-table by contract). JSON array only — deliberately no comma shorthand, because a slipped bare string would swap 51 default rows for one. `[]` = the explicit "no write-protection table at all" posture. Replacing logs one **loud** boot line naming every default row you dropped (`write_protection_table_replaced`; the empty posture logs `write_protection_table_disabled`) — use `WRITE_PROTECTED_EXTRA` when you meant to ADD. Same refuse-to-start conditions as its sibling, plus: both knobs set = two writers on one surface = refuses to start |
|
|
212
212
|
| `MANUAL_MODE_SHELL_GATE` | unset | `always` — the operator floor: keep every `Bash` call under the engine's shape-tier approval question regardless of the client's permission mode, lane or settings (applied at the governance layer). **Unset is not "off"** and `off` is a no-op (the knob only tightens); `classify` was retired in 7.106.0 (core 7.34.0 folds the classifier into the engine's own mode arbitration) and now **refuses to boot** (the boot error names the retirement and the two remaining words; no error code — it is a config parse refusal, not a wire code). The catalog row (`GET /v1/config/catalog`) lists `enumValues: ["always","off"]`, `echoWords: ["always"]`. |
|
package/README.zh-CN.md
CHANGED
|
@@ -175,7 +175,7 @@ curl -s localhost:8090/v1/tasks -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>"
|
|
|
175
175
|
| `CONFIG_PROVIDER` | 未设 | 配置来源:`local`(单机文件 `config.d/`)/ `remote`(`SEMA_WEB_ADMIN_URL` 那只 registry 控制面 —— 写了 `remote` 而没设这个地址拒启)。未设 = 设了 `SEMA_WEB_ADMIN_URL` 即中心,否则纯 env。闭集、逐字比较(7.104.0 起):其余任何值(大小写不同、带首尾空白)拒启;空串 = 未设 |
|
|
176
176
|
| `DEFAULT_SCENARIO` | `code` | 请求体未指定场景时的缺省场景;必须是本部署在册的场景名,否则拒启 |
|
|
177
177
|
| `SANDBOX_PKG_SOURCE` | `global` | 沙箱内装包源:`global`(官方源)/ `cn`(国内镜像)/ `custom` / `none` |
|
|
178
|
-
| `SENSITIVE_WRITE_PATTERNS` | core 推荐集 | 敏感路径写拒集;逗号分隔值为整体替换,`off` **或留空**关闭。在治理层无条件施加(与客户端权限模式/lane/settings 在场性无关),`run-local`
|
|
178
|
+
| `SENSITIVE_WRITE_PATTERNS` | core 推荐集 | 敏感路径写拒集;逗号分隔值为整体替换,`off` **或留空**关闭。在治理层无条件施加(与客户端权限模式/lane/settings 在场性无关),`run-local` 腿同样生效。射程:拒的是**文件工具**(Write / Edit / NotebookEdit,按路径);shell 命令写同一路径(重定向 / `tee` / `cp` …)**不被这个集拒绝**,是一条普通审批问,和别的 shell 写同一条出路(人答;`auto` 下交分类器);编译不出守卫集的值(如 `/`)启动即拒 |
|
|
179
179
|
| `WRITE_PROTECTED_EXTRA` | 未设(引擎缺省表) | 给 core 的**写保护名表**加行(字面名表:命中即把幸存的 `allow` 降级成 `ask`,作用于 Write/Edit/NotebookEdit)。逗号分隔裸名(裸名匹配**任意路径段**,含 `/` 的名匹配连续段)或 JSON 数组(`"name"` 串 / `{name, kind}` 行,`kind`:`basename` \| `segment` \| `segment-run`)。值按 `[...core 缺省表, …]` 组合,**丢不掉任何缺省行**。未设 = 不铸座 = 引擎缺省表在岗(本仓从不复制那张表)。两形按**内容**判而不是猜首字符:值里出现 JSON 结构字符(`[ ] { } "`)即按 JSON 解析,且顶层**必须是数组**(少写一对方括号 ⇒ 拒启,而不是被拆成垃圾裸名静默收下)。空值 / 坏值(通配符、未知 kind、kind 与名字段数矛盾)/ 与 `WRITE_PROTECTED_TABLE_REPLACE` 同时设置 ⇒ **启动即拒**。读面:`GET /v1/capabilities` 的 `writeProtection.{armed,rows,replaced}`;`GET /v1/diagnostics/wiring` 的 `writeProtection.{rows,source,droppedDefaultRows}`(operator-only) |
|
|
180
180
|
| `WRITE_PROTECTED_TABLE_REPLACE` | 未设(引擎缺省表) | **整表替换**写保护名表(core 的座按契约就是整表)。只收 JSON 数组 —— 刻意不给逗号简写:一个手滑的裸串会把 51 行换成 1 行。`[]` = 显式「完全不要这张表」。替换时 boot 期发一条**响亮**日志逐名列出被丢的缺省行(`write_protection_table_replaced`;空表走 `write_protection_table_disabled`)—— 想「加两行」请用 `WRITE_PROTECTED_EXTRA`。拒启条件同姊妹键,外加:两根同写 = 一条语义面两个写者 ⇒ 拒启 |
|
|
181
181
|
| `MODEL_FIRST_BYTE_TIMEOUT_MS` | 未设(core 缺省) | `fetch()` → 响应头的等待,毫秒(7.103.0 起;取代退役的 `MODEL_CONNECT_TIMEOUT_MS`,设了旧键**拒启** —— core 7.33.0 起建连(TCP + TLS)是传输层自己的钟)。未设 = 不传键,core 缺省当家(另加按请求体大小的上传宽限,到点 core 自有一次加宽重试)。`0` = 该段不设引擎钟、传输层的响应头 / 响应体钟也关(TCP + TLS 建连仍归传输层自己的钟)。须为 `[0, 2147483647]` 内整数,其余拒启。配了 `MODEL_GATEWAY_FALLBACK_URLS` 时每条网关路由同样是首窗 + 一次加宽重试之后才切备(server 不铸 core `firstByteRetries`:调用方可按请求关 failover,那一次身后没有备)。failover 拓扑须显式设:未设时接了连接却不回头的主网关要等 core 的首字节 lane(缺省窗 + 加宽重试)走完才切备,预算更短的调用(code-review council 镜头 180 s)在备网关被尝试之前就被取消;这类部署起服时打一条 `failover_first_byte_lane` warn |
|
package/USAGE.md
CHANGED
|
@@ -57,9 +57,12 @@ docker compose up --build --scale service=4 # 4 个无状态 worker,nginx
|
|
|
57
57
|
> 显式带 `DB_BACKEND=mysql`。同版:`DB_BACKEND=mysql|pg` 显式而店打不开,拒句点名 `DB_BACKEND=<引擎>`(修前只有驱动的一句 `connect ECONNREFUSED …`)。
|
|
58
58
|
> 🔴 **7.119.0 起 `SESSION_BACKEND=auto` 配了坐标而库连不上同样拒启,不再有「auto 内存起服」这条出路**:`auto` = 「配了该引擎的坐标就是那只库(boot 期窗内重试、到窗拒启),没配就是内存」,
|
|
59
59
|
> 由配置决定、不由起库成败决定;内存部署写 `DB_BACKEND=memory` 或 `SESSION_BACKEND=memory`。`GET /health` 的 `sessionBackend` 如实说装好的后端(`durable(pg)` / `memory`)。持久化姿态读面:caps `store`(附录 B)。
|
|
60
|
+
> 🔴 **显式 `DB_BACKEND=mysql|pg` 而该引擎的坐标一个都没配 ⇒ 配置期拒启,与 `SESSION_BACKEND` 怎么写无关**(未设 / `auto` / `mysql` / `memory` 同一句拒句,`REQUIRE_PRINCIPAL=true` 亦然):写下 `DB_BACKEND=pg` 就是要这只持久引擎,没有坐标它开不了店。修前 `SESSION_BACKEND=auto`(「坐标不在就不探测」)下这一形静默跑内存、`/health` 照样 200、姿态位照报 `declared: "pg"`。拒句点名缺的坐标键名(`PG_HOST` / `PG_USER` / `PG_DATABASE`;`MYSQL_*` 同形),不回显任何值;出路:补齐坐标;或要无 SQL 的部署写 `DB_BACKEND=local`(单用户文件店)/ `DB_BACKEND=memory`。坐标齐、`DB_BACKEND=local|memory`、不写 `DB_BACKEND` 的形零变化。同族:`MEMORY_ENGINE_BACKEND=pg|mysql` 要绑的池没开而 `DB_BACKEND` 已点名该引擎时,拒句改点名真正开店的条件(持久会话后端 + 必需坐标键),不再说「要 `DB_BACKEND=…`」。
|
|
60
61
|
|
|
61
62
|
> 🔴 7.96.0 起根 `docker-compose.yml` 的 `REMOTE_EXEC`(执行车道)是**必填**:不设 ⇒ `docker compose config` 当场失败(此前静默起成一个没有手的 worker)。单人自用 `REMOTE_EXEC=host`(手落在 worker 容器里);多人 / 生产选隔离车道 `e2b`(配 `E2B_API_KEY`)或 `k8s`(`K8S_SANDBOX_IMAGE`、`K8S_NAMESPACE`〔没有内置缺省〕都是必需件,未设、空串或只含空白一律按缺 ⇒ 起服拒;`K8S_API_URL` 与 `K8S_TOKEN` 也要设;根 compose 透传前两名〔空串透传 = 按缺,要填〕,后两名要在 compose override 里加进服务的 `environment`,或改走随包 chart `deploy/sema-up`)。
|
|
62
63
|
|
|
64
|
+
> 🔴 **`REMOTE_EXEC` 的形是部署声明的有序车道表**(契约 `runtime.execution.lanes` 渲成 env 的形:逗号分隔、首项是缺省车道;单词 = 一条车道的表,读法与以前逐字同)。每段逐字是一个车道词(不 trim、不折大小写),不许空段、不许同一车道出现两次;写着契约退役车道值(如 `remote-docker`)⇒ 拒句给出去向。**本引擎每个进程只装一条车道的执行座**:表里不止一条(`REMOTE_EXEC=k8s,device`)⇒ 起服拒,拒句点名全部声明的车道与出路(一台引擎一条车道:`REMOTE_EXEC=k8s`,其余车道各起一台)—— 不只服务首项而让其余车道无声地什么都不跑。
|
|
65
|
+
|
|
63
66
|
> 🔴 **7.104.0 起多租户姿态不许跑不分租户的执行车道**:`REQUIRE_PRINCIPAL=true` ∧ 最终生效的车道在执行车道能力表上不分租户 ⇒ **拒启**。按表不按词,今天覆盖 `host` / `ssh` / `adb`(所有任务落同一个共享目标:worker 宿主 / 一台 SSH 对端 / 一台 ADB 设备)。判的是合成后的车道(env 的 `REMOTE_EXEC`、`CONFIG_PROVIDER=local` 而 `REMOTE_EXEC` 未设的隐式 host、local 形 `config.d/remote-exec.json` 的覆写,在中心拉取与任何配置应用之前合成)。拒因(逐字,以 host 为例):`REQUIRE_PRINCIPAL=true (multi-tenant posture) with the "host" execution lane runs every tenant's Bash on one shared target — this lane does not separate tenants; set REMOTE_EXEC to e2b / k8s / local-docker / device, or unset REQUIRE_PRINCIPAL for a single-user box`。车道 × 租户形:
|
|
64
67
|
>
|
|
65
68
|
> | 车道 | 单用户 | 多租户(`REQUIRE_PRINCIPAL=true`) | `READ_FACE` 缺席时的读面缺省(7.133.0 起车道行声明) |
|
|
@@ -71,6 +74,8 @@ docker compose up --build --scale service=4 # 4 个无状态 worker,nginx
|
|
|
71
74
|
> | `device`(每人自己的设备) | ✅ | ✅ | 单用户 `open`(来源 `posture`);多租户 不铸 = 引擎默认 `roots` |
|
|
72
75
|
> | 未点名(云形进程内 stub,零手带工具、非手带工具照常执行) | ✅(`REQUIRE_EXECUTION_LANE=true` 可改成拒启) | ✅(同左) | 单用户 `open`(来源 `posture`);多租户 不铸 = 引擎默认 `roots` |
|
|
73
76
|
|
|
77
|
+
> 🔴 **`REMOTE_EXEC=device` 必须声明设备入口 `DEVICE_RELAY_URL`(无缺省)**。两种合法值:设备连不到引擎自己的地址(引擎在中继 / 网关之后)时设备该拨的那一个 `ws://` / `wss://` 绝对地址(逐字上 `GET /v1/capabilities` 的 `deviceExecutor.relayUrl`);或字面 `none`(没有中继,设备按引擎地址 + `deviceExecutor.wsPath` 拨号,能力面不带 `relayUrl`)。缺席 / 空串 / 只含空白 ⇒ 起服拒,拒在车道必需 env 门(与 `K8S_NAMESPACE` 等其余车道必需键同一句:`required env DEVICE_RELAY_URL is unset, empty or whitespace-only`);写了却不合文法 ⇒ 起服拒,拒句点名两种合法值(规则文字取自契约包)。`none` 而根会话上还有设备绑定 ⇒ 起服 warn `device_relay_withdrawn_with_bindings`(`bindings` = 绑定条数,不带会话 id)。撤中继声明的回滚序:先恢复引擎自己的入口,再把值改成 `none`。
|
|
78
|
+
|
|
74
79
|
> 🔴 **7.104.0 起 `CONFIG_PROVIDER` 是闭集**:只认 `local` / `remote` / 不设(空串 = 不设),**逐字**比较 —— `Local`、` local`、`remote ` 这类写法**拒启**,拒因句点名旋钮并列出合法词。此前认不出的词照起,却被配置源当成 `local`、被隐式 host 车道当成「不是 local」,local 配置源的根还落回进程 cwd(与车道文件覆写读的本地根分家)。本地配置根只有一条链:`CONFIG_LOCAL_DIR` → `AGENT_DATA_DIR` → `~/.ai-agent`,配置源与 `config.d/remote-exec.json` 读同一个。
|
|
75
80
|
|
|
76
81
|
> 🔴 **`CONFIG_PROVIDER=remote` 要中心地址**:`remote` 说的是「这台 worker 的配置来自中心」,中心就是 `SEMA_WEB_ADMIN_URL` 那一只 —— 写了 `remote` 而没设 `SEMA_WEB_ADMIN_URL` ⇒ **拒启**,
|
|
@@ -444,21 +449,21 @@ MODEL_ID=<your-model-name> MODEL_CHEAP_ID=<your-cheap-model-name>
|
|
|
444
449
|
MODEL_CODE_ROLES=default,subagent # 不设=全中立;仅这些角色在「任务自己没说角色基底」时跑编码基底
|
|
445
450
|
```
|
|
446
451
|
- 经 `RoleSpec.promptRole: "code"` 挂在**角色**上(7.137.0 起 / 引擎 7.56.0;此前是把同一段目录文本粘进 `RoleSpec.systemPrompt`),非开发角色保持中立。角色基底只有一条来源链:任务 → 请求的模型角色的预设 → 引擎委派子代的人设,**第一个说出基底的来源整个说了算** —— 任务自带 `systemPrompt`(或客户端注入)、或场景自己写了角色词(cowork 场景写 `cowork`)时任务优先;这些 run 的宿主角色是 `code`(按 `when.host.role` 条件的 overlay 自此对它们生效),基底字节与此前相同。
|
|
447
|
-
- **验证门**(core 1.44,opt-in):请求体带 `verify:true`(可选 `verifyRounds`,夹到 [1,5]、默认 2)→ 任务跑完后由**独立只读 verifier**(`verifier` 角色,默认=主模型)证据强制地"试图 break 它",FAIL 则把 findings 注回同 session 续跑修复→重验,循环到 PASS 或轮数上限。结果带 `verification:{verdict,rounds,findings,evidence}`(`verdict` 看质量,`result`/`status`
|
|
452
|
+
- **验证门**(core 1.44,opt-in):请求体带 `verify:true`(可选 `verifyRounds`,夹到 [1,5]、默认 2)→ 任务跑完后由**独立只读 verifier**(`verifier` 角色,默认=主模型)证据强制地"试图 break 它",FAIL 则把 findings 注回同 session 续跑修复→重验,循环到 PASS 或轮数上限。结果带 `verification:{verdict,rounds,findings,evidence}`(`verdict` 看质量,`result`/`status` 仍是实现的)。`findings` / `evidence` 是验证器模型写的自由文本(常引命令与输出),7.142.0 起与 `result` 同一只脱敏器脱:认出的凭据片段换成 `«redacted…»` 记号,条数与顺序不变,判词 / 轮数逐字(同步体、`GET /v1/runs/:id`、`/events` 回放与落库同读)。**仅 `/v1/tasks`(同步)与 `/v1/runs`(异步)**——`/v1/tasks/stream` 不支持(多轮非单流,请求 verify 会 400)。verifier 工具默认 = 实现任务工具滤掉 `effect:"write"`(只读边界)。`/metrics` 加 `verifications_total{verdict}`。⚠️ 同步 `/v1/tasks` 形**没有事件通道**(过程帧无处回放,只回终局 JSON)——带 `verify`/`cascade` 的 200 体自 7.23.0 起附可选 `notice` 键指路 `POST /v1/runs`(要过程可见性用异步形)。
|
|
448
453
|
- **实现腿撞资源限(`RESOURCE_SUSPEND` 开着)**:`verify:true` 任务的实现腿(或某一轮修复)撞预算 / turns / 墙钟限时**停驻**而不是 `failed`:`POST /v1/runs` 的行停在 `suspended`(门 `resource_limit`,无失败码)、会话保持占用;`POST /v1/tasks` 答停驻回执;用 `POST /v1/assistant/tasks/:id/resume` 续,续完照常过验证门。验证器自己那一腿由引擎另铸 spec、不带这个 opt-in,撞限照旧失败。跨片总额(`RESOURCE_SUSPEND_TOTAL_*` / `_MAX_SLICES`)按**一条腿的**续跑链记:验证门的每一轮修复是引擎另起的一次运行,账从零起,所以 verify 任务的花费上界是实现腿那条链与各轮修复各自那条链的上界之和,没有跨腿的总额。没开 `RESOURCE_SUSPEND` 的部署行为不变(撞限 `failed` + `limits.*` 码)。停驻期间同会话再提交 / 删会话 / 换绑设备 / 会话同步都 409,先续跑或取消;被弃置的停驻由 `RESOURCE_SUSPEND_TTL_SEC` 到期收回(缺省 30 天)。
|
|
449
454
|
- **记忆(文件记忆引擎,2026-07-08 起唯一记忆面)**:core 注入式文件引擎——任务开始时 materialize 记忆目录(`MEMORY_ENGINE_DIR`,默认 `~/.ai-agent`),模型用**普通文件技能**读写记忆(CC `# Memory` 指令 + 派生索引;无 remember/recall 工具),任务边界 harvest 门(secret/cap 扫描)提交。单用户默认开,`MEMORY_ENGINE=off` 显式关;多租户恒关(文件基座无租户隔离,fail-closed)。旧 SQL 记忆面(`MEMORY_BACKEND`/`EMBEDDING_*`/`MEMORY_READ_LIMIT`/去重/向量检索、`GET/DELETE /v1/memory` 与 session memory 写 verb)已退役,数据不迁移——升级后对库跑一次 `scripts/drop-memory-tables.sql`。`body.memoryWrite:false` 仍是每请求只读开关(harvest 不提交)。
|
|
450
455
|
**`MEMORY_PERSISTENCE_CAPABLE`(三态,7.14.0 起)**=**部署自述**「本机能不能把用户的『记住 X』落到持久处」,与请求键 `memoryWrite` 两轴正交(后者收紧本次运行,前者是 operator 声明;任一取否即只读方向)。缺省不设=引擎按 roster 自行推断;`true`=本部署有推断看不见的持久通道(自定义 writer / 记忆 MCP / 远程执行车道与记忆根共享挂载);`false`=强制只读披露并关掉文件工具往记忆根的写通道。不认得的词拒启。
|
|
451
456
|
🔴 **`false` 自 core 5.27.0(7.14.0 提货)起还多一层——但只在 file 记忆引擎上**(`MEMORY_ENGINE_BACKEND` 未设 = 默认单机形):该会话是**受限会话**——materialize/搜索/harvest 一律按**已提交账**供给,记忆根下无事务背书的磁盘分歧既不收编也不供给,而是留盘 + 响亮点名(`restricted_divergence`,本服务把它计进 `memory_harvest_rejections_total{code}` 并 warn 一条),等下一次**非受限**会话走正常门收编。合法流程不受影响:用户手改、`git pull` 落下的删除照旧(延后,不销毁),并发的可写会话提交的变更算有事务背书。
|
|
452
|
-
⚠️ **`MEMORY_ENGINE_BACKEND=pg|
|
|
453
|
-
🔴 **降级前必须先停写排空(core 5.33.0 / server 7.21.0 起,运维 BREAKING)**:file 记忆后端的账本升到 **schema v2**(slug/scope rebind 与跨 scope transfer 改成 journaled 事务),而 **v2 journal 被 ≤5.32 的旧读者响亮拒**——这是**有意的 fail-closed**(拒启比静默读半张账好)。⇒ 要把服务降回 <5.33 的镜像:①**先停写、把在跑的记忆写排空**;②按 core 设计稿 §3.6 用 `transfers.jsonl` + journal 回放清账;③**再**降版。**排空这一步没做就降级 = 数据面响亮拒,不是静默丢**。`MEMORY_ENGINE_BACKEND=pg|
|
|
457
|
+
⚠️ **`MEMORY_ENGINE_BACKEND=pg|mysql` 上没有这一层**(引擎的受限视图是 file 后端的实装):那两条腿的读侧本来就走库、盘上目录只是每任务的投影工作区,不存在「读磁盘即收编」的通道,所以也无洞可堵——`false` 在它们上仍然照常买到披露、写门与零收编 harvest 三件(与后端无关)。
|
|
458
|
+
🔴 **降级前必须先停写排空(core 5.33.0 / server 7.21.0 起,运维 BREAKING)**:file 记忆后端的账本升到 **schema v2**(slug/scope rebind 与跨 scope transfer 改成 journaled 事务),而 **v2 journal 被 ≤5.32 的旧读者响亮拒**——这是**有意的 fail-closed**(拒启比静默读半张账好)。⇒ 要把服务降回 <5.33 的镜像:①**先停写、把在跑的记忆写排空**;②按 core 设计稿 §3.6 用 `transfers.jsonl` + journal 回放清账;③**再**降版。**排空这一步没做就降级 = 数据面响亮拒,不是静默丢**。`MEMORY_ENGINE_BACKEND=pg|mysql` 的部署不受此条约束(账本在库里,不走 file journal)。
|
|
454
459
|
⚠️ **口径别混**:「受限」是**会话级的这一个声明**;请求键 `memoryWrite:false` 铸出的只读**平面**(以及 org 层默认只读、双根非写面)**保持原样的 adopt-on-read**——它只是不 harvest,照旧看得见盘上的新内容。
|
|
455
|
-
⚠️ **core 5.26.0 起,remote 执行车道上的 `# Memory` 写指令被撤**(沙箱手带够不着 host 记忆根;读与注入不变)。**判据是「`REMOTE_EXEC` 有没有设」,不是那个旗**——凡设了 `REMOTE_EXEC`(含 `host`)且这次任务真有记忆面,写指令就被撤。因此被打到的**不止**显式 `MEMORY_ENGINE_REMOTE_LANE=allow` 的部署,还包括:① `MEMORY_ENGINE_BACKEND=pg|
|
|
456
|
-
另:记忆**没有写工具**,模型是用普通文件工具往记忆根写的——所以记忆根必须落在任务的 fs 授权边界内。结构性够不着时启动会 warn 并给出三条改法(把根挪进 workspace / 经 `additionalDirectories` 授权 / 声明 `MEMORY_PERSISTENCE_CAPABLE=false` 让披露诚实)。⚠️ **「挪根」用哪个旋钮按记忆后端分腿**:file 引擎是 `MEMORY_ENGINE_DIR`;`MEMORY_ENGINE_BACKEND=pg|
|
|
460
|
+
⚠️ **core 5.26.0 起,remote 执行车道上的 `# Memory` 写指令被撤**(沙箱手带够不着 host 记忆根;读与注入不变)。**判据是「`REMOTE_EXEC` 有没有设」,不是那个旗**——凡设了 `REMOTE_EXEC`(含 `host`)且这次任务真有记忆面,写指令就被撤。因此被打到的**不止**显式 `MEMORY_ENGINE_REMOTE_LANE=allow` 的部署,还包括:① `MEMORY_ENGINE_BACKEND=pg|mysql` 的 DB 记忆面(它不受那个旗管辖——旗只管 file 引擎,库是持久真身,任何车道上都照常点亮)= 最常见的云形;② `REMOTE_EXEC=host` + file 引擎(文件平面就在本机,但 core 的执行环境判决仍是 remote)。若该车道确实够得着记忆根,`MEMORY_PERSISTENCE_CAPABLE=true` 是官方恢复路径(启动日志 `memory_remote_lane_write_instruction_dropped` 会点名这一条);够不着就表 `false`,让只读状态对模型说明白。
|
|
461
|
+
另:记忆**没有写工具**,模型是用普通文件工具往记忆根写的——所以记忆根必须落在任务的 fs 授权边界内。结构性够不着时启动会 warn 并给出三条改法(把根挪进 workspace / 经 `additionalDirectories` 授权 / 声明 `MEMORY_PERSISTENCE_CAPABLE=false` 让披露诚实)。⚠️ **「挪根」用哪个旋钮按记忆后端分腿**:file 引擎是 `MEMORY_ENGINE_DIR`;`MEMORY_ENGINE_BACKEND=pg|mysql` 的根是 `<数据根>/memory-work`(数据根 = `LOCAL_DATA_ROOT`/`AGENT_DATA_DIR` 族),那两条腿**不读** `MEMORY_ENGINE_DIR`——启动 warn 的文案自己会按腿指对旋钮。
|
|
457
462
|
- **记忆店根搬了家 ⇒ 拒启(7.126.0 / 引擎 7.49.0 起,file 记忆后端)**:店根的物理路径记在店的控制面里(`root-anchor.json`),每次打开都比对。目录被搬走、
|
|
458
463
|
或换成指向别处的链接之后,起服**拒**(码 `memory.target_outside_store`;不降级成「记忆暗」—— 店还在,只是搬了家,静默降级会让这台部署在没人知道的情况下丢掉全部记忆)。
|
|
459
464
|
拒句点名控制面记下的路径与现在解析到的路径,并给出两条出路:**① 把目录放回原处**;**② 在本服务的目录里跑一次重锚**:
|
|
460
465
|
`node --input-type=module -e 'import("@sema-agent/core").then(m => m.reanchorMemoryStoreRoot("<path>", { controlDir: "<controlDir>" }))'`
|
|
461
|
-
(两个坐标拒句里逐字给出),然后再起服。`MEMORY_ENGINE_BACKEND=pg|
|
|
466
|
+
(两个坐标拒句里逐字给出),然后再起服。`MEMORY_ENGINE_BACKEND=pg|mysql` 与 `MEMORY_ENGINE=off` 的部署不经这一判。
|
|
462
467
|
- **数据根的写豁免只有一个来源(7.126.0 / 引擎 7.49.0 起)**:路径守卫对「本服务自己的数据根」的豁免,只读引擎的 `memoryEngineDir` 一处 —— 本服务把记忆引擎根
|
|
463
468
|
**恒**交给它,**`MEMORY_ENGINE=off` 的部署也交**(否则豁免根缺席,数据根下的写会被当成普通受保护路径拒)。运维零动作。
|
|
464
469
|
- **写目标的真落点读不出 ⇒ 有守卫行的面拒这次写(7.126.0 / 引擎 7.49.0 起,所有权限模式含 `bypassPermissions`)**:`Write` / `Edit` / `NotebookEdit` 的目标
|
|
@@ -468,7 +473,7 @@ MODEL_CODE_ROLES=default,subagent # 不设=全中立;仅这些角色在「
|
|
|
468
473
|
读落点(代理不转发链接链 ⇒ 部署守卫表在这些车道上只判落点,不逐跳;始终在岗的写保护表读适配器本身);`device` —— 设备协议必答 `canonicalPath`,
|
|
469
474
|
不答链接链(只判落点)。这些车道上一次瞬时失败(pod exec 超时、设备掉线、写门代理还没绑定本任务的沙箱)就是一次「读不出」⇒ 受守的写被拒,
|
|
470
475
|
重试那一次写即可(本服务不提供关掉始终在岗写保护表的旋钮)。
|
|
471
|
-
- **记忆检索的向量面(embedder,7.14.0 起)**:记忆检索有三档——`lexical`(词面 jaccard)/ `portable`(库内存向量,进程内算余弦)/ `native`(库侧向量算子)。⚠️ **没有档位旋钮**:档位是「记忆后端上限 × embedder 在不在场」**推断**出来的结果(显式选档只会造出「选了 native 却没 embedder」这类矛盾态)。**配上 embedder = 唯一的开法**,而且只在 `MEMORY_ENGINE_BACKEND=pg` 上有意义(
|
|
476
|
+
- **记忆检索的向量面(embedder,7.14.0 起)**:记忆检索有三档——`lexical`(词面 jaccard)/ `portable`(库内存向量,进程内算余弦)/ `native`(库侧向量算子)。⚠️ **没有档位旋钮**:档位是「记忆后端上限 × embedder 在不在场」**推断**出来的结果(显式选档只会造出「选了 native 却没 embedder」这类矛盾态)。**配上 embedder = 唯一的开法**,而且只在 `MEMORY_ENGINE_BACKEND=pg` 上有意义(mysql 记忆后端 v1 是词面档,file 引擎没有 embedder 接缝——两者配了 `MEMORY_EMBEDDER_*` 一律**拒启**点名)。不配 = 保持 `lexical`(默认姿态,零 warn)。
|
|
472
477
|
|
|
473
478
|
| env | 缺省 | 说明 |
|
|
474
479
|
|---|---|---|
|
|
@@ -490,8 +495,18 @@ MODEL_CODE_ROLES=default,subagent # 不设=全中立;仅这些角色在「
|
|
|
490
495
|
- ⚠️ **换 embedder 请停机换:先 `scale 0`,再起**。指纹门管的是 **boot 面**;**滚动升级窗**里新副本清完列之后,仍在服役的旧副本还在按**旧**模型写向量,滚动结束后表里混着两个空间而元表已是新指纹 ⇒ 此后恒判「相等」,门再也不会复检。这是纪律面的残余,不假装根治(行级 embedder 记账列可结构性根治,超出本件射程)。滚动事故后的补救 = 手动清一次:`UPDATE agent_memory_engine_entry SET embedding = NULL WHERE embedding IS NOT NULL;`(同一条也可用于「误配后立刻重置」)。
|
|
491
496
|
🔴 **同族的第二格:回滚到指纹门之前的版本**(7.14.x / 7.15.x —— 有 embedder、无指纹门)。那些版本照写 `embedding` 列却**根本不认识这张元表**,所以「装本版(元表记 B)→ 回滚到旧版跑一段(往列里写 A 空间向量,元表纹丝不动)→ 再升回本版、配置仍是 B」这条路走完,元表与配置都说 B 而列里躺着 A 空间向量 ⇒ 此后恒判「相等」,门再也不会复检。**跨门回滚与滚动窗要做同一件事**:回滚之前(或重新升级之后)手动跑上面那条清列 SQL,或干脆 `DELETE FROM agent_memory_engine_meta WHERE meta_key = 'embedder_identity';` 让下次启动按「无主向量」保守清一次。
|
|
492
497
|
- **没配 `MEMORY_EMBEDDER_*` 时门整个不装**(元表不动,旧指纹保留),启动日志 `memory_embedder_identity_absent` 说明:缺席期间**被改写过**的行,其 embedding 本来就被写成 NULL,所以「配置回归同一 identity 后向量续用」只对缺席期间**未被触碰**的行成立。
|
|
493
|
-
- 残余:同名模型在不同供应商若其实是不同实现(自托管 finetune 撞名),指纹辨不出——明知异实现时改 `MEMORY_EMBEDDER_MODEL` 名,或手动跑上面那条清列 SQL。`MEMORY_ENGINE_BACKEND=
|
|
498
|
+
- 残余:同名模型在不同供应商若其实是不同实现(自托管 finetune 撞名),指纹辨不出——明知异实现时改 `MEMORY_EMBEDDER_MODEL` 名,或手动跑上面那条清列 SQL。`MEMORY_ENGINE_BACKEND=mysql` 无向量面(v1 词面档),没有这张元表也没有这道门。
|
|
494
499
|
📋 **档位对运维可见**:启动日志 `memory_engine_enabled` 行带 `vectorMode` 字段(取自后端实例的真值,不是配置推断)——`lexical` 在跑就必须看得见;配了 embedder 时同行还带 `embedderModel`/`embedderDim`,换模型这件事在日志里留痕。
|
|
500
|
+
- **记忆同步(本机 file 引擎腿 ↔ DB 中心)**:本机腿由 `MEMORY_SYNC_URL`(中心基址;令牌只放 `MEMORY_SYNC_TOKEN`)开起,在起服时与每次任务写进记忆之后后台同步;
|
|
501
|
+
它的同步身份 = `MEMORY_SYNC_URL` 的规范形(小写协议与主机、无缺省端口、路径去尾斜杠)。中心用 `MEMORY_SYNC_SERVE_IDENTITY` 声明同一个值(能力位 `memorySyncServe.identity` 逐字是它),
|
|
502
|
+
只服务点名这一身份的轮(不是规范形 ⇒ 400 `request.field_invalid`;别的身份 ⇒ 409 `config.memory_sync_target_mismatch`,零读零写;没声明 ⇒ 501 `feature.memory_sync_serve_disabled`)。
|
|
503
|
+
壳在把会话推上云之前调 `POST /v1/sessions/:id/memory/sync`(体 `{ target }` = 目标引擎的 `memorySyncServe.identity`;能力位 `sessionMemorySync`),拿到引擎的同步报告:
|
|
504
|
+
这个会话读的每一层一个结局(`synced` / `incomplete` / `refused` / `failed`),或整轮 `refused`(目标不是本机腿到达的那台 / 会话有在飞 run,或读完它的记忆观测之后又受理了 run / 会话记录前进了)。
|
|
505
|
+
|
|
506
|
+
| env | 缺省 | 说明 |
|
|
507
|
+
|---|---|---|
|
|
508
|
+
| `MEMORY_SYNC_SERVE_IDENTITY` | 缺省(= 本中心不服务同步) | **中心侧**:客户端到达本中心同步口用的基址,必须已是规范形(不是 ⇒ 拒启,拒句给出规范形;带凭据 / 查询 / 片段 / 非 http(s) / 超过 190 字符 ⇒ 拒启)。引擎关着也读。只在 DB 记忆平面上服务同步;file 平面上读了不用 |
|
|
509
|
+
|
|
495
510
|
- **org 记忆准入(7.0.0 起 BREAKING)**:`org:*` 记忆 scope 分**两个来源**——部署自证
|
|
496
511
|
(env `MEMORY_SCOPE` 的 org 形 + **单用户部署**的 `projects[].defaultScopes` org 键)直通;**多租户**
|
|
497
512
|
部署里由调用方 `projectId` 选中的登记簿 org 键算 **request 来源**,必须拿到授权目录的逐 principal
|
|
@@ -608,6 +623,19 @@ MODEL_CASCADE_LADDER=deepseek-flash,deepseek-pro # 目录里的模型名,cheap
|
|
|
608
623
|
- 数据驻留提示:`DB_BACKEND=local` 下显式 `SESSION_BACKEND=memory` 会被收编为 **durable(local)**
|
|
609
624
|
(1.292+ 裸 boot 默认 durable;/health 的 `sessionBackend` 报 `durable(local)`)——session 行落盘在
|
|
610
625
|
数据根下,清数据/隐私预期要按「sessions 在 engine-data 里」来做,不要按「只在内存」。
|
|
626
|
+
- **后台子代的转录住哪、活多久(按车道)**:规则一条 —— 一只后台子代的持久记录在,它的转录就是宿主会话店委派分区里的一只分区会话:活过重启、随记录同亡;
|
|
627
|
+
进程内短 TTL 店只装没有持久记录指着的会话(普通子任务、前台子代)。`subagent_type: "fork"` 的后台子代不在这条规则里(各车道同):它的转录是从父会话分叉出来、
|
|
628
|
+
住宿主会话店的一只普通会话,记录被收割时保留(归会话留存管),也不能经 `SendMessage` 复活(工具结果是错误,`revive.fork_unsupported`)—— 下表的居所与续话两列不适用于它。
|
|
629
|
+
|
|
630
|
+
| 车道 | 后台子代转录的居所 | 接线清单 `fleet.subagentTranscripts` | 重启后对已结束的子代 `SendMessage` |
|
|
631
|
+
| --- | --- | --- | --- |
|
|
632
|
+
| `DB_BACKEND=mysql` / `pg` | 会话表里的分区行(`session_meta` 的委派元组列) | `full` | 续上(带原上下文复活) |
|
|
633
|
+
| `DB_BACKEND=local` | `<数据根>/sessions/<id>.jsonl`(存档行头记着委派元组) | `full` | 续上(带原上下文复活) |
|
|
634
|
+
| `DB_BACKEND=memory` | 进程内(没有后台记录店) | `none` | 不可续(记录与转录都随进程走) |
|
|
635
|
+
|
|
636
|
+
分区会话不进会话列表(`GET /v1/sessions`、`/resume`);属主按帧上的 `transcriptId` 读 `GET /v1/sessions/<transcriptId>`(体上带 `agent` 键)。记录被收割时转录一并删除(`BG_AGENT_RETENTION_MS`,缺省 7 天;
|
|
637
|
+
记录已不在的分区会话由分区孤儿腿按同一视界收);删根会话不连带删子代转录。会话同步往子代 id 上写 ⇒ `409 conflict.session_placed`。
|
|
638
|
+
本机形升级前停驻时被拷进宿主店的旧子代转录是普通会话(进列表、不随记录删),要清就 `DELETE /v1/sessions/<id>`。
|
|
611
639
|
- **任务清单(TaskCreate/TaskList 家族)的持久边界**:清单按**会话**分区,同一会话
|
|
612
640
|
跨 turn/跨 resume 连续,跨会话互不可见。配了 SQL 后端(`SESSION_BACKEND=mysql` / `DB_BACKEND=pg`)
|
|
613
641
|
时落 `task_list_meta`/`task_list_item` 两表 ⇒ **跨副本、跨重启都续得上**;**没有 SQL 后端的形态
|
|
@@ -616,6 +644,8 @@ MODEL_CASCADE_LADDER=deepseek-flash,deepseek-pro # 目录里的模型名,cheap
|
|
|
616
644
|
条边界,不为它自造持久性。**删除权**:`DELETE /v1/sessions/:id` 与托管留存 sweep 两条腿都把清单
|
|
617
645
|
行与编号高水位一并抹掉(同 anchors/附件/快照的级联)——会话 id 可被重新认领,残留就等于把上一位
|
|
618
646
|
主人的任务标题与编号进度交给下一个化身。
|
|
647
|
+
- **会话的行事实只住在数据根的 `session-incarnations.json`**(每只会话一格:属主 / 化身 / 执行放置 / 建档时刻 / fork 谱系);`sessions/*.jsonl` 是匿名的对话内容。
|
|
648
|
+
备份 / 迁数据根时两样一起搬;更早版本写下的带属主戳的存档由起服一次性迁移改写(改不了的点名,fork 与改日志推送答 409),快照目录 `session-archive-m33/` 非空且消化不了 ⇒ 拒启(MIGRATION 写了出路)。
|
|
619
649
|
- 多实例边界:同一数据根同时只允许一个实例(BootLock 独占,第二个进程拒启;死主自愈含 SIGKILL)。
|
|
620
650
|
core 5.54.0 起拒启错误带**可分派 code**(`FileStoreLockError`,message 点名占用方 pid),运维按码
|
|
621
651
|
三动作:`store.dir_in_use`=另一个活进程持有该目录 → 停掉它(或换数据根/迁 SQL 后端);
|
|
@@ -728,6 +758,7 @@ MODEL_CASCADE_LADDER=deepseek-flash,deepseek-pro # 目录里的模型名,cheap
|
|
|
728
758
|
host 车道 = 引擎的整文件替换(同目录暂存 + fsync + rename);ssh / adb / local-docker / k8s / e2b = 先在目标目录下建一只生来 0700 的私有目录
|
|
729
759
|
`.<名>.stage-<12 位十六进制>/`,整份传进去,再在目标机上一次 `mv -f` 换上去;device = 设备侧执行器在同一步里暂存再换上。
|
|
730
760
|
传输中途断、取消、写到一半出错 ⇒ 目标逐字是旧内容,私有目录被删(删不掉 ⇒ 错误句点名残留的目录)。修前 host 与五条远端车道是就地截断写:中途中断留下新内容的前半截,原件找不回。
|
|
761
|
+
- **服务进程被 `SIGKILL` 时,暂存目录会留在目标旁(可直接删)**:上一条的清理是服务进程自己做的 —— `kill -9`、内存杀手、容器被强停这类**没有机会跑清理**的退出,正在传输的那一次写留下 `.<名>.stage-<12 位十六进制>/`,里面是在传的新内容(上传途中被杀只有前半截,传完才被杀则是整份);**目标逐字是旧内容**,整文件替换的保证不受影响,多出来的只是这只目录。ssh 车道实测(被强杀的写都留下了);其余四条远端车道走同一段暂存脚本,同形。取消(Ctrl-C 中断那一次写)不留 —— 取消路径上清理那一往返照跑。**本版不自动清**:下一次对同一目标的写不会去扫陈旧的暂存目录,它会一直留着,确认没有另一个进程正在写同一个目标之后 `rm -rf` 即可(名字里的十六进制每次写都不同,在写的那一只和陈旧的那一只光看名字分不出)。host 车道的暂存是引擎的,同形的残留名是 `<目标>.tmp.<进程号>.<十六进制>`,同样可以删。
|
|
731
762
|
- 暂存自创建起不比目标更可读:远端五车道的暂存只在私有目录里(别的用户进不去;替换 0600 的文件时新内容在传输期间只有写入方与 root 读得到),device 的暂存件以 0600 打开;
|
|
732
763
|
host 车道的这一保证在引擎原语里:引擎 7.60.0 起目标存在时暂存件以 0600 打开。新建的文件是写入方身份的 umask 形(local-docker = 容器内镜像用户的)。
|
|
733
764
|
私有目录建出后要读回核实是 0700 且属写入方;**核不过(`chmod` 被拒、文件系统不认权限位、缺省 ACL 的掩码收不下来、目标机没有 `stat`)⇒ 不暂存,退回就地写目标**
|
|
@@ -894,6 +925,7 @@ FLEET_ADVERTISE_ADDRESS=http://<本机可达IP>:8090 # 可选:设了才启公
|
|
|
894
925
|
生效与否的观测口=`/health` 世代账键(`configTargetVersion`/`configAppliedVersion`+两 ordinal+`configApplyStaleMs`,见 API 表 `/health` 行)——target≠applied 持续=「改了没生效」的机读信号。
|
|
895
926
|
- **`run-local`(一次性本机 CLI)上三张审批名单同样执法**(7.101.0 起,TTY 问 / 无 TTY 拒):`APPROVAL_DENY` 当场拒;`APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` 命中 ⇒ stdin 是 TTY 就 `y/N` 问人,否则当场拒并在 stderr 说出路(7.116.0 起按**这一问的类**说,不再对每一问打同一句全量旋钮清单:没人表态的服务器工具调用 ⇒ 指 `APPROVAL_GRANT`;名单产的问 ⇒ 点名三张名单键;部署治理盖了出身的问 ⇒ 点治理旋钮;引擎自己的问 ⇒ 不点旋钮、只说去终端答;引擎没有说明这一问的类 ⇒ 说明这一点、只给终端出路);`APPROVAL_AUTO_BUDGET` 照常生效(never-auto 不吃预算);TTY 问句带上这次调用的参数,人答 N 而停下的 run 退 1(停因 `haltedOnUserRejection`)。**无 TTY 的拒记在部署政策名下**(7.110.0 起;此前记成人拒):该次调用 `tool_end.gate.settlement` = `{kind:"policy_refused", who:{party:"policy"}}`(7.113.0 起;7.110.x–7.112.x 为 `party:"none"`),模型读到的是引擎的策略句(「部署政策拒了、此处没有交互审批,别重试,先做不需要审批的部分」)加一句拒因,而不是「用户不想继续,停下来等他」—— 不停批,模型接着做别的部分;那只要人批的动作没执行 ⇒ run 照样退 1,非 `--json` 形 stderr 停因行是 `task incomplete (approval unanswered): …`。参数展示不出而不问就拒的那一形(TTY 在场也一样)同此。这条腿没有 checkpoint 店也**不**拒启 —— 它有一只当场作答的席,名单的 ask 不需要 park(上表「无 checkpoint 店 ⇒ 整组拒」只说服务腿)。此前三张名单在这条腿上无声不生效。
|
|
896
927
|
- **仅 `/v1/tasks`(同步)+ `/v1/runs`(异步)**——`/v1/tasks/stream` 不支持(多次尝试非单流,400)。与 `verify` **互斥**(同时给 → 400)。
|
|
928
|
+
- 结果带 `attempts[]`(每级一行:`index` / `model` / `passed` / `status` 逐字;`errorCode` 与 `terminal.code` 同一条对外词法 —— 出了本服务码形的读作 `internal.store_error`);门抛出的 `gateError` 与门附的 `diagnostics` 是自由文本,7.142.0 起过同一只结果脱敏器(认出的凭据片段换成 `«redacted…»`)。
|
|
897
929
|
- 成本上界 = 任务的 `maxCostUsd`(防冷重跑税)。**三条 core 警示**:① 每档**冷重跑**重付输入成本(便宜档常过才划算);② 门收到**未脱敏**输出(自定义门转发外部 verifier 要脱敏);③ **写工具会跑 N 次**——**只用于只读/幂等任务**(每次升级整任务重跑)。开放式任务(找全 bug/文笔)没有可判定 oracle、级联会空转,那种让模型用 Agent 工具委派几路子代再综合(广度交叉),而非级联(深度阶梯)。
|
|
898
930
|
|
|
899
931
|
**可选 — AskUserQuestion 的裁量窗(问活人的三个帽子)**
|
|
@@ -1275,7 +1307,9 @@ READ_DENY_PATTERNS='[{"pattern":"**/secrets/**"},{"pattern":".ssh","caseSensitiv
|
|
|
1275
1307
|
`neverAuto` 在策略折叠里),本服务不另合一份并集。
|
|
1276
1308
|
- **`neverAuto`** 与部署的 `APPROVAL_NEVER_AUTO` 同级:命中的调用必须由真人在**这一次**答 —— `bypassPermissions`、请求自己的 `allow`、持久规则、「本会话放行」、auto 分类器都放不掉;无人可问时按无审批面的终局拒。
|
|
1277
1309
|
名字文法与永不匹配的名字(退役名、无前缀短名……)的判决与 env 腿同一只判官:有这类名字 ⇒ 整请求 422。审批卡的问句是 `human approval required to run "<工具名>"`;出处串(`settings.permissions.neverAuto(<命中的工具名>)`)只在引擎闸内部消费、不上卡(部署的 `APPROVAL_NEVER_AUTO` 同样)。
|
|
1278
|
-
- **合规禁项是「拒而不是收窄」**:请求禁了某能力而任务自己带着它 ⇒ 整个任务以 `config.compliance_denied` 失败(`workflows` + `selfOrchestration`;`
|
|
1310
|
+
- **合规禁项是「拒而不是收窄」**:请求禁了某能力而任务自己带着它 ⇒ 整个任务以 `config.compliance_denied` 失败(`workflows` + `selfOrchestration`;`web_fetch` + 花名册挂着 `WebFetch`)。
|
|
1311
|
+
`mcp_servers` 分两形:请求自带的 MCP 条目在本部署本就挂不上时(多租户姿态、`mcp` 锁、部署合规档禁了 `mcp_servers`),它们在受理时被否决 —— 用户面一条 `mcp.injection_dropped` 通告,任务照跑;
|
|
1312
|
+
条目挂得上(单用户部署)或部署自带 MCP 服务器时,任务真带着 MCP 服务器 ⇒ 同样整个任务 `config.compliance_denied`。
|
|
1279
1313
|
⚠️ 单用户部署的默认工具面恒挂 `WebFetch`,请求的 `excludeTools` 补偿不了(引擎先查花名册、后卸载),所以 `web_fetch` 这个词今天只在多租户部署的请求座上可用。不需要部署配 `COMPLIANCE_PROFILE`(env 腿需要)。
|
|
1280
1314
|
- **`readDenyPatterns` 的请求侧界**:请求里**一段最多 2 颗 `*`**(每一颗都算,相邻的也逐颗算;`**` 整段、`a**b`、`id_rsa*`、`*.pem`、`*secret*` 都在内)、**整张列表合计最多 16 颗**、**最多 32 条**;超了 ⇒ 400,句子点名坐标与上限。这是请求面的受理口径(请求是不可信的写者);引擎 7.55.0 起路径段按 `*` glob 匹配,星的个数不再影响匹配代价。进任务的就是写下的那一份(不改写模式)。需要更复杂或更多的行,合并成更宽的模式、改用不带星的字面形,或让运维写进 `READ_DENY_PATTERNS`(部署表不受此界)。
|
|
1281
1315
|
- **坏值不静默丢**:不是数组 / 超帽(读拒模式 32 条,其余三座 1000 条)/ 坏条目 ⇒ 400 `request.field_invalid` + `{ field, reason: "bad_entry" | "over_cap", index | count + cap }`;续跑重放存体时同判(409 `resume_blocked_by_policy`)。
|
|
@@ -1573,6 +1607,7 @@ ENGINE_ORPHAN_LINGER_MS=2000 # 可选,默认 2s(父没了之后的窗;见上一
|
|
|
1573
1607
|
`inflight` / `idleForMs` / `lingerMs`,孤儿还带 `orphanedForMs`),随后就是那条 `draining_started`。
|
|
1574
1608
|
`reason` 是闭集:`"idle"`(没人用了)/ `"reparented"` / `"esrch"`(后两者 = 父没了那一路,`orphan:true`)。
|
|
1575
1609
|
同一份读数会写进 `<数据根>/exit-last.json`(见上一节)。
|
|
1610
|
+
- **租约窗可读(`GET /health` 的 `engineLease`,7.141.0 起)**:装了自退腿的引擎在 `/health`(无鉴权)上多一个对象键 `engineLease: { lingerMs, tickMs }` —— `lingerMs` = 自退腿会执行的**最短**静默窗(`ENGINE_LINGER_MS` 与 `ENGINE_ORPHAN_LINGER_MS`〔装了父监视才有〕取小),`tickMs` = 采样拍(自退发生在**生效窗**满之后、至多再晚一拍;父还活着时生效的是较长的父活着的窗,所以实际自退可以比 `lingerMs` 晚得多 —— `lingerMs` 是安全节拍的上界(触点比它密,在任何状态下都先于自退),不是自退时刻的预言)。壳持租约的触点节拍据此定:比 `lingerMs` 密,在任何状态下都留得住引擎(附着着 SSE 流时本来就留得住,约束的是没有 SSE 的纯轮询壳),不必再按交给 spawn 的那份推 —— 别处起的短窗引擎、父死之后只剩孤儿窗的引擎也读得到。**取最短、不取「此刻生效」**:此刻生效的窗在父死那一拍从长窗掉到孤儿窗,按旧读数定节拍的壳会在下一次读 `/health` 之前被拆台。两个数与上一条 `engine_lease_armed` 日志是同一组窗。没装自退腿(两键都没设)、或腿已因排空 / 自退触发而收摊 ⇒ 键缺席(不补 0)。
|
|
1576
1611
|
- **坏值拒启**:`ENGINE_LINGER_MS` 必须是落在 **`[1000, 86400000]`(1s…24h)** 的整数毫秒,**两端都承重**:
|
|
1577
1612
|
下界防 `ENGINE_LINGER_MS=60`(以为单位是秒)—— 60ms 的窗等于把整条防误杀腿静默摘掉;上界防 `1e100`
|
|
1578
1613
|
这类值 —— 它能过朴素的「是正整数吗」检查,而计时**永远追不上它**,于是配置看着好好的、自退其实整件
|
|
@@ -1674,7 +1709,9 @@ invalid_using_default` 警告 + 退回缺省值」这条臂随词表放宽一并
|
|
|
1674
1709
|
继承整份用户环境(CC 交互形,用户自己的凭据形变量在内)—— 🔴 **但不含本服务自己的凭据**(7.129.0 起,引擎 7.51.1):配置目录全部 `type:"secret"` 名
|
|
1675
1710
|
(`SERVICE_AUTH_TOKEN(S)` / `APPROVAL_HMAC_KEYS` / `MODEL_API_KEY` …)与名单型旋钮名起服已向引擎声明为本进程自有凭据,生效配置里每条模型条目的 `apiKeyEnv` 也在名单里
|
|
1676
1711
|
(中心热应用新增 / 改名条目时在模型目录换代前重声明,名单只随落地的世代增长 —— 改名后旧名照扣到重启,没落地的候选不留痕;条目的 `apiKeyEnv` 是引擎扣不住的名,或它点到的名正被某只名单型旋钮交给沙箱 / 语言服务器(见下文沙箱名单段)⇒ 该候选整拒),`"all"` = 整份环境**减**它们,任何继承词都不把它们
|
|
1677
|
-
交给模型 shell(能力位 `inherit_env.own_credentials_withheld` = 最近一次声明 ⊇ 当前生效配置应声明的集合;真要让模型 shell 持某枚令牌 ⇒ 另放一个不在配置目录、也不是任何模型条目 `apiKeyEnv` 的名,或经 `settings.env` 显式授予)
|
|
1712
|
+
交给模型 shell(能力位 `inherit_env.own_credentials_withheld` = 最近一次声明 ⊇ 当前生效配置应声明的集合;真要让模型 shell 持某枚令牌 ⇒ 另放一个不在配置目录、也不是任何模型条目 `apiKeyEnv` 的名,或经 `settings.env` 显式授予);这些变量此刻的**值**也交给引擎按值扣(同值换名的副本同样进不了模型 shell),引擎判某个值「不是凭据值」(空白 / 占位词 / 一个字符重复 / 不足 8 字符)⇒
|
|
1713
|
+
那一个值不按值扣(名照扣、不拒启,能力位 `inherit_env.own_credential_values_withheld` 答 false),起服与模型目录换代时每个这样的变量出**一条** warn 结构化行 `own_credential_value_not_withheld { name, reason }`
|
|
1714
|
+
(`reason` 是引擎的拒句原文,从不回显值;起服第一步 logger 还没建时,这一行当拍以同一行形写 stderr,不缓冲)—— 按事件名告警,给该变量一个真值即可;`"scrub"` / 缺席 = 上面的缺省剥除。🔴 **`"all"` 只在单用户部署兑现**:`REQUIRE_PRINCIPAL=true`
|
|
1678
1715
|
⇒ 422 `request.host_posture_refused`(射程与写容纳面那条腿同一只谓词,`TASK_WRITE_FACE_ESCALATION` 不管它);非 host 车道带 `"all"` ⇒ 400。词表外的值(`"ALL"` · `""` · 名单 `["PATH"]` · 布尔 · `null` …)、非 host 车道带 `"all"`、部署不接 authorizer 时带 `"all"` 这三只都是 `400 request.field_invalid`,7.137.0 起体另带 `field: "inheritEnv"` 与 `reason`(`"unknown_word"` = 是字符串但不在词表;`"not_a_string"` = 根本不是字符串;`"lane_not_host"` = `"all"` 落在非 host 车道;`"no_authorizer_session"` = `"all"` 而部署不接 authorizer),壳按这两位认拒因、不解析句子(句子 / 码 / 状态不变;续跑腿同判,折叠 409 随体带同一组)。托管部署的 `422 request.host_posture_refused` 不在这组:它说的是「这台部署的姿态不给」,不是这个键写错,按 `errorCode` 认、不带这两位。部署方
|
|
1679
1716
|
**没有**旋钮能替调用方打开它,也没有旋钮能在单用户部署上关掉它(单用户部署的用户把他自己的环境交给他自己驱动的 shell);起服一行 info
|
|
1680
1717
|
`task_inherit_env_honored {honored}` 告诉你这台机器认不认。上面「部署级名单不给模型驱动 shell」那条不变 —— 两件事是两条轴(部署名单 vs 调用方 × 单用户射程)。
|
|
@@ -1716,7 +1753,7 @@ bake-runner 要用 ⇒ `LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW` 点名放回。
|
|
|
1716
1753
|
(`A,,B`、尾逗号)、非变量名形(`1BAD`、带空格、`NAME=value` 整段贴进来)、点名名单型旋钮(`E2B_SANDBOX_ENV=E2B_SANDBOX_ENV`,
|
|
1717
1754
|
或 `LSP_ENV_ALLOW` / 另一只沙箱名单)⇒ 起服失败,拒句点名键与第几段,**不回显原值**。**点名本服务自有凭据名** —— 配置目录里的 secret 型变量(如
|
|
1718
1755
|
`SERVICE_AUTH_TOKEN(S)` / `APPROVAL_HMAC_KEYS` / `MODEL_API_KEY` / `E2B_API_KEY` / `K8S_TOKEN` / `GIT_API_TOKEN`)—— 同样起服失败:名单会把这枚凭据原样装进模型读得到的沙箱;
|
|
1719
|
-
与 `LSP_ENV_ALLOW` 同一条律、同一只判官(引擎拒白名单的那一只,按平台比名),拒句同一个开头 `this deployment's own credential —
|
|
1756
|
+
与 `LSP_ENV_ALLOW` 同一条律、同一只判官(引擎拒白名单的那一只,按平台比名),拒句同一个开头 `this deployment's own credential — `,点名键与第几段(`entry #k of n`,k 从 1 起,就是你写的名单里的第 k 项;一句话里只有这一套序号),不回显名也不回显值。
|
|
1720
1757
|
沙箱要凭据 ⇒ 给它铸一把自己的(名与值都不同于本服务的任何凭据),放进服务进程环境再点那个名;判的是名字,把同一个值换个名字再点,起服认不出、值照样进沙箱 ——
|
|
1721
1758
|
所以「值也不同」是出路的一半。**中心 / config.d 模型条目后来点到同一个名**:条目的 `apiKeyEnv` 在模型目录换代时才并进本服务自有凭据名,那一刻对本表三只与
|
|
1722
1759
|
`LSP_ENV_ALLOW` 此刻交出去的名用同一只判官重判 —— 新并进的名正被某只名单交出去 ⇒ 那份候选整拒、上一代照常服务,拒句点名旋钮、名与条目;出路二选一:给沙箱另铸一把并改名单
|
|
@@ -1795,7 +1832,7 @@ PostgreSQL 硬上限 ⇒ 只有缩小),运维日志一行 `submit_ctx_row_too_la
|
|
|
1795
1832
|
| `objective` | ✅ | 要做什么(自然语言)。**唯一必填。** |
|
|
1796
1833
|
| `sessionId` | — | 续聊:带上次返回的 `sessionId`,服务端自动 wake 历史。**只收 canonical uuid**(任意版本,小写;与会话口同一只形判):自选名 / 业务键 / 空串 ⇒ `400 request.id_invalid`,缺省请**省略这个键**(服务端现铸 uuid)。想要好记的名字,自己记 name → uuid 的映射 |
|
|
1797
1834
|
| `images` | — | 图文输入 `[{data,mimeType}|{url}]`(模型需支持 vision)。**随提交的这条目标一次送达**:续跑 / 投递腿(审批 / 资源停车 / wake / plan_review 续跑、在宿主会话上新起的一跑)重建配置时不再带它(与 `userAttachments` 同律;图在首跑已是会话里的消息) |
|
|
1798
|
-
| `attachmentIds` | — | D-1 通用文件上传(1.289+):先 `POST /v1/attachments?name=…`(raw body,content-type=mime)拿句柄,提交时引用 ≤16 个;文件物化到执行环境工作目录 `attachments/`
|
|
1835
|
+
| `attachmentIds` | — | D-1 通用文件上传(1.289+):先 `POST /v1/attachments?name=…`(raw body,content-type=mime)拿句柄,提交时引用 ≤16 个;文件物化到执行环境工作目录 `attachments/` 下(沙箱车道在恢复点放:沙箱铸出或恢复之后、交给任务之前),objective 尾部自动追加文件清单(内容不进会话流)。一只上传一经绑定就属于那个会话,交给别的会话 ⇒ `409 attachment.bound_elsewhere`(7.142.0 起;每个会话各传一次)。mime 为 `application/vnd.sema.project-bundle` 的是**项目包**(工作区的种子,只进沙箱车道,见 §9.3j)。单文件缺省 ≤32 MiB(`ATTACHMENT_MAX_BYTES`);可配 mime 白名单(`ATTACHMENT_MIME_ALLOWLIST` CSV,缺省不限);上传后未引用的按 `ATTACHMENT_UNBOUND_TTL_MS`(缺省 24h)回收。**云形态(tidb/pg)字节本体存对象存储——MinIO 必配**(`MINIO_ENDPOINT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY`,与快照 lane 同一组变量),未配则附件面 501;local 形走本地文件店。 |
|
|
1799
1836
|
| `userAttachments` | — | 请求层附件(≤20 条),原样交给引擎、随**这条目标**送到模型:`{ path, lines? }` 读这次 run 的工作区 / `{ name, text, startLine? }` 宿主给的文本 / `{ name, image: { data, mimeType } }` 宿主给的图片(base64)。形判属主是引擎:坏形、带行号超 Read 上限(100 000 字符)的 text、过不了准入的图 ⇒ `400 config.user_attachment_invalid`(`error` 以字段路径起);`path` 只在有手场景(这次 run 有工作区)受理 —— 无手场景(`scan` / `code-review`、无手叠层、`provider: "in-process"` 的部署)上整条 `path` 条目同码 400,改发 text / image 条目;能力位 `supplies` 是席位能承载的供给,不按场景裁 —— **这个场景在本部署上受理哪些**读 `GET /v1/capabilities/scenarios/<name>` 的 `attachmentSupplies`(7.133.0 起;席位 `supplies` 的子集,不含 `path` 的场景发 path 条目必同码 400,发之前读它,不必撞 400);读不到的文件不拒,它的消息里说明没附上,结局见流上目标那一帧 `human_input.attachments`。只随目标走:steer / interrupt 带它 400,续跑不重发。带附件的提交在第一次回复出来之前被切断(halt / interrupt)时,这次 run 不落回退锚 —— 拿它的 taskId 去 `resumeAt` ⇒ `404 resume_at.unknown_event`,请显式给 resumeAt。与 `attachmentIds` 分工:那条把文件放进工作区让模型按需去读(内容不进上下文),这条把内容直接送进上下文。能力位 `userAttachments` |
|
|
1800
1837
|
| `scenario` | — | 省略时取本部署的 `DEFAULT_SCENARIO`(工厂缺省场景名 = **`code`**——CC 编码 persona 蒸馏版,default 全量工具面,终验旋钮独立;`default` 场景**已非出厂缺省**,要用它须显式传 `scenario:"default"`,或部署方显式设 `DEFAULT_SCENARIO=default`)。可选内建名:`default`(通用/助理场景,域中性 persona,CC agent loop 全量工具面)/ **`cowork`**(办公向场景,**7.133.0+**:`default` 的工具面去掉编码类工具 —— 不带 `Bash` / `Edit` / `Write` / `NotebookEdit` / `RepoMap` / `LSP` / `EnterWorktree` / `ExitWorktree` / `Monitor`,留 `Read` / `Glob` / `Grep` 文件读、浏览(WebFetch / WebSearch)与连接器挂载;role 层是 core 的 Cowork 角色基底,调用方的 `systemPrompt` 照样整替它;仍挂手,所以附件 `path` 在有执行环境的部署上照常受理;你自己请求体里的 `excludeTools` 与它取并,只会多卸)/ `code-review`(见 §5)/ `scan`(同 §5 的 repo 只读工具但**中性无框架提示词**——objective+中心下发 skill 全权主导输出,OA 扫描类用;与 `code-review` 同属 clone-free 无执行环境场景,见 §5 末)/ **配置控制面可声明任意新场景**(`{name, toolset: none\|repo-readonly, prompt?}`,组合即配置、能力写死在部署;restart-to-apply;center 可覆盖内建名,boot 日志 `config_center_scenarios.shadowsBuiltin` 可审计)。**缺省与指派都必须是本部署在册的场景名,悬空不回落 `default`**:`DEFAULT_SCENARIO` 不在册 ⇒ **起服拒**(拒句点名那个名字与在册词表);中心按主体指派的场景名本部署没有 ⇒ 该主体的 run 答 **503 `state.scenario_assignment_unknown`**(体 `detail: { scenario, source: "ruling" }`,不带 `Retry-After`;修法 = 中心改指派,或把那个场景加回本部署,然后原样重试);请求体显式给的未知名仍是 400 `scenario_unknown` |
|
|
1801
1838
|
| `repo` | — | `code-review`/`scan` 必填,见 §5(7.126.0 起 `council` / `debate` / `lenses` / `rounds` / `team` / `businessContext` 是未知键 ⇒ 400:它们喂的评审团腿与 `discuss` 场景随引擎 7.49.0 删掉团队运行时一并删除) |
|
|
@@ -1917,7 +1954,8 @@ curl -s http://<host>:8090/v1/runs/<taskId> -H 'x-agent-principal: user:42' #
|
|
|
1917
1954
|
```bash
|
|
1918
1955
|
curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
|
|
1919
1956
|
-H 'x-agent-principal: user:42' -d '{"objective":"…"}'
|
|
1920
|
-
# → SSE
|
|
1957
|
+
# → SSE,每条两行:event: <type> + data: <原始 TaskEvent>,如 event: text_delta / data: {"type":"text_delta","delta":"…"} … event: done / data: {"type":"done","result":{…}}
|
|
1958
|
+
# (带 eventId 的帧在最前面多一行 id: <eventId>;心跳 = event: heartbeat + data: {}。7.141.0 起每帧都具名,此前引擎帧与 done 只有 data 行)
|
|
1921
1959
|
# 注意:这是「同实例逐 token」;跨 worker 断线重连用 §4 的 /v1/runs(turn 粒度)。
|
|
1922
1960
|
```
|
|
1923
1961
|
> **7.127.0 起两处帧形(引擎 7.50.0)**:
|
|
@@ -2043,7 +2081,7 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
|
|
|
2043
2081
|
> - **未设 + 没有便宜模型**(`MODEL_CHEAP_ID` 未设时 summarize 落主模型)⇒ **关** + 起服一行 warn
|
|
2044
2082
|
> `memory_consolidation_default_off_no_cheap_model`(点名 `MODEL_CHEAP_ID`;显式写 `off` 即静音)。理由:一轮整库
|
|
2045
2083
|
> 折叠读 ~1e5 prompt tokens,落主模型就是按最贵的价记账。
|
|
2046
|
-
> - **未设 + 结构上跑不起来**(下面 ①②③ 三形:多租户 / `MEMORY_ENGINE=off` / pg·
|
|
2084
|
+
> - **未设 + 结构上跑不起来**(下面 ①②③ 三形:多租户 / `MEMORY_ENGINE=off` / pg·mysql 记忆后端 / `MEMORY_PROVENANCE=off`)
|
|
2047
2085
|
> ⇒ **恒关、零提示**(配不配便宜模型它都开不了;缺省不造新拒启)。
|
|
2048
2086
|
> - **显式 `on` / `off` 恒赢**。显式 `on` 而座落主模型 ⇒ 照开,起服一行 warn `memory_consolidation_on_main_model`
|
|
2049
2087
|
> 说清按主模型计费(部署方显式承担)。
|
|
@@ -2345,10 +2383,11 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
|
|
|
2345
2383
|
| HTTP `200` / `202` 应答里的 `warnings`(7.133.0 起;同步腿 200 体 · 流式腿 `meta` 帧 · 异步腿 202 回执;**有话说才在场**) | 请求的放行侧选择器清单(根 `allowTools`、子代定义的 `allowTools`)里有什么也不放的条目,而受理口没拒(放行侧只拒近似名,其余交引擎):`reason` 是引擎条目读法的原因词(`tool_name` · `grammar` · …)或 `not_in_roster`(读得出、却不在名册 —— 引擎目录 ∪ 本服务自铸工具 ∪ 本请求挂的调用方工具(主名 · 别名 · 子代工具池);协议命名空间名 `mcp__*` / `a2a__*` 懒挂载、`*` 是「不设名单」,都不判)。每条 `{ code, field, entry, reason }`,形同上一行。这不是拒:请求照常受理、照跑,引擎对这些条目的既有处置不变 | 把 `warnings` 当提示给用户看(「这几条什么也没放」);同一 `Idempotency-Key` 的重放从 run 记录答,不重判、不带;在飞合流回放的是首发那一腿铸的应答 |
|
|
2346
2384
|
| HTTP `422`(`request settings cannot be applied as written: …`)/ HTTP `400` + `errorCode:"request.field_invalid"`(7.131.0 起的读成空) | 请求体 `settings.permissions.deny` / `ask` 里的孪生与退役名 ⇒ 422、句子点名带内容的现名(`BASH(*)` ⇒ 写 `Bash(*)`);同两桶里参数不属于该工具的规则(`WebFetch(foo:…)`、`WebSearch(domain:…)`)⇒ 422 `unsupported.param_unknown`,句子列出该工具能写的参数(7.135.0 起;此前受理、永不命中);`settings.permissions.allow` 与技能 `allowedTools` 里的**近似名**(`BASH`)⇒ 400(退役名 · 内容形 · 文法读不出(带空白 / 括号不配 / 规则内容文法不成立,如 `Bash(echo $HOME)`)· 对端段通配照 7.130.0 受理,引擎通告)—— 全部读**同一张名册**(引擎目录 ∪ 本服务自铸的工具名)。运维 `APPROVAL_REQUIRE` / `APPROVAL_DENY` / `APPROVAL_NEVER_AUTO` / `APPROVAL_GRANT` 里的孪生 **拒启**,中心下发的 `governance.approvalRequire` 里的孪生整组被拒、保前值。续跑:停驻在升级前的任务,超 1000 条的清单(任一方向)与限制方向的存量孪生 `409 resume_blocked_by_policy`,放行方向的存量近似名照旧续跑 + 一行 warn `stored_allow_list_inert_resumed` | 改成句子里 `write` 后的现名(或删掉条目);超帽的合并成更宽的条目 |
|
|
2347
2385
|
| HTTP `400` + `errorCode:"request.field_invalid"` + `detail.problems[].reason:"below_trust_floor"`(7.133.0 起) | 多租部署(`REQUIRE_PRINCIPAL=true`)上调用方的信任档低于 `settings.permissions.allow`(或 `userInvokedSkills` 点用的自带技能的 `allowedTools`,`field: skills[i].allowedTools`)要的 `global`:档只由这次请求验过的凭据推 —— 部署的 service 凭据、或中心登录令牌在活动 scope 里的角色 ≥ `editor`(settings-schema 的治理写角色)⇒ `global`;角色更低 / 令牌不带角色 / 直连门 principal 令牌 / 没有验过的凭据 ⇒ `project`(`detail.callerTrust`)。`deny` / `ask` 与空 `allow` 照收;单用户部署任何调用方都是 `global` | 去掉 `allow`、开跑时答卡;请运维把规则放进 `APPROVAL_GRANT`;或请 scope 管理员把成员角色抬到 `editor` 及以上。提交前可读 `GET /v1/capabilities` 的 `settings.permissions.callerTrust` |
|
|
2386
|
+
| HTTP `422`(`request settings cannot be applied as written: …`)+ `detail.problems[].reason:"home_unresolvable"`,句子说 `user-settings path rule rooted at the configuration directory`(7.141.0 起) | 请求 `settings.permissions.deny` / `ask` 里一条 `layer:"userSettings"` 的 `/` 形路径规则,而这条沙箱车道既没把 `SEMA_CONFIG_DIR` 转进沙箱、也没有可知的 home(k8s / local-docker / ssh / adb / device 且未声明 `REMOTE_EXEC_HOME_DIR`)—— 配置根读不出,不猜目录(续跑同体 409 同句) | 往沙箱 env 名单里加 `SEMA_CONFIG_DIR`,或声明 `REMOTE_EXEC_HOME_DIR`,或把规则写成 `//` 绝对形 / 放进项目层(读在任务根);见 9.4d |
|
|
2348
2387
|
| HTTP `429` + `errorCode:"usage.window_exhausted"` | 部署级治理窗耗尽(`USAGE_WINDOWS`,token 或 $ 天花板先满者) | 看响应体 `retryAfterSec` 退避;窗滑动/桶到期后放行 |
|
|
2349
2388
|
| `terminal:{kind:"failed", code:"usage.window_exhausted"}` | 已受理的 run 在 **turn 边界**撞上治理窗且无法 durable 挂起 | 同上退避后重投;配好 checkpoint 基建则改为 `suspended` 等窗自动续跑 |
|
|
2350
2389
|
| HTTP `501`(`/v1/runs`) | 内存模式不支持异步 | 配持久存储(`DB_BACKEND=mysql` / `pg` + 坐标;7.106.0 起给了坐标必须点名 `DB_BACKEND`) |
|
|
2351
|
-
| HTTP `500` + `errorCode:"corrupt_session"`(7.104.0 起;流式口在应答头之后则是 `done` 帧的 `result.terminal.code`,后台 run 是 run 行的 `errorCode`) | 这只会话的**存档读不出**、唤不醒(文件后端:会话日志没有会话头;SQL 后端:一行事件读不出)。这一轮没跑,一个 token 没烧。直接读这只会话的口(头探针 / 事件订阅 / 会话视图 / 改名 / 导出 / 分叉 / 2c 同步)同答(契约 §17;文件后端上事件订阅与改名 7.136.0 起同答,此前一个 200 起流却零帧、一个 404) | **别重试**(确定性失败)。**文件后端**:运维看 `fail_open_total{tag="server.session-repo.corrupt-record-skipped"}` 的计数、stderr 契约行 `[sema] fail-open: server.session-repo.corrupt-record-skipped` 与随带的一条 `fail_open` warn(后两者每进程每 tag 只一次,warn 带首条明细);逐条明细(文件路径、会话 id、行号、成因)每命中一行进探针文件 —— 起服前设 `SEMA_FAILOPEN_PROBE=<文件路径>`(会话头那一行本身读不出时,它就是其中一条);修或移开那份存档。**SQL 后端**不经这只座:坏的那一行由错误句子点名(`session_event.payload` + 会话 id + 序号 `seq`)。要继续工作就换一个新会话 |
|
|
2390
|
+
| HTTP `500` + `errorCode:"corrupt_session"`(7.104.0 起;流式口在应答头之后则是 `done` 帧的 `result.terminal.code`,后台 run 是 run 行的 `errorCode`) | 这只会话的**存档读不出**、唤不醒(文件后端:会话日志没有会话头;SQL 后端:一行事件读不出)。这一轮没跑,一个 token 没烧。直接读这只会话的口(头探针 / 事件订阅 / 会话视图 / 改名 / 导出 / 分叉 / 2c 同步)同答(契约 §17;文件后端上事件订阅与改名 7.136.0 起同答,此前一个 200 起流却零帧、一个 404)。会话列表 `GET /v1/sessions` 里它仍是一行,行带 `unreadable: { errorCode }`,码就是这些口对它答的那一个(文件后端,7.142.0 起;此前它从列表里消失;存档文件本身读不出 —— 权限 / I/O —— 时码是 `internal.error`) | **别重试**(确定性失败)。**文件后端**:运维看 `fail_open_total{tag="server.session-repo.corrupt-record-skipped"}` 的计数、stderr 契约行 `[sema] fail-open: server.session-repo.corrupt-record-skipped` 与随带的一条 `fail_open` warn(后两者每进程每 tag 只一次,warn 带首条明细);逐条明细(文件路径、会话 id、行号、成因)每命中一行进探针文件 —— 起服前设 `SEMA_FAILOPEN_PROBE=<文件路径>`(会话头那一行本身读不出时,它就是其中一条);修或移开那份存档。**SQL 后端**不经这只座:坏的那一行由错误句子点名(`session_event.payload` + 会话 id + 序号 `seq`)。要继续工作就换一个新会话 |
|
|
2352
2391
|
| HTTP `500` + `errorCode:"invalid_session"`(7.137.0 起;流式口在应答头之后则是 `done` 帧的 `result.terminal.code`,后台 run 是 run 行的 `errorCode`) | 这只会话**存着的日志**读得出、结构走不通:某条目的父不在日志里(悬空)、条目是自己的祖先(自指 / 成环)、叶子不在日志里。这一轮没跑、一个 token 没烧(同步提交答 500、不计费)。读整条分支的口(会话视图 `GET /v1/sessions/:id` / `…/memory-status`)同答;事件订阅与头探针只读会话头的叶子,对这一形照旧 200 / 起流(契约 §17.7)。体的 `error` 是引擎原句(点名条目 id,不含盘上路径与会话 id),没有 `reason` 机读位。会话同步**导入**时调用方交来的日志没过校验是另一件事:`422 invalid_entries` | **别重试**(确定性失败)。换一个新会话;或从断点之上的条目分叉;或由运维修好 / 移走那份日志。同一 `Idempotency-Key` 重发会重新受理(这类零工作的拒不占键) |
|
|
2353
2392
|
| 流里一帧 `engine_notice` `code:"session.records_skipped"`,`detail:{ dropped, entriesKept, sessionId }`(7.104.0 起,只在文件后端) | 这只会话的存档打开时有 `dropped` 条记录读不出、被跳过了;这一轮**照跑**,但模型读到的历史只剩 `entriesKept` 条。存档没修好之前,每次真正打开这只会话都会再说一次(会话缓存命中的轮次不打开、不说;`SESSION_CACHE_TTL_SEC=0` 时每一轮都说) | 告诉用户「这段对话的一部分历史丢了」;运维按 `fail_open_total{tag="server.session-repo.corrupt-record-skipped"}` 的计数与探针文件(`SEMA_FAILOPEN_PROBE=<文件路径>`,每命中一行)里的逐条明细(文件路径、会话 id、行号、成因)查那份文件。非流式 `POST /v1/tasks` 收不到通告帧(只有运维面的计数与探针) |
|
|
2354
2393
|
| 流里一帧 `engine_notice` `code:"route.finish_reason_unknown"`,`detail:{ finishReason, sessionId, runId }`(7.126.0 起) | 提供方用一个引擎读不懂的结束原因结束了这一轮:回答按模型留下的样子保留,但可能被提供方截短了 | 告诉用户「这一段回答可能不完整」;同一个词同一 run 只说一次。运维按 `finishReason` 查是哪家网关 / 模型发的 |
|
|
@@ -2363,13 +2402,15 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
|
|
|
2363
2402
|
|
|
2364
2403
|
**进程警告面(日志采集方注意)**:引擎(core ≥5.16)在持久 agent 行的 org 判决写回被丢弃等场合走
|
|
2365
2404
|
Node `process.emitWarning`,警告文案前缀固定 `sema durable-agents:`——采集规则按该前缀匹配,别当噪音过滤掉。
|
|
2366
|
-
server 自身的兜底留痕走 stderr
|
|
2405
|
+
server 自身的兜底留痕走 stderr 上的一行 JSON 日志(`msg` 逐字 `[sema] fail-open: <tag>`,字段 `{ tag, count }`,逐 tag 一次,不随 `LOG_LEVEL`)+ `fail_open_total` 指标,
|
|
2367
2406
|
tag 词表与每条的最坏后果见 `docs/FAIL-OPEN-CENSUS.md`。引擎装配期忠告(core `onError(phase:"config")`)落
|
|
2368
2407
|
`runner_config_advisory` 日志行,带结构化 `code`(如 `config.toolpolicy.unmatched_names`)与 `classification`
|
|
2369
2408
|
(core 给宿主定级的判别词;词表外原样透传并标 `classificationKnown:false`),指标 `runner_config_advisory_total`
|
|
2370
2409
|
按 `code` / `classification` / `level` 打标;其中 `shell-gate-off` 在本 session 显式声明 `permissionMode:
|
|
2371
2410
|
"bypassPermissions"` 时是调用方要的姿态,降为 **info** 并标 `expected`——只有没表态落到引擎默认 off 的无壳直连
|
|
2372
|
-
形才 warn
|
|
2411
|
+
形才 warn。引擎交来的错自带机器码(`err.code` 是非空串、且**是码**:不超过 64 字符的短 token,不含空白 / `=` / 换行,也不是 `sk-…` / `AKIA…` / `ghp_…` 这类凭据形)时,`onError` 汇点上的日志行一律把它写成结构化 `code` 字段 ——
|
|
2412
|
+
`mcp_server_unavailable` / `a2a_peer_unavailable` / `task_degraded` / `prompt_composition_warning` / `prompt_cache_break` / `runner_config_advisory` / `runner_error` 同一条律(如
|
|
2413
|
+
`mcp.tools_capability_absent`:MCP 服务器没申报 `tools` 能力而 `allowTools` 非空)。告警规则按这个字段匹配,别去句子里找(句子不一定带那串码);错不带码(没有 / 不是串 / 空串)或带的不是码时该键缺席(`runner_config_advisory_total` 的 `code` 标签同判);记忆引擎事故行 `memory_engine_incident` 与计数 `memory_engine_incident_total` 的 `code` 位、起服面三只 operator 面引擎座(`memory_compliance_incident` / `memory_origin_incident` / `memory_consolidation_incident`)的 `code` 位、子代额外工具故障行 `subagent_extra_tools_error` 的 `code` 同一条律(无码 / 不是码 ⇒ `code` 键与标签缺席,不写 `null` / `none` 占位)。子代 `agents[].denyTools` / `allowTools` 的**名字**归引擎开跑前一只判(7.126.0 起与根 run 的 `allowTools` / `excludeTools` 是同一只工具选择器):
|
|
2373
2414
|
7.129.0 起(引擎 7.51.0)没有任何工具答应、也不是某只已挂载工具另一种拼法的名字(**真未知名**)**引擎不再拒跑**:条目原样保留(今天什么都不拒 / 不准,之后挂上同名工具即生效),运维行 `runner_config_advisory` 每条告知一次(句子带该写的拼法;委派工具声明了逐次注入工具的名册,引擎列得出子代工具池);
|
|
2374
2415
|
引擎开跑前拒(`config.agent.unknown_tool`)的是任何工具名都不可能有的拼法(空白、括号不配、空名)、非字符串条目,以及(引擎 7.52.0 起,两侧同判)写成**已挂载工具另一种拼法**的条目:大小写孪生(`BASH`)与有后继的退役名(`Task` ⇒ `Agent`、`bash` ⇒ `Bash`)。**7.131.0 起本服务把其中写错现名的在受理口前置拒:限制侧四类全拒、放行侧只拒近似名** —— `denyTools:["BASH"]` / `["bash"]` 以为禁了 `Bash`、子代照用(静默放行),`allowTools:["BASH"]` 想放 `Bash` 却什么都没放(静默收窄);
|
|
2375
2416
|
提交 400 `config.agent.unknown_tool`(根 run 的清单是 `config.tool_face_control`),句子点名条目、原因词与现名;放行侧的**内容形**(`Agent(Explore)`)与没有后继的退役名(`MultiEdit`)仍照 7.130.0 受理、交引擎既有通告,选择器清单(根 / 子代 `allowTools`)里**有后继的退役名**(`Task` · `bash`)7.132.0 起由引擎开跑前拒,规则表里的退役名照旧受理、引擎开跑时告运维;文法读不出的放行条目授不出去 = 收窄而不是放行:规则表(`permissions.allow` / 技能 `allowedTools`)上受理口不拒、引擎开跑时告运维;选择器清单(根 / 子代 `allowTools`)上受理口不拒、引擎开跑前自己拒(子代 ⇒ `config.agent.unknown_tool`、根 ⇒ `config.tool_face_control`,同步腿都是 `400`〔7.132.0 起;此前子代这一形答 HTTP 200 + failed 终局体〕;异步 / 活流腿 HTTP 2xx、同码落在终态 run 行);存量体续跑见 MIGRATION 7.131.0 第 8 条。判官仍是引擎的条目读法。**真未知名**(没有近似也没有退役对应:懒挂载的合法形)照旧只告运维、不拒。名字按工具名原拼写 `Bash`。这两张表管子代可挂载的**全部**工具 —— 委派池、内建 hands(`Read` / `Edit` / `Write` / `NotebookEdit` / `Bash` / `Grep` /
|
|
@@ -2530,6 +2571,7 @@ k8s 车道每条 run 一只新 pod(pod 寿命 = 泄漏护栏,不跨 run 复用)
|
|
|
2530
2571
|
它恰是服务为 env Secret 真发的调用;不要给 `get`(服务从不读回,给了就读得到命名空间里每一只 Secret)与 `delete`(Secret 随属主 pod 由集群回收)。租约 Secret 的 `patch` 只在 §9.3h 的平面打开时要。
|
|
2531
2572
|
名单非空时起服各问一次 SelfSubjectAccessReview:答了「不许」⇒ **拒启**,拒句带 `[sandbox-secret-rbac]`、点名缺的动词与这条规则;问不到(API 连不上 / 审查本身被拒)⇒ 照常起服,
|
|
2532
2573
|
一行 `sandbox_secret_seat_unverified` + fail-open 计数 `server.sandbox-secret.seat-unverified` —— 那时若 Role 真缺,第一个要转发的 run 在连接时被拒、它的 pod 被删。
|
|
2574
|
+
这一行的 `detail` 是哪只动词没问到、为什么(请求失败的原因句);原因句与起服面别的运维行里的异常句同一读法:认出的凭据形换成记号、剥控制字符、界 200 码元。
|
|
2533
2575
|
- **放弃的 pod 删不掉(运维面,7.137.0 起)**:上面这类拒绝(env Secret 建不成 · 成员凭据代理的租约 Secret 建不成 · 代理镜像拉不下)要删那只刚建的 pod;这一删自己失败(请求抛 / API 回 403 或 5xx,比如 Role 缺 pods `delete`)时,
|
|
2534
2576
|
连接的拒答不变,服务多记一行 error `sandbox_pod_delete_failed`(`pod` / `namespace` / `why` / `cause`,不带值、不带 API 文本)+ fail-open 计数 `server.sandbox-pod.delete-failed`;pod 与它名下的 Secret 留给回收器(§9.3g)。
|
|
2535
2577
|
计数持续非零就按 `cause` 核 Role 的 pods `delete` 与 API 可达性。
|
|
@@ -2605,7 +2647,8 @@ k8s 车道每条 run 一只新 pod(pod 寿命 = 泄漏护栏,不跨 run 复用)
|
|
|
2605
2647
|
|
|
2606
2648
|
**起服自检**(`REMOTE_EXEC=k8s`,起服一次、不挡起服):服务用自己的 k8s 账号读节点表(`nodes` get / list,集群级)与沙箱 ns 的 NetworkPolicy(`networkpolicies` get / list),
|
|
2607
2649
|
按「选中沙箱 pod 的 Egress 策略的放行规则并集」判每个节点的每个 InternalIP / ExternalIP。读出的缺口每个一行 warn `sandbox_egress_policy_gap`(带 `effect` 后果句)并计数
|
|
2608
|
-
`server.sandbox-egress.policy-gap`(fail-open 登记表第 135 行,记债);零缺口一行 info `sandbox_egress_policy_checked
|
|
2650
|
+
`server.sandbox-egress.policy-gap`(fail-open 登记表第 135 行,记债);零缺口一行 info `sandbox_egress_policy_checked`;自检本身半途抛了一行 error `sandbox_egress_policy_check_crashed`。
|
|
2651
|
+
读不到时 `detail` 与 `error` 里的原因句(客户端异常原文)认出的凭据形换成记号、剥控制字符、界 200 码元。`kind` 闭集:
|
|
2609
2652
|
|
|
2610
2653
|
| `kind` | 什么时候 | 去哪改 |
|
|
2611
2654
|
|---|---|---|
|
|
@@ -2682,11 +2725,47 @@ ssh / adb / local-docker 三条车道的流式调用同读这一条律:没有车
|
|
|
2682
2725
|
租约卷只读、0400、只挂代理容器;`shareProcessNamespace:false`;连接要等代理容器就绪(exec 探针)才算成。部署的 pod 补丁在代理在场时只许 `volumes` / `volumeMounts` / `containerSecurityContext` / `labels`
|
|
2683
2726
|
(容器级只落 agent 容器),**`podSecurityContext` 整只不许** —— 用了它的部署,平面关(`pod_patch_reaches_broker`)而不拒启;把 pod 级加固挪进 `containerSecurityContext`。
|
|
2684
2727
|
- **平面开没开,看一处**:`GET /v1/capabilities` 的 `credentialPlane.sandboxGit`(`on` + 逐 origin `delivers`,或 `off` + 第一个不成立的前提词,九词闭集与判序见契约附录 B)。
|
|
2685
|
-
|
|
2728
|
+
读数每次读时求值(起服读数 —— 秘密座答复、补丁判官 —— 加当前生效配置的 `sandboxGit` 块),不是起服时存下的一份。起服时若是 k8s 多租户部署,日志一行 `credential_plane_sandbox_git`(`state` / `reason` / `why`,记的是那一刻的读数)。
|
|
2729
|
+
- **代理哪些 origin**:有效配置的 `sandboxGit` 块 —— 控制台按部署登记册投影,只在本 worker 自己的拉取上出现(配了 `SEMA_WEB_ADMIN_WORKER`);没有 env 旋钮,本地配置源(`CONFIG_PROVIDER=local`)没有这一块。
|
|
2730
|
+
块随有效配置的每次提交热换代、不签重启(刷新拍 / 迟到起服 / LKG 起服都一样;中心凭证换人降档时随整份中心配置撤下):能力位下一次读就是新代;k8s 每只 pod 在建起时读一次平面,
|
|
2731
|
+
已在跑的 pod 的路由表不变 —— 删 / 加 origin 对新 pod 生效。块判不过契约(重复 / 超过 16 项 / 非规范 origin / `connectUrl` 不是 https / 不是对象)⇒ 当作没有任何 origin(`no_origins`;`@sema-agent/settings-schema` 消费契约 §12.8 的读法),
|
|
2732
|
+
一行 warn `web_admin_sandbox_git_refused`(`issues` 逐条坐标 + 契约拒句,不回显值),同一份候选的其余配置照常落地;块换代一行 info `web_admin_sandbox_git { version, origins }`。
|
|
2686
2733
|
- **旋钮**:`K8S_SANDBOX_BROKER_IMAGE`(代理容器的镜像;建议填本引擎自身镜像 —— 代理是本包里固定路径的程序;不设 ⇒ `broker_image_unset`)。Role 在 §9.3c 的 `create` 之外还要 `patch`(改写租约;租约 Secret 只用这两个;本版平面恒关,不用先给)。
|
|
2687
|
-
- ⚠️
|
|
2688
|
-
run 行的身份来源不是接线点:读的是受理时记在 run
|
|
2689
|
-
|
|
2734
|
+
- ⚠️ **平面仍恒 `off`**:一处读口还没接线 —— 取值口的 worker 凭据;有效配置的 `sandboxGit` 块已接(上一条)。读数停在 `no_caller_credential`(或更前的词),没有 pod 会挂上代理。
|
|
2735
|
+
run 行的身份来源不是接线点:读的是受理时记在 run 行上的那一份身份(连同登录令牌的 scope 与化身号 `sub_inc` 一起记下;化身号超过 64 字符不记,一行 `run_identity_claim_unrecorded`)。
|
|
2736
|
+
本节写的是组件的行为与边界;本版没有取值与续期(它们随 worker 凭据接线一起落),所以任何凭据都不进 pod。
|
|
2737
|
+
|
|
2738
|
+
### 9.3i 沙箱三车道的读拒表字节地板:`SANDBOX_READ_FLOOR`(7.141.0 起;本版模块不服务任何车道)
|
|
2739
|
+
|
|
2740
|
+
读拒表(`READ_DENY_PATTERNS` / 出厂读拒档)判拒的路径,读工具会拒;「字节地板」说的是更强的一件:**命令跑的每个程序**都打不开这些路径(或这只沙箱拒起这条命令)。车道守不守它,看能力块的 `keepsReadFloor`。
|
|
2741
|
+
|
|
2742
|
+
- **判据只有一条**:沙箱车道(e2b / k8s / local-docker)守地板 ⇔ 读地板模块服务这条车道 ∧ `SANDBOX_READ_FLOOR` 不是 `off`。主机 / ssh / adb / device 恒不守(这些环境约束不了进程)。
|
|
2743
|
+
**本版模块不服务任何车道** ⇒ 三条沙箱车道的 `keepsReadFloor` 仍是 `false`,沙箱里的起动与上一版逐字同。
|
|
2744
|
+
- **看一处**:起服行 `remote_exec_enabled` 的 `keepsReadFloor`,沙箱车道上再加 `sandboxReadFloor`:`unserved`(模块还没服务这条车道)/ `off`(部署关了)/ `kept`(守)。
|
|
2745
|
+
- **守地板的车道上会多出的两种拒起**(都是 `spawn_error`,命令一个进程都不起):① 这只沙箱守不住整张表 —— 首句 `read floor unavailable on this sandbox (<原因词>)`,原因词九选一
|
|
2746
|
+
(`arch` / `user_notif` / `addfd_send` / `uid_zero` / `writable_system_path` / `binary_digest` / `relay_silent` / `relay_identity` / `provenance`),句中点名表首行与 `SANDBOX_READ_FLOOR=off`;
|
|
2747
|
+
② 一次不带地板的引擎起动(流式执行面,以及本服务里几处替引擎干活的内部调用方今天都不带)—— 句子点名车道与 `SANDBOX_READ_FLOOR=off`。
|
|
2748
|
+
- **不想守**:`SANDBOX_READ_FLOOR=off`。块如实答 `false`;读拒表非空的 run 照旧每 run 一条运维通告 `config.read_deny_floor_unkept`,部署设了 `READ_DENY_FLOOR_REQUIRED=true` 时准备期拒(同码)。
|
|
2749
|
+
|
|
2750
|
+
### 9.3j 沙箱三车道:项目包 —— 没有 git 的项目作为工作区的种子(7.142.0 起)
|
|
2751
|
+
|
|
2752
|
+
没有 git 的本机项目经附件链上云:上传一只**项目包**,在会话的首次提交里绑定,沙箱车道(e2b / k8s / local-docker)在为这只会话**铸出新工作区**时把它解到工作根本身。
|
|
2753
|
+
|
|
2754
|
+
- **形**:gzip 压缩的 POSIX tar(`tar czf` 的形),顶层就是工作根(不要包装目录);只放普通文件、目录、相对符号链接(落点按包自己的树解 —— 经过包里别的链接 —— 仍在包内);不放顶层 `.git`(有 git 的项目走 git 引用)与顶层 `attachments`(附件的落点);
|
|
2755
|
+
不经符号链接写子路径;每条路径 ≤ 4095 字节、每段名字 ≤ 255 字节;pax 扩展头只收 `path` / `linkpath` / `size` 与元数据(时间、属主、扩展属性、ACL —— 解出来不带),稀疏文件等改变内容读法的扩展拒(`entry_type`);
|
|
2756
|
+
展开 ≤ 512 MiB、≤ 200,000 个对象(条目 + 路径隐含的目录);压缩体照附件上限 `ATTACHMENT_MAX_BYTES`(缺省 32 MiB)。项目身份照旧:包顶的 `.sema/project` 记号由引擎读,服务不读不写。
|
|
2757
|
+
- **上传**:`POST /v1/attachments?name=<名>`,`Content-Type: application/vnd.sema.project-bundle` → 201 `{ id, sha256, sizeBytes }`。读不出项目包 ⇒ `400 attachment.bundle_invalid`,体 `reason`(`not_archive` / `unsafe_path` / `entry_type` / `reserved_path` / `duplicate_path` / `expanded_too_large` / `too_many_entries`)与 `path`(被拒条目的落点;放不下的超长路径不带)。
|
|
2758
|
+
配了 `ATTACHMENT_MIME_ALLOWLIST` 的部署要把这个 mime 加进去,否则 415。
|
|
2759
|
+
- **绑定**:提交体 `attachmentIds: [id]`(首次提交;重试带同一 id 幂等)。车道不隔离 ⇒ `409 attachment.bundle_lane_not_isolated`(先读能力位 `executionLane.isolated`);会话已有种子 ⇒ `409 attachment.bundle_seed_fixed`;
|
|
2760
|
+
这只上传已绑在别的会话上 ⇒ `409 attachment.bound_elsewhere`(一只上传只给一个会话 —— 这条对所有附件都成立)。
|
|
2761
|
+
- **什么时候解**:只在车道铸出新工作区、且没有可恢复的树时(k8s:空间没有 `latest` 或 `latest` 的归档已没;e2b / local-docker:每只新沙箱),解完再放附件。
|
|
2762
|
+
恢复出来的工作区(k8s 空间的 `latest`、停驻快照的续跑)从不解种子,所以模型改过 / 删过的文件不会被种子还原。fork 出来的会话不带种子。委派子代不解。
|
|
2763
|
+
**跨回合是否保留改动看车道**:读能力位 `workspaceSync.persist === "space"`(k8s 工作区空间)才保留;e2b / local-docker / `WORKSPACE_PERSIST=off` 的 k8s 每个新回合都从上传态开始。
|
|
2764
|
+
k8s 工作区快照剔除名单(`WORKSPACE_SNAPSHOT_EXCLUDE`)里的目录:首轮收尾快照不含它,下一轮恢复时它不在,种子也不补。
|
|
2765
|
+
- **镜像契约**:沙箱镜像要带支持 gzip 的 `tar`(缺 ⇒ 这一次执行环境拒,句子点名 `tar`);镜像若在工作目录预置了与项目顶层同名的内容 ⇒ 拒,句子点名路径(不覆写、不合并);
|
|
2766
|
+
镜像别在工作根的祖先目录放 `.git`(引擎按向上找到的那只仓判项目身份)。
|
|
2767
|
+
- **运维**:每次播种一行 info `workspace_seeded{sessionId, bundleId, entries}`;删会话时种子随附件一并删。
|
|
2768
|
+
- **不删包**:首交成功之后不要 `DELETE /v1/attachments/:id` —— 无持久的车道每个新回合都要再解它。
|
|
2690
2769
|
|
|
2691
2770
|
### 9.4 auto 模式(`permissionMode:"auto"`):武装三态、本地 org deny、自查(与 core 的意图武装式合修)
|
|
2692
2771
|
|
|
@@ -2780,6 +2859,27 @@ plan 起步的任务把计划交给人之后停在 `plan_review` 门上。`POST
|
|
|
2780
2859
|
机读两桶逐字点名,**不再静默丢** —— 与 `/v1/approvals/:id/decide` 同一只机器、同码同串。
|
|
2781
2860
|
逐字契约见 `docs/ASSISTANT-WIRE-CONTRACT.md` §4c。
|
|
2782
2861
|
|
|
2862
|
+
### 9.4c 两层「放行 / 拒绝」别读混:单用户 allow-all 基线与敏感路径守卫集(7.141.0 起成文)
|
|
2863
|
+
|
|
2864
|
+
- **起服行 `tool_policy_single_user_default`(info)说的是部署工具策略层的 allow-all 基线,不是逐调用放行**:单用户 turnkey 且没有任何门意图(没有审批名单、没有显式启用 `DURABLE_APPROVAL`)时,部署层铺一条在场的、看效果的 allow-all 基线,
|
|
2865
|
+
好让引擎的「写手无裁决」告警不再响;这一层自己不问也不拒。每次调用仍由本次运行的权限模式与引擎写门裁(例如 `auto` 下 shell 的写 / 删照样出问、交分类器)。要收紧用 `APPROVAL_REQUIRE` / `AUTONOMY` / `commandPolicy`(起服行的 `tighten` 键同一句)。
|
|
2866
|
+
- **`SENSITIVE_WRITE_PATTERNS` 拒的是文件工具,shell 写同一路径不被它拒绝,走普通审批问**:守卫集对 Write / Edit / NotebookEdit 按路径做 deny;shell 命令写同一条路径(重定向、`tee`、`cp` …)是一条普通审批问,和这次运行里别的 shell 写同一条出路(人答;`auto` 下交分类器),不会因为命中这个集而被拒。
|
|
2867
|
+
要让某类 shell 写在你的部署里被问或被拒,管 shell 本身:`commandPolicy` / `AUTONOMY` / `APPROVAL_REQUIRE`。
|
|
2868
|
+
|
|
2869
|
+
### 9.4d 设置层的路径规则读在它那一层的根:`settings.permissions.deny` / `ask` 的带层条目(7.141.0 起)
|
|
2870
|
+
|
|
2871
|
+
- **一句规则**:一条路径规则的 `/` 读在它所在那一层的根上;`~/`、`//`、相对形在每一层读法相同。端从设置文件读规则时可以把出处层一起发:
|
|
2872
|
+
`"deny": ["Read(/secret/**)", { "rule": "Read(/secret/**)", "layer": "userSettings" }]` —— 纯串是请求自己写的规则(读在任务根,读法不变);带层条目的 `layer` 是设置来源词
|
|
2873
|
+
(`userSettings` · `projectSettings` · `localSettings` · `flagSettings` · `policySettings` · `foreignProjectSettings`)。能力位 `settings.permissions.layers` 为真才发。
|
|
2874
|
+
- **只有 user 层的 `/` 形随层变**:`userSettings` 里的 `Read(/secret/**)` 守的是**执行环境的配置根**下的 `secret`(host 车道 = 本服务的 `SEMA_CONFIG_DIR`,缺省 `~/.sema`),
|
|
2875
|
+
不再守任务根下的 `secret` —— 与参照实现读 user 层 `/` 的位置相同。别的来源与纯串读在任务根。要守每个项目自己的目录:把规则放进项目层,或写相对形 `secret/**`(任务根下任意深度);固定位置写 `//` 绝对形。
|
|
2876
|
+
- **沙箱车道的配置根**:运维把 `SEMA_CONFIG_DIR` 列进 `E2B_SANDBOX_ENV` / `K8S_SANDBOX_ENV` / `DOCKER_SANDBOX_ENV` 转进沙箱 ⇒ 读那个值;没转 ⇒ 执行环境 home 下的 `.sema`
|
|
2877
|
+
(e2b = `/home/user/.sema`;k8s / local-docker / ssh / adb / device 要 `REMOTE_EXEC_HOME_DIR` 声明 home)。两样都没有 ⇒ 这样的条目 422,`detail.problems[].reason:"home_unresolvable"`(与 `~/` 缺 home 同一个词);
|
|
2878
|
+
出路:转 `SEMA_CONFIG_DIR`、声明 `REMOTE_EXEC_HOME_DIR`,或把规则写成 `//` 绝对形。转进去的值不是绝对路径 ⇒ 422 `unsupported.path_base`。
|
|
2879
|
+
- **层不改准入**:多租部署上的准入档只按这次请求验过的凭据推(9 节速查 `below_trust_floor` 一行);条目上的层只决定规则读在哪。
|
|
2880
|
+
- **回滚 / 混版副本**:本版之前的服务对带层条目是桶门 `bad_entry`(新提交 400,续跑 409),不会静默读丢;端见位才发,所以没升级的服务上它照旧只收到纯串。
|
|
2881
|
+
- **已知限制**:`allow` 桶只收纯串(带层条目 400 `bad_entry`);user 层的 `/` 形 allow 今天仍按任务根放行。
|
|
2882
|
+
|
|
2783
2883
|
### 9.5 Web search:两车道优先级、per-request `settings.webSearch`、错误形
|
|
2784
2884
|
|
|
2785
2885
|
**两车道,整段整取(不是逐键 merge)**:部署 env(`WEB_SEARCH_*`,§0)与 per-request `body.settings.webSearch`
|
|
@@ -2905,6 +3005,11 @@ WebSearch 工具的 `tool_result` 错误文本,回到模型的对话里,**不是
|
|
|
2905
3005
|
- 每个 header 值剥 CR / LF / NUL;header 名不展开。
|
|
2906
3006
|
- 置空(名单外 / 凭据名)时日志一行 `hook_http_header_env_blanked`(名字与原因,不带值)。
|
|
2907
3007
|
例:`"headers": { "Authorization": "Bearer ${HOOK_TOKEN}" }`、`"allowedEnvVars": ["HOOK_TOKEN"]`,并在请求 `settings.env` 里给 `HOOK_TOKEN`。7.125.x 及更早的读法不同(升级见 MIGRATION)。
|
|
3008
|
+
**两张名单 `settings.allowedHttpHookUrls` / `settings.httpHookAllowedEnvVars`(7.142.0 起;CC settings 同名键)**:读法与判决都在契约包 settings-schema,本服务只在 http 条目**拨出之前**问一次(能力位 `taskSettings.httpHookAllowlists`,单用户车道为真):
|
|
3009
|
+
- `allowedHttpHookUrls`(URL 模式的串数组,例 `["https://hooks.example.com/*"]`)在场 ⇒ 条目 `url` 必须命中其中一条才发出;不命中 / 名单是 `[]` / 名单不是串数组 ⇒ **一个字节都不发**。非托管组:这次 hook 算非阻断故障(fleet 流 `hook_notice` `url_not_allowed`,运维 warn `hook_http_withheld`);
|
|
3010
|
+
托管组(`source: managedPolicy` / `managedPlugin:*`):失效关闭,`PreToolUse` 在没有否决时改问人。句子点名 `settings.hooks.<事件>` 与规则(`url` / `empty` / `malformed`)。出路:把地址的模式加进名单,或改 hook 的 `url`。
|
|
3011
|
+
- `httpHookAllowedEnvVars`(变量名的串数组)在场 ⇒ header 能展开的变量 = 条目 `allowedEnvVars` 与它的交集,交集外的引用置空(上面那行 `hook_http_header_env_blanked`,`not-allowed`)。
|
|
3012
|
+
- 两张都不写 ⇒ 不限(与 7.141.x 同)。提交时不判名单的值;续跑重放同读。多租户车道 `settings.hooks` 整只被忽略,两键无作用。
|
|
2908
3013
|
**`url` 不得带凭据(7.135.0 起)**:`http` 条目的 `url` 带 userinfo 或凭据名表里的 query / fragment 参数 ⇒ 新提交 `400 request.field_invalid`,体带 `field: "settings.hooks.<事件>[g].hooks[h].url"` 与 `reason`;凭据走同一条目的 `headers`(上面的 `$NAME` + `allowedEnvVars`)。整条规则与出路见 9.5g。
|
|
2909
3014
|
|
|
2910
3015
|
### 9.5c-bis `settings.hooks` 的执行模型与时限(7.132.0 起)
|
|
@@ -2947,6 +3052,7 @@ WebSearch 工具的 `tool_result` 错误文本,回到模型的对话里,**不是
|
|
|
2947
3052
|
- **`transport.url` 不得带凭据(7.135.0 起)**:http 传输的 `url` 带 userinfo(`https://user:pass@host/mcp`,只有用户名也算),或带名字在凭据名表里的 query / fragment 参数(`?api_key=` · `?key=` · `?token=` · `#access_token=` …;表 = 本服务日志脱敏器认作凭据名的那一张,全表见契约附录 A `request.field_invalid` 行;名字大小写不敏感,按解一次百分号编码读)⇒ 新提交 `400 request.field_invalid`,体另带 `field: "mcpServers[i].transport.url"` 与 `reason`(`url_userinfo` | `url_credential_param`),原因句点名出路:**凭据改写进 `transport.headers`**(如 `"Authorization": "Bearer …"`)。为什么:任务停驻时提交体整份进续跑上下文,`transport.headers` 的值在那里只以封签存在,`url` 照原样存(日志与读面同理)。值从不回显;解析不了的 url 不在这一问里判(拨号时失败)。7.134.x 及以前照收、原样落停驻上下文;带 userinfo 的 url 本就连不上(fetch 对带凭据的 URL 构造即抛),带名表参数的升级后要改。同一条规则在 A2A 对端 / http 钩子 / 搜索后端 / 图片 URL 上的几座见 9.5g。
|
|
2948
3053
|
- **耐久 resume 重放存量请求**:不拒(拒会把升级前 park 的任务永久卡死;`transport.url` 带凭据的存量条目照挂、url 逐字交引擎)。写坏的 `name` · `transport` 的 `kind`/`command`/`url` · `allowTools` · `toolAxes` · `toolFaces` · `sessionMetaKey` ⇒ 这一条 server 整条不进,运维 warn `mcp_injection_dropped`(`reason: malformed_entry`,`field` 点名)并投用户面通告 `mcp.injection_dropped`(其中 `toolAxes` 在一次性迁移 M19 的窗开着时先按升级前读法重读一次,过了就挂,见上文 `toolAxes` 一节);写坏的 `contentOrigin` · `elicitation` · `source` · `transport` 的 `args`/`principalHeader` 与词表外的键 ⇒ 丢掉那一个键、server 照挂;`transport` 的 `env`/`headers`(名 → 串记录)对 JSON 存体按 7.131.x 的读法交:有值不是串的成员 ⇒ 整键不交,只有 `__proto__` 名的成员坏 ⇒ 剔掉它、其余照交;server 照挂,一行运维 warn `mcp_transport_members_dropped` 点名(见 9.5c-bis 同段);条目不是对象 ⇒ 这一条不进(`malformed_entry`);超过 32 条 ⇒ 第 33 条起只记 `over_cap`;整只不是数组 ⇒ 整只忽略 + 运维 warn `mcp_injection_ignored`。
|
|
2949
3054
|
- `POST /v1/capabilities/mcp/probe` 问的是新提交那**同一只判官**:上面每一形同码同句(含 `unknownKeys`,与 url 带凭据那一形的 `field` / `reason`),拒之前零拨号;判官受理的申报,探测口拨的就是一条任务提交会交给引擎的那一份(判官的合法归一照收)。它多出的两形:本口的体就是这份列表,`mcpServers` 缺席或为 `null` ⇒ `400 request.body_shape`(缺必需字段);声明了 `transport.assertionHeader` 的条目 ⇒ `400 request.field_invalid`(见 9.5d:本版承载、不发送,新提交照挂,探测不拨一份少了断言头的配置 —— 同一只谓词,后果按门分)。7.131.x 上本口另有一只判法(申报原文与读器产物逐字比),列表不是数组 / 条目不是对象答 `request.body_shape`。
|
|
3055
|
+
- **`transport.kind` 的词表可读(7.141.0 起)**:`GET /v1/capabilities` 的 `mcpTransportKinds`(`["stdio","http"]`,书写序,每种部署形都在场、不随部署形变)= 请求面读器与引擎今天能拨的传输种类。客户端在投影 `mcpServers` 条目之前据此判目标传输读不读得了(只拒那一台、其余照投),不必靠整次提交挨 400 去试。**位不是放行单**:位外的词(引擎的 `host`、别家的 `sse` / `sdk` / `websocket`)在新提交与探测口上照旧整次 400;本部署收不收自带的 `mcpServers` 读 `mcpInjection`,「端到端可达」没有任何位承诺。键缺席 = 老 server,读作 `["stdio","http"]`;位里出现不认识的词按「不支持该种类」处理。
|
|
2950
3056
|
- **`toolFaces` 的判官是引擎的 `readToolFaces`(7.134.0 起;此前本服务自带一只只判 JSON 形的读器)**:它在门口就判声明本身能说的一切 —— 成员与类型、五张闭词表、上界、跨成员律 ——
|
|
2951
3057
|
所以下面几形 7.133.x 受理、7.134.0 起 400(重放腿整条 server 不进、中心 / `config.d` 腿跳过该 server 并点名 warn):空工具名;保留审批卡(`renderHints.approvalCard: "question"` / `"plan"`);
|
|
2952
3058
|
🔴 **`pathTarget.access` 是闭集 `read` / `create` / `edit`** —— 写成 `"write"`(或任何别的词)整条拒;**`pathTarget.base: "root"` 要求 `access: "read"`**(写面落根基底整条拒);
|
|
@@ -3064,6 +3170,10 @@ WebSearch 工具的 `tool_result` 错误文本,回到模型的对话里,**不是
|
|
|
3064
3170
|
|
|
3065
3171
|
**日志不是原形面**:运维结构化日志里 `engine_notice` 行的 `message` 与会话流上同一条通知的 `message` 过同一只脱敏(认出凭据形才换成 `«redacted…»`,没有凭据形的句子逐字节原样;会话流行另有 1000 字上限,日志行不截),`detail` 里的规则文本(`permission.allowed_tool_not_granted` 的 `entries[].entry`、`permission.rule_row_dropped` 的 `rows[].rule`)是条目的脱敏原值、`detail` 其余字段逐字 —— 同一条规则文本在 `message` 与 `detail` 里的脱敏是同一只脱敏器;已知边界:引擎把条目里的零宽字符写成 `\u200b` 转义,夹零宽字符的凭据在 `message` 里(日志行与会话流行同)认不出,机读位的规则文本是在原串上认的、不受此限。
|
|
3066
3172
|
|
|
3173
|
+
**自由文本的已知漏形**(两形;结果、账本回放、流式与同步体、运维日志行同读):① 复合凭据名(`api_key` / `apikey` / `api-key` / `access_token` / `refresh_token` / `id_token` / `private_key` / `x-amz-signature` / `x-amz-security-token` / `x-amz-credential`)在自由文本 `名=值` 形上没有名字锚,值只有自身形状被别的臂认出(`ghp_…` / `sk-…` / `AKIA…` 这类)时才遮 ——
|
|
3174
|
+
同一批名字在 JSON 字段与 URL 参数位上照遮,`password` / `passwd` / `pwd` / `secret` / `client_secret` 在赋值符两侧零空白的 `名=值` 形上、值是以字母数字起头的字面量时照遮(`$VAR` / `%s` / `<占位>` / 表达式 / `None` 一类不算值);② 强锚名紧贴在前一枚凭据的尾巴上(`-----END PRIVATE KEY-----password=…`;PGP 收尾栅栏、PuTTY 的 `Private-MAC:` 行、AWS 键 id 同形;中间无分隔)时首遍不遮
|
|
3175
|
+
(流式 done 帧、同步体、日志行明文;run 行与账本回放读面再过一遍,被遮)。两形都与旁边的私钥块无关,块本身照遮;要靠脱敏挡住的凭据别以这两形写出(MIGRATION「自由文本脱敏的两处已知漏形」)。
|
|
3176
|
+
|
|
3067
3177
|
### 9.7 bake-runner(构建宿主守护进程)的 env(7.103.0 起成文)
|
|
3068
3178
|
|
|
3069
3179
|
`bake-runner`(`npm run start:bake-runner` = `node dist/bake-runner/main.js`)是跑在构建宿主上的**独立进程**:它向 image-api
|
|
@@ -3098,7 +3208,7 @@ docker 推送的鉴权走构建宿主上的 docker 凭据存储(`docker login`),
|
|
|
3098
3208
|
`git fetch` 的 askpass 读 `GIT_TOKEN`)⇒ 点名它,runner 把该键从本进程 env **原样**放回给每一只子进程组(部署方显式承担)。
|
|
3099
3209
|
与服务侧 `LSP_ENV_ALLOW` 同一只解析器、同一只放行谓词:
|
|
3100
3210
|
- 形错(空段 / 尾逗号 / 非变量名形,如 `$NPM_TOKEN`、`a b`、`NAME=value` 整段贴入 / 点名任一只名单型旋钮 / 点名本服务自有凭据名,7.132.0 起)⇒ runner **拒启**,
|
|
3101
|
-
`bake_runner_fatal`
|
|
3211
|
+
`bake_runner_fatal` 那一行点名旋钮与第几段(`entry #k of n`,一句话只有这一套序号),**不回显值**(自有凭据那一形与服务侧同一句:说明这是本部署自己的凭据、给出路,并说明引擎拒它进任何名单);
|
|
3102
3212
|
- 本进程环境里没有的名 ⇒ 起服一行 `config_env_entry_rejected`(只报序号)、不放行;
|
|
3103
3213
|
- 旋钮原文本身按凭据类对待,不进子进程;
|
|
3104
3214
|
- 生效名单(点到且环境里真有的名)见起服行 `bake_runner_start.envAllow`(只键名);
|
|
@@ -3320,12 +3430,19 @@ web-admin 拉取 / fleet 公告 / 凭证续签、WebSearch、对象存储、OTLP
|
|
|
3320
3430
|
- **按车分库是硬规则**(7.105.0 起):点了名的每一条都必须显式给出非空的 `GATE_<名>` —— **在场但为空**
|
|
3321
3431
|
(`GATE_INNODB_TEST_URL=""` 想关掉那条腿)⇒ `REMOTE_GATE_DSN_EMPTY` 红停;**缺席** ⇒ `REMOTE_GATE_DSN_ABSENT` 红停。脚本不再有共享库缺省
|
|
3322
3432
|
(旧形把空串 / 缺席回落到共享的 `sema_server_test` 等库,车QC 的锁形套在共享库上整表 DELETE 了别车的行)。要关一条腿:别在 `--dsn` 里点它;
|
|
3323
|
-
要用:给按车库(`eval "$(node scripts/db-lane.mjs <车>)"` 建 `aiagent_test_<车>` / `sema_server_test_
|
|
3324
|
-
`GATE_*_TEST_URL`
|
|
3433
|
+
要用:给按车库(`eval "$(node scripts/db-lane.mjs <车>)"` 建 `aiagent_test_<车>` / `sema_server_test_<车>`;起它时 shell 里已有的
|
|
3434
|
+
`GATE_*_TEST_URL` 跟着换成同一只车道库,没有就自己显式 export 三条指 k3s8 上那几只库);发车链由 `scripts/chain-launch.sh` 显式传三台引擎的坐标,
|
|
3435
|
+
门 2 的真库组进组时各自换成自己的车道库(下一条)。
|
|
3325
3436
|
值**不进任何 argv**:经 ssh 的 stdin 送到远端 shell,再以 `docker run -e <名>`(只有名字)交给容器 —— 本机与 k3s8 的 `ps` 都看不见口令,
|
|
3326
3437
|
值里带 `&` / 空格也不会切断远端命令;值里有换行 ⇒ 红停。远端先 unset 点了名的每一条、只收点了名的名,核每一条都收到且解得开才起容器
|
|
3327
3438
|
(没收到 ⇒ `REMOTE_GATE_DSN_LOST`,解不开 ⇒ `REMOTE_GATE_DSN_BAD`),核完打一行机读 `REMOTE_GATE_DSN handed=<名,…|-> skipped=<n>`
|
|
3328
3439
|
(skipped = 闭集里这一跑没交给容器的引擎数);发车链把它抄上 `GATE2 …` 读数行的 `skipped=`(本机臂按换门交出的名数;远端红 ⇒ `unknown`)。
|
|
3440
|
+
- **门 2 的真库组各跑在自己的车道库上**(7.142.0 起):一次套件跑不与任何别的进程共用一只库。门 2 的组只要「门 × 凭据」表把引擎 DSN(本机腿或远端孪生 `GATE_*`)交给它,
|
|
3441
|
+
`gate2_group` 进组时就经 `scripts/db-lane.mjs <车道>` 建库并暖库(生产 boot 同款全部 ensure 腿;实测约 14 s),车道 DSN 只在组的命令的子 shell 里导出,出组即删(组红也删)。
|
|
3442
|
+
车道名 = 本次 `release.sh` 的前缀 `r<pid>_<epoch>` + 组名(`.` 换 `_`),链日志每组一行「车道库 <车道> 已建」。建不成 ⇒ 那一组红停(不回落共享库);删不掉 ⇒ 响亮一句,
|
|
3443
|
+
手收:`node scripts/db-lane.mjs <车道> --drop`。起链者传的六条 DSN 只是引擎坐标:链里没有一组读写共享测试库的表,手跑的钉 / 别的车 / 别的仓在共享库上留下的瞬时行进不了门 2,
|
|
3444
|
+
链里的破坏性钉也不落在别人用的库上。`db-lane.mjs` 三条腿同一坐标读法(手里那条 DSN;InnoDB 缺席才起夹具),坐标在手的腿建不成 ⇒ 整只车道失败,`--drop` 则三条腿逐只都试、没删掉的逐只点名并 rc 1;暖库的 DSN 只从环境读
|
|
3445
|
+
(`TIDB_TEST_URL=… PG_TEST_URL=… npx tsx scripts/db-lane-warm.ts`)。
|
|
3329
3446
|
- **起链 = `scripts/chain-launch.sh <version>`**(7.105.0 起;取代 sema-internal 的 chain-helper):
|
|
3330
3447
|
```bash
|
|
3331
3448
|
nohup bash scripts/chain-launch.sh 7.105.0 > scratchpad/chain-7.105.0.log 2>&1 & disown # 在 node_modules 是真目录的树(主树)里
|