@sema-agent/server 7.141.0 → 7.143.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 +657 -0
- package/USAGE.md +102 -30
- package/dist/adoption/plan.js +22 -0
- package/dist/approval-ask-audit-store.d.ts +61 -43
- package/dist/approval-ask-audit-store.js +69 -44
- package/dist/approval-ask-machine.d.ts +15 -7
- package/dist/approval-ask-machine.js +10 -4
- package/dist/approval-card.d.ts +126 -27
- package/dist/approval-card.js +103 -23
- 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-queue-kind.d.ts +27 -0
- package/dist/approval-queue-kind.js +6 -0
- package/dist/approval-reconciler.d.ts +41 -9
- package/dist/approval-reconciler.js +45 -42
- package/dist/audit.js +4 -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 +17 -1
- package/dist/boot/budget-tracing.js +10 -6
- package/dist/boot/device-lane.d.ts +1 -1
- package/dist/boot/execution-env.d.ts +24 -4
- package/dist/boot/execution-env.js +26 -23
- package/dist/boot/execution-lane.js +2 -1
- package/dist/boot/exit-boundary.js +5 -4
- package/dist/boot/governance-seams.d.ts +26 -41
- package/dist/boot/governance-seams.js +61 -28
- package/dist/boot/late-binds.d.ts +7 -4
- package/dist/boot/late-binds.js +3 -1
- package/dist/boot/leader.js +2 -4
- package/dist/boot/memory-consolidation.d.ts +0 -8
- package/dist/boot/memory-consolidation.js +5 -4
- 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.js +9 -7
- package/dist/boot/resolve-spec.d.ts +1 -1
- package/dist/boot/resolve-spec.js +19 -10
- package/dist/boot/retention-lane.js +5 -3
- package/dist/boot/runner-deps.d.ts +10 -7
- package/dist/boot/runner-deps.js +20 -29
- package/dist/boot/runtime-caps.js +3 -2
- package/dist/boot/session-faces.js +4 -3
- package/dist/boot/shutdown.d.ts +9 -0
- package/dist/boot/shutdown.js +19 -4
- package/dist/boot/stage-02-web-admin-pull.js +3 -0
- package/dist/boot/stage-03-store-backend.d.ts +4 -1
- package/dist/boot/stage-03-store-backend.js +1 -2
- package/dist/boot/stage-04-stores.d.ts +5 -2
- package/dist/boot/stage-04-stores.js +6 -7
- package/dist/boot/stage-05-execution-env.d.ts +6 -3
- package/dist/boot/stage-05-execution-env.js +8 -6
- package/dist/boot/stage-06-runners.d.ts +6 -3
- package/dist/boot/stage-06-runners.js +3 -4
- package/dist/boot/stage-07-capability-layer.d.ts +6 -3
- package/dist/boot/stage-07-capability-layer.js +7 -2
- package/dist/boot/stage-08-reapers.d.ts +6 -3
- package/dist/boot/stage-08-reapers.js +3 -2
- package/dist/boot/stage-09-leader.d.ts +6 -3
- package/dist/boot/stage-10-http-server.d.ts +6 -3
- package/dist/boot/stage-10-http-server.js +14 -5
- package/dist/boot/stores.d.ts +5 -2
- package/dist/boot/stores.js +10 -9
- package/dist/boot/web-admin.d.ts +5 -1
- package/dist/boot/web-admin.js +48 -36
- 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/hands-lane.d.ts +9 -39
- package/dist/capabilities/hands-lane.js +8 -13
- package/dist/capabilities/mcp-probe.d.ts +3 -2
- package/dist/capabilities/scenarios.d.ts +11 -1
- package/dist/capabilities/scenarios.js +1 -0
- package/dist/capabilities/skills.d.ts +1 -17
- package/dist/capabilities/skills.js +0 -8
- package/dist/capability-facts.d.ts +31 -7
- package/dist/capability-facts.js +27 -4
- package/dist/card-void.d.ts +6 -9
- package/dist/config-catalog.js +2 -1
- package/dist/config-dir-trust.js +58 -29
- package/dist/config-invariants.d.ts +7 -1
- package/dist/config-invariants.js +7 -0
- package/dist/config-provider.d.ts +10 -0
- package/dist/config-provider.js +15 -4
- package/dist/config-root-migration.d.ts +13 -0
- package/dist/config-root-migration.js +99 -0
- package/dist/config-types.d.ts +19 -8
- package/dist/config.d.ts +10 -3
- package/dist/config.js +18 -4
- package/dist/delegated-session-owner.d.ts +5 -3
- package/dist/delegated-session-owner.js +1 -1
- package/dist/device-ws-protocol.d.ts +1 -0
- package/dist/device-ws-protocol.js +2 -1
- package/dist/env-model-table-gate.d.ts +53 -0
- package/dist/env-model-table-gate.js +53 -0
- package/dist/execution-lane-caps.d.ts +2 -1
- package/dist/fleet/fleet-bus.d.ts +34 -55
- package/dist/fleet/fleet-bus.js +35 -100
- package/dist/fleet/fleet-reconciler.d.ts +4 -4
- package/dist/fleet/fleet-reconciler.js +1 -1
- package/dist/fleet/subagent-tail-bus.d.ts +14 -11
- package/dist/fleet/subagent-tail-bus.js +15 -28
- package/dist/hooks/hook-runner.d.ts +6 -0
- package/dist/hooks/hook-runner.js +58 -8
- package/dist/host-decision.d.ts +54 -20
- package/dist/host-decision.js +42 -14
- package/dist/http/admission.d.ts +1 -1
- package/dist/http/admission.js +7 -3
- package/dist/http/approval-sweeps.js +11 -8
- package/dist/http/caller-trust.d.ts +1 -1
- package/dist/http/dispatch.js +4 -2
- package/dist/http/durable-run-leg.js +2 -2
- package/dist/http/engine-refusal.d.ts +16 -0
- package/dist/http/engine-refusal.js +17 -0
- package/dist/http/execution-context.d.ts +2 -2
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -3
- package/dist/http/memory-compliance-failure-reply.js +4 -6
- package/dist/http/owner-access.d.ts +11 -0
- package/dist/http/owner-access.js +13 -0
- package/dist/http/principal-gate.d.ts +3 -1
- package/dist/http/principal-gate.js +17 -8
- package/dist/http/resume-legs.d.ts +21 -7
- package/dist/http/resume-legs.js +76 -58
- package/dist/http/resume-restatement.d.ts +39 -0
- package/dist/http/resume-restatement.js +25 -0
- package/dist/http/route-ctx.d.ts +35 -10
- package/dist/http/route-ctx.js +1 -1
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/approvals-assistant.d.ts +9 -1
- package/dist/http/routes/approvals-assistant.js +142 -31
- package/dist/http/routes/attachments.js +18 -0
- package/dist/http/routes/capabilities.js +16 -4
- package/dist/http/routes/memory-policy.d.ts +2 -2
- package/dist/http/routes/memory-policy.js +27 -7
- package/dist/http/routes/notify-wake.js +23 -25
- package/dist/http/routes/rules.js +48 -13
- package/dist/http/routes/runs.js +12 -11
- package/dist/http/routes/session-memory-sync.d.ts +91 -0
- package/dist/http/routes/session-memory-sync.js +174 -0
- package/dist/http/routes/session-sync.js +13 -20
- package/dist/http/routes/sessions-list.d.ts +2 -1
- package/dist/http/routes/sessions.d.ts +2 -2
- package/dist/http/routes/sessions.js +22 -23
- package/dist/http/routes/tasks.js +34 -54
- package/dist/http/run-read-face.d.ts +7 -0
- package/dist/http/run-read-face.js +9 -3
- package/dist/http/send.d.ts +5 -0
- package/dist/http/send.js +9 -2
- package/dist/http/server.d.ts +27 -15
- package/dist/http/server.js +4 -6
- package/dist/http/stored-body-replay.js +15 -4
- 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/http/wire-types.d.ts +17 -7
- package/dist/identity-source.d.ts +21 -2
- package/dist/identity-source.js +6 -0
- package/dist/leader/leader.js +5 -2
- package/dist/leader/wire.d.ts +7 -1
- package/dist/leader/wire.js +6 -5
- package/dist/leg-facts.d.ts +37 -0
- package/dist/leg-facts.js +15 -0
- package/dist/memory-bundle-engine.d.ts +1 -4
- package/dist/memory-bundle-engine.js +2 -2
- package/dist/memory-incident-sink.d.ts +19 -6
- package/dist/memory-incident-sink.js +8 -4
- package/dist/memory-operator-faces.d.ts +30 -66
- package/dist/memory-operator-faces.js +17 -88
- package/dist/memory-scope-stores.d.ts +38 -40
- package/dist/memory-scope-stores.js +51 -36
- package/dist/memory-scope.d.ts +0 -9
- package/dist/memory-scope.js +0 -9
- package/dist/memory-sync-client.d.ts +21 -21
- package/dist/memory-sync-client.js +62 -43
- package/dist/memory-sync-identity.d.ts +24 -0
- package/dist/memory-sync-identity.js +57 -0
- package/dist/memory-sync.d.ts +27 -5
- package/dist/memory-sync.js +29 -7
- package/dist/model-plane-face.d.ts +13 -7
- package/dist/model-plane-face.js +2 -1
- package/dist/observability/fail-open.d.ts +47 -14
- package/dist/observability/fail-open.js +37 -11
- package/dist/observability/run-terminal.d.ts +92 -34
- package/dist/observability/run-terminal.js +171 -162
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -19
- package/dist/orchestration/workflow-completion-inbox.js +0 -12
- package/dist/orchestration/workflow-notify-journal.d.ts +3 -2
- package/dist/orchestration/workflow-park-decision.d.ts +8 -3
- package/dist/orchestration/workflow-park-decision.js +5 -3
- package/dist/org-delivery-gate.d.ts +11 -0
- package/dist/org-delivery-gate.js +19 -1
- package/dist/parked-decide.d.ts +13 -9
- package/dist/parked-decide.js +7 -7
- package/dist/parked-revive-surface.js +1 -1
- package/dist/peer-inbound-face.d.ts +127 -0
- package/dist/peer-inbound-face.js +158 -0
- package/dist/permission-rule-list.d.ts +13 -9
- package/dist/permission-rule-list.js +7 -3
- package/dist/plugins/approval-ask-store-file.d.ts +14 -4
- package/dist/plugins/approval-ask-store-file.js +64 -11
- package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
- package/dist/plugins/approval-ask-store-memory.js +17 -14
- package/dist/plugins/approval-ask-store-sql.d.ts +70 -23
- package/dist/plugins/approval-ask-store-sql.js +79 -30
- package/dist/plugins/checkpoint-store-sql.d.ts +4 -4
- package/dist/plugins/checkpoint-store-sql.js +9 -7
- package/dist/plugins/file-history-store-sql.d.ts +24 -18
- package/dist/plugins/file-history-store-sql.js +24 -19
- package/dist/plugins/file-run-store.d.ts +35 -1
- package/dist/plugins/file-run-store.js +108 -9
- package/dist/plugins/imported-layer-root-retirement.d.ts +82 -0
- package/dist/plugins/imported-layer-root-retirement.js +96 -0
- package/dist/plugins/local-checkpoint-store.d.ts +1 -1
- package/dist/plugins/local-checkpoint-store.js +2 -2
- package/dist/plugins/local-session-store.d.ts +42 -9
- package/dist/plugins/local-session-store.js +83 -33
- package/dist/plugins/local-task-attachment-store.d.ts +12 -2
- package/dist/plugins/local-task-attachment-store.js +67 -43
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +9 -31
- package/dist/plugins/mailbox-recipient-lifecycle.js +4 -0
- package/dist/plugins/mailbox-store-sql.d.ts +12 -8
- package/dist/plugins/mailbox-store-sql.js +76 -7
- package/dist/plugins/memory-key-guards.d.ts +3 -3
- package/dist/plugins/memory-run-store.d.ts +6 -1
- package/dist/plugins/memory-run-store.js +11 -1
- package/dist/plugins/memory-sync-store-pg.d.ts +15 -0
- package/dist/plugins/memory-sync-store-pg.js +21 -0
- package/dist/plugins/memory-sync-store-tidb.d.ts +2 -0
- package/dist/plugins/memory-sync-store-tidb.js +13 -1
- package/dist/plugins/one-time-migrations.d.ts +58 -2
- package/dist/plugins/one-time-migrations.js +161 -4
- package/dist/plugins/org-delivery-quota-store.d.ts +1 -1
- package/dist/plugins/org-delivery-quota-store.js +2 -12
- package/dist/plugins/park-commit-watch.d.ts +1 -1
- package/dist/plugins/permission-rule-store-file.d.ts +10 -1
- package/dist/plugins/permission-rule-store-file.js +15 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +31 -1
- package/dist/plugins/permission-rule-store-sql.js +35 -2
- package/dist/plugins/remote-env-device.d.ts +8 -11
- package/dist/plugins/remote-env-device.js +6 -3
- package/dist/plugins/remote-env-e2b.d.ts +23 -4
- package/dist/plugins/remote-env-e2b.js +111 -28
- package/dist/plugins/remote-env-k8s.d.ts +61 -22
- package/dist/plugins/remote-env-k8s.js +133 -33
- package/dist/plugins/remote-env-local-docker.d.ts +15 -3
- package/dist/plugins/remote-env-local-docker.js +40 -12
- package/dist/plugins/retention-store-sql.d.ts +2 -2
- package/dist/plugins/run-store-sql.d.ts +9 -1
- package/dist/plugins/run-store-sql.js +9 -1
- package/dist/plugins/sandbox-read-floor.d.ts +5 -7
- package/dist/plugins/sandbox-read-floor.js +2 -7
- package/dist/plugins/sql-errors.d.ts +10 -1
- package/dist/plugins/sql-errors.js +13 -0
- package/dist/plugins/store-backend.d.ts +33 -35
- package/dist/plugins/store-backend.js +10 -1
- package/dist/plugins/store-contracts.d.ts +50 -1
- package/dist/plugins/store-contracts.js +6 -0
- package/dist/plugins/task-attachment-store.d.ts +112 -14
- package/dist/plugins/task-attachment-store.js +207 -29
- package/dist/plugins/tool-result-store-sql.d.ts +9 -8
- package/dist/plugins/tool-result-store-sql.js +23 -2
- package/dist/plugins/wiring-section-codec.d.ts +32 -0
- package/dist/plugins/wiring-section-codec.js +55 -0
- 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/rule-entry-list.d.ts +3 -2
- package/dist/rule-entry-list.js +5 -1
- package/dist/rules-consent.d.ts +28 -5
- package/dist/rules-consent.js +40 -28
- package/dist/run-local.js +11 -13
- package/dist/runs.d.ts +12 -8
- package/dist/runs.js +6 -8
- package/dist/runtime-governance.d.ts +1 -1
- 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 +9 -0
- package/dist/security.js +8 -0
- package/dist/server-secret-env.d.ts +4 -0
- package/dist/session-error-wire.d.ts +36 -0
- package/dist/session-error-wire.js +13 -0
- package/dist/session-incarnation.d.ts +1 -1
- package/dist/session-notify-door.d.ts +106 -0
- package/dist/session-notify-door.js +93 -0
- package/dist/session-sync.d.ts +9 -14
- package/dist/session-sync.js +5 -5
- package/dist/session-workspace.d.ts +3 -13
- package/dist/session-workspace.js +0 -9
- package/dist/standing-answer-grant.d.ts +5 -0
- package/dist/standing-answer-grant.js +10 -0
- package/dist/stores-sql/session-policy-store-sql.d.ts +4 -2
- package/dist/stores-sql/session-policy-store-sql.js +3 -13
- package/dist/task-mcp.d.ts +1 -1
- package/dist/task-settings.d.ts +21 -10
- package/dist/task-settings.js +46 -13
- package/dist/terminal.d.ts +39 -19
- package/dist/terminal.js +65 -22
- package/dist/tool-approval.d.ts +56 -37
- package/dist/tool-approval.js +78 -71
- package/dist/trace/core-keyset-guard.d.ts +134 -14
- package/dist/trace/engine-notice-wire.d.ts +9 -3
- package/dist/trace/engine-notice-wire.js +7 -3
- package/dist/trace/exit-seat.d.ts +9 -2
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/ledger-sink.d.ts +10 -6
- package/dist/trace/ledger-sink.js +2 -2
- package/dist/trace/model-segment.d.ts +55 -25
- package/dist/trace/model-segment.js +101 -33
- package/dist/trace/project.d.ts +25 -5
- package/dist/trace/project.js +22 -0
- package/dist/trace/redact.d.ts +61 -9
- package/dist/trace/redact.js +1490 -468
- package/dist/trace/self-minted-wire.d.ts +745 -24
- package/dist/trace/self-minted-wire.js +239 -9
- package/dist/trace/wire-projection-faces.d.ts +2 -2
- package/dist/trace/wire-projection-faces.js +2 -2
- package/dist/verifier-pause-card.d.ts +33 -5
- package/dist/verifier-pause-card.js +15 -10
- package/dist/web-admin-client/apply-effective.d.ts +12 -16
- package/dist/web-admin-client/apply-effective.js +109 -9
- package/dist/web-admin-client/effective-keys.js +2 -0
- package/dist/web-admin-client/types.d.ts +4 -0
- package/dist/workspace-space.d.ts +19 -3
- package/dist/workspace-space.js +8 -4
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -1
- package/package.json +3 -2
- package/wire-changes/server@7.142.0.json +639 -0
- package/wire-changes/server@7.143.0.json +1167 -0
package/dist/task-settings.d.ts
CHANGED
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
* - `deny` / `ask` are folded via `tightenTaskSpec` (deny-wins `combinePolicies`); it THROWS on any override that would
|
|
16
16
|
* LOOSEN a stricter base safety field. Through those two buckets the client can only ADD denies / asks on top of the
|
|
17
17
|
* deployment + operator baseline.
|
|
18
|
-
* - `allow` (server 7.117.0, core 7.42.0) is NOT a policy: the list rides WHOLE
|
|
18
|
+
* - `allow` (server 7.117.0, core 7.42.0) is NOT a policy: the list rides WHOLE, one member per entry in the entry's position, into `TaskSpec.allowedTools`
|
|
19
|
+
* (a string verbatim; a settings layer's `{ rule, layer }` entry as its rule text, or — when its `/` reads at the configuration root — as
|
|
20
|
+
* `{ rule, pathBases: { root } }`, the same anchor its deny / ask twin's set declares: {@link allowMemberOf}),
|
|
19
21
|
* the request member of the engine's ONE allow layer (beside a deployment's `RunnerDeps.allowedTools`, a person's stored
|
|
20
22
|
* rows, an active skill's `allowed-tools` and a PreToolUse hook's `allow`), read under one predicate. It IS an accepted
|
|
21
23
|
* loosening for this run: an entry clears the `unstated` / `ordinary` questions the engine raises for the calls it covers
|
|
@@ -52,6 +54,7 @@ import { type EntryProblem } from "./entry-problems.js";
|
|
|
52
54
|
import { type RuleListEntry } from "./permission-rule-list.js";
|
|
53
55
|
import { type KeyClosureIssue } from "./request-key-closure.js";
|
|
54
56
|
import { type RunnableHooksConfig } from "./hooks/hook-runner.js";
|
|
57
|
+
import { type HttpHookAllowlistLayer } from "@sema-agent/settings-schema";
|
|
55
58
|
import type { StoredHooksRereadM20 } from "./stored-request-hooks-m20.js";
|
|
56
59
|
import type { EntryPermissionMode } from "./runtime-governance.js";
|
|
57
60
|
import { type TightenOnlySeatValues } from "./tighten-only-seats.js";
|
|
@@ -197,7 +200,8 @@ export declare function skillListingMaxDescOk(v: unknown): v is number;
|
|
|
197
200
|
* deferred (submit 路径另有 400 fail-loud),valid `hooks` 进 applied shape(hook-runner 阶段一)。 */
|
|
198
201
|
export interface ParsedTaskSettings {
|
|
199
202
|
permissions?: {
|
|
200
|
-
|
|
203
|
+
/** 与 `deny` 同一条目形(带层条目的层只选 `/` 的锚);投 `TaskSpec.allowedTools` 的唯一写点 {@link applyTaskSettings}。 */
|
|
204
|
+
allow?: RuleListEntry[];
|
|
201
205
|
/** 纯串 = 请求自己写的规则;`{ rule, layer }` = 端从某个设置层读来的规则(`permission-rule-list.ts` 的 {@link RuleListEntry};层只选 `/` 的锚)。 */
|
|
202
206
|
deny?: RuleListEntry[];
|
|
203
207
|
/** 同 `deny` 的条目形;编译与 `deny` 同一口({@link deriveSettingsPolicy})。 */
|
|
@@ -242,6 +246,9 @@ export interface ParsedTaskSettings {
|
|
|
242
246
|
* wire 位置由座位表说(三座在 `settings` 顶层,`neverAuto` 在 `settings.permissions`),解析后与位置无关。空数组 ≡ 缺席(不铸键)。
|
|
243
247
|
* 去处:三座经 {@link applyTaskSettings} 落 core 任务层席;`neverAuto` 经 {@link deriveSettingsPolicy} 落请求叶策略。 */
|
|
244
248
|
tightenOnly?: TightenOnlySeatValues;
|
|
249
|
+
/** http hook 两张名单(`settings.allowedHttpHookUrls` / `settings.httpHookAllowedEnvVars`)作为**一个设置层**:源名 {@link REQUEST_SETTINGS_SOURCE} + 两键里在场的那几把,值原样(本服务不读内容)。
|
|
250
|
+
* 两键都缺席 ⇒ 不铸键。唯一读者 = `hooks/hook-runner.ts` 的 http 腿(经 hooks 注册上下文的 `httpHookAllowlistLayers`)。 */
|
|
251
|
+
httpHookAllowlist?: HttpHookAllowlistLayer;
|
|
245
252
|
}
|
|
246
253
|
/** The result of parsing an untrusted `body.settings`: the applied subset + the names of present-but-deferred
|
|
247
254
|
* fields (so the caller can log/advertise them — no silent drop). `null` settings ⇒ `{ settings: undefined }`. */
|
|
@@ -293,8 +300,8 @@ export interface SettingsPermissionBucketIssue {
|
|
|
293
300
|
/**
|
|
294
301
|
* 三桶的**唯一**判据(纯函数)。`perms` 不是对象 ⇒ 不判(那一形归「settings.permissions must be an object」那道门);桶缺席 / `null`
|
|
295
302
|
* ⇒ 不判(与 `permissions: null` 的「容器缺席」同一约定)。逐桶按 {@link SETTINGS_PERMISSION_BUCKETS} 的序、按该桶的条目规则:不是数组 ⇒ `bad_entry`
|
|
296
|
-
* (无 `index`);`rule_policy` 桶超帽 ⇒ `over_cap`(先判,拒体有界)、首个不合条目律的项(不是非空串、也不是合形的带层条目)⇒ `bad_entry` + 它的下标;`allow_layer`
|
|
297
|
-
* `bad_entry` +
|
|
303
|
+
* (无 `index`);`rule_policy` 桶超帽 ⇒ `over_cap`(先判,拒体有界)、首个不合条目律的项(不是非空串、也不是合形的带层条目)⇒ `bad_entry` + 它的下标;`allow_layer` 桶首个既不是串、
|
|
304
|
+
* 也不是合形带层条目的项 ⇒ `bad_entry` + 它的下标,超帽同样 `over_cap`(帽的理由不同,见段头)。全合法 ⇒ `null`。
|
|
298
305
|
*/
|
|
299
306
|
export declare function settingsPermissionBucketIssue(perms: unknown): SettingsPermissionBucketIssue | null;
|
|
300
307
|
/** 本 service 真正**消费**的 `settings` 顶层键 —— 闭集。每一个都有消费点:
|
|
@@ -313,8 +320,12 @@ export declare function settingsPermissionBucketIssue(perms: unknown): SettingsP
|
|
|
313
320
|
* 🔴 两个 `skillListing*`([ref],7.77.0)= **CC settings 同名键**,值域抄 CC 的 schema 声明
|
|
314
321
|
* (`skillListingBudgetFraction` 是 `gt(0).lte(1)`、`skillListingMaxDescChars` 是 `int().positive()`);
|
|
315
322
|
* 消费点 = 本文件的 parse + `boot/resolve-spec.ts` 的 `TaskSpec` 透传。语义(预算怎么花、描述怎么裁、
|
|
316
|
-
* 溢出怎么退成 name-only)整个归引擎,本仓一个字节都不渲染,也**不复刻默认值**——缺席即整键不写。
|
|
317
|
-
|
|
323
|
+
* 溢出怎么退成 name-only)整个归引擎,本仓一个字节都不渲染,也**不复刻默认值**——缺席即整键不写。
|
|
324
|
+
*
|
|
325
|
+
* 🔴 `allowedHttpHookUrls` / `httpHookAllowedEnvVars` = **CC settings 同名键**(契约包的 http hook 两张名单,键表属主 = 契约包 `HTTP_HOOK_ALLOWLIST_KEYS`):
|
|
326
|
+
* 消费点 = {@link parseTaskSettings} 把它们原样收成一层({@link requestHttpHookAllowlistLayer})→ `boot/resolve-spec.ts` 交给 hooks 注册 → `hooks/hook-runner.ts` 的 http 腿
|
|
327
|
+
* 在拨出之前问契约包判官。受理面只判键名(本门),不判值:名单的读法只有判官那一只(坏形由判官答 `malformed`、拦)。 */
|
|
328
|
+
export declare const TASK_SETTINGS_KEYS: readonly ["allowedHttpHookUrls", "approvalFrameFamilies", "complianceAdditionalDenies", "env", "hooks", "httpHookAllowedEnvVars", "model", "outputStyle", "permissions", "readDenyPatterns", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch", "writeProtectedExtra"];
|
|
318
329
|
/** 本 service 消费的 `settings.permissions` 子键 —— 闭集(值形校验另有既有门,本门只判键名)。 */
|
|
319
330
|
export declare const TASK_SETTINGS_PERMISSION_KEYS: readonly ["allow", "ask", "defaultMode", "deny", "disableAutoMode", "neverAuto"];
|
|
320
331
|
/** CC/SDK 合约里合法、本 service **不接线**的顶层键。词表外的 CC 键落 `unknown` —— 两列都是 400,标签只影响
|
|
@@ -451,7 +462,7 @@ export interface FsWriteGateWiring {
|
|
|
451
462
|
taskHome?: string;
|
|
452
463
|
/**
|
|
453
464
|
* **执行环境的配置根**(唯一属主 `execution-config-root.ts` 的 `executionConfigRootOf`):user 设置层里 `/` 形路径规则的根 —— 带 `layer: "userSettings"`
|
|
454
|
-
* 且要 `root` 的条目编进只声明 `{ root: configRoot }`
|
|
465
|
+
* 且要 `root` 的条目编进只声明 `{ root: configRoot }` 的那一集、allow 桶里的投成带同一声明的那一员(`permission-rule-list.ts` 的 `ruleRootOf`)。缺席(沙箱车道既没转 `SEMA_CONFIG_DIR`、home 也读不出)
|
|
455
466
|
* ⇒ 这样的条目由 {@link rejectUnmatchableSettingsNames} 响亮拒(422 `home_unresolvable`),不猜目录。拒点与存体预判读同一只函数。
|
|
456
467
|
*/
|
|
457
468
|
configRoot?: string;
|
|
@@ -478,7 +489,7 @@ export type RulePolicyBucket = (typeof RULE_POLICY_BUCKETS)[number];
|
|
|
478
489
|
/**
|
|
479
490
|
* deny / ask 两桶的**完整规则判**,唯一一只(拒点 {@link rejectUnmatchableSettingsNames} 与存体预判 `http/stored-body-replay.ts` 同调):
|
|
480
491
|
* ② 按 {@link RULE_POLICY_BUCKETS} 的序逐桶、桶内按 `RULE_ROOTS` 的序逐集(`permission-rule-list.ts` 的 `ruleSetsOf`:判的就是要编的那一集)问 `judgeUnmatchableToolNames`(名字层 + core 规则文法);
|
|
481
|
-
* ③ 再判「这条规则要的基本部署给不出」那一拒:`~/` 形缺 home;配置根那一集缺配置根(
|
|
492
|
+
* ③ 再判「这条规则要的基本部署给不出」那一拒:`~/` 形缺 home(deny / ask);配置根那一集缺配置根(三桶,{@link LAYER_ROOT_BUCKETS};两者都落在执行环境的 home 上,同词 `home_unresolvable`)。答 `{ bucket, message, problems }`:`bucket` 与 `message` 是**第一处**坏处的
|
|
482
493
|
* (句子冻结,先撞上的那一条),`problems` 是**两段、两只桶判下来的全部**坏条目(机读位的原料,形的属主 `entry-problems.ts`;`entry` = 规则原文,带层条目也一样)。
|
|
483
494
|
* 入参:桶、{@link RulePolicyBases}。**home 同源**:拒点的 home 是 `resolve-spec.ts` 的 `laneHomeBase()` 经 `executionLaneHomeDir(config)` 算出的,预判传同一个函数对同一份部署配置算出的;配置根同理(`executionConfigRootOf`)。
|
|
484
495
|
* **任务根那一集声明给文法的基**只有拒点有(根 + home 的并集,执行车道才知道根):core 的规则文法对**没声明**的基不下判词(见 `config.ts` `uncompilableRuleGuidance`),所以预判什么也不声明、两腿逐字同句;
|
|
@@ -494,8 +505,8 @@ export interface RulePolicyBases {
|
|
|
494
505
|
/** 执行环境的配置根(配置根那一集的根;拒点与预判都给);读不出 ⇒ 缺席。 */
|
|
495
506
|
readonly configRoot?: string;
|
|
496
507
|
}
|
|
497
|
-
export declare function rulePolicyBucketsRefusal(permissions: Readonly<Partial<Record<
|
|
498
|
-
readonly bucket:
|
|
508
|
+
export declare function rulePolicyBucketsRefusal(permissions: Readonly<Partial<Record<SettingsPermissionBucket, readonly RuleListEntry[]>>>, bases: RulePolicyBases): {
|
|
509
|
+
readonly bucket: SettingsPermissionBucket;
|
|
499
510
|
readonly message: string;
|
|
500
511
|
readonly problems: readonly EntryProblem[];
|
|
501
512
|
} | undefined;
|
package/dist/task-settings.js
CHANGED
|
@@ -2,13 +2,13 @@ import { combinePolicies, parseRuleText, resolveReasoningProfile, rankOf, isThin
|
|
|
2
2
|
import { judgeUnmatchableToolNames } from "./config.js";
|
|
3
3
|
import { NAME_TABLE_BEHAVIOR } from "./namespaced-rule-name.js";
|
|
4
4
|
import { entryProblem } from "./entry-problems.js";
|
|
5
|
-
import { MAX_PERMISSION_RULES_PER_LIST, RULE_ROOTS, createRuleListPolicy, ruleListEntryOk, ruleSetsOf, ruleSourceOf, ruleTextOf } from "./permission-rule-list.js";
|
|
6
|
-
import { allowLayerEntryCountIssue, describeAllowLayerOverCap
|
|
5
|
+
import { MAX_PERMISSION_RULES_PER_LIST, RULE_ROOTS, allowListEntryOk, createRuleListPolicy, ruleListEntryOk, ruleRootOf, ruleSetsOf, ruleSourceOf, ruleTextOf } from "./permission-rule-list.js";
|
|
6
|
+
import { allowLayerEntryCountIssue, describeAllowLayerOverCap } from "./rule-entry-list.js";
|
|
7
7
|
import { limitRefusal } from "./limit-refusal.js";
|
|
8
8
|
import { tightenGoverned } from "./governance-overrides.js";
|
|
9
9
|
import { MAX_KEY_ECHO, keyClosureClause, scanKeyClosure } from "./request-key-closure.js";
|
|
10
10
|
import { hooksCoordinate, parseHooksConfig } from "./hooks/hook-runner.js";
|
|
11
|
-
import { SETTINGS_SOURCES } from "@sema-agent/settings-schema";
|
|
11
|
+
import { HTTP_HOOK_ALLOWLIST_KEYS, SETTINGS_SOURCES } from "@sema-agent/settings-schema";
|
|
12
12
|
import { heldRuleName } from "./tool-rule-names.js";
|
|
13
13
|
import { policyAskStandingAnswerFacts, standingAnswerDurablyRecordable } from "./tool-approval.js";
|
|
14
14
|
import { createRequestNeverAutoPolicy } from "./approval.js";
|
|
@@ -113,8 +113,8 @@ function bucketIssueMessage(f, rule) {
|
|
|
113
113
|
: `${f.field}[${f.index}] is neither a non-empty rule string nor a { "rule", "layer" } entry (exactly those two keys; rule = a non-empty rule string; layer = one of ${SETTINGS_SOURCES.join(", ")}) — every entry must be one. Refused rather than dropped, because a dropped entry reads as "in effect" to the caller`;
|
|
114
114
|
case "allow_layer":
|
|
115
115
|
return f.index === undefined
|
|
116
|
-
? `${f.field} must be an array of
|
|
117
|
-
: `${f.field}[${f.index}] is
|
|
116
|
+
? `${f.field} must be an array of rule entries (a rule string, or { "rule": <rule>, "layer": <settings source> }) — refused rather than ignored, because an ignored list reads as "in effect" to the caller`
|
|
117
|
+
: `${f.field}[${f.index}] is neither a rule string nor a { "rule", "layer" } entry (exactly those two keys; rule = a non-empty rule string; layer = one of ${SETTINGS_SOURCES.join(", ")}) — every entry must be one. Refused rather than dropped, because a dropped entry reads as "in effect" to the caller`;
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -146,8 +146,11 @@ export function settingsPermissionBucketIssue(perms) {
|
|
|
146
146
|
const over = allowLayerEntryCountIssue(field, v);
|
|
147
147
|
if (over !== undefined)
|
|
148
148
|
fields = { field, reason: "over_cap", count: over.facts.count, cap: over.facts.cap };
|
|
149
|
-
else
|
|
150
|
-
|
|
149
|
+
else {
|
|
150
|
+
const index = v.findIndex((x) => !allowListEntryOk(x));
|
|
151
|
+
if (index >= 0)
|
|
152
|
+
fields = { field, reason: "bad_entry", index };
|
|
153
|
+
}
|
|
151
154
|
break;
|
|
152
155
|
}
|
|
153
156
|
}
|
|
@@ -160,7 +163,7 @@ export function settingsPermissionBucketIssue(perms) {
|
|
|
160
163
|
function acceptedRuleList(v) {
|
|
161
164
|
return Array.isArray(v) && v.length > 0 ? v.slice() : undefined;
|
|
162
165
|
}
|
|
163
|
-
export const TASK_SETTINGS_KEYS = ["approvalFrameFamilies", "complianceAdditionalDenies", "env", "hooks", "model", "outputStyle", "permissions", "readDenyPatterns", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch", "writeProtectedExtra"];
|
|
166
|
+
export const TASK_SETTINGS_KEYS = ["allowedHttpHookUrls", "approvalFrameFamilies", "complianceAdditionalDenies", "env", "hooks", "httpHookAllowedEnvVars", "model", "outputStyle", "permissions", "readDenyPatterns", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch", "writeProtectedExtra"];
|
|
164
167
|
export const TASK_SETTINGS_PERMISSION_KEYS = ["allow", "ask", "defaultMode", "deny", "disableAutoMode", "neverAuto"];
|
|
165
168
|
export const TASK_SETTINGS_UNSUPPORTED_KEYS = ["apiKeyHelper", "crossSessionInbound", "dialogExpiry", "sandbox", "statusLine"];
|
|
166
169
|
export const TASK_SETTINGS_UNSUPPORTED_PERMISSION_KEYS = ["additionalDirectories", "disableBypassPermissionsMode"];
|
|
@@ -228,6 +231,16 @@ export function hooksKeyIssue(raw, config) {
|
|
|
228
231
|
export function taskHooksHonored(config) {
|
|
229
232
|
return !DEPLOYMENT_SHAPE_PREDICATES.multiTenant.holds(config);
|
|
230
233
|
}
|
|
234
|
+
const REQUEST_SETTINGS_SOURCE = "flagSettings";
|
|
235
|
+
function requestHttpHookAllowlistLayer(s) {
|
|
236
|
+
const present = HTTP_HOOK_ALLOWLIST_KEYS.filter((key) => Object.hasOwn(s, key));
|
|
237
|
+
if (present.length === 0)
|
|
238
|
+
return undefined;
|
|
239
|
+
const layer = { source: REQUEST_SETTINGS_SOURCE };
|
|
240
|
+
for (const key of present)
|
|
241
|
+
layer[key] = s[key];
|
|
242
|
+
return layer;
|
|
243
|
+
}
|
|
231
244
|
function tightenOnlySeatDeferredName(name) {
|
|
232
245
|
return tightenOnlySeatField(name).replace(/^settings\./, "");
|
|
233
246
|
}
|
|
@@ -303,6 +316,9 @@ export function parseTaskSettings(raw, seats = {}) {
|
|
|
303
316
|
deferred.push(tightenOnlySeatDeferredName(name));
|
|
304
317
|
if (Object.keys(tightenSeats.values).length > 0)
|
|
305
318
|
out.tightenOnly = tightenSeats.values;
|
|
319
|
+
const httpHookAllowlist = requestHttpHookAllowlistLayer(s);
|
|
320
|
+
if (httpHookAllowlist !== undefined)
|
|
321
|
+
out.httpHookAllowlist = httpHookAllowlist;
|
|
306
322
|
return { settings: Object.keys(out).length > 0 ? out : undefined, deferred, ...(hooksReread !== undefined ? { hooksReread } : {}) };
|
|
307
323
|
}
|
|
308
324
|
export function acceptAppendSystemPrompt(v, warn) {
|
|
@@ -359,6 +375,7 @@ export class SettingsRuleRefusalError extends Error {
|
|
|
359
375
|
}
|
|
360
376
|
export const SETTINGS_RULE_REFUSAL_CODE = "request.unprocessable";
|
|
361
377
|
export const RULE_POLICY_BUCKETS = ["ask", "deny"];
|
|
378
|
+
const LAYER_ROOT_BUCKETS = [...RULE_POLICY_BUCKETS, "allow"];
|
|
362
379
|
export function rulePolicyBucketsRefusal(permissions, bases) {
|
|
363
380
|
let first;
|
|
364
381
|
const problems = [];
|
|
@@ -410,7 +427,7 @@ export function rulePolicyBucketsRefusal(permissions, bases) {
|
|
|
410
427
|
}
|
|
411
428
|
}
|
|
412
429
|
if (bases.configRoot === undefined) {
|
|
413
|
-
for (const bucket of
|
|
430
|
+
for (const bucket of LAYER_ROOT_BUCKETS) {
|
|
414
431
|
const field = `permissions.${bucket}`;
|
|
415
432
|
for (const name of ruleSetsOf(permissions[bucket] ?? [], bucket).configuration.map(ruleTextOf)) {
|
|
416
433
|
first ??= {
|
|
@@ -430,9 +447,25 @@ function ruleSetBases(root, taskBases, configRoot) {
|
|
|
430
447
|
case "task":
|
|
431
448
|
return taskBases;
|
|
432
449
|
case "configuration":
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
450
|
+
return configurationSetBases(configRoot);
|
|
451
|
+
default: {
|
|
452
|
+
const unhandled = root;
|
|
453
|
+
return unhandled;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
function configurationSetBases(configRoot) {
|
|
458
|
+
if (configRoot === undefined)
|
|
459
|
+
throw new Error("a user-settings path rule reached the compiler without a configuration root — the admission judgement refuses it first (home_unresolvable); refusing rather than anchoring it at the task root");
|
|
460
|
+
return { root: configRoot };
|
|
461
|
+
}
|
|
462
|
+
function allowMemberOf(entry, configRoot) {
|
|
463
|
+
const root = ruleRootOf(entry, "allow");
|
|
464
|
+
switch (root) {
|
|
465
|
+
case "task":
|
|
466
|
+
return ruleTextOf(entry);
|
|
467
|
+
case "configuration":
|
|
468
|
+
return { rule: ruleTextOf(entry), pathBases: configurationSetBases(configRoot) };
|
|
436
469
|
default: {
|
|
437
470
|
const unhandled = root;
|
|
438
471
|
return unhandled;
|
|
@@ -490,7 +523,7 @@ export function applyTaskSettings(base, settings, bases) {
|
|
|
490
523
|
next = tightenGoverned(next, { ...(toolPolicy !== undefined ? { toolPolicy } : {}), ...seatSpec });
|
|
491
524
|
const allow = settings.permissions?.allow;
|
|
492
525
|
if (allow !== undefined)
|
|
493
|
-
next = { ...next, allowedTools: allow };
|
|
526
|
+
next = { ...next, allowedTools: allow.map((entry) => allowMemberOf(entry, bases?.configRoot)) };
|
|
494
527
|
if (settings.outputStyle) {
|
|
495
528
|
const appended = next.appendSystemPrompt ? `${next.appendSystemPrompt}\n\n${settings.outputStyle}` : settings.outputStyle;
|
|
496
529
|
next = { ...next, appendSystemPrompt: appended };
|
package/dist/terminal.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 终局因由(`TaskResult.terminal`)的 server 侧**读**面 ——
|
|
2
|
+
* 终局因由(`TaskResult.terminal`)的 server 侧**读**面 —— 一个叶子模块:依赖 `@sema-agent/core`、进程级记录器(`observability/fail-open.ts`)
|
|
3
|
+
* 与秘密脱敏器(`trace/redact.ts`,只作码判官 {@link isCodeToken} 的一条合取);本仓的结果汇点 / 出口座反过来依赖本模块,本模块不依赖它们。
|
|
3
4
|
*
|
|
4
5
|
* core 7.6.0([ref] S6 D-8,BREAKING)把 `TaskResult` 上并列的八个平面键
|
|
5
6
|
* (`status` / `errorCode` / `errorMessage` / `blockedReason` / `checkpointToken` / `checkpointId` /
|
|
@@ -57,18 +58,30 @@ export declare const STORE_ERROR_CODE = "internal.store_error";
|
|
|
57
58
|
*
|
|
58
59
|
* ⚠️ **辖域如实**:本臂触发条件是「码出了本仓的词法」,所以任何依赖铸出的域外码都落这里,不只 SQL 驱动。
|
|
59
60
|
* 今天可观察的产出方**只有**耐久店那一层(引擎自己的传输/brain 错误在 core 侧已被分类成小写码),故码名
|
|
60
|
-
* 取 `internal.store_error`;原码逐字进 message 尾注(随结果过汇点脱敏)
|
|
61
|
+
* 取 `internal.store_error`;原码逐字进 message 尾注(随结果过汇点脱敏)、是码时进运维线索({@link isCodeToken}),归因从不丢失。
|
|
61
62
|
*/
|
|
62
63
|
export declare function outwardFailureCode(code: string): string;
|
|
63
64
|
/**
|
|
64
|
-
* 一个错误的 `code`
|
|
65
|
-
*
|
|
66
|
-
*
|
|
65
|
+
* 一个错误的 `code` 只在它**是**码时才说出口 —— 一只判官,两条合取:
|
|
66
|
+
* ① **形**:短 token。驱动码 `ER_*` / SQLSTATE / `ECONNRESET` 全在这一形里;带空白、`=`、换行或超过 64 字符的就是一句话,不是码;
|
|
67
|
+
* ② **不是凭据形**:秘密脱敏器({@link redactSecrets})原样放过它。`sk-…` / `AKIA…` / `ghp_…` 这类秘密过得了 ①,而 wire 上同一只脱敏器
|
|
68
|
+
* 会把它从 message 尾注里遮掉 —— 日志行若照印,就是 wire 遮、日志露;所以「长得像码的秘密」在这里判「不是码」,日志与 wire 同读。
|
|
69
|
+
* 先判 ①:脱敏器只读 ≤ 64 个 token 字符(扫描代价有界);只问不出门(`observe: false`,与影子重扫同口 —— 不计「已脱」读数)。
|
|
70
|
+
* 读者两只,同一条判据:折码的运维线索(本文件 {@link sealResultForExit} / {@link sealStoredResult})与执行车道占位读的故障词(`boot/execution-env.ts`)。
|
|
67
71
|
*/
|
|
68
72
|
export declare function isCodeToken(code: unknown): code is string;
|
|
73
|
+
/**
|
|
74
|
+
* 一个错误**说得出口**的机器码,以日志字段 / 指标标签的形交回:`err.code` 是串且 {@link isCodeToken} 判它是码 ⇒ `{ code }`(逐字);其余(没有 / 不是串 / 空串 / 非 `Error` 抛出物 / 读取时抛 / 不是码)⇒ `{}`
|
|
75
|
+
* —— 键缺席,不补 `null` / `none` 之类的占位。「读口 + 判官 + 字段形」的**唯一**组合:引擎交来的错上的 `code` 是别人写的串,凡把它写进运维日志行或指标标签的汇点
|
|
76
|
+
* (`onError` 汇点的七条行与 `runner_config_advisory_total` 的标签、记忆引擎事故席)都经这一只,不各写一份读法、也不各设一份形判。读口 {@link errorCodeOf} 不抛。
|
|
77
|
+
* 显式标注返回类型:推断型 `{ code?: undefined } | { code: string }` 进不了指标标签 `Record<string, string>`。
|
|
78
|
+
*/
|
|
79
|
+
export declare function codeFieldOf(err: unknown): {
|
|
80
|
+
readonly code?: string;
|
|
81
|
+
};
|
|
69
82
|
/**
|
|
70
83
|
* 存量结果被**再观看**的读座(闭集):`GET /v1/runs/:id → result`(终态行与停驻行同一座)与账本 `done` 行的回放(三条耐久读腿共用)。
|
|
71
|
-
*
|
|
84
|
+
* 读入口 {@link sealStoredResult} 必须点名其一(类型级必填);`exit` 不在这里 —— 它只由写入口 {@link sealResultForExit} 给。
|
|
72
85
|
*/
|
|
73
86
|
export type StoredResultReadSeat = "run.result" | "ev.done.result";
|
|
74
87
|
/**
|
|
@@ -111,7 +124,7 @@ export declare function mapPauseSeats<T>(result: T, f: (seat: SeatObject, keys:
|
|
|
111
124
|
/**
|
|
112
125
|
* **一条结果离开引擎、进入本仓(可重放账本 / run 行 / wire)的唯一封口** —— 两件事,一个出口:
|
|
113
126
|
* ①摘掉**耐久恢复能力凭据**(`CheckpointToken`)—— 座表 {@link PAUSE_SEATS} 上的每一座;②把**域外的失败码**折成本仓的
|
|
114
|
-
* `internal.store_error`({@link outwardFailureCode},[ref])。
|
|
127
|
+
* `internal.store_error`({@link outwardFailureCode},[ref])—— 码座两只:因由的 `terminal.code` 与 cascade 每一级的 `attempts[].errorCode`(同一类码,见 {@link foldOutwardFailureCodes})。
|
|
115
128
|
*
|
|
116
129
|
* 🔴 为什么两件事合在一只函数里而不是并列两只(7.92.2 改名 `stripResumeToken` → `sealResultForExit`):
|
|
117
130
|
* 它们是**同一个出口上的同一件事** —— 「这条结果可以见人了吗」。并列两只 = 六个结算点各自要记得调两次,
|
|
@@ -129,23 +142,30 @@ export declare function mapPauseSeats<T>(result: T, f: (seat: SeatObject, keys:
|
|
|
129
142
|
* `/v1/approvals` 决策端点,凭 `checkpointId` 对账,从来不是拿 token 直连引擎。
|
|
130
143
|
*
|
|
131
144
|
* **出口全集都经这一口**:三家 run 店的行写口与账本店的 `done` 行写口在店入口调它(`observability/run-terminal.ts`),
|
|
132
|
-
* 同步 200 体 / 流 done 帧 /
|
|
133
|
-
* 升级前落盘、还带着凭据的存量行在读面上同样摘掉。两件事都**幂等**,重复过口是同形。
|
|
134
|
-
*
|
|
135
|
-
* ──
|
|
136
|
-
* `
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* ·
|
|
140
|
-
* ·
|
|
141
|
-
*
|
|
142
|
-
*
|
|
145
|
+
* 同步 200 体 / 流 done 帧 / 续跑决定腿在铸体处调它;`GET /v1/runs/:id{,/events}` 等读面在回放前过同一套封口的**读入口**
|
|
146
|
+
* {@link sealStoredResult} —— 升级前落盘、还带着凭据的存量行在读面上同样摘掉。两件事都**幂等**,重复过口是同形。
|
|
147
|
+
*
|
|
148
|
+
* ── 折码的运维线索:一句定形字段,两只入口各说一只词 ──
|
|
149
|
+
* 字段 `original=<码 | <not-a-code>> outward=<对外词> messageBytes=<n> at=<观看点>`,只有闭集词、数字与码({@link isCodeToken}):
|
|
150
|
+
* 失败句只报字节数,**永不**报原文 —— 失败句是自由文本(驱动句里可以有连接串 / 口令),结果里的那份由结果汇点脱敏,运维线索没有汇点,
|
|
151
|
+
* 所以压根不带它;码形座里装着文字的、长得像码的秘密同理只报 `<not-a-code>`。`at` 说这是哪一次观看,**一个入口一只词**(类型给定,不靠记得传):
|
|
152
|
+
* · 本函数 = 结果**第一次**离开引擎(店的写口 / 出口铸体)⇒ `at=exit`,每折一次一行 `[terminal] outward_failure_code_folded <字段>` —— 每次都是一件新的失败;
|
|
153
|
+
* · {@link sealStoredResult} = 存量行的**再观看**(读座必填)⇒ 走 fail-open 纪律(登记 tag `server.terminal.stored-result-code-folded`):
|
|
154
|
+
* 逐读计数 + 逐读探针行 + 每进程一次 warn,detail 即上面那句字段。读面每次轮询 / 每个观看者 / 每次重连都重放同一批行 ——
|
|
155
|
+
* 计数让「旧失败被读了多少次」看得见,一次 warn 让日志不随读次放大;去重归记录器一只,不另造表。
|
|
143
156
|
*
|
|
144
157
|
* 对任何输入安全(非普通对象 / 无可摘的座 / 码在词法内 ⇒ **同一引用**原样返回,不重塑)。
|
|
145
158
|
*/
|
|
146
159
|
export declare function sealResultForExit<T extends {
|
|
147
160
|
readonly terminal?: unknown;
|
|
148
|
-
}>(result: T
|
|
161
|
+
}>(result: T): T;
|
|
162
|
+
/**
|
|
163
|
+
* **存量结果被再观看时的封口** —— 与 {@link sealResultForExit} 同一套封口(摘凭据 + 折码,同判同形),只差运维线索的观看点:
|
|
164
|
+
* 读座({@link StoredResultReadSeat})**必填**,于是新开一条读腿忘了点名读座是 tsc 红,不是悄悄落成 `at=exit`、按读次放大。
|
|
165
|
+
*/
|
|
166
|
+
export declare function sealStoredResult<T extends {
|
|
167
|
+
readonly terminal?: unknown;
|
|
168
|
+
}>(result: T, seat: StoredResultReadSeat): T;
|
|
149
169
|
/**
|
|
150
170
|
* **投影出口的唯一属主**([ref])—— core 的 `terminalProjection` + 对外码归一,一次。
|
|
151
171
|
*
|
package/dist/terminal.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { terminalProjection } from "@sema-agent/core";
|
|
2
|
+
import { errorCodeOf } from "./observability/err-text.js";
|
|
2
3
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
4
|
+
import { redactSecrets } from "./trace/redact.js";
|
|
3
5
|
export function failureCodeOf(terminal) {
|
|
4
6
|
return terminal.kind === "failed" ? terminal.code : undefined;
|
|
5
7
|
}
|
|
@@ -9,9 +11,13 @@ export function outwardFailureCode(code) {
|
|
|
9
11
|
return OUTWARD_CODE_SHAPE.test(code) ? code : STORE_ERROR_CODE;
|
|
10
12
|
}
|
|
11
13
|
export function isCodeToken(code) {
|
|
12
|
-
return typeof code === "string" && CODE_TOKEN_SHAPE.test(code);
|
|
14
|
+
return typeof code === "string" && CODE_TOKEN_SHAPE.test(code) && redactSecrets(code, { observe: false }) === code;
|
|
13
15
|
}
|
|
14
16
|
const CODE_TOKEN_SHAPE = /^[A-Za-z0-9_.:-]{1,64}$/;
|
|
17
|
+
export function codeFieldOf(err) {
|
|
18
|
+
const code = errorCodeOf(err);
|
|
19
|
+
return isCodeToken(code) ? { code } : {};
|
|
20
|
+
}
|
|
15
21
|
export const PAUSE_SEATS = [
|
|
16
22
|
{ path: ["terminal"], token: "token", gate: "gate" },
|
|
17
23
|
{ path: ["terminal", "nestedPause"], token: "token", gate: "gate" },
|
|
@@ -41,36 +47,73 @@ function dropCapability(seat, keys) {
|
|
|
41
47
|
const { [keys.token]: _drop, ...rest } = seat;
|
|
42
48
|
return rest;
|
|
43
49
|
}
|
|
44
|
-
export function sealResultForExit(result
|
|
50
|
+
export function sealResultForExit(result) {
|
|
51
|
+
return seal(result, "exit");
|
|
52
|
+
}
|
|
53
|
+
export function sealStoredResult(result, seat) {
|
|
54
|
+
return seal(result, seat);
|
|
55
|
+
}
|
|
56
|
+
function seal(result, at) {
|
|
45
57
|
if (result === null || typeof result !== "object")
|
|
46
58
|
return result;
|
|
47
|
-
return
|
|
59
|
+
return foldOutwardFailureCodes(mapPauseSeats(result, dropCapability), at);
|
|
48
60
|
}
|
|
49
|
-
function
|
|
50
|
-
const
|
|
51
|
-
|
|
61
|
+
function foldOutwardFailureCodes(result, at) {
|
|
62
|
+
const terminal = foldCauseCode(result.terminal, at);
|
|
63
|
+
const priorAttempts = result.attempts;
|
|
64
|
+
const attempts = foldAttemptCodes(priorAttempts, at);
|
|
65
|
+
const terminalKept = Object.is(terminal, result.terminal);
|
|
66
|
+
const attemptsKept = Object.is(attempts, priorAttempts);
|
|
67
|
+
if (terminalKept && attemptsKept)
|
|
52
68
|
return result;
|
|
69
|
+
return { ...result, ...(terminalKept ? {} : { terminal }), ...(attemptsKept ? {} : { attempts }) };
|
|
70
|
+
}
|
|
71
|
+
function foldCauseCode(terminal, at) {
|
|
72
|
+
const t = failedCauseWithCode(terminal);
|
|
73
|
+
if (t === undefined)
|
|
74
|
+
return terminal;
|
|
53
75
|
const outward = outwardFailureCode(t.code);
|
|
54
76
|
if (outward === t.code)
|
|
55
|
-
return
|
|
56
|
-
reportFold(t.code, outward, t.message,
|
|
77
|
+
return terminal;
|
|
78
|
+
reportFold(t.code, outward, t.message, at);
|
|
57
79
|
const message = typeof t.message === "string" ? t.message : "the durable store failed";
|
|
58
|
-
return { ...
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (readFoldLatch.has(key))
|
|
80
|
+
return { ...t, code: outward, message: `${message} [original code: ${t.code}]` };
|
|
81
|
+
}
|
|
82
|
+
function foldAttemptCodes(attempts, at) {
|
|
83
|
+
if (!Array.isArray(attempts))
|
|
84
|
+
return attempts;
|
|
85
|
+
let folded;
|
|
86
|
+
attempts.forEach((attempt, i) => {
|
|
87
|
+
if (attempt === null || typeof attempt !== "object")
|
|
67
88
|
return;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
89
|
+
const code = attempt.errorCode;
|
|
90
|
+
if (typeof code !== "string")
|
|
91
|
+
return;
|
|
92
|
+
const outward = outwardFailureCode(code);
|
|
93
|
+
if (outward === code)
|
|
94
|
+
return;
|
|
95
|
+
reportFold(code, outward, undefined, at);
|
|
96
|
+
(folded ??= [...attempts])[i] = { ...attempt, errorCode: outward };
|
|
97
|
+
});
|
|
98
|
+
return folded ?? attempts;
|
|
99
|
+
}
|
|
100
|
+
const STORED_RESULT_FOLD_TAG = "server.terminal.stored-result-code-folded";
|
|
101
|
+
function reportFold(code, outward, message, at) {
|
|
72
102
|
const messageBytes = typeof message === "string" ? Buffer.byteLength(message, "utf8") : 0;
|
|
73
|
-
|
|
103
|
+
const fields = `original=${isCodeToken(code) ? code : "<not-a-code>"} outward=${outward} messageBytes=${messageBytes} at=${at}`;
|
|
104
|
+
switch (at) {
|
|
105
|
+
case "exit":
|
|
106
|
+
console.warn(`[terminal] outward_failure_code_folded ${fields}`);
|
|
107
|
+
return;
|
|
108
|
+
case "run.result":
|
|
109
|
+
case "ev.done.result":
|
|
110
|
+
recordFailOpen(STORED_RESULT_FOLD_TAG, fields);
|
|
111
|
+
return;
|
|
112
|
+
default: {
|
|
113
|
+
const unhandled = at;
|
|
114
|
+
throw new Error(`unhandled fold sighting: ${String(unhandled)}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
74
117
|
}
|
|
75
118
|
function failedCauseWithCode(t) {
|
|
76
119
|
if (t === null || typeof t !== "object")
|