@sema-agent/server 7.122.0 → 7.124.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 +209 -0
- package/README.md +7 -2
- package/README.zh-CN.md +5 -2
- package/USAGE.md +76 -56
- package/dist/approval-ask-audit-store.d.ts +27 -32
- package/dist/approval-ask-audit-store.js +10 -9
- package/dist/approval-crash-convergence.d.ts +2 -2
- package/dist/approval-crash-convergence.js +5 -5
- package/dist/approval-deny-reasons.d.ts +163 -51
- package/dist/approval-deny-reasons.js +79 -8
- package/dist/approval-policy-settlement.d.ts +4 -1
- package/dist/approval-policy-settlement.js +3 -2
- package/dist/approval-reconciler.d.ts +3 -3
- package/dist/approval-reconciler.js +10 -10
- package/dist/approval.d.ts +1 -1
- package/dist/approval.js +1 -1
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +53 -23
- package/dist/auth-bridge.d.ts +8 -8
- package/dist/auth-bridge.js +6 -6
- package/dist/auth-keys.d.ts +2 -2
- package/dist/auto-mode-face.d.ts +13 -9
- package/dist/auto-mode-face.js +8 -7
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/execution-env.js +1 -0
- package/dist/boot/leader.d.ts +1 -1
- package/dist/boot/memory-consolidation.d.ts +4 -4
- package/dist/boot/org-memory.d.ts +3 -3
- package/dist/boot/org-memory.js +5 -5
- package/dist/boot/resolve-spec.js +7 -7
- package/dist/boot/runner-deps.d.ts +1 -1
- package/dist/boot/runtime-caps.d.ts +1 -1
- package/dist/boot/runtime-caps.js +10 -10
- package/dist/boot/shutdown.d.ts +2 -2
- package/dist/boot/shutdown.js +2 -2
- package/dist/boot/side-query-lane.d.ts +3 -3
- package/dist/boot/{stage-02-registry-pull.d.ts → stage-02-web-admin-pull.d.ts} +2 -2
- package/dist/boot/{stage-02-registry-pull.js → stage-02-web-admin-pull.js} +4 -4
- package/dist/boot/stage-03-store-backend.d.ts +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +6 -6
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +6 -5
- package/dist/boot/stage-08-reapers.d.ts +3 -3
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +3 -3
- package/dist/boot/stage-09-leader.js +7 -7
- package/dist/boot/stage-10-http-server.d.ts +3 -3
- package/dist/boot/stage-10-http-server.js +19 -19
- package/dist/boot/unpriced-ceiling-verdict.d.ts +1 -1
- package/dist/boot/{config-center.d.ts → web-admin.d.ts} +11 -11
- package/dist/boot/{config-center.js → web-admin.js} +39 -20
- package/dist/boot/webfetch-summarize-lane.d.ts +2 -2
- package/dist/brain.d.ts +1 -1
- package/dist/brain.js +1 -1
- package/dist/budget.d.ts +3 -3
- package/dist/canonical-json.d.ts +2 -2
- package/dist/capabilities/center-plugins.d.ts +1 -1
- package/dist/capabilities/center-wiring.d.ts +12 -5
- package/dist/capabilities/center-wiring.js +11 -2
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capabilities/team.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/center-credential-renewer.d.ts +1 -1
- package/dist/center-credential-renewer.js +7 -7
- package/dist/center-credential.d.ts +9 -9
- package/dist/center-credential.js +6 -6
- package/dist/config-catalog.d.ts +7 -10
- package/dist/config-catalog.js +16 -16
- package/dist/config-d-migration.d.ts +32 -0
- package/dist/config-d-migration.js +59 -0
- package/dist/config-invariants.d.ts +14 -4
- package/dist/config-invariants.js +31 -2
- package/dist/config-lkg.d.ts +34 -11
- package/dist/config-lkg.js +76 -48
- package/dist/config-provider.d.ts +26 -21
- package/dist/config-provider.js +25 -27
- package/dist/config-types.d.ts +59 -50
- package/dist/config.d.ts +17 -54
- package/dist/config.js +99 -181
- package/dist/execution-lane-caps.d.ts +1 -1
- package/dist/fleet/drain-entry.d.ts +1 -1
- package/dist/fleet/engine-signal.d.ts +61 -30
- package/dist/fleet/engine-signal.js +29 -5
- package/dist/fleet/fleet-bus.d.ts +12 -3
- package/dist/fleet/fleet-bus.js +13 -9
- package/dist/fleet/serving-lease.d.ts +3 -3
- package/dist/fleet/serving-lease.js +1 -1
- package/dist/fleet-client.d.ts +15 -13
- package/dist/fleet-client.js +9 -7
- package/dist/fleet-lease.d.ts +3 -3
- package/dist/fleet-lease.js +2 -2
- package/dist/host-lsp-manager.d.ts +1 -1
- package/dist/hosted-posture.d.ts +4 -4
- package/dist/http/admission.js +4 -4
- package/dist/http/checkpoint-ctx.d.ts +20 -3
- package/dist/http/checkpoint-ctx.js +13 -5
- package/dist/http/dispatch.js +7 -16
- package/dist/http/durable-run-leg.js +2 -1
- package/dist/http/health-self-report.d.ts +7 -4
- package/dist/http/health-self-report.js +3 -3
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +31 -18
- package/dist/http/route-ctx.d.ts +8 -0
- package/dist/http/routes/admin-config-refresh.d.ts +1 -1
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.d.ts +1 -1
- package/dist/http/routes/admin-drain.js +5 -4
- package/dist/http/routes/approvals-assistant.js +4 -4
- package/dist/http/routes/capabilities.js +6 -5
- package/dist/http/routes/config-catalog.js +2 -3
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/runs.js +8 -4
- package/dist/http/routes/sessions-list.js +2 -1
- package/dist/http/routes/sessions.js +2 -5
- package/dist/http/routes/side-query.js +3 -3
- package/dist/http/routes/tasks.js +3 -2
- package/dist/http/run-meta.d.ts +1 -1
- package/dist/http/run-meta.js +2 -2
- package/dist/http/server.d.ts +7 -7
- package/dist/http/server.js +1 -1
- package/dist/http/stored-body-replay.d.ts +4 -3
- package/dist/http/stored-body-replay.js +5 -5
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/key-resolver.d.ts +1 -1
- package/dist/leader/leader.d.ts +7 -6
- package/dist/leader/leader.js +3 -1
- package/dist/leader/run-entry.d.ts +2 -2
- package/dist/leader/run-entry.js +3 -3
- package/dist/leader/wire.d.ts +4 -4
- package/dist/leader/wire.js +2 -1
- package/dist/main.js +1 -1
- package/dist/mcp-tool-faces.d.ts +2 -2
- package/dist/model-entry-refusal.d.ts +20 -11
- package/dist/model-entry-refusal.js +22 -17
- package/dist/model-provider.d.ts +2 -2
- package/dist/model-route-endpoint.d.ts +22 -2
- package/dist/model-route-endpoint.js +9 -3
- package/dist/model-route-gap.d.ts +103 -0
- package/dist/model-route-gap.js +80 -0
- package/dist/model-route-url.d.ts +1 -1
- package/dist/model-route-url.js +2 -1
- package/dist/model-select.d.ts +24 -21
- package/dist/model-select.js +22 -17
- package/dist/namespaced-rule-name.d.ts +16 -30
- package/dist/namespaced-rule-name.js +2 -20
- package/dist/observability/fail-open.d.ts +0 -4
- package/dist/observability/fail-open.js +0 -4
- package/dist/observability/metrics.d.ts +1 -1
- package/dist/org-memory-admission.d.ts +1 -1
- package/dist/plugins/approval-ask-store-file.d.ts +4 -2
- package/dist/plugins/approval-ask-store-file.js +3 -3
- package/dist/plugins/approval-ask-store-memory.d.ts +4 -3
- package/dist/plugins/approval-ask-store-memory.js +10 -4
- package/dist/plugins/approval-ask-store-sql.d.ts +16 -2
- package/dist/plugins/approval-ask-store-sql.js +20 -13
- package/dist/plugins/caching-session-store.d.ts +0 -10
- package/dist/plugins/caching-session-store.js +0 -3
- package/dist/plugins/file-run-store.js +9 -3
- package/dist/plugins/leader-run-store-sql.d.ts +3 -2
- package/dist/plugins/leader-run-store-sql.js +3 -2
- package/dist/plugins/local-session-store.d.ts +20 -27
- package/dist/plugins/local-session-store.js +19 -17
- package/dist/plugins/memory-run-store.js +9 -3
- package/dist/plugins/one-time-migrations.js +51 -0
- package/dist/plugins/scheduler-support.d.ts +26 -7
- package/dist/plugins/scheduler-support.js +96 -53
- package/dist/plugins/session-policy-store-sql.js +1 -2
- package/dist/plugins/store-backend.js +1 -1
- package/dist/plugins/store-contracts.d.ts +20 -4
- package/dist/plugins/web-search.d.ts +1 -1
- package/dist/plugins/web-search.js +2 -1
- package/dist/plugins/workflow-run-store-sql.d.ts +4 -2
- package/dist/posture-source.d.ts +1 -1
- package/dist/read-face-posture.d.ts +3 -3
- package/dist/read-face-posture.js +1 -1
- package/dist/rule-entry-list.d.ts +3 -13
- package/dist/rule-entry-list.js +1 -12
- package/dist/run-local.js +10 -7
- package/dist/runtime-caps-resolver.d.ts +4 -4
- package/dist/runtime-caps-resolver.js +2 -2
- package/dist/runtime-governance.d.ts +36 -13
- package/dist/runtime-governance.js +7 -2
- package/dist/sealed-key.d.ts +4 -4
- package/dist/sealed-key.js +3 -2
- package/dist/security.d.ts +3 -3
- package/dist/service-version.d.ts +1 -1
- package/dist/service-version.js +5 -0
- package/dist/session-policy-wire.d.ts +47 -49
- package/dist/session-policy-wire.js +41 -36
- package/dist/session-sync.d.ts +5 -1
- package/dist/session-sync.js +2 -1
- package/dist/session-titler.d.ts +0 -11
- package/dist/session-titler.js +3 -5
- package/dist/shared-memory-scope-authorizer.d.ts +4 -4
- package/dist/spec-fields.d.ts +4 -4
- package/dist/spec-fields.js +1 -4
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-settings.d.ts +4 -5
- package/dist/task-settings.js +5 -8
- package/dist/tool-approval.d.ts +43 -4
- package/dist/tool-approval.js +147 -98
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/project.d.ts +3 -3
- package/dist/trace/redact.d.ts +2 -23
- package/dist/trace/redact.js +1 -6
- package/dist/trace/self-minted-wire.d.ts +147 -3
- package/dist/trace/self-minted-wire.js +50 -9
- package/dist/unattended-permission-mode.d.ts +3 -3
- package/dist/unattended-permission-mode.js +2 -2
- package/dist/url-refusal.d.ts +35 -0
- package/dist/url-refusal.js +15 -0
- package/dist/user-authored-text.d.ts +31 -0
- package/dist/user-authored-text.js +18 -0
- package/dist/{config-center → web-admin-client}/apply-effective.d.ts +13 -70
- package/dist/{config-center → web-admin-client}/apply-effective.js +104 -121
- package/dist/{config-center → web-admin-client}/apply-ledger.d.ts +2 -2
- package/dist/{config-center → web-admin-client}/center-request.d.ts +7 -7
- package/dist/{config-center → web-admin-client}/center-request.js +5 -4
- package/dist/{config-center → web-admin-client}/effective-keys.d.ts +1 -3
- package/dist/{config-center → web-admin-client}/effective-keys.js +0 -9
- package/dist/{config-center → web-admin-client}/facade.d.ts +6 -6
- package/dist/{config-center → web-admin-client}/facade.js +2 -2
- package/dist/{config-center → web-admin-client}/http-client.d.ts +6 -10
- package/dist/{config-center → web-admin-client}/http-client.js +15 -15
- package/dist/{config-center → web-admin-client}/pull-state.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/read-face.js +4 -4
- package/dist/web-admin-client/read-warnings.d.ts +137 -0
- package/dist/web-admin-client/read-warnings.js +168 -0
- package/dist/{config-center → web-admin-client}/restart-signal.d.ts +5 -3
- package/dist/{config-center → web-admin-client}/restart-signal.js +3 -4
- package/dist/{config-center → web-admin-client}/skills-mcp.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/skills-mcp.js +13 -13
- package/dist/{config-center → web-admin-client}/stage-limits.d.ts +1 -7
- package/dist/{config-center → web-admin-client}/stage-limits.js +6 -7
- package/dist/{config-center → web-admin-client}/types.d.ts +19 -47
- package/package.json +3 -3
- package/skills/find-skills.md +2 -2
- package/dist/config-center/read-warnings.d.ts +0 -109
- package/dist/config-center/read-warnings.js +0 -110
- package/dist/url-shape.d.ts +0 -31
- package/dist/url-shape.js +0 -41
- /package/dist/{config-center → web-admin-client}/apply-ledger.js +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.js +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.js +0 -0
- /package/dist/{config-center → web-admin-client}/pull-state.js +0 -0
- /package/dist/{config-center → web-admin-client}/read-face.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/types.js +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { validateHeaderValue } from "node:http";
|
|
2
2
|
import { createSearxngSearchBackend } from "@sema-agent/core";
|
|
3
|
-
import { isHierarchicalUrl
|
|
3
|
+
import { isHierarchicalUrl } from "@sema-agent/settings-schema";
|
|
4
|
+
import { redactSecrets } from "../trace/redact.js";
|
|
4
5
|
export const WEB_SEARCH_PROVIDERS = ["brave", "tavily", "searxng"];
|
|
5
6
|
function isWebSearchProvider(word) {
|
|
6
7
|
return WEB_SEARCH_PROVIDERS.includes(word);
|
|
@@ -68,8 +68,10 @@ type WorkflowRun = Parameters<WorkflowRunStore["put"]>[1];
|
|
|
68
68
|
export declare const MAX_RUN_BLOB_BYTES: number;
|
|
69
69
|
declare const onWarnType: (msg: string, meta: Record<string, unknown>) => void;
|
|
70
70
|
export type InboxWarn = typeof onWarnType;
|
|
71
|
-
/** S-107:workflow_run 行的 `error`(脚本抛出的 `err.message
|
|
72
|
-
* 同一口脱;`result` 由 core 完成时源头脱。幂等,不抛(超大 ⇒ 占位)。
|
|
71
|
+
/** S-107:workflow_run 行的 `error`(脚本抛出的 `err.message`)在**两条写腿**(put / update 常态 + oversize 降级)
|
|
72
|
+
* 同一口脱;`result` 由 core 完成时源头脱。幂等,不抛(超大 ⇒ 占位)。
|
|
73
|
+
* core 7.48.0 起 `error` 在铸点也过 core 的 `redactSecrets`,但两张脱敏表互不为超集(本仓的表多认几种记号,core 的表多认另几种)⇒ 这一口暂留;
|
|
74
|
+
* 退役条件 = core 的脱敏表成为两表的并集(本仓的每一种记号它都认)—— 到那时这一口与它的两条调用一起删。 */
|
|
73
75
|
export declare function withRedactedError<T extends {
|
|
74
76
|
error?: string | undefined;
|
|
75
77
|
}>(run: T): T;
|
package/dist/posture-source.d.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* 得到一句谁都不认的空话,或者更坏:一句**对某些键是假的**话。
|
|
20
20
|
*
|
|
21
21
|
* 🔴 `centerMeaning` 是 G-7(test [ref])的修复面,成因是一次真的过期断言:这一臂原本硬编码
|
|
22
|
-
* 「applied from the
|
|
22
|
+
* 「applied from the web-admin (**restart-to-apply**)」,而 S-174(core 7.10.0 [ref])之后
|
|
23
23
|
* `readFace.face` 是**热换席**(`Runner.swapDeps({readFace})`,下一拍 refresh 当场换进全部 Runner,
|
|
24
24
|
* `read-face` 重启片也不再为它签理由)——运维照那句话去滚动重启一片 fleet,重启的是一个已经生效的变更。
|
|
25
25
|
* 生效时机是**键**的事实,不是四词表的属性,所以它跟 `postureMeaning` 一样归键。
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
*
|
|
12
12
|
* 于是本模块把「档位」与「档位是谁定的」拆成两个字段:值仍是 `open | roots | 缺席`,来源是本文件的
|
|
13
13
|
* **四词闭集**。来源不是装饰:
|
|
14
|
-
* ① `
|
|
14
|
+
* ① `web-admin-client/read-face.ts` 的 **env 恒赢**判据此前用的是「`config.readFace` 键在不在场」这个
|
|
15
15
|
* **代理**;posture 会铸键,代理当场失真(center 的 face 会被一台从没设过 env 的机器挡掉)。
|
|
16
16
|
* 换成读来源之后判据说的就是它真正想说的那件事:**这台机器的 env 显式占住了这个键吗**。
|
|
17
17
|
* ② 运维面:`GET /v1/diagnostics/wiring` 报 `{face, source, note}`,「为什么这台机器是 open」有答案
|
|
18
18
|
* (裁定的补偿项:升级即放开,得让运维看得见并知道怎么钉回)。
|
|
19
19
|
*
|
|
20
20
|
* ## 优先序(三态,与 `config.ts` 的 `postureOn` 同形)
|
|
21
|
-
* `env 显式` > `center 发布` > `posture 派生` > `引擎默认`。env 恒赢的论证逐字见 `
|
|
21
|
+
* `env 显式` > `center 发布` > `posture 派生` > `引擎默认`。env 恒赢的论证逐字见 `web-admin-client/read-face.ts`
|
|
22
22
|
* 头注①(READ 容纳面描述的是**这台机器的磁盘上有什么**,组织的下发面不知道)。
|
|
23
23
|
*
|
|
24
24
|
* ## 定界
|
|
@@ -54,7 +54,7 @@ export declare function readFaceForPosture(singleUserTurnkey: boolean): ReadFace
|
|
|
54
54
|
*
|
|
55
55
|
* 🔴 `center` 那句话的事实来源是 S-174(core 7.10.0 [ref]):`RunnerDeps.readFace` 进了 core 的可换席
|
|
56
56
|
* 闭集 `SWAPPABLE_DEP_SEATS` ⇒ 组织发布/撤回一个档位,**下一拍 refresh 当场换进全部 Runner**,
|
|
57
|
-
* `
|
|
57
|
+
* `web-admin-client/restart-signal.ts` 的 `read-face` 片也不再为它签重启理由(判据同源 =
|
|
58
58
|
* `CENTER_READ_FACE_LIVE_KEYS`,由 core 的 `isSwappableDepSeat` 派生)。本句此前逐字写着
|
|
59
59
|
* 「(restart-to-apply)」—— G-7 抓获的那条过期断言,方向恰好是「让运维为一个已生效的变更重启 fleet」。
|
|
60
60
|
* ⚠️ 只说 `face` 这一席:三个 deny 键仍是 boot-baked,那半场的话不在这条读面上(它们没有来源位)。 */
|
|
@@ -7,7 +7,7 @@ export function readFaceSourceNote(source) {
|
|
|
7
7
|
return postureSourceNote({
|
|
8
8
|
knob: "READ_FACE",
|
|
9
9
|
source,
|
|
10
|
-
centerMeaning: "published by the
|
|
10
|
+
centerMeaning: "published by the web-admin and applied HOT — the containment FACE is a swappable engine seat (core 7.10.0), so the next refresh (or POST /v1/admin/config/refresh) swaps it into every Runner with NO restart; set READ_FACE on this machine to take the key back",
|
|
11
11
|
postureMeaning: "derived from the single-user turnkey posture (REQUIRE_PRINCIPAL is not set): reads outside the workspace roots are allowed by default — set READ_FACE=roots to pin the containing posture back",
|
|
12
12
|
});
|
|
13
13
|
}
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
* ① **形**({@link ruleEntryListShapeOk}):字符串数组。引擎逐条迭代;一个裸字符串会被逐字符读成几条(deny 侧 = 意图静默落空)。
|
|
10
10
|
* 本谓词不带条数帽(引擎的 `screenAllowedToolsValue` 只判形);条数帽是另一只函数 {@link allowLayerEntryCountIssue}(`MAX_ALLOW_LAYER_ENTRIES`,
|
|
11
11
|
* 请求 allow 桶、技能两只清单、运维表四张表同一只、同一句)。
|
|
12
|
-
* ②
|
|
13
|
-
*
|
|
12
|
+
* ② (7.116.0–7.122.x 的「引擎读不到的一形」—— 工具段为空的协议名 `mcp__srv__` 四张表都拒 —— 随 core 7.48.0 #1400 退役:引擎判官给它判词
|
|
13
|
+
* `unmintable_segment`,条目由下面 ③ 读成 `tool_name`,与对端段铸不出的名字同一条路。)
|
|
14
14
|
* ③ **引擎读成空的条目**({@link inertRuleEntriesOf},判据 = 引擎包根 `compileAllowList(entries, behavior, 名册)`,名册 = 空集 `NO_DECLARED_TOOL_NAMES`
|
|
15
|
-
* —— 条目的工具名也过引擎判官:退役名 / 无前缀短名 /
|
|
15
|
+
* —— 条目的工具名也过引擎判官:退役名 / 无前缀短名 / 对端段或工具段铸不出、为空读成 `tool_name`,带判词与 1:1 现名;原因词是引擎的 `ALLOW_ENTRY_INERT_REASONS`):
|
|
16
16
|
* 运维的 allow 表拒启(运维自己的配置,写错了当场改);技能的拒侧(`disallowedTools`)拒 —— 提交 400、存量体重放 409(下面的 {@link skillDenyInertEntryOf});
|
|
17
17
|
* 请求的 allow 侧(`settings.permissions.allow`、技能 `allowedTools`)不拒:引擎在开跑时发 `permission.allowed_tool_not_granted`(受众 = 用户)。
|
|
18
18
|
* 技能拒侧那一拒与引擎 #1372(core 7.43.0:那只技能不激活)是同一件事的两处 —— 7.118.0 重估过、本版**不退**:本仓的续跑腿把引擎的
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
* (重估读数与退役条件在下面那只函数头注)。
|
|
21
21
|
*/
|
|
22
22
|
import { compileAllowList } from "@sema-agent/core";
|
|
23
|
-
import { emptyToolSegmentOf } from "./namespaced-rule-name.js";
|
|
24
23
|
/** ① 形:字符串数组(空串也是字符串 —— 引擎把它读成 `grammar` 并通告 / 拒,见 ③)。 */
|
|
25
24
|
export declare const ruleEntryListShapeOk: (v: unknown) => v is readonly string[];
|
|
26
25
|
/**
|
|
@@ -42,15 +41,6 @@ export declare function allowLayerEntryCountIssue(field: string, list: readonly
|
|
|
42
41
|
readonly count: number;
|
|
43
42
|
readonly cap: number;
|
|
44
43
|
} | undefined;
|
|
45
|
-
/** 一张表里第一条「引擎读不到、却永远匹配不到」的条目(工具段为空的协议名)。 */
|
|
46
|
-
export interface EmptyToolSegmentEntry {
|
|
47
|
-
readonly entry: string;
|
|
48
|
-
readonly ns: NonNullable<ReturnType<typeof emptyToolSegmentOf>>;
|
|
49
|
-
}
|
|
50
|
-
/** ② 第一条工具段为空的协议名条目(没有 ⇒ `undefined`)。纯字符串运算。 */
|
|
51
|
-
export declare function emptyToolSegmentEntryOf(list: readonly string[]): EmptyToolSegmentEntry | undefined;
|
|
52
|
-
/** ② 的句子(`<field> names "<entry>", which can never match a tool (…)`;后半与配置表 / 会话规则写口同一只)。 */
|
|
53
|
-
export declare function describeEmptyToolSegmentEntry(field: string, u: EmptyToolSegmentEntry): string;
|
|
54
44
|
/** 一条引擎读成空的条目(引擎的形:原因词,名字层另带判词 / 1:1 现名;包根不导出这只具名型 ⇒ 从 `compileAllowList` 的返回型取,不手抄)。 */
|
|
55
45
|
export type InertRuleEntry = ReturnType<typeof compileAllowList>["inert"][number];
|
|
56
46
|
/** ③ 引擎按 `behavior` 读这张表时读成空的条目(引擎的整表读法:allow 表里的 `*` 让整表读成空;deny 表里的 `*` 只读空它自己);条目名过引擎判官(名册 = 空集)。 */
|
package/dist/rule-entry-list.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { compileAllowList } from "@sema-agent/core";
|
|
2
2
|
import { displayListEntry } from "./list-entry-display.js";
|
|
3
|
-
import {
|
|
3
|
+
import { NO_DECLARED_TOOL_NAMES } from "./namespaced-rule-name.js";
|
|
4
4
|
export const ruleEntryListShapeOk = (v) => Array.isArray(v) && v.every((x) => typeof x === "string");
|
|
5
5
|
export const MAX_ALLOW_LAYER_ENTRIES = 1_000;
|
|
6
6
|
export function describeAllowLayerOverCap(field, count) {
|
|
@@ -12,17 +12,6 @@ export function allowLayerEntryCountIssue(field, list) {
|
|
|
12
12
|
return undefined;
|
|
13
13
|
return { message: describeAllowLayerOverCap(field, list.length), count: list.length, cap: MAX_ALLOW_LAYER_ENTRIES };
|
|
14
14
|
}
|
|
15
|
-
export function emptyToolSegmentEntryOf(list) {
|
|
16
|
-
for (const entry of list) {
|
|
17
|
-
const ns = emptyToolSegmentOf(ruleEntryToolName(entry));
|
|
18
|
-
if (ns !== undefined)
|
|
19
|
-
return { entry, ns };
|
|
20
|
-
}
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
export function describeEmptyToolSegmentEntry(field, u) {
|
|
24
|
-
return `${field} names ${displayListEntry(u.entry)}, which can never match a tool (${describeEmptyToolSegment(u.ns)})`;
|
|
25
|
-
}
|
|
26
15
|
export function inertRuleEntriesOf(list, behavior) {
|
|
27
16
|
return compileAllowList(list, behavior, NO_DECLARED_TOOL_NAMES).inert;
|
|
28
17
|
}
|
package/dist/run-local.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { DEFAULT_MODEL_REF, resolveTaskModel } from "./model-select.js";
|
|
2
|
+
import { DEFAULT_AT_MENTION, DEFAULT_MODEL_REF, resolveTaskModel } from "./model-select.js";
|
|
3
3
|
import { defaultModelRefusal, modelUnavailableMessage } from "./model-entry-refusal.js";
|
|
4
4
|
import { createDurableAbsenceSeat } from "./observability/corrupt-read-seat.js";
|
|
5
5
|
import { outwardPlane } from "./terminal.js";
|
|
@@ -14,7 +14,7 @@ import { withUnattendedLeg } from "./unattended-permission-mode.js";
|
|
|
14
14
|
import { buildUnattendedPolicyRefusal } from "./tool-approval.js";
|
|
15
15
|
import { createBrain } from "./brain.js";
|
|
16
16
|
import { assertGuardPatternsUsable, buildOnlySensitiveBaselineWarning, buildApprovalGrantNotice, createApprovalBaselinePolicy, createDeploymentGovernanceInputs, } from "./deployment-governance.js";
|
|
17
|
-
import { applyRuntimeGovernance, autonomyModeFloor } from "./runtime-governance.js";
|
|
17
|
+
import { applyRuntimeGovernance, autonomyModeFloor, entryPermissionMode } from "./runtime-governance.js";
|
|
18
18
|
import { ForkRoutingSessionStore } from "./plugins/fork-routing-session-store.js";
|
|
19
19
|
import { taskWallClockSec } from "./task-workflow.js";
|
|
20
20
|
import { applyCatalogToSource } from "./capabilities/center-prompts.js";
|
|
@@ -25,7 +25,8 @@ import { acquireLocalBackendWithWait } from "./plugins/store-lock-wait.js";
|
|
|
25
25
|
import { configLocalRoot, configProviderKind, createConfigProvider } from "./config-provider.js";
|
|
26
26
|
import { composeExecutionLane } from "./boot/execution-lane.js";
|
|
27
27
|
import { judgeConsolidationValve } from "./boot/memory-consolidation.js";
|
|
28
|
-
import {
|
|
28
|
+
import { logConfigDirMigration, migrateLocalConfigDirectory } from "./config-d-migration.js";
|
|
29
|
+
import { applyEffective, applyCenterReadFace, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./web-admin-client/facade.js";
|
|
29
30
|
import { hostExecutionEnvFactory } from "./plugins/remote-env-host.js";
|
|
30
31
|
import { executionLaneHomeDir, executionLaneOf } from "./execution-lane-caps.js";
|
|
31
32
|
import { makeLoadProjectMemory, makeProbeInstructionSources } from "./project-memory.js";
|
|
@@ -337,6 +338,8 @@ export async function runLocal(argv, deps = {}) {
|
|
|
337
338
|
return 2;
|
|
338
339
|
}
|
|
339
340
|
const configProvider = createConfigProvider(providerInput);
|
|
341
|
+
if (configProvider.kind === "local")
|
|
342
|
+
logConfigDirMigration(logger, await migrateLocalConfigDirectory(root));
|
|
340
343
|
let effective;
|
|
341
344
|
try {
|
|
342
345
|
const r = await configProvider.fetchEffective(undefined);
|
|
@@ -344,7 +347,7 @@ export async function runLocal(argv, deps = {}) {
|
|
|
344
347
|
for (const de of r.domainErrors ?? [])
|
|
345
348
|
logger.warn("config_domain_invalid", { domain: de.domain, error: de.error, note: "domain fell to schema defaults; other domains applied normally" });
|
|
346
349
|
for (const d of r.droppedEntries ?? [])
|
|
347
|
-
logger.warn("config_entry_dropped", { domain: d.domain, entry: d.entry, error: d.error, version: r.effective.version, phase: "boot", note: "this one entry failed its domain schema and was dropped on its own — the rest of the candidate applies (per-entry tolerance); fix the named entry to bring it back" });
|
|
350
|
+
logger.warn("config_entry_dropped", { domain: d.domain, entry: d.entry, reasonCode: d.reasonCode, error: d.error, version: r.effective.version, phase: "boot", note: "this one entry failed its domain schema and was dropped on its own — the rest of the candidate applies (per-entry tolerance); fix the named entry to bring it back" });
|
|
348
351
|
effective = r.effective;
|
|
349
352
|
applyEffective(config, r.effective, logger, { leg: "boot" });
|
|
350
353
|
if (effective?.mcp)
|
|
@@ -613,7 +616,7 @@ export async function runLocal(argv, deps = {}) {
|
|
|
613
616
|
}
|
|
614
617
|
throw err;
|
|
615
618
|
}
|
|
616
|
-
const mention = resolveTaskModel(undefined, args.objective, config.models,
|
|
619
|
+
const mention = resolveTaskModel(undefined, args.objective, config.models, DEFAULT_AT_MENTION, config.modelRefusals);
|
|
617
620
|
if (mention.unavailable !== undefined) {
|
|
618
621
|
const { requested, name, refusal } = mention.unavailable;
|
|
619
622
|
printErr(`cannot run: ${modelUnavailableMessage("@-mention", requested, name, refusal)}`);
|
|
@@ -633,9 +636,9 @@ export async function runLocal(argv, deps = {}) {
|
|
|
633
636
|
...(maxCostUsd !== undefined ? { maxCostUsd } : {}),
|
|
634
637
|
...(maxTokens !== undefined ? { maxTokens } : {}),
|
|
635
638
|
};
|
|
636
|
-
const
|
|
639
|
+
const entryWord = entryPermissionMode(undefined, autonomyModeFloor(config.autonomy)).effective;
|
|
637
640
|
const spec = withUnattendedLeg(applyLocalGovernance({
|
|
638
|
-
...(
|
|
641
|
+
...(entryWord !== undefined ? { permissionMode: entryWord } : {}),
|
|
639
642
|
objective: mention.cleanedObjective,
|
|
640
643
|
sessionId,
|
|
641
644
|
backgroundScope: "session",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
*/
|
|
66
66
|
import type { RuntimeCaps } from "@sema-agent/core";
|
|
67
67
|
import type { EntitlementRuntimeCaps } from "@sema-agent/settings-schema";
|
|
68
|
-
import { fetchPrincipalCaps, type ExecutionRuling } from "./
|
|
69
|
-
import type { CenterEndpoint } from "./
|
|
68
|
+
import { fetchPrincipalCaps, type ExecutionRuling } from "./web-admin-client/facade.js";
|
|
69
|
+
import type { CenterEndpoint } from "./web-admin-client/center-request.js";
|
|
70
70
|
import type { ScenarioRuling } from "./capabilities/scenarios.js";
|
|
71
71
|
import type { ServiceConfig } from "./config-types.js";
|
|
72
72
|
import { type Logger } from "./observability/logger.js";
|
|
@@ -75,7 +75,7 @@ export declare function resetExecutionLaneDefaultTraceForTest(): void;
|
|
|
75
75
|
export interface EntitlementsResolverOpts {
|
|
76
76
|
/** S-651:中心端点(基址 + 凭证**来源**;每次抓取取一次值,不持有启动快照)。 */
|
|
77
77
|
center: CenterEndpoint;
|
|
78
|
-
/** This worker's name (`
|
|
78
|
+
/** This worker's name (`SEMA_WEB_ADMIN_WORKER`), passed as `?worker=` so a worker-scoped `wpt_<self>` token can
|
|
79
79
|
* resolve its OWN worker's principal caps (caps-only); harmless on a full token (the caps value
|
|
80
80
|
* is worker-independent). Omitted ⇒ no `?worker=` (a full-token, non-fleet deployment). */
|
|
81
81
|
worker?: string;
|
|
@@ -135,7 +135,7 @@ export declare function toCoreRuntimeCaps(ent: EntitlementRuntimeCaps | null | u
|
|
|
135
135
|
* (`RuntimeCaps.autoMode` 三态逐 principal 解,[ref] 起「缺席=不阻」),任何部署级布尔都对它说不了话——
|
|
136
136
|
* 所以本谓词为 false **不再**意味着 auto 不武装;「会不会武装」由 `auto-mode-face.ts` 的三项合取答。
|
|
137
137
|
*/
|
|
138
|
-
export declare function centerEntitlementSourceWired(config: Pick<ServiceConfig, "
|
|
138
|
+
export declare function centerEntitlementSourceWired(config: Pick<ServiceConfig, "webAdmin">): boolean;
|
|
139
139
|
/** The two per-principal faces served off ONE caps fetch + cache. */
|
|
140
140
|
export interface PrincipalEntitlementsClient {
|
|
141
141
|
/** core's `RunnerDeps.runtimeCapsResolver` seam — FAIL-CLOSED on error (deny workflows/fork/autoMode;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchPrincipalCaps } from "./
|
|
1
|
+
import { fetchPrincipalCaps } from "./web-admin-client/facade.js";
|
|
2
2
|
import { createIdentityBins } from "./center-credential.js";
|
|
3
3
|
import { HttpError } from "./security.js";
|
|
4
4
|
import { createLogger } from "./observability/logger.js";
|
|
@@ -53,7 +53,7 @@ export function toCoreRuntimeCaps(ent) {
|
|
|
53
53
|
return Object.keys(caps).length ? caps : undefined;
|
|
54
54
|
}
|
|
55
55
|
export function centerEntitlementSourceWired(config) {
|
|
56
|
-
return config.
|
|
56
|
+
return config.webAdmin !== undefined && !config.webAdmin.dryRun;
|
|
57
57
|
}
|
|
58
58
|
export function gateExecutionLane(ruling, ownLane, logger = defaultLogger) {
|
|
59
59
|
if (!ruling) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Runtime governance compiler — the "second baton" (center §10, core 1.114.0): turn the
|
|
3
|
-
* operator's declarative `
|
|
4
|
-
* carried to the service
|
|
3
|
+
* operator's declarative `governance.autonomy` + `governance.commandPolicy` (`@sema-agent/settings-schema`,
|
|
4
|
+
* carried to the service in the effective config's `governance` domain) into TIGHTEN-ONLY overrides on the
|
|
5
5
|
* per-task `TaskSpec`. Pure so it is unit-testable in isolation (the spec is otherwise assembled inside
|
|
6
6
|
* main.ts's `resolveSpec`).
|
|
7
7
|
*
|
|
@@ -28,7 +28,7 @@ import { GovernanceConfig } from "@sema-agent/settings-schema";
|
|
|
28
28
|
import { type GovernanceAskMarks } from "./governance-ask-marks.js";
|
|
29
29
|
import { type GovernanceOverrides } from "./governance-overrides.js";
|
|
30
30
|
/** 运维 autonomy 四档的**闭集**(同上)。`config.ts` 的 `parseAutonomy` 也从这里读 —— 四档词表全仓一份。 */
|
|
31
|
-
export declare const AUTONOMY_MODES:
|
|
31
|
+
export declare const AUTONOMY_MODES: ("plan" | "auto" | "ask" | "read-only")[];
|
|
32
32
|
/** A per-command governance rule (registry `runtime.commandPolicy[]`) —— **型也从契约派生**:
|
|
33
33
|
* 契约给 `command` 加一条 refine / 给 `decision` 加一个判词,本仓的型当场跟上(或在下面的
|
|
34
34
|
* `RANK` / 穷尽 switch 上编译红),而不是靠人记得把手写联合改一遍。 */
|
|
@@ -39,7 +39,7 @@ export type Autonomy = NonNullable<GovernanceConfig["autonomy"]>;
|
|
|
39
39
|
export declare const COARSE_SHELL_TOOLS_MIRROR: readonly string[];
|
|
40
40
|
/** Validate `commandPolicy` rules — the shape (array of {command, decision}), the `command` (a bare argv[0] name,
|
|
41
41
|
* see {@link VALID_COMMAND_NAME}), AND the `decision` enum. Returns the list of human-readable errors (empty =
|
|
42
|
-
* OK). Called at config-apply (
|
|
42
|
+
* OK). Called at config-apply (web-admin-client/facade.ts `applyRuntimeHot`) so a malformed rule that BYPASSED the
|
|
43
43
|
* registry schema (a hand-edited config.d / a non-conformant publish) is rejected LOUDLY rather than
|
|
44
44
|
* silently mis-compiling — review MEDIUM: an out-of-enum `decision` (e.g. "DENY") would otherwise fall through
|
|
45
45
|
* {@link compileCommandPolicyLayers}'s `decision==="deny"?…:"ask"` to ASK, silently WEAKENING an intended deny. */
|
|
@@ -90,7 +90,7 @@ export declare function compileCommandPolicyLayers(rules: CommandRule[] | undefi
|
|
|
90
90
|
*
|
|
91
91
|
* 🔴 **规则:按段重折的只有静态围栏,模式词不在这里。** 只读手 + roots、shell 地板没有出口 —— 每一段续跑都该在,所以每一段都折。
|
|
92
92
|
* `plan` 是有出口的**生命周期词**(`plan_review` 把计划带出 plan),不是围栏:它是**提交入口的模式词地板**({@link autonomyModeFloor}),
|
|
93
|
-
* 盖在每一个 spec
|
|
93
|
+
* 盖在每一个 spec 出生点一次(词 = {@link entryPermissionMode} 的 `effective`):受理门盖进存储的提交体(`task-settings.ts` `stampEntryPermissionMode`)、run-local 盖在它自建的 spec 上、
|
|
94
94
|
* leader run 盖在它出生时的入口体上(`leader/run-entry.ts`;入口词是 `plan` 的 leader run 进不了那条车道 —— worker 会话没有计划审阅通道 ⇒ 受理口响亮拒)。此后一条 run 的模式词
|
|
95
95
|
* 只有存储体一个源,写者是每一个出生点(新的持久化写都经 `http/checkpoint-ctx.ts` `buildCheckpointCtx`)与 `plan_review` 写回。按段折一个模式词 = 第二个源:被批准的计划会在下一次挂起→续跑
|
|
96
96
|
* 被拉回 plan。收紧入参的型上因此没有 `permissionMode`(`governance-overrides.ts`)。(上一个发布版本里本档不碰模式词,按段折的是只读手 +
|
|
@@ -118,18 +118,41 @@ export declare function autonomyOverrides(autonomy: Autonomy | undefined): Gover
|
|
|
118
118
|
/**
|
|
119
119
|
* 运维 autonomy 给**提交入口**的模式词地板 —— 唯一属主(规则全文见 {@link autonomyOverrides} 顶注)。`plan` ⇒ `"plan"`:每个新提交的 run
|
|
120
120
|
* 以 plan 起步,请求的词按 core 的模式秩钳到它之下;其余三档与缺席 ⇒ 无地板(它们的表态全在按段的围栏里)。
|
|
121
|
-
*
|
|
122
|
-
* leader run 的入口体(`leader/run-entry.ts` `leaderRunEntry`,同一只盖章;leader 的 HTTP 受理口用它判「这条车道收不收」);能力面的两位 ——
|
|
123
|
-
* `taskWriteFaceOpen` 的治理半({@link autonomyKeepsOpenWriteFace})与 `permissionModeAuto.armed` 的意图(`auto-mode-face.ts`),两位都经 core
|
|
124
|
-
* `clampPermissionMode` 读「地板把请求词钳成什么」,与盖章同一只钳;存量停驻体能否重放的第三问(`http/stored-body-replay.ts`:没有当前读法记号的行,
|
|
125
|
-
* 体的生效词被此刻的地板钳会变 ⇒ 拒)。
|
|
121
|
+
* 「一个词在这块地板下变成什么」只有一只函数答:{@link entryPermissionMode}(读者全表在它的头注)。
|
|
126
122
|
* 闭集**穷尽** switch:契约给 autonomy 加一档 ⇒ 这里编译红([ref])。
|
|
127
123
|
*/
|
|
128
124
|
export declare function autonomyModeFloor(autonomy: Autonomy | undefined): PermissionMode | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* 一个模式词进入一块地板之后的**读数** —— {@link entryPermissionMode} 的答。四键:调用方声明的词(`requested`,缺席 = 没声明)、地板(`floor`,
|
|
127
|
+
* 缺席 = 这里没有地板)、生效词(`effective`)与「地板改了调用方的词」(`clamped`,core 的同名位:只在声明了词、且那个词被折回地板时为真 ——
|
|
128
|
+
* 没声明词而取地板本身不算改词)。
|
|
129
|
+
*/
|
|
130
|
+
export interface EntryPermissionMode<W extends PermissionMode | undefined = PermissionMode | undefined> {
|
|
131
|
+
readonly requested: W;
|
|
132
|
+
readonly floor: PermissionMode | undefined;
|
|
133
|
+
readonly effective: W | PermissionMode;
|
|
134
|
+
readonly clamped: boolean;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 「请求词 `word` 在地板 `floor` 下变成什么」—— **唯一**的一只函数(本仓对 core `clampPermissionMode` 的唯一调用点;秩只在 core 一处)。
|
|
138
|
+
*
|
|
139
|
+
* 规则:地板缺席 ⇒ 词原样、`clamped:false`;地板在场 ⇒ core `clampPermissionMode(word, floor)` 的答(词缺席 ⇒ 地板本身;比地板松的词 ⇒ 折回地板、`clamped:true`)。
|
|
140
|
+
* 本仓「地板」即 core 的天花板(`plan` 秩最低:比它松的词都折成它)。
|
|
141
|
+
*
|
|
142
|
+
* 读者(都调这一只,不另写「缺席原样否则钳」):
|
|
143
|
+
* · spec 出生点写 `effective` —— 受理门(`task-settings.ts` `stampEntryPermissionMode` 盖进存储体)、run-local 自建的 spec、
|
|
144
|
+
* leader run 的入口词(`leader/run-entry.ts` `leaderRunEntry`)、leader 车道合并口(`leader/leader.ts` `withLeaderLeg`:spec 的词钳在入口词之下)、
|
|
145
|
+
* 无人值守腿(`unattended-permission-mode.ts` `withUnattendedLeg`:`default` 钳在 spec 的词之下);
|
|
146
|
+
* · 「这个词会变成什么」的读者 —— 能力面写面开不开({@link autonomyKeepsOpenWriteFace}:bypass 声明过地板)、能力面 auto 读面
|
|
147
|
+
* (`auto-mode-face.ts` `judgeAutoModeArming`:意图过地板;`clamped` 且不是 auto ⇒ 未武装原因 `operator_floor`)、
|
|
148
|
+
* 存量停驻体能否按此刻的地板重放(`http/stored-body-replay.ts`:体的词经钳会变 ⇒ 拒)。
|
|
149
|
+
* `test/entry-permission-mode.test.ts` 按语法树钉:core 钳在 `src/` 只此一处调用,上面八处各调本函数一次。
|
|
150
|
+
*/
|
|
151
|
+
export declare function entryPermissionMode<W extends PermissionMode | undefined>(word: W, floor: PermissionMode | undefined): EntryPermissionMode<W>;
|
|
129
152
|
/**
|
|
130
153
|
* 运维 autonomy 留不留得住请求层「掀开写围栏」那条声明(`permissionMode:"bypassPermissions"`,引擎模式表那一列 `writeFace:"open"`)——
|
|
131
|
-
* 能力面 `taskWriteFaceOpen` 的治理那一半。判据读**两只属主本身**,与一条真提交走的路同序:bypass 声明先过入口地板(
|
|
132
|
-
*
|
|
154
|
+
* 能力面 `taskWriteFaceOpen` 的治理那一半。判据读**两只属主本身**,与一条真提交走的路同序:bypass 声明先过入口地板({@link entryPermissionMode},
|
|
155
|
+
* 与受理门的盖章同一只函数),再交给本档的按段围栏(`tightenGoverned` → core `tightenTaskSpec`),
|
|
133
156
|
* 看折出来的 spec 还开不开写面 —— 显式席 `"roots"` 胜过模式列(`read-only`),入口词被钳成别的词时读那个词的模式列(`plan`)。
|
|
134
157
|
* 本仓不另写一张「哪几档钳写面」的表:档位怎么钳 / 怎么折由两只属主说,写面开不开由引擎的模式表说。
|
|
135
158
|
*/
|
|
@@ -153,7 +176,7 @@ export declare function autonomyKeepsOpenWriteFace(autonomy: Autonomy | undefine
|
|
|
153
176
|
* 是 always」。`commandPolicy` 不入判据:它产的是 `toolPolicy` 的 ask,不抬 shellGate 档,与本格无关。
|
|
154
177
|
*
|
|
155
178
|
* ⚠️ **已知残留(codex 交叉复审 2026-08-11 逮到,如实登记而不是掩盖)**:本判据读的是**当下**的
|
|
156
|
-
* config,而 `config.autonomy` 是**热改**的(`
|
|
179
|
+
* config,而 `config.autonomy` 是**热改**的(`web-admin-client/apply-effective.ts` 就地写 `config.autonomy`)。
|
|
157
180
|
* 于是失真是**双向**的,不是我原先写的「只往缺席方向」:
|
|
158
181
|
* · 缺席向(常见):mint 之后运维把 `AUTONOMY=ask` 撤了 ⇒ 老 park 行归不出治理出身,少标一个;
|
|
159
182
|
* · **在场向**(窄):一条**纯 SUP 路由**产的门(`ROUTER_ENABLED` 开 ∧ 路由判 supervisor ∧ 当时治理层
|
|
@@ -121,9 +121,14 @@ export function autonomyModeFloor(autonomy) {
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
|
+
export function entryPermissionMode(word, floor) {
|
|
125
|
+
if (floor === undefined)
|
|
126
|
+
return { requested: word, floor, effective: word, clamped: false };
|
|
127
|
+
const { effective, clamped } = clampPermissionMode(word, floor);
|
|
128
|
+
return { requested: word, floor, effective, clamped };
|
|
129
|
+
}
|
|
124
130
|
export function autonomyKeepsOpenWriteFace(autonomy) {
|
|
125
|
-
const
|
|
126
|
-
const entry = floor === undefined ? "bypassPermissions" : clampPermissionMode("bypassPermissions", floor).effective;
|
|
131
|
+
const entry = entryPermissionMode("bypassPermissions", autonomyModeFloor(autonomy)).effective;
|
|
127
132
|
const folded = tightenGoverned({ objective: "", permissionMode: entry }, autonomyOverrides(autonomy));
|
|
128
133
|
return folded.writeFace !== "roots" && folded.permissionMode !== undefined && modePolicyOf(folded.permissionMode).writeFace === "open";
|
|
129
134
|
}
|
package/dist/sealed-key.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Logger } from "./observability/logger.js";
|
|
|
2
2
|
/** Algorithm tag — MUST equal registry-core's `SEALED_BOX_ALG` (v1 sole value; a different alg on
|
|
3
3
|
* the wire is a loud per-model rejection in applyEffective, never a guess). */
|
|
4
4
|
export declare const SEALED_KEY_ALG = "libsodium-sealedbox-x25519";
|
|
5
|
-
/** The subset applyEffective needs (keeps
|
|
5
|
+
/** The subset applyEffective needs (keeps web-admin decoupled from fs/boot concerns). */
|
|
6
6
|
export interface SealedKeyOpener {
|
|
7
7
|
has(publicKeyId: string): boolean;
|
|
8
8
|
/** All private-key ids this host holds (surfaces in the no-private-key warn for operator triage). */
|
|
@@ -62,17 +62,17 @@ export declare function deriveKeyId(publicKeyRaw: Uint8Array): string;
|
|
|
62
62
|
*/
|
|
63
63
|
export declare function ensureSealedKeyStore(dir: string, logger?: Logger): Promise<SealedKeyStore>;
|
|
64
64
|
/**
|
|
65
|
-
* Best-effort public-key registration with the
|
|
65
|
+
* Best-effort public-key registration with the web-admin (`POST /api/config/execution-keys`).
|
|
66
66
|
*
|
|
67
67
|
* HONESTY over fake automation: that endpoint is ADMIN-gated, and a fleet worker only holds
|
|
68
68
|
* SERVICE_PULL_TOKEN — so automatic registration works ONLY when the operator deliberately provides
|
|
69
|
-
* an admin token (
|
|
69
|
+
* an admin token (SEMA_WEB_ADMIN_ADMIN_TOKEN in this service's env; its older names are settings-schema tombstones). Without
|
|
70
70
|
* one we do the next-best REAL thing: print the FULL public key + id at boot (a public key is not a
|
|
71
71
|
* secret) with the exact registration instructions, and warn that the web "paste key" face stays
|
|
72
72
|
* dark for this host until an admin registers it. Never throws (fire-and-forget from boot).
|
|
73
73
|
*/
|
|
74
74
|
export declare function reportExecutionPublicKey(opts: {
|
|
75
|
-
/**
|
|
75
|
+
/** web-admin base URL (config.webAdmin.baseUrl). Absent = no center → manual print only. */
|
|
76
76
|
baseUrl?: string;
|
|
77
77
|
/** Admin bearer for the center's config write face. Absent = manual print (see above). */
|
|
78
78
|
adminToken?: string;
|
package/dist/sealed-key.js
CHANGED
|
@@ -4,7 +4,8 @@ import { join } from "node:path";
|
|
|
4
4
|
import _sodium from "libsodium-wrappers";
|
|
5
5
|
import { buildDisplaySafeUrl } from "./trace/redact.js";
|
|
6
6
|
import { createCenterCredentialSource } from "./center-credential.js";
|
|
7
|
-
import { centerFetch } from "./
|
|
7
|
+
import { centerFetch } from "./web-admin-client/center-request.js";
|
|
8
|
+
import { WEB_ADMIN_ENV } from "@sema-agent/settings-schema";
|
|
8
9
|
export const SEALED_KEY_ALG = "libsodium-sealedbox-x25519";
|
|
9
10
|
const SEAL_OVERHEAD_BYTES = 48;
|
|
10
11
|
const BASE64_STRICT = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
@@ -101,7 +102,7 @@ export async function reportExecutionPublicKey(opts) {
|
|
|
101
102
|
});
|
|
102
103
|
};
|
|
103
104
|
if (!baseUrl || !adminToken) {
|
|
104
|
-
manual(!baseUrl ?
|
|
105
|
+
manual(!baseUrl ? `no web-admin configured (${WEB_ADMIN_ENV.url} unset)` : `no admin token (${WEB_ADMIN_ENV.adminToken} unset; the worker's pull token cannot write execution keys)`);
|
|
105
106
|
return;
|
|
106
107
|
}
|
|
107
108
|
try {
|
package/dist/security.d.ts
CHANGED
|
@@ -17,9 +17,9 @@ export interface SessionListItem {
|
|
|
17
17
|
/** K-5c (shell §K): the latest run's task_id — the shell's one-hop live-tail re-attach anchor on resume. */
|
|
18
18
|
lastRunId: string | null;
|
|
19
19
|
/** [ref]([ref]/[ref]):the LATEST run's **engine run id**(`TaskResult.runId`)when known —— OMIT-when-absent,
|
|
20
|
-
* 恒不铸 null
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* 恒不铸 null。所有 lister(SQL 双生、local 会话店 —— 它的 run 店是必填位)从 latest run 的 `result` JSON 提取(终局与 park 时写、认领续跑即清空 —— S-173
|
|
21
|
+
* ⇒ 在跑 latest 键诚实缺席)。
|
|
22
|
+
* 读法一致:缺席 = 「此行无已知 engine runId」,禁读成其它含义。⚠️ 与 `lastRunId`(= latest run 的 **task_id**)
|
|
23
23
|
* 是两条身份轴,命名对齐 core `SessionStoreSummary.lastTaskRunId`。wire:additive 键零投影透传
|
|
24
24
|
* (sessions-list.ts);sema-sdk spec `SessionSummary` 闭集候 SDK 半场开键([ref]/.82 班车)。 */
|
|
25
25
|
lastTaskRunId?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Service version for GET /v1/capabilities — read from the package.json shipped next to src/ in the
|
|
2
|
-
* image (Dockerfile COPYs it). Best-effort: an unreadable file reports "unknown", never crashes boot. */
|
|
2
|
+
* image (Dockerfile COPYs it), once per process. Best-effort: an unreadable file reports "unknown", never crashes boot. */
|
|
3
3
|
declare function serviceVersion(): string;
|
|
4
4
|
export { serviceVersion };
|
|
5
5
|
//# sourceMappingURL=service-version.d.ts.map
|
package/dist/service-version.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
+
let cachedServiceVersion;
|
|
2
3
|
function serviceVersion() {
|
|
4
|
+
cachedServiceVersion ??= readServiceVersion();
|
|
5
|
+
return cachedServiceVersion;
|
|
6
|
+
}
|
|
7
|
+
function readServiceVersion() {
|
|
3
8
|
try {
|
|
4
9
|
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
5
10
|
return pkg.version ?? "unknown";
|
|
@@ -29,13 +29,14 @@
|
|
|
29
29
|
* 里同点同调它;准备阶段的名审计与本仓配置表读的是同一只 `judgeRuleToolName`)—— 本仓手写的那一只(`legacyToolNameOf`)删除,零双读;
|
|
30
30
|
* 「哪几桶装工具名」归 core(它的 `HOLDS_TOOL_NAMES`)。
|
|
31
31
|
*
|
|
32
|
-
* ── 7.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
32
|
+
* ── 7.123.0(core 7.48.0):两问都只剩引擎的判 ──────────────────────────────────────────────────────────────────────
|
|
33
|
+
* ① **桶**能不能写:core 7.48.0 #1471 起 `normalizeRules` 对「不是一列非空字符串」的桶抛 `TypeError`(裸字符串、`null`、混入非字符串、`""` /
|
|
34
|
+
* 纯空白项),句子点名桶与值类型。写口读者逐桶问它({@link engineRuleListOf})⇒ 两条写口是唯一拒点(`400 request.field_invalid`,句子原样),
|
|
35
|
+
* 店里的 `normalizeRules` 对这两条写口的输入不再可能抛。修前本仓的形读者只判「字符串数组」,`[""]` / `[" "]` 过它、在店里抛 ⇒ 500。
|
|
36
|
+
* 本仓自己的「字符串数组」判只留在**读回**({@link readSessionPermissionRules}:SQL 店读出的行,读不出形 ⇒ `corrupt`)—— 读回与写口是两个问题,
|
|
37
|
+
* 读回不许判「引擎还肯不肯写」:7.47.x 及以前写下的空串项存量行必须读得出来(运营方清它、准备阶段照常执行它都要先读到它)。
|
|
38
|
+
* ② **名字**够不够得着工具:core 7.48.0 #1400 起工具段为空的协议名(`mcp__srv__`)也是引擎判官的判词 `unmintable_segment` ⇒ 本仓 7.116.0 起
|
|
39
|
+
* 自答的那一问(「引擎判官放行、却一只工具都够不着」)整只退役,写口拒码随之由 `request.field_invalid` 变 `rules.legacy_tool_name`。
|
|
39
40
|
*
|
|
40
41
|
* ── 文案也在这里(codex 一轮追加:两条腿各铸一份句子 = 第二份手抄)───────────────────────────────
|
|
41
42
|
* 初版把 wire 文案留在两个路由各自铸,理由是错误文案冻结门(`test/api-error-text-freeze.test.ts`)锚的是
|
|
@@ -46,24 +47,9 @@
|
|
|
46
47
|
*/
|
|
47
48
|
import { SessionPolicyError } from "@sema-agent/core";
|
|
48
49
|
import type { SessionPermissionRules, SessionRuleNameRefusal, SessionRulesRecord } from "@sema-agent/core";
|
|
49
|
-
import { emptyToolSegmentOf } from "./namespaced-rule-name.js";
|
|
50
50
|
/** core `SessionPermissionRules` 的桶名全集(派生,不是手抄)。 */
|
|
51
51
|
export declare const SESSION_PERMISSION_RULE_FIELDS: readonly (keyof SessionPermissionRules)[];
|
|
52
|
-
/**
|
|
53
|
-
export interface SessionRuleUnreachableName {
|
|
54
|
-
readonly field: SessionRuleNameRefusal["field"];
|
|
55
|
-
readonly name: string;
|
|
56
|
-
readonly ns: NonNullable<ReturnType<typeof emptyToolSegmentOf>>;
|
|
57
|
-
}
|
|
58
|
-
/** 逐桶逐条问引擎读不到的那一形;第一条交回,全部够得着 ⇒ `undefined`。调用方先过引擎判官({@link legacyToolNameRefusalOf} / `assertSessionRuleNamesCurrent`)。 */
|
|
59
|
-
export declare function unreachableSessionRuleNameOf(rules: SessionPermissionRules): SessionRuleUnreachableName | undefined;
|
|
60
|
-
/**
|
|
61
|
-
* SQL 会话规则店写口的同一问(core 判官之后、收紧门之前,与 `assertSessionRuleNamesCurrent` 同点):够不着 ⇒ 抛,一条写语句都不发。
|
|
62
|
-
* 抛的是普通 `Error`(不是 `SessionPolicyError`:core 那张闭集里没有这个词,也不往里塞)—— 本服务的两条 HTTP 写口在读者那一层先拒,
|
|
63
|
-
* 走到这里 = 有一个绕过写口读者的写者,HTTP 上落 500(服务端自身的失误,响亮)。
|
|
64
|
-
*/
|
|
65
|
-
export declare function assertSessionRuleNamesReachable(rules: SessionPermissionRules): void;
|
|
66
|
-
/** 一条规则体的**形**问题。判词而非文案(见文件头注的「文案属主」一段)。 */
|
|
52
|
+
/** **读回**的形问题(SQL 店读出的行;判词而非文案,见文件头注的「文案属主」一段)。 */
|
|
67
53
|
export type SessionPermissionRulesShapeProblem =
|
|
68
54
|
/** 整体不是一只普通对象(`null` / 数组 / 标量 / 缺席)。 */
|
|
69
55
|
{
|
|
@@ -74,18 +60,23 @@ export type SessionPermissionRulesShapeProblem =
|
|
|
74
60
|
kind: "field-not-string-array";
|
|
75
61
|
field: keyof SessionPermissionRules;
|
|
76
62
|
};
|
|
77
|
-
/** 一条**要写进店**的规则体的问题
|
|
78
|
-
export type
|
|
79
|
-
|
|
63
|
+
/** 一条**要写进店**的规则体的问题 —— 三问都只有一个判官:容器形(本仓)、桶(引擎 `normalizeRules`)、名字(引擎 `assertSessionRuleNamesCurrent`)。 */
|
|
64
|
+
export type SessionPermissionRulesWriteProblem = {
|
|
65
|
+
kind: "not-an-object";
|
|
66
|
+
}
|
|
67
|
+
/** 引擎不肯把这一桶写成规则表(core 7.48.0 #1471);`refusal` = 引擎的句子(点名桶与值类型),原样上 wire。 */
|
|
80
68
|
| {
|
|
81
|
-
kind: "
|
|
82
|
-
|
|
69
|
+
kind: "field-not-rule-list";
|
|
70
|
+
field: keyof SessionPermissionRules;
|
|
71
|
+
refusal: string;
|
|
83
72
|
}
|
|
84
|
-
/**
|
|
73
|
+
/** S-800 / S-1047:桶形对,但工具名桶里有一条引擎判官判非现役的名字;`refusal` = core 判官交回的 detail(原样上 wire)。 */
|
|
85
74
|
| {
|
|
86
|
-
kind: "
|
|
87
|
-
|
|
75
|
+
kind: "legacy-tool-name";
|
|
76
|
+
refusal: SessionRuleNameRefusal;
|
|
88
77
|
};
|
|
78
|
+
/** 两只读者的判词并集(句子铸点 {@link describeSessionPermissionRulesProblem} 读它)。 */
|
|
79
|
+
export type SessionPermissionRulesProblem = SessionPermissionRulesShapeProblem | SessionPermissionRulesWriteProblem;
|
|
89
80
|
/** 两只读者的读数:有问题给判词,没问题给**已收窄**的规则体(调用方零 cast)。`P` = 这只读者会给的判词集。 */
|
|
90
81
|
export type SessionPermissionRulesRead<P extends SessionPermissionRulesProblem = SessionPermissionRulesProblem> = {
|
|
91
82
|
problem: P;
|
|
@@ -95,27 +86,34 @@ export type SessionPermissionRulesRead<P extends SessionPermissionRulesProblem =
|
|
|
95
86
|
rules: SessionPermissionRules;
|
|
96
87
|
};
|
|
97
88
|
/**
|
|
98
|
-
*
|
|
99
|
-
* (
|
|
100
|
-
* `readSessionRulesBody`:读不出形的行判 `corrupt`)。
|
|
89
|
+
* **读回**的形读者:读一只 `SessionPermissionRules`,形不对给判词,形对给**只含五桶**的规则体。消费者 = SQL 店的读回
|
|
90
|
+
* (`session-policy-store-sql.ts` 的 `readSessionRulesBody`:读不出形的行判 `corrupt`)。
|
|
101
91
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* 本读者与它同口径。
|
|
92
|
+
* 认识面窄得刻意:**只判「五桶各是字符串数组」**,不判引擎还肯不肯写(空串 / 纯空白项)、不判名字 —— 那是写口的问题
|
|
93
|
+
* ({@link readWritableSessionPermissionRules})。7.47.x 及以前写下的空串项存量行必须读得出:读回把它判坏 ⇒ 运营方清它的 PUT 在写前快照上 500、
|
|
94
|
+
* 准备阶段也读不到它(同 S-800 的「判官只在写口」)。未知键**照旧忽略**:core 的 `normalizeRules` 本来就只搬这五桶,本读者与它同口径。
|
|
106
95
|
*/
|
|
107
96
|
export declare function readSessionPermissionRules(raw: unknown): SessionPermissionRulesRead<SessionPermissionRulesShapeProblem>;
|
|
108
97
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
98
|
+
* 一份规则体(写口的入参,或店里读出来的一行)里**引擎不肯写**的第一只桶 —— 没有 ⇒ `undefined`。判官同 {@link engineRuleListOf}。
|
|
99
|
+
* 两个读者:写口读者(拒)与 2c 重放的同内容判据(`session-sync.ts` 的 `sameRulesContent`:目的端存量行是这一形 ⇒ 答「不同内容」,写交给店的收紧门)。
|
|
100
|
+
*/
|
|
101
|
+
export declare function unwritableRuleListOf(rules: Readonly<Partial<Record<keyof SessionPermissionRules, unknown>>>): {
|
|
102
|
+
field: keyof SessionPermissionRules;
|
|
103
|
+
refusal: string;
|
|
104
|
+
} | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* **写口读者**(S-800)—— 两条写入腿(`PUT /v1/sessions/:id/policy`、sync/import 的 `policy` 面经 {@link readSessionRulesRecords})往会话规则店
|
|
107
|
+
* 写之前的**唯一**判据,三问按序、每问一个判官:
|
|
108
|
+
* ① 容器形 —— 一只普通对象(本仓);
|
|
109
|
+
* ② 每一只桶 —— 引擎肯不肯把它写成规则表({@link engineRuleListOf},core 7.48.0 #1471;与引擎店同序:先 `normalizeRules` 再判名);
|
|
110
|
+
* ③ 工具名桶里的每一条 —— 引擎判官({@link legacyToolNameRefusalOf}:退役名 / 无前缀 `__` 名 / 对端段或工具段铸不出、为空)。
|
|
111
|
+
* 拿到规则体 = 店里的 `normalizeRules` 与 `assertSessionRuleNamesCurrent` 对它都不会再抛(同一只判官先问过)。
|
|
112
|
+
* 🔴 **只在写口,不在读回**:SQL 店读回同一行时只判形({@link readSessionPermissionRules})。早先写进去的退役名行 / 空串项行必须**读得出来** ——
|
|
113
|
+
* 那是运营方清掉它的唯一路径(operator 的 PUT 先读写前快照),也是 core 准备阶段报 `config.legacy_tool_name` 而不是一只 500 `corrupt` 的前提
|
|
114
|
+
* (7.105.0 车QQ 双库套件实抓,修在同批)。
|
|
117
115
|
*/
|
|
118
|
-
export declare function readWritableSessionPermissionRules(raw: unknown): SessionPermissionRulesRead
|
|
116
|
+
export declare function readWritableSessionPermissionRules(raw: unknown): SessionPermissionRulesRead<SessionPermissionRulesWriteProblem>;
|
|
119
117
|
/** 一条 `SessionRulesRecord` 的形问题(`policy[]` 的元素级;桶级问题原样转载在 `rules` 位)。 */
|
|
120
118
|
export type SessionRulesRecordProblem =
|
|
121
119
|
/** `policy` 本身不是数组。 */
|
|
@@ -133,11 +131,11 @@ export type SessionRulesRecordProblem =
|
|
|
133
131
|
kind: "principal-not-a-string";
|
|
134
132
|
index: number;
|
|
135
133
|
}
|
|
136
|
-
/** 第 `index` 条的 `rules`
|
|
134
|
+
/** 第 `index` 条的 `rules` 写不进(转载写口读者的判词)。 */
|
|
137
135
|
| {
|
|
138
136
|
kind: "rules";
|
|
139
137
|
index: number;
|
|
140
|
-
problem:
|
|
138
|
+
problem: SessionPermissionRulesWriteProblem;
|
|
141
139
|
};
|
|
142
140
|
/** {@link readSessionRulesRecords} 的读数。 */
|
|
143
141
|
export type SessionRulesRecordsRead = {
|