@sema-agent/server 7.140.0 → 7.141.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 +290 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +75 -13
- package/dist/approval-batch-census.d.ts +27 -0
- package/dist/approval-batch-census.js +27 -0
- package/dist/approval-card.d.ts +31 -16
- package/dist/approval-card.js +6 -3
- 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/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.js +8 -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 +1 -1
- package/dist/boot/reapers.d.ts +2 -2
- package/dist/boot/resolve-spec.js +7 -4
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +4 -3
- package/dist/boot/shutdown.js +5 -0
- package/dist/boot/stage-05-execution-env.js +3 -1
- package/dist/boot/stage-06-runners.d.ts +0 -2
- package/dist/boot/stage-06-runners.js +1 -1
- package/dist/boot/stage-07-capability-layer.d.ts +0 -1
- package/dist/boot/stage-07-capability-layer.js +8 -10
- package/dist/boot/stage-08-reapers.d.ts +0 -1
- package/dist/boot/stage-09-leader.d.ts +0 -1
- package/dist/boot/stage-10-http-server.d.ts +0 -1
- package/dist/boot/stage-10-http-server.js +1 -0
- package/dist/boot/stores.js +10 -4
- package/dist/boot/web-admin.js +1 -0
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +9 -0
- package/dist/capability-facts.js +9 -0
- package/dist/card-void.d.ts +38 -0
- package/dist/card-void.js +23 -0
- package/dist/config-catalog.js +11 -8
- package/dist/config-provider.d.ts +13 -13
- package/dist/config-provider.js +19 -33
- package/dist/config-types.d.ts +26 -8
- package/dist/config.js +55 -46
- 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 +49 -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/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 +4 -0
- package/dist/http/live-frame.d.ts +24 -0
- package/dist/http/live-frame.js +16 -0
- package/dist/http/resume-legs.js +37 -20
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/approvals-assistant.js +1 -0
- package/dist/http/routes/capabilities.js +5 -4
- 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 +2 -2
- 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/session-sync.d.ts +3 -6
- package/dist/http/routes/session-sync.js +7 -2
- package/dist/http/routes/sessions.js +5 -4
- package/dist/http/routes/tasks.js +63 -66
- package/dist/http/run-read-face.js +3 -3
- package/dist/http/send.d.ts +1 -1
- package/dist/http/send.js +2 -2
- package/dist/http/server.d.ts +9 -2
- 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/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-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 +14 -2
- package/dist/memory-sync-client.js +80 -18
- package/dist/observability/fail-open.d.ts +30 -2
- package/dist/observability/fail-open.js +30 -2
- package/dist/observability/metrics.js +0 -1
- package/dist/observability/run-terminal.d.ts +6 -2
- package/dist/observability/run-terminal.js +25 -26
- 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/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 +2 -2
- package/dist/plugins/file-run-store.js +1 -1
- 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 +227 -35
- package/dist/plugins/local-session-store.js +518 -37
- package/dist/plugins/local-session-window.d.ts +17 -3
- package/dist/plugins/local-session-window.js +7 -13
- package/dist/plugins/memory-run-store.d.ts +2 -2
- package/dist/plugins/memory-run-store.js +1 -1
- package/dist/plugins/one-time-migrations.d.ts +42 -2
- package/dist/plugins/one-time-migrations.js +65 -3
- 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 +24 -3
- package/dist/plugins/remote-env-e2b.js +131 -18
- package/dist/plugins/remote-env-k8s.d.ts +20 -1
- package/dist/plugins/remote-env-k8s.js +148 -25
- package/dist/plugins/remote-env-local-docker.d.ts +25 -11
- package/dist/plugins/remote-env-local-docker.js +87 -21
- package/dist/plugins/run-store-sql.d.ts +3 -3
- package/dist/plugins/run-store-sql.js +4 -3
- 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 +31 -0
- package/dist/plugins/store-backend.js +21 -4
- package/dist/plugins/store-contracts.d.ts +9 -2
- 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/run-cancel-context.d.ts +34 -0
- package/dist/run-cancel-context.js +7 -0
- package/dist/runs.d.ts +39 -12
- package/dist/runs.js +68 -53
- package/dist/security.d.ts +2 -2
- package/dist/server-secret-env.d.ts +2 -1
- package/dist/server-secret-env.js +2 -4
- package/dist/session-error-wire.d.ts +22 -4
- package/dist/session-error-wire.js +16 -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 +52 -25
- package/dist/task-settings.js +91 -28
- package/dist/terminal.d.ts +77 -20
- package/dist/terminal.js +66 -20
- package/dist/trace/core-keyset-guard.d.ts +79 -2
- package/dist/trace/exit-seat.d.ts +7 -0
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/model-segment.d.ts +2 -2
- package/dist/trace/redact.js +323 -90
- package/dist/trace/self-minted-wire.d.ts +168 -2
- package/dist/trace/self-minted-wire.js +63 -0
- 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 +2 -2
- package/dist/web-admin-client/candidate-gate.d.ts +1 -1
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
- package/package.json +2 -2
- package/wire-changes/server@7.141.0.json +367 -0
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 站着的答案的**授予绑定**的唯一读口:这一问的应答授不授予「这一次调用」之外的东西,授予的话绑定是什么。
|
|
3
|
+
*
|
|
4
|
+
* 站着的答案(活的「本会话放行」、耐久的 `remember:"session"`)记下的是**上一次**应答;它只配代答「上一次应答覆盖得到」的问。
|
|
5
|
+
* 有一类卡的应答还**授予**别的东西:批准引擎的 `Skill` = 激活那只技能 + 本 run 内它 `allowedTools` 上的工具免问。这类卡的答案只能按
|
|
6
|
+
* 「工具 + 授予绑定」记、只代答绑定相同的问(core 原句「an answer is remembered by "this tool + this binding"」)。判据本身在
|
|
7
|
+
* `tool-approval.ts` 的 `standingAnswerHome`(本读口是它的一位);本文件只回答「授不授予、绑定是什么」,是叶模块。
|
|
8
|
+
*
|
|
9
|
+
* 🔴 **一条律:只读引擎的词,载体不论**。引擎的绑定工厂给一次调用的每一个载体盖**同一组词**、恰带一臂:`boundGrantDigest`(对引擎 `Skill` 工具的
|
|
10
|
+
* 激活:技能名 + 两只清单规范拼写的摘要)或 `boundGrantAbsence`(闭集 core `BOUND_GRANT_ABSENCES`:`not_bindable` = 不绑任何授予 / `unreadable` = 绑着却读不出)。
|
|
11
|
+
* 载体 = 活的 `AskRequest`、停驻行 `PendingAction.tool_approval`、读这两者的运维队列行 / inbox 行,以及 core 7.59.0 起 Runner 交给策略层的 `ToolCallRequest`
|
|
12
|
+
* (部署名单门、workflow 问句门在交出自己的问之前读它)。读法与 core 自己的 inbox 投影逐臂同一条:摘要是串 ⇒ `bound`;否则摘要不在且词是 `not_bindable`
|
|
13
|
+
* ⇒ `none`;其余(词是 `unreadable`、摘要在而不是串、集外词、两者都不说)⇒ `unreadable`。**不读工具名**。
|
|
14
|
+
* · 两者都不说的载体:7.51.0 之前停驻的行(core:「it does not say」)、宿主不经 Runner 自建的请求 —— 读作 `unreadable`:不可记、不被代答(fail-closed)。
|
|
15
|
+
* · 读面上的那一臂({@link grantBindingArm})是本读口的逆像:停驻行的运维队列行 / `/stream` 的 `pending` 帧投的就是 `grantBindingArm(grantBindingOf(行))` ——
|
|
16
|
+
* 恰带摘要与缺席词之一,与 core 投收件箱行的那一臂同值;卡上显示的臂与「本会话放行」记不记得住由同一次读定,不会两答。
|
|
17
|
+
* · 部署名单自己的问(答案记在 server 的会话豁免店,按 (会话, 工具名))的写侧、名单门的读侧、豁免列表三处读同一组词 —— 7.129.0–7.137.x 读侧手里的请求
|
|
18
|
+
* 不带词,三处只好按工具名读调用载体;那只读口随 core 7.59.0 退役。
|
|
19
|
+
*/
|
|
20
|
+
import type { BoundGrantAbsence } from "@sema-agent/core";
|
|
1
21
|
/** 载体:引擎给一次调用盖过绑定词的任何形(活的 `AskRequest`、停驻行的 `tool_approval` 臂、运维队列行、策略层的 `ToolCallRequest` 都结构上满足)。 */
|
|
2
22
|
export interface StandingAnswerCard {
|
|
3
23
|
readonly boundGrantDigest?: unknown;
|
|
@@ -12,6 +32,15 @@ export type GrantBinding = {
|
|
|
12
32
|
} | {
|
|
13
33
|
readonly kind: "unreadable";
|
|
14
34
|
};
|
|
15
|
-
/** 载体上的授予绑定 —— 只读引擎的词(读法见文件头注):摘要是串 ⇒ bound;摘要不在且词是 `not_bindable` ⇒ none;其余 ⇒ unreadable。
|
|
16
|
-
|
|
35
|
+
/** 载体上的授予绑定 —— 只读引擎的词(读法见文件头注):摘要是串 ⇒ bound;摘要不在且词是 `not_bindable` ⇒ none;其余 ⇒ unreadable。
|
|
36
|
+
* 形参是任意对象(载体不论):读自持久层的停驻行(运维队列行的投影、`/decide` 的原始行)两座都按 `unknown` 读,结构上满足 {@link StandingAnswerCard} 的载体照传。 */
|
|
37
|
+
export declare function grantBindingOf(card: StandingAnswerCard | object): GrantBinding;
|
|
38
|
+
/** 授予绑定在读面上的形:恰一臂 —— 摘要,或缺席词(闭集 core `BOUND_GRANT_ABSENCES`)。 */
|
|
39
|
+
export type GrantBindingArm = {
|
|
40
|
+
readonly boundGrantDigest: string;
|
|
41
|
+
} | {
|
|
42
|
+
readonly boundGrantAbsence: BoundGrantAbsence;
|
|
43
|
+
};
|
|
44
|
+
/** {@link GrantBinding} 投回读面的那一臂(逐臂穷尽:core 给绑定加一态而这里不跟 ⇒ 编译红):bound ⇒ 摘要;none ⇒ `not_bindable`;unreadable ⇒ `unreadable`。 */
|
|
45
|
+
export declare function grantBindingArm(binding: GrantBinding): GrantBindingArm;
|
|
17
46
|
//# sourceMappingURL=standing-answer-grant.d.ts.map
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
const NOT_BINDABLE = "not_bindable";
|
|
2
|
+
const UNREADABLE = "unreadable";
|
|
2
3
|
export function grantBindingOf(card) {
|
|
3
|
-
const digest = card.boundGrantDigest;
|
|
4
|
+
const digest = "boundGrantDigest" in card ? card.boundGrantDigest : undefined;
|
|
4
5
|
if (typeof digest === "string")
|
|
5
6
|
return { kind: "bound", digest };
|
|
6
|
-
|
|
7
|
+
const word = "boundGrantAbsence" in card ? card.boundGrantAbsence : undefined;
|
|
8
|
+
return digest === undefined && word === NOT_BINDABLE ? { kind: "none" } : { kind: "unreadable" };
|
|
9
|
+
}
|
|
10
|
+
export function grantBindingArm(binding) {
|
|
11
|
+
switch (binding.kind) {
|
|
12
|
+
case "bound":
|
|
13
|
+
return { boundGrantDigest: binding.digest };
|
|
14
|
+
case "none":
|
|
15
|
+
return { boundGrantAbsence: NOT_BINDABLE };
|
|
16
|
+
case "unreadable":
|
|
17
|
+
return { boundGrantAbsence: UNREADABLE };
|
|
18
|
+
}
|
|
7
19
|
}
|
|
8
20
|
//# sourceMappingURL=standing-answer-grant.js.map
|
package/dist/store-posture.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ## 形
|
|
10
10
|
* `declared` = 运维的声明(`DB_BACKEND` 词,含缺省推导);`backend` = **装配出的**后端 kind(没装出后端 = `memory`);两者不等是合法的
|
|
11
|
-
* 形(`DB_BACKEND=pg` + `SESSION_BACKEND=memory` = 声明 pg
|
|
11
|
+
* 形(`DB_BACKEND=pg` + 坐标在场 + `SESSION_BACKEND=memory` = 声明 pg、刻意不持久 —— 坐标缺席的声明在配置期拒启,见 `sql-engine-coordinates.ts`;缺省推导 local 起不来)—— 两位都上 wire,
|
|
12
12
|
* 由调用方自己读出落差。`degradedReason` present-iff 降级臂走过(按后端族定词,{@link storeDegradedReasonFor})。
|
|
13
13
|
* 顶层 `sql` 并入 `store.sql`(硬 breaking,零别名;对象逐字同形)。
|
|
14
14
|
*/
|
package/dist/task-a2a.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export declare const A2A_PEER_DISPOSITION: {
|
|
|
57
57
|
readonly toolAxes: "engine";
|
|
58
58
|
};
|
|
59
59
|
/** 请求体 `a2aPeers[i]` 的键闭集 = 处置表的键(书写序即判序)。 */
|
|
60
|
-
export declare const A2A_PEER_ENTRY_KEYS: readonly ("name" | "headers" | "
|
|
60
|
+
export declare const A2A_PEER_ENTRY_KEYS: readonly ("name" | "headers" | "url" | "principalHeader" | "toolAxes" | "cardUrl" | "allowSkills")[];
|
|
61
61
|
/**
|
|
62
62
|
* **请求入口的一次读**(`boot/resolve-spec.ts` 在腿首铸一份,受理门与读器——续跑重放腿只有读器——都吃这一份):`body.a2aPeers` 若是数组,返回同形数组
|
|
63
63
|
* (每个对象条目换成它的 {@link PeerSnapshot};非对象条目原样;长度保真 —— 界外的条数仍是受理门撞帽拒与读器丢弃留声的依据,只快照界内的条目);不是数组(缺席 / `null` / 别的形)原样返回。
|
package/dist/task-mcp.d.ts
CHANGED
|
@@ -71,7 +71,7 @@ export declare const MCP_SERVER_ENTRY_KEYS: readonly ["allowTools", "contentOrig
|
|
|
71
71
|
/** `transport.kind:"stdio"` 的键闭集 = stdio 臂处置表的键(`env` 是件,其余进声明)。 */
|
|
72
72
|
export declare const STDIO_MCP_TRANSPORT_KEYS: readonly ("env" | "kind" | "args" | "command")[];
|
|
73
73
|
/** `transport.kind:"http"` 的键闭集 = http 臂处置表的键(`headers` 是件,`assertionHeader` 承载不发送,其余进声明)。 */
|
|
74
|
-
export declare const HTTP_MCP_TRANSPORT_KEYS: readonly ("headers" | "kind" | "
|
|
74
|
+
export declare const HTTP_MCP_TRANSPORT_KEYS: readonly ("headers" | "kind" | "url" | "principalHeader" | "assertionHeader")[];
|
|
75
75
|
/**
|
|
76
76
|
* Does THIS deployment honor caller-supplied per-request MCP servers? TRUE for a SINGLE-USER deployment
|
|
77
77
|
* (deployment-shape row `multiTenant` does not hold) — the requester is the super-admin of their own worker, so their `.mcp.json` is
|
package/dist/task-settings.d.ts
CHANGED
|
@@ -49,10 +49,11 @@
|
|
|
49
49
|
*/
|
|
50
50
|
import { type PathRuleBases, type TaskSpec, type ThinkingLevel, type ToolPolicy, type PermissionMode } from "@sema-agent/core";
|
|
51
51
|
import { type EntryProblem } from "./entry-problems.js";
|
|
52
|
+
import { type RuleListEntry } from "./permission-rule-list.js";
|
|
52
53
|
import { type KeyClosureIssue } from "./request-key-closure.js";
|
|
53
54
|
import { type RunnableHooksConfig } from "./hooks/hook-runner.js";
|
|
54
55
|
import type { StoredHooksRereadM20 } from "./stored-request-hooks-m20.js";
|
|
55
|
-
import {
|
|
56
|
+
import type { EntryPermissionMode } from "./runtime-governance.js";
|
|
56
57
|
import { type TightenOnlySeatValues } from "./tighten-only-seats.js";
|
|
57
58
|
/**
|
|
58
59
|
* 请求面 `permissionMode` 的闭集 = core `PERMISSION_MODES` **全集**(顶层 `permissionMode` / `settings.permissions.defaultMode` /
|
|
@@ -112,23 +113,21 @@ export declare function planReviewDecisionExitsPlan(decision: "approve" | "edit"
|
|
|
112
113
|
/**
|
|
113
114
|
* 运维 `AUTONOMY=plan` 的**入口词地板**盖进提交体 —— 此后一条 run 的模式词只有存储体顶层 `permissionMode` 一个源。
|
|
114
115
|
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* `settings.permissions.defaultMode` 不动 —— 顶层赢过它
|
|
118
|
-
*
|
|
116
|
+
* 入口词由受理判官答(`permission-mode-admission.ts` `admitPermissionModeWord`:两口 —— 提交受理口与在飞 run 的切档口 —— 同一只;它交回的
|
|
117
|
+
* `entry` 就是「词在地板下变成什么」那一次求值的读数,秩是 core 的)。本函数只做「写进体」这一半:地板缺席 ⇒ 体**原物**交回(零字节变化);地板在场 ⇒
|
|
118
|
+
* 新体 `{ ...body, permissionMode: entry.effective }`,调用方的对象不改;bundle 的 `settings.permissions.defaultMode` 不动 —— 顶层赢过它
|
|
119
|
+
* ({@link effectivePermissionMode} 的优先序),再改它就是同一语义的第二个写者。披露这一折的通告(`entry-mode-clamp-notice.ts`)读的也是同一份 `entry`。
|
|
119
120
|
*
|
|
120
|
-
*
|
|
121
|
+
* 调用点一个:提交入口的那一步 `permission-mode-admission.ts` `stampSubmissionEntryMode`(受理判官的入口一步;`http/admission.ts` 的 `prepareSpec` 调它:值形门全部判完之后、`resolveSpec` 之前)。那一份体就是首跑装配读的体,也是
|
|
121
122
|
* `buildCheckpointCtx` 持久化的体 ⇒ 一处盖章同时覆盖首跑与每一次续跑重建;装配腿与续跑腿都不读地板(两处读 = 两个源)。
|
|
122
|
-
*
|
|
123
|
-
*
|
|
123
|
+
* 另外两个写者是 `plan_review` 写回(`http/resume-legs.ts` `drivePlanReview`,判据 {@link planReviewDecisionExitsPlan})与在飞 run 的切档口写回
|
|
124
|
+
* (`http/routes/run-permission-mode.ts`,写的是同一只判官准入的词)。
|
|
125
|
+
* 热改 `AUTONOMY` 只影响之后提交的任务与之后的切档:续跑腿保持存储体里的词。地板的属主是 `runtime-governance.ts` 的 `autonomyModeFloor`。
|
|
124
126
|
*/
|
|
125
127
|
export declare function stampEntryPermissionMode<B extends {
|
|
126
128
|
permissionMode?: unknown;
|
|
127
129
|
settings?: unknown;
|
|
128
|
-
}>(body: B,
|
|
129
|
-
readonly body: B;
|
|
130
|
-
readonly entry: EntryPermissionMode;
|
|
131
|
-
};
|
|
130
|
+
}>(body: B, entry: EntryPermissionMode): B;
|
|
132
131
|
/**
|
|
133
132
|
* [ref] —— **一条已持久化的提交体的生效 permission mode**,单点。
|
|
134
133
|
*
|
|
@@ -150,8 +149,8 @@ export declare function storedBodyPermissionMode(body: {
|
|
|
150
149
|
* future-proof). Awareness rides for free: core composes ORCHESTRATION_AWARENESS from thinking∈{xhigh,max}, no field. */
|
|
151
150
|
export declare function effectiveThinking(reasoningEffort: unknown, ultracode: boolean): ThinkingLevel | undefined;
|
|
152
151
|
/**
|
|
153
|
-
* [ref] §6-1 —— 本请求的**生效** permission mode
|
|
154
|
-
*
|
|
152
|
+
* [ref] §6-1 —— 本请求的**生效** permission mode,单点 = 调用方的词({@link requestedPermissionMode})经本任务 settings 的 kill-switch 折叠
|
|
153
|
+
* ({@link foldDisableAutoMode})。两处都没有 ⇒ `undefined` = **无表态**(调用点据此不写键,而不是替调用方选一个默认值;引擎把缺席读成 `default`)。
|
|
155
154
|
*
|
|
156
155
|
* 🔴 为什么必须是一只函数:同一个「生效模式」此前在 resolve-spec 里被算过两次(hooks 腿的 `permission_mode` 载荷、settings 折叠腿),
|
|
157
156
|
* 两处各算各的,任何一次优先序修订都会让两面分家,而分家在这条轴上的形态是「壳发的 bundle bypass 在 A 面生效、在 B 面没生效」这种
|
|
@@ -160,6 +159,23 @@ export declare function effectiveThinking(reasoningEffort: unknown, ultracode: b
|
|
|
160
159
|
export declare function effectivePermissionMode(body: {
|
|
161
160
|
permissionMode?: unknown;
|
|
162
161
|
}, settings: ParsedTaskSettings | undefined): PermissionMode | undefined;
|
|
162
|
+
/**
|
|
163
|
+
* 调用方在提交体上说出的模式词 —— 顶层 `body.permissionMode`(本轮显式表态)赢过 bundle 的 `settings.permissions.defaultMode`;两处都没有 ⇒ `undefined`。
|
|
164
|
+
* 读者两个:{@link effectivePermissionMode}(存储体读法)与提交口交给受理判官入口一步的那一个词(`permission-mode-admission.ts` `stampSubmissionEntryMode`)。
|
|
165
|
+
*/
|
|
166
|
+
export declare function requestedPermissionMode(body: {
|
|
167
|
+
permissionMode?: unknown;
|
|
168
|
+
}, settings: ParsedTaskSettings | undefined): PermissionMode | undefined;
|
|
169
|
+
/**
|
|
170
|
+
* [ref] 件⑥([ref] §3.4,[ref]/[ref]):本任务 settings 的 kill-switch `permissions.disableAutoMode` 的**唯一**折叠(tighten-only,CC 250 `Ct`
|
|
171
|
+
* 棘轮形):把 auto 折 default(座不写 ⇒ 引擎不武装,与 CC「auto 不可用 ⇒ 回 default」同向)。只关 auto;缺席不动;没有放宽臂。
|
|
172
|
+
* 读者两个:存储体读法 {@link effectivePermissionMode} 与受理判官(`permission-mode-admission.ts`,提交口与切档口同一只)—— 切档口的
|
|
173
|
+
* `auto` 因此与提交口的 `auto` 在同一份 settings 下折成同一个词。`disableBypassPermissionsMode` 落点归 [ref]。
|
|
174
|
+
* 🔴 [ref] 放宽一档:折叠触发词是 **`"disable"` 或 `true`** —— 两套**已发布**的合法拼写(CC 250 `Ct` 的严极词 /
|
|
175
|
+
* `@sema-agent/sdk` 8.1.0 `SettingsPermissions.disableAutoMode?: boolean`),同义同折。显式 `false` = 「不禁」,
|
|
176
|
+
* 合法输入、**零效果**(不是「开 auto」的开关 —— 本键只有关的半场,放宽臂在这条轴上从来不存在)。
|
|
177
|
+
*/
|
|
178
|
+
export declare function foldDisableAutoMode(word: PermissionMode | undefined, settings: ParsedTaskSettings | undefined): PermissionMode | undefined;
|
|
163
179
|
/**
|
|
164
180
|
* [ref] —— [ref] 技能清单预算两旋钮的**值域谓词**(一对具名单铸点)。
|
|
165
181
|
*
|
|
@@ -182,9 +198,10 @@ export declare function skillListingMaxDescOk(v: unknown): v is number;
|
|
|
182
198
|
export interface ParsedTaskSettings {
|
|
183
199
|
permissions?: {
|
|
184
200
|
allow?: string[];
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
201
|
+
/** 纯串 = 请求自己写的规则;`{ rule, layer }` = 端从某个设置层读来的规则(`permission-rule-list.ts` 的 {@link RuleListEntry};层只选 `/` 的锚)。 */
|
|
202
|
+
deny?: RuleListEntry[];
|
|
203
|
+
/** 同 `deny` 的条目形;编译与 `deny` 同一口({@link deriveSettingsPolicy})。 */
|
|
204
|
+
ask?: RuleListEntry[];
|
|
188
205
|
defaultMode?: PermissionMode;
|
|
189
206
|
/** [ref] 件⑥([ref] §3.4,[ref];PM 裁 [ref]):CC settings 的 kill-switch `permissions.disableAutoMode`,cli 投影
|
|
190
207
|
* (settingsRulesWire.ts toWireSettings)而此前本白名单丢弃 ⇒ 用户/managed 层关 auto 到不了引擎。语义 = 只能关
|
|
@@ -276,7 +293,7 @@ export interface SettingsPermissionBucketIssue {
|
|
|
276
293
|
/**
|
|
277
294
|
* 三桶的**唯一**判据(纯函数)。`perms` 不是对象 ⇒ 不判(那一形归「settings.permissions must be an object」那道门);桶缺席 / `null`
|
|
278
295
|
* ⇒ 不判(与 `permissions: null` 的「容器缺席」同一约定)。逐桶按 {@link SETTINGS_PERMISSION_BUCKETS} 的序、按该桶的条目规则:不是数组 ⇒ `bad_entry`
|
|
279
|
-
* (无 `index`);`rule_policy` 桶超帽 ⇒ `over_cap`(先判,拒体有界)
|
|
296
|
+
* (无 `index`);`rule_policy` 桶超帽 ⇒ `over_cap`(先判,拒体有界)、首个不合条目律的项(不是非空串、也不是合形的带层条目)⇒ `bad_entry` + 它的下标;`allow_layer` 桶首个非串项 ⇒
|
|
280
297
|
* `bad_entry` + 它的下标(整表判据 = `ruleEntryListShapeOk`),超帽同样 `over_cap`(帽的理由不同,见段头)。全合法 ⇒ `null`。
|
|
281
298
|
*/
|
|
282
299
|
export declare function settingsPermissionBucketIssue(perms: unknown): SettingsPermissionBucketIssue | null;
|
|
@@ -432,6 +449,12 @@ export interface FsWriteGateWiring {
|
|
|
432
449
|
* 运维在**下单那一刻**就知道这条规则这条车道读不了,而不是等到跑起来每次都弹一张 ask。
|
|
433
450
|
*/
|
|
434
451
|
taskHome?: string;
|
|
452
|
+
/**
|
|
453
|
+
* **执行环境的配置根**(唯一属主 `execution-config-root.ts` 的 `executionConfigRootOf`):user 设置层里 `/` 形路径规则的根 —— 带 `layer: "userSettings"`
|
|
454
|
+
* 且要 `root` 的条目编进只声明 `{ root: configRoot }` 的那一集(`permission-rule-list.ts` 的 `ruleRootOf`)。缺席(沙箱车道既没转 `SEMA_CONFIG_DIR`、home 也读不出)
|
|
455
|
+
* ⇒ 这样的条目由 {@link rejectUnmatchableSettingsNames} 响亮拒(422 `home_unresolvable`),不猜目录。拒点与存体预判读同一只函数。
|
|
456
|
+
*/
|
|
457
|
+
configRoot?: string;
|
|
435
458
|
}
|
|
436
459
|
/**
|
|
437
460
|
* 请求的 `settings.permissions.deny` / `ask` 有永远不生效的条目 ⇒ 拒点({@link rejectUnmatchableSettingsNames})抛的错:句子(`message`)与这一遍判下来的**全部**问题(`problems`,机读位的原料)。
|
|
@@ -454,20 +477,24 @@ export declare const RULE_POLICY_BUCKETS: readonly ["ask", "deny"];
|
|
|
454
477
|
export type RulePolicyBucket = (typeof RULE_POLICY_BUCKETS)[number];
|
|
455
478
|
/**
|
|
456
479
|
* deny / ask 两桶的**完整规则判**,唯一一只(拒点 {@link rejectUnmatchableSettingsNames} 与存体预判 `http/stored-body-replay.ts` 同调):
|
|
457
|
-
* ② 按 {@link RULE_POLICY_BUCKETS}
|
|
458
|
-
* (
|
|
459
|
-
*
|
|
460
|
-
*
|
|
480
|
+
* ② 按 {@link RULE_POLICY_BUCKETS} 的序逐桶、桶内按 `RULE_ROOTS` 的序逐集(`permission-rule-list.ts` 的 `ruleSetsOf`:判的就是要编的那一集)问 `judgeUnmatchableToolNames`(名字层 + core 规则文法);
|
|
481
|
+
* ③ 再判「这条规则要的基本部署给不出」那一拒:`~/` 形缺 home;配置根那一集缺配置根(两者都落在执行环境的 home 上,同词 `home_unresolvable`)。答 `{ bucket, message, problems }`:`bucket` 与 `message` 是**第一处**坏处的
|
|
482
|
+
* (句子冻结,先撞上的那一条),`problems` 是**两段、两只桶判下来的全部**坏条目(机读位的原料,形的属主 `entry-problems.ts`;`entry` = 规则原文,带层条目也一样)。
|
|
483
|
+
* 入参:桶、{@link RulePolicyBases}。**home 同源**:拒点的 home 是 `resolve-spec.ts` 的 `laneHomeBase()` 经 `executionLaneHomeDir(config)` 算出的,预判传同一个函数对同一份部署配置算出的;配置根同理(`executionConfigRootOf`)。
|
|
484
|
+
* **任务根那一集声明给文法的基**只有拒点有(根 + home 的并集,执行车道才知道根):core 的规则文法对**没声明**的基不下判词(见 `config.ts` `uncompilableRuleGuidance`),所以预判什么也不声明、两腿逐字同句;
|
|
461
485
|
* 预判不能把 home 当「半个基」声明给文法 —— core 的路径族只从根推,缺根时一个合法的 Windows 形 home 会按默认族被判 `unsupported.path_base`(V6-k)。
|
|
462
|
-
*
|
|
486
|
+
* **配置根那一集**两腿都声明 `{ root: 配置根 }`:两腿都算得出它,`{ root }` 自带路径族(没有「半个基」),一个用不了的配置根(转进沙箱的相对值)两腿同为引擎的 `unsupported.path_base`。
|
|
487
|
+
* ③ 排在最后:一条同时文法不成立又缺基的规则,先说文法(补上基它仍被文法拒,先说基是误导)。
|
|
463
488
|
*/
|
|
464
489
|
export interface RulePolicyBases {
|
|
465
|
-
/** 声明给 core
|
|
490
|
+
/** 声明给 core 规则文法的任务根那一集的路径基(这条 task 的根 + home):拒点才有;存体预判不声明。 */
|
|
466
491
|
readonly declared?: PathRuleBases;
|
|
467
492
|
/** 执行环境的 home(`~/` 形规则的前提);这个部署解不出 ⇒ 缺席。 */
|
|
468
493
|
readonly home?: string;
|
|
494
|
+
/** 执行环境的配置根(配置根那一集的根;拒点与预判都给);读不出 ⇒ 缺席。 */
|
|
495
|
+
readonly configRoot?: string;
|
|
469
496
|
}
|
|
470
|
-
export declare function rulePolicyBucketsRefusal(permissions: Readonly<Partial<Record<RulePolicyBucket, readonly
|
|
497
|
+
export declare function rulePolicyBucketsRefusal(permissions: Readonly<Partial<Record<RulePolicyBucket, readonly RuleListEntry[]>>>, bases: RulePolicyBases): {
|
|
471
498
|
readonly bucket: RulePolicyBucket;
|
|
472
499
|
readonly message: string;
|
|
473
500
|
readonly problems: readonly EntryProblem[];
|
package/dist/task-settings.js
CHANGED
|
@@ -2,14 +2,14 @@ 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, createRuleListPolicy } from "./permission-rule-list.js";
|
|
5
|
+
import { MAX_PERMISSION_RULES_PER_LIST, RULE_ROOTS, createRuleListPolicy, ruleListEntryOk, ruleSetsOf, ruleSourceOf, ruleTextOf } from "./permission-rule-list.js";
|
|
6
6
|
import { allowLayerEntryCountIssue, describeAllowLayerOverCap, ruleEntryListShapeOk } 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
12
|
import { heldRuleName } from "./tool-rule-names.js";
|
|
12
|
-
import { entryPermissionMode } from "./runtime-governance.js";
|
|
13
13
|
import { policyAskStandingAnswerFacts, standingAnswerDurablyRecordable } from "./tool-approval.js";
|
|
14
14
|
import { createRequestNeverAutoPolicy } from "./approval.js";
|
|
15
15
|
import { readTightenOnlySeats, tightenOnlySeatField, tightenOnlySpecSeats } from "./tighten-only-seats.js";
|
|
@@ -39,9 +39,8 @@ export function planReviewDecisionExitsPlan(decision) {
|
|
|
39
39
|
return false;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
export function stampEntryPermissionMode(body,
|
|
43
|
-
|
|
44
|
-
return { body: entry.floor === undefined ? body : { ...body, permissionMode: entry.effective }, entry };
|
|
42
|
+
export function stampEntryPermissionMode(body, entry) {
|
|
43
|
+
return entry.floor === undefined ? body : { ...body, permissionMode: entry.effective };
|
|
45
44
|
}
|
|
46
45
|
export function storedBodyPermissionMode(body) {
|
|
47
46
|
return effectivePermissionMode(body, parseTaskSettings(body.settings).settings);
|
|
@@ -54,11 +53,16 @@ export function effectiveThinking(reasoningEffort, ultracode) {
|
|
|
54
53
|
return explicit && rankOf(explicit) > rankOf(ultra) ? explicit : ultra;
|
|
55
54
|
}
|
|
56
55
|
export function effectivePermissionMode(body, settings) {
|
|
57
|
-
|
|
56
|
+
return foldDisableAutoMode(requestedPermissionMode(body, settings), settings);
|
|
57
|
+
}
|
|
58
|
+
export function requestedPermissionMode(body, settings) {
|
|
59
|
+
return coercePermissionMode(body.permissionMode) ?? settings?.permissions?.defaultMode;
|
|
60
|
+
}
|
|
61
|
+
export function foldDisableAutoMode(word, settings) {
|
|
58
62
|
const kill = settings?.permissions?.disableAutoMode;
|
|
59
|
-
if (
|
|
63
|
+
if (word === "auto" && (kill === "disable" || kill === true))
|
|
60
64
|
return "default";
|
|
61
|
-
return
|
|
65
|
+
return word;
|
|
62
66
|
}
|
|
63
67
|
export function skillListingBudgetFractionOk(v) {
|
|
64
68
|
return typeof v === "number" && Number.isFinite(v) && v > 0 && v <= 1;
|
|
@@ -105,12 +109,12 @@ function bucketIssueMessage(f, rule) {
|
|
|
105
109
|
switch (rule) {
|
|
106
110
|
case "rule_policy":
|
|
107
111
|
return f.index === undefined
|
|
108
|
-
? `${f.field} must be an array of non-empty rule
|
|
109
|
-
: `${f.field}[${f.index}] is
|
|
112
|
+
? `${f.field} must be an array of rule entries (a non-empty rule string, or { "rule": <rule>, "layer": <settings source> }) — refused rather than ignored, because an ignored list reads as "in effect" to the caller`
|
|
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`;
|
|
110
114
|
case "allow_layer":
|
|
111
115
|
return f.index === undefined
|
|
112
116
|
? `${f.field} must be an array of permission-rule strings — refused rather than ignored, because an ignored list reads as "in effect" to the caller`
|
|
113
|
-
: `${f.field}[${f.index}] is not a string — every entry must be a permission-rule string. Refused rather than dropped, because a dropped entry reads as "in effect" to the caller`;
|
|
117
|
+
: `${f.field}[${f.index}] is not a string — every entry must be a permission-rule string (a settings layer's { "rule", "layer" } entry is read in deny / ask only). Refused rather than dropped, because a dropped entry reads as "in effect" to the caller`;
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
}
|
|
@@ -132,7 +136,7 @@ export function settingsPermissionBucketIssue(perms) {
|
|
|
132
136
|
if (v.length > MAX_PERMISSION_RULES_PER_LIST)
|
|
133
137
|
fields = { field, reason: "over_cap", count: v.length, cap: MAX_PERMISSION_RULES_PER_LIST };
|
|
134
138
|
else {
|
|
135
|
-
const index = v.findIndex((x) =>
|
|
139
|
+
const index = v.findIndex((x) => !ruleListEntryOk(x));
|
|
136
140
|
if (index >= 0)
|
|
137
141
|
fields = { field, reason: "bad_entry", index };
|
|
138
142
|
}
|
|
@@ -336,8 +340,12 @@ export function createWorkflowAskPolicy(isExempt) {
|
|
|
336
340
|
nameSets: [{ ask: WORKFLOW_ASK_NAMES }],
|
|
337
341
|
};
|
|
338
342
|
}
|
|
339
|
-
function rejectUnmatchableSettingsNames(perms, pathBases) {
|
|
340
|
-
const refused = rulePolicyBucketsRefusal(perms, {
|
|
343
|
+
function rejectUnmatchableSettingsNames(perms, pathBases, configRoot) {
|
|
344
|
+
const refused = rulePolicyBucketsRefusal(perms, {
|
|
345
|
+
...(pathBases !== undefined ? { declared: pathBases } : {}),
|
|
346
|
+
...(pathBases?.home !== undefined ? { home: pathBases.home } : {}),
|
|
347
|
+
...(configRoot !== undefined ? { configRoot } : {}),
|
|
348
|
+
});
|
|
341
349
|
if (refused !== undefined)
|
|
342
350
|
throw new SettingsRuleRefusalError(refused.message, refused.problems);
|
|
343
351
|
}
|
|
@@ -354,21 +362,40 @@ export const RULE_POLICY_BUCKETS = ["ask", "deny"];
|
|
|
354
362
|
export function rulePolicyBucketsRefusal(permissions, bases) {
|
|
355
363
|
let first;
|
|
356
364
|
const problems = [];
|
|
365
|
+
const declaredFor = (root) => {
|
|
366
|
+
switch (root) {
|
|
367
|
+
case "task":
|
|
368
|
+
return bases.declared;
|
|
369
|
+
case "configuration":
|
|
370
|
+
return bases.configRoot !== undefined ? { root: bases.configRoot } : undefined;
|
|
371
|
+
default: {
|
|
372
|
+
const unhandled = root;
|
|
373
|
+
return unhandled;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
};
|
|
357
377
|
for (const bucket of RULE_POLICY_BUCKETS) {
|
|
358
|
-
const
|
|
359
|
-
if (!
|
|
378
|
+
const entries = permissions[bucket];
|
|
379
|
+
if (!entries)
|
|
360
380
|
continue;
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
381
|
+
const sets = ruleSetsOf(entries, bucket);
|
|
382
|
+
for (const root of RULE_ROOTS) {
|
|
383
|
+
const names = sets[root].map(ruleTextOf);
|
|
384
|
+
if (names.length === 0)
|
|
385
|
+
continue;
|
|
386
|
+
const declared = declaredFor(root);
|
|
387
|
+
const judged = judgeUnmatchableToolNames(`permissions.${bucket}`, names, { consumer: "rule-policy", behavior: bucket, ...(declared !== undefined ? { pathBases: declared } : {}) });
|
|
388
|
+
if (judged === undefined)
|
|
389
|
+
continue;
|
|
390
|
+
first ??= { bucket, message: judged.message };
|
|
391
|
+
for (const b of judged.bad)
|
|
392
|
+
problems.push(entryProblem(SETTINGS_RULE_REFUSAL_CODE, `settings.permissions.${bucket}`, b.name, b.reason));
|
|
393
|
+
}
|
|
367
394
|
}
|
|
368
395
|
if (bases.home === undefined) {
|
|
369
396
|
for (const bucket of RULE_POLICY_BUCKETS) {
|
|
370
397
|
const field = `permissions.${bucket}`;
|
|
371
|
-
for (const name of permissions[bucket] ?? []) {
|
|
398
|
+
for (const name of (permissions[bucket] ?? []).map(ruleTextOf)) {
|
|
372
399
|
const parsed = parseRuleText(name, bucket);
|
|
373
400
|
if ("rule" in parsed && ruleToolGrammarOf(parsed.rule.tool) === "path" && parsed.rule.command.startsWith("~/")) {
|
|
374
401
|
first ??= {
|
|
@@ -382,8 +409,36 @@ export function rulePolicyBucketsRefusal(permissions, bases) {
|
|
|
382
409
|
}
|
|
383
410
|
}
|
|
384
411
|
}
|
|
412
|
+
if (bases.configRoot === undefined) {
|
|
413
|
+
for (const bucket of RULE_POLICY_BUCKETS) {
|
|
414
|
+
const field = `permissions.${bucket}`;
|
|
415
|
+
for (const name of ruleSetsOf(permissions[bucket] ?? [], bucket).configuration.map(ruleTextOf)) {
|
|
416
|
+
first ??= {
|
|
417
|
+
bucket,
|
|
418
|
+
message: `${field} has a user-settings path rule rooted at the configuration directory (${name}) but this deployment cannot name the EXECUTION environment's configuration root — ` +
|
|
419
|
+
`it is the SEMA_CONFIG_DIR forwarded into the sandbox, else .sema under the execution environment's home, and this lane's home is unknown; the engine never guesses one. ` +
|
|
420
|
+
`Spell the path absolutely (${"Read(//abs/path/**)"} form), forward SEMA_CONFIG_DIR into the sandbox env, declare the lane's home with REMOTE_EXEC_HOME_DIR, or run the task on a lane whose home this worker knows.`,
|
|
421
|
+
};
|
|
422
|
+
problems.push(entryProblem(SETTINGS_RULE_REFUSAL_CODE, `settings.${field}`, name, "home_unresolvable"));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
385
426
|
return first === undefined ? undefined : { ...first, problems };
|
|
386
427
|
}
|
|
428
|
+
function ruleSetBases(root, taskBases, configRoot) {
|
|
429
|
+
switch (root) {
|
|
430
|
+
case "task":
|
|
431
|
+
return taskBases;
|
|
432
|
+
case "configuration":
|
|
433
|
+
if (configRoot === undefined)
|
|
434
|
+
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");
|
|
435
|
+
return { root: configRoot };
|
|
436
|
+
default: {
|
|
437
|
+
const unhandled = root;
|
|
438
|
+
return unhandled;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
387
442
|
export const REQUEST_SETTINGS_REFUSAL_PREFIX = "request settings cannot be applied as written: ";
|
|
388
443
|
export function deriveSettingsPolicy(settings, bases) {
|
|
389
444
|
const perms = settings.permissions;
|
|
@@ -396,11 +451,19 @@ export function deriveSettingsPolicy(settings, bases) {
|
|
|
396
451
|
const pathBases = bases?.taskRoot !== undefined || bases?.taskHome !== undefined
|
|
397
452
|
? { ...(bases.taskRoot !== undefined ? { root: bases.taskRoot } : {}), ...(bases.taskHome !== undefined ? { home: bases.taskHome } : {}) }
|
|
398
453
|
: undefined;
|
|
399
|
-
rejectUnmatchableSettingsNames(perms, pathBases);
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
454
|
+
rejectUnmatchableSettingsNames(perms, pathBases, bases?.configRoot);
|
|
455
|
+
for (const [bucket, entries] of [["deny", deny], ["ask", ask]]) {
|
|
456
|
+
if (!entries)
|
|
457
|
+
continue;
|
|
458
|
+
const sets = ruleSetsOf(entries, bucket);
|
|
459
|
+
for (const root of RULE_ROOTS) {
|
|
460
|
+
const set = sets[root];
|
|
461
|
+
if (set.length === 0)
|
|
462
|
+
continue;
|
|
463
|
+
const table = RULE_SOURCE_BY_BEHAVIOR[bucket];
|
|
464
|
+
policies.push(createRuleListPolicy(set.map((e) => ({ rule: ruleTextOf(e), source: ruleSourceOf(table, e) })), bucket, table, ruleSetBases(root, pathBases, bases?.configRoot)));
|
|
465
|
+
}
|
|
466
|
+
}
|
|
404
467
|
}
|
|
405
468
|
if (neverAuto !== undefined) {
|
|
406
469
|
const refused = neverAutoNamesRefusal(neverAuto);
|
package/dist/terminal.d.ts
CHANGED
|
@@ -57,13 +57,61 @@ export declare const STORE_ERROR_CODE = "internal.store_error";
|
|
|
57
57
|
*
|
|
58
58
|
* ⚠️ **辖域如实**:本臂触发条件是「码出了本仓的词法」,所以任何依赖铸出的域外码都落这里,不只 SQL 驱动。
|
|
59
59
|
* 今天可观察的产出方**只有**耐久店那一层(引擎自己的传输/brain 错误在 core 侧已被分类成小写码),故码名
|
|
60
|
-
* 取 `internal.store_error`;原码逐字进 message
|
|
60
|
+
* 取 `internal.store_error`;原码逐字进 message 尾注(随结果过汇点脱敏)、是码 token 时进运维 warn 行({@link isCodeToken}),归因从不丢失。
|
|
61
61
|
*/
|
|
62
62
|
export declare function outwardFailureCode(code: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* 一个错误的 `code` 只在它**是**码(短 token)时才说出口 —— 码形座里装着文字的,不是码(驱动码 `ER_*` / SQLSTATE / `ECONNRESET`
|
|
65
|
+
* 全在这一形里;带空白、`=`、换行或超过 64 字符的就是一句话)。读者两只,同一条判据:折码的运维 warn 行(本文件 {@link sealResultForExit})
|
|
66
|
+
* 与执行车道占位读的故障词(`boot/execution-env.ts`)。
|
|
67
|
+
*/
|
|
68
|
+
export declare function isCodeToken(code: unknown): code is string;
|
|
69
|
+
/**
|
|
70
|
+
* 存量结果被**再观看**的读座(闭集):`GET /v1/runs/:id → result`(终态行与停驻行同一座)与账本 `done` 行的回放(三条耐久读腿共用)。
|
|
71
|
+
* 封口在读座上折码时,运维行按 (读座, 原码) 只报一次 —— 见 {@link sealResultForExit}。
|
|
72
|
+
*/
|
|
73
|
+
export type StoredResultReadSeat = "run.result" | "ev.done.result";
|
|
74
|
+
/**
|
|
75
|
+
* **一次耐久停驻在一条结果上够得着的全部座** —— 本仓**唯一**一张座表。两个属主共读它,不各抄一份:
|
|
76
|
+
* · 出口封口 {@link sealResultForExit} 按它**摘凭据**(`token` 键);
|
|
77
|
+
* · 结果汇点 `observability/run-terminal.ts` 的 `redactTerminalResult` 按它**脱门**(`gate` 键,门上有模型 / 人可控的展示文本)。
|
|
78
|
+
*
|
|
79
|
+
* 每座 = 从结果根出发的路径 + 该座上的凭据键名与门键名(引擎在两种形上给同一件事起了两套名字:因由形 `token` / `gate`,
|
|
80
|
+
* 验证器停驻形 `checkpointToken` / `checkpointGate`)。三座是**类型的形状**,不是三个特判:
|
|
81
|
+
* · `terminal` —— 本腿自己 park(`paused` 臂);
|
|
82
|
+
* · `terminal.nestedPause` —— 嵌套边界(verify / cascade)遇到自己驱动不了的耐久暂停,在它的边界上如实报 `failed`,
|
|
83
|
+
* 把那次暂停整只带在这里(正是这条路径当年让凭据漏进过账本);
|
|
84
|
+
* · `verification.verifierPause` —— 验证门里**验证器自己**的停驻(core `VerificationOutcome.verifierPause`,
|
|
85
|
+
* `unverifiedReason: "verifier_paused"`):在结果因由**之外**,宿主判官看不见它,run 照常终局。
|
|
86
|
+
*
|
|
87
|
+
* 表是否完整**不靠记性**:`trace/core-keyset-guard.ts` ⑩f 从 core 的结果类型(普通腿 / verify / cascade 三种出口结果)
|
|
88
|
+
* **派生**出每一条凭据型路径与门型路径,与本表逐条对账 —— core 在结果的任何一层加一个凭据座或门座 ⇒ tsc 当场红。
|
|
89
|
+
*/
|
|
90
|
+
export declare const PAUSE_SEATS: readonly [{
|
|
91
|
+
readonly path: readonly ["terminal"];
|
|
92
|
+
readonly token: "token";
|
|
93
|
+
readonly gate: "gate";
|
|
94
|
+
}, {
|
|
95
|
+
readonly path: readonly ["terminal", "nestedPause"];
|
|
96
|
+
readonly token: "token";
|
|
97
|
+
readonly gate: "gate";
|
|
98
|
+
}, {
|
|
99
|
+
readonly path: readonly ["verification", "verifierPause"];
|
|
100
|
+
readonly token: "checkpointToken";
|
|
101
|
+
readonly gate: "checkpointGate";
|
|
102
|
+
}];
|
|
103
|
+
/** 座表的一行(类型门 ⑩f 从它派生「本仓摘 / 脱的路径」)。 */
|
|
104
|
+
export type PauseSeat = (typeof PAUSE_SEATS)[number];
|
|
105
|
+
type SeatObject = Readonly<Record<string, unknown>>;
|
|
106
|
+
/**
|
|
107
|
+
* 对一条结果上**每一座**施一次 `f`,不动的座保持同一引用(一座都没动 ⇒ 整条结果同一引用)。
|
|
108
|
+
* 对任何输入安全:路径上任一层缺席 / 非普通对象(含数组)⇒ 那一座跳过,不抛、不重塑(读盘面纪律:旧持久 blob / 非 core 的 Runner 实现)。
|
|
109
|
+
*/
|
|
110
|
+
export declare function mapPauseSeats<T>(result: T, f: (seat: SeatObject, keys: PauseSeat) => SeatObject): T;
|
|
63
111
|
/**
|
|
64
112
|
* **一条结果离开引擎、进入本仓(可重放账本 / run 行 / wire)的唯一封口** —— 两件事,一个出口:
|
|
65
|
-
* ①摘掉**耐久恢复能力凭据**(`CheckpointToken`)
|
|
66
|
-
* ({@link outwardFailureCode},[ref])。
|
|
113
|
+
* ①摘掉**耐久恢复能力凭据**(`CheckpointToken`)—— 座表 {@link PAUSE_SEATS} 上的每一座;②把**域外的失败码**折成本仓的
|
|
114
|
+
* `internal.store_error`({@link outwardFailureCode},[ref])。
|
|
67
115
|
*
|
|
68
116
|
* 🔴 为什么两件事合在一只函数里而不是并列两只(7.92.2 改名 `stripResumeToken` → `sealResultForExit`):
|
|
69
117
|
* 它们是**同一个出口上的同一件事** —— 「这条结果可以见人了吗」。并列两只 = 六个结算点各自要记得调两次,
|
|
@@ -71,26 +119,33 @@ export declare function outwardFailureCode(code: string): string;
|
|
|
71
119
|
* 旧名只说了摘凭据那一半,一个只做一半的名字会让下一个人在另一半上另开出口。
|
|
72
120
|
*
|
|
73
121
|
* ── ① 摘凭据 ──
|
|
74
|
-
* token 就是 resume 凭据(token-as-auth,search [18] Q1b)
|
|
75
|
-
* `
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* 在**它的**边界上如实报 `failed`,而把那次暂停的因由整只带在这里(顶层调用方据此仍能恢复)。
|
|
82
|
-
* 正是这条路径当年让 `checkpointToken` 漏进过账本 —— 摘除腿从来不是「理论上的对称」。
|
|
83
|
-
* 两处走**同一条**摘除规则({@link stripPausedToken}),不是两条。
|
|
84
|
-
*
|
|
85
|
-
* wire 上的形:paused 因由**缺席 `token`**(core 类型里它是必填座,那是**引擎内**的契约;本服务的 wire
|
|
86
|
-
* 契约逐字声明这一座不出服务边界 —— 见 `docs/ASSISTANT-WIRE-CONTRACT.md`)。消费端要动这次暂停,走
|
|
122
|
+
* token 就是 resume 凭据(token-as-auth,search [18] Q1b),**永不离开本服务**;非密的门 / `checkpointId` /
|
|
123
|
+
* `restoreMode` / 验证器停驻的 `status` 与 `sessionId` 有意保留(对账位;门的自由文本由结果汇点脱)。
|
|
124
|
+
* 凭据住在哪几座是 {@link PAUSE_SEATS} 一张表的事,本函数**不**在别处另开摘除臂:漏掉的那一座(验证器停驻,修前)
|
|
125
|
+
* 正是「座表只写了两座」造成的,修法是座表加一行,不是另起第二处摘字。
|
|
126
|
+
*
|
|
127
|
+
* wire 上的形:每一座**缺席**凭据键(core 类型里因由的 `token` 是必填座,那是**引擎内**的契约;本服务的 wire
|
|
128
|
+
* 契约逐字声明这一座不出服务边界 —— 见 `docs/ASSISTANT-WIRE-CONTRACT.md`)。消费端要动一次停驻,走
|
|
87
129
|
* `/v1/approvals` 决策端点,凭 `checkpointId` 对账,从来不是拿 token 直连引擎。
|
|
88
130
|
*
|
|
89
|
-
*
|
|
131
|
+
* **出口全集都经这一口**:三家 run 店的行写口与账本店的 `done` 行写口在店入口调它(`observability/run-terminal.ts`),
|
|
132
|
+
* 同步 200 体 / 流 done 帧 / 续跑决定腿在铸体处调它,`GET /v1/runs/:id{,/events}` 等读面在回放前再调一次 ——
|
|
133
|
+
* 升级前落盘、还带着凭据的存量行在读面上同样摘掉。两件事都**幂等**,重复过口是同形。
|
|
134
|
+
*
|
|
135
|
+
* ── 折码的运维线索:一行定形句,两个观看点同一句 ──
|
|
136
|
+
* `[terminal] outward_failure_code_folded original=<码 | <not-a-code>> outward=<对外词> messageBytes=<n> at=<exit | 读座>`。
|
|
137
|
+
* 字段只有闭集词、数字与码 token({@link isCodeToken}):失败句只报字节数,**永不**报原文 —— 失败句是自由文本(驱动句里可以有连接串 / 口令),
|
|
138
|
+
* 结果里的那份由结果汇点脱敏,日志行没有汇点,所以日志行压根不带它;码形座里装着文字的同理只报 `<not-a-code>`。`at` 说这是哪一次观看:
|
|
139
|
+
* · 省略 `readSeat` = 结果**第一次**离开引擎(店的写口 / 出口铸体)⇒ 每折一次报一次 —— 每次都是一件新的失败;
|
|
140
|
+
* · 给出读座({@link StoredResultReadSeat})= 存量行的**再观看** ⇒ 同一读座同一原码(按它在行上的样子)只报一次,表有界(先进先出)——
|
|
141
|
+
* 读面每次轮询 / 每个观看者 / 每次重连都重放同一批行,逐读逐报会把一次旧失败放大成读次那么多行,而它们说的是同一件事。
|
|
142
|
+
* 折**本身**照旧逐读做(wire 上永远是对外词),去重的只是日志行。
|
|
143
|
+
*
|
|
144
|
+
* 对任何输入安全(非普通对象 / 无可摘的座 / 码在词法内 ⇒ **同一引用**原样返回,不重塑)。
|
|
90
145
|
*/
|
|
91
146
|
export declare function sealResultForExit<T extends {
|
|
92
|
-
terminal
|
|
93
|
-
}>(result: T): T;
|
|
147
|
+
readonly terminal?: unknown;
|
|
148
|
+
}>(result: T, readSeat?: StoredResultReadSeat): T;
|
|
94
149
|
/**
|
|
95
150
|
* **投影出口的唯一属主**([ref])—— core 的 `terminalProjection` + 对外码归一,一次。
|
|
96
151
|
*
|
|
@@ -146,7 +201,8 @@ export declare function pausedCauseOf(terminal: TerminalCause): PausedCause | un
|
|
|
146
201
|
*
|
|
147
202
|
* 前提:结果出自 core 的组合器(可信产者)—— `failed.nestedPause` 只由引擎的嵌套边界包停驻铸,`paused` 只在卡行写入确认之后返回。
|
|
148
203
|
* 判官**不**验证那张卡在不在、是不是这一张、此刻什么态;会话相等不是对卡的校验。验证器**自己**的停驻
|
|
149
|
-
* (`verification.verifierPause`)不在结果因由里,本函数看不见它 ——
|
|
204
|
+
* (`verification.verifierPause`)不在结果因由里,本函数看不见它 —— 那一形照常终局;它那张卡本服务兑现不了,由结算点当场作废
|
|
205
|
+
* (`verifier-pause-card.ts`),凭据由封口按座表摘。
|
|
150
206
|
*
|
|
151
207
|
* 纯函数,不读店、不抛。凭据随提升上来,摘除仍归 {@link sealResultForExit}(调用方照旧先 graft 后封口)。
|
|
152
208
|
* 判官只答「该不该停驻」;认领保不保得住是停驻写口**写成功**与否的事(行写口对 `running` / `suspended` 行 CAS)。
|
|
@@ -178,4 +234,5 @@ export declare function persistedPlaneOf(result: unknown): {
|
|
|
178
234
|
errorMessage?: string;
|
|
179
235
|
blockedReason?: string;
|
|
180
236
|
};
|
|
237
|
+
export {};
|
|
181
238
|
//# sourceMappingURL=terminal.d.ts.map
|