@sema-agent/settings-schema 17.1.0 → 18.0.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/CHANGELOG.md +212 -0
- package/README.md +73 -5
- package/conformance/VERSION +1 -1
- package/conformance/baseline.json +3 -0
- package/conformance/cases/c01-entry-salvage-then-typo/expected.json +4 -1
- package/conformance/cases/c02-hosts-clamp-stacked/expected.json +4 -1
- package/conformance/cases/c03-literal-dotted-top-key/expected.json +4 -1
- package/conformance/cases/c04-all-bad-collection-not-salvaged/expected.json +4 -1
- package/conformance/cases/c07-hooks-is-not-a-config-domain/expected.json +4 -1
- package/conformance/cases/c08-limits-unknown-carried-64/expected.json +4 -1
- package/conformance/cases/c09-limits-unknown-carried-65/expected.json +4 -1
- package/conformance/cases/c10-record-key-secret-redacted-twice/expected.json +4 -1
- package/conformance/cases/c11-unicode-unknown-keys/expected.json +4 -1
- package/conformance/cases/c12-prototype-name-top-keys/expected.json +4 -1
- package/conformance/cases/c13-models-field-null/expected.json +4 -1
- package/conformance/cases/c14-models-field-empty-array/expected.json +4 -1
- package/conformance/cases/c15-models-field-number/expected.json +4 -1
- package/conformance/cases/c16-deep-nesting-205/expected.json +3 -0
- package/conformance/cases/c17-empty-domain-file/expected.json +3 -0
- package/conformance/cases/c18-wire-envelope-not-an-object/expected.json +4 -1
- package/conformance/cases/c19-wire-envelope-no-version/expected.json +4 -1
- package/conformance/cases/c21-governance-empty-object-wins/expected.json +4 -1
- package/conformance/cases/c23-mixed-validity-models/expected.json +4 -1
- package/conformance/cases/c24-valid-entries-with-unknown-keys/expected.json +4 -1
- package/conformance/cases/c25-published-roundtrip-zero-warnings/expected.json +4 -1
- package/conformance/cases/c26-hosts-array-1024/expected.json +4 -1
- package/conformance/cases/c27-hosts-array-1025/expected.json +4 -1
- package/conformance/cases/c28-large-document-over-1mb/expected.json +4 -1
- package/conformance/cases/c29-salvage-then-domain-refine-fails/expected.json +4 -1
- package/conformance/cases/c30-version-triple-a-first/expected.json +4 -1
- package/conformance/cases/c31-version-triple-b-changed/expected.json +4 -1
- package/conformance/cases/c32-version-triple-a-restored/expected.json +4 -1
- package/conformance/cases/c33-limits-nested-carried-key/expected.json +4 -1
- package/conformance/cases/c34-skills-content-vs-manifest/expected.json +7 -1
- package/conformance/cases/c35-portable-domain-file-is-null/expected.json +3 -0
- package/conformance/cases/c36-skills-entry-without-content/expected.json +7 -1
- package/conformance/cases/c37-skills-field-null/expected.json +6 -0
- package/conformance/cases/c38-remote-exec-is-a-non-domain-file/expected.json +4 -1
- package/conformance/cases/c39-hidden-file-in-config-d/expected.json +4 -1
- package/conformance/cases/c40-s712-identity-only-what-reads-out/expected.json +4 -1
- package/conformance/cases/c41-s792-encoded-pem-identity/expected.json +4 -1
- package/conformance/cases/c42-s792-unknown-key-secret-redacted/expected.json +4 -1
- package/conformance/cases/c43-s792-form-and-deep-encoded-pem/expected.json +4 -1
- package/conformance/cases/c44-s792-utf8-escape-glued-token/expected.json +4 -1
- package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/expected.json +4 -1
- package/conformance/cases/c46-s811-host-name-url-userinfo-withheld/expected.json +4 -1
- package/conformance/cases/c47-s811-roles-key-url-userinfo-withheld/expected.json +4 -1
- package/conformance/cases/c48-s935-model-headers-transported/expected.json +4 -1
- package/conformance/cases/c49-s935-model-headers-secret-entry-dropped/expected.json +4 -1
- package/conformance/cases/c50-s784-lane-host-legal/expected.json +4 -1
- package/conformance/cases/c51-s784-lane-e2b-legal/expected.json +4 -1
- package/conformance/cases/c52-s784-lane-k8s-legal/expected.json +4 -1
- package/conformance/cases/c53-s784-lane-ssh-legal/expected.json +4 -1
- package/conformance/cases/c54-s784-lane-adb-legal/expected.json +4 -1
- package/conformance/cases/c55-s784-lane-local-docker-legal/expected.json +4 -1
- package/conformance/cases/c56-s784-lane-device-legal/expected.json +4 -1
- package/conformance/cases/c57-s784-g1-enabled-no-lane/expected.json +4 -1
- package/conformance/cases/c58-s784-g2-multitenant-host/expected.json +4 -1
- package/conformance/cases/c59-s784-g3-k8s-missing-image/expected.json +4 -1
- package/conformance/cases/c60-s784-g3-e2b-missing-key/expected.json +4 -1
- package/conformance/cases/c61-s784-g3-other-lane-key/expected.json +4 -1
- package/conformance/cases/c62-s784-g7a-session-tidb/expected.json +4 -1
- package/conformance/cases/c63-s784-host-two-replicas/expected.json +4 -1
- package/conformance/cases/c64-s784-multitenant-local-store/expected.json +4 -1
- package/conformance/cases/c65-s784-pg-without-db/expected.json +4 -1
- package/conformance/cases/c66-s784-memory-backend-mismatch/expected.json +4 -1
- package/conformance/cases/c67-s784-retired-field-loud/expected.json +4 -1
- package/conformance/cases/c68-s784-device-local-store/expected.json +4 -1
- package/conformance/cases/c69-deep-encoded-token-past-every-reading/expected.json +4 -1
- package/conformance/cases/c70-rewritten-token-in-front-of-encoded-pem-header/expected.json +4 -1
- package/conformance/cases/c71-one-scanner-write-reads-display-forms/expected.json +4 -1
- package/conformance/cases/c72-dangling-reference-write-seat-refuses/expected.json +4 -1
- package/conformance/cases/c73-projects-extended-registration-reads/expected.json +4 -1
- package/conformance/cases/c74-projects-over-bound-refused/expected.json +4 -1
- package/conformance/cases/c75-projects-patch-remote-uniqueness/expected.json +4 -1
- package/conformance/cases/c76-projects-entry-salvage-nested/expected.json +4 -1
- package/conformance/cases/c77-prompts-center-artifact-carried/expected.json +4 -1
- package/conformance/cases/c78-prompts-empty-bindings-refused/expected.json +4 -1
- package/conformance/cases/c79-prompts-bad-worker-artifact-not-salvaged/expected.json +4 -1
- package/conformance/cases/c80-prompts-wire-v2-verbatim/expected.json +7 -1
- package/conformance/cases/c81-prompts-declaration-bindings-refused/expected.json +4 -1
- package/conformance/cases/c82-prompts-v1-catalog-refused/expected.json +4 -1
- package/conformance/cases/c83-prompts-bad-overlay-not-salvaged/expected.json +4 -1
- package/conformance/cases/c84-sandbox-git-block-carried-verbatim/expected.json +7 -1
- package/conformance/cases/c85-sandbox-git-refused-block-still-carried/expected.json +7 -1
- package/conformance/cases/c86-a2a-peers-legal/expected.json +135 -0
- package/conformance/cases/c86-a2a-peers-legal/input.json +32 -0
- package/conformance/cases/c86-a2a-peers-legal/meta.json +5 -0
- package/conformance/cases/c87-a2a-credential-refs-not-partially-salvaged/expected.json +123 -0
- package/conformance/cases/c87-a2a-credential-refs-not-partially-salvaged/input.json +39 -0
- package/conformance/cases/c87-a2a-credential-refs-not-partially-salvaged/meta.json +5 -0
- package/conformance/cases/cc01-mcp-toolfaces-non-object/expected.json +4 -1
- package/conformance/cases/cc02-mcp-source-key-is-transported/expected.json +4 -1
- package/conformance/cases/cc03-model-compat-unknown-subkey/expected.json +4 -1
- package/conformance/cases/cli01-model-name-nfc-vs-nfd/expected.json +4 -1
- package/conformance/cases/cli02-control-and-zero-width-chars/expected.json +4 -1
- package/conformance/cases/cli03-credential-pasted-into-unknown-key/expected.json +4 -1
- package/conformance/cases/cli04-env-value-with-newline/expected.json +4 -1
- package/conformance/cases/cli05-long-and-prefix-colliding-names/expected.json +4 -1
- package/conformance/cases/t01-absent-domain-key-not-null/expected.json +4 -1
- package/conformance/cases/t03-prototype-name-key-not-swallowed/expected.json +4 -1
- package/conformance/cases/t04-secret-literal-never-in-warning-value/expected.json +4 -1
- package/conformance/cases/z01-every-domain-empty-object/expected.json +4 -1
- package/conformance/cases/z02-every-domain-unknown-key/expected.json +4 -1
- package/dist/atomic-write.d.ts +4 -3
- package/dist/atomic-write.js +25 -11
- package/dist/catalog-manages.d.ts +8 -3
- package/dist/catalog-manages.js +16 -7
- package/dist/center-refs.d.ts +4 -3
- package/dist/center-refs.js +8 -6
- package/dist/cli.d.ts +1 -1
- package/dist/config-d-file.d.ts +4 -2
- package/dist/config-d-file.js +27 -6
- package/dist/config-fns.d.ts +6 -1
- package/dist/config-fns.js +16 -2
- package/dist/config-root-documents.d.ts +2 -2
- package/dist/config-root-documents.js +1 -1
- package/dist/config-root-node.d.ts +8 -1
- package/dist/config-root-node.js +105 -23
- package/dist/env-model-table.js +3 -3
- package/dist/execution-lanes.d.ts +158 -11
- package/dist/execution-lanes.js +76 -11
- package/dist/file-edit.d.ts +1 -1
- package/dist/file-edit.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp-request-entry.d.ts +11 -21
- package/dist/mcp-request-entry.js +21 -38
- package/dist/node.d.ts +4 -1
- package/dist/node.js +6 -2
- package/dist/one-time-migrations.js +1 -1
- package/dist/portable-domains.d.ts +1 -1
- package/dist/portable-domains.js +1 -1
- package/dist/remote-exec.d.ts +5 -0
- package/dist/remote-exec.js +5 -0
- package/dist/reserved-member-name.d.ts +13 -0
- package/dist/reserved-member-name.js +14 -0
- package/dist/retired-envs.js +2 -0
- package/dist/secret-refs.d.ts +1 -1
- package/dist/secret-refs.js +5 -1
- package/dist/settings-units.d.ts +3 -0
- package/dist/settings-units.js +18 -0
- package/dist/types.d.ts +70 -41
- package/dist/types.js +179 -32
- package/dist/url-credential.d.ts +12 -2
- package/dist/url-credential.js +164 -9
- package/dist/wire-name.d.ts +19 -0
- package/dist/wire-name.js +21 -0
- package/docs/API-SURFACE.md +31 -6
- package/docs/CC-DIVERGENCE.md +6 -0
- package/docs/CONSUMER-INTEGRATION.md +127 -7
- package/llms-full.txt +40 -17
- package/llms.txt +9 -9
- package/package.json +1 -1
package/dist/env-model-table.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* ## 律
|
|
6
6
|
* · **env 两槽只在这里读一次**({@link readEnvModelSlots}):`MODEL_ID` 缺席或空串 = 没有主槽(纯空白算在场 —— 与引擎的 env 路由读口同尺);
|
|
7
7
|
* cheap 槽四态({@link EnvCheapSlot})。「env 模型表已声明」({@link envModelTableDeclared})与角色底({@link buildEnvModelBaseline})都由它派生 ——
|
|
8
|
-
* 这道闸的执行方(
|
|
8
|
+
* 这道闸的执行方(服务端的本地配置腿)与写者的计划助手调同一份(一次性迁移 SS-M11 只用两槽点名被顶替的 env 模型,铸不铸不看它),不各写一份。env 快照按「读到即算」(下标读;原型分层的快照里继承来的键算在场)。
|
|
9
9
|
* 引擎另有「名册占位 ⇒ env 表算空」一格,那是引擎自己的部署事实,不在本包。
|
|
10
10
|
* · **计划助手判序**({@link planEnvModelTableWrite}):目标腿不读 `config.d`(remote / none)⇒ 照写 → 候选不管模型面 ⇒ 照写 →
|
|
11
11
|
* env 表未声明 ⇒ 照写、**不写确认** → 配置根的决定是 `replaced` ⇒ 照写 →
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* 读成未设、按角色回退链落下一级并说一次 —— 没有哪种读法因它拒组;它照样写在回执里(`dangles`),要确认的写法把它给用户看。
|
|
19
19
|
*/
|
|
20
20
|
import { z } from "zod";
|
|
21
|
-
import {
|
|
21
|
+
import { catalogManagesModelPlane, isExplicitlyDisabledEntry } from "./catalog-manages.js";
|
|
22
22
|
import { parseDomainSalvaged, isDisclosableIdentity, resolveActiveTiers, withheldNameToken } from "./config-fns.js";
|
|
23
23
|
import { ENV_MODELS_DOCUMENT } from "./config-root-documents.js";
|
|
24
24
|
import { resolveCatalogDefaultModel } from "./default-model.js";
|
|
@@ -128,7 +128,7 @@ function candidateView(candidate) {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
function buildReceipt(baseline, view, decision) {
|
|
131
|
-
const enabled = view.models.filter((m) =>
|
|
131
|
+
const enabled = view.models.filter((m) => !isExplicitlyDisabledEntry(m)).map((m) => ({ name: m.name, id: m.id }));
|
|
132
132
|
const byName = new Map(enabled.map((e) => [e.name, e]));
|
|
133
133
|
const tiers = resolveActiveTiers(view);
|
|
134
134
|
/** 一个名采纳后落到哪条:经与引擎同一张档位展开(目录键先赢;env 底继承来的 `flash` 一类档位词按活跃组解)。 */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 执行车道 + 存储后端的**词表正本**(7.0.0,M-R2 WorkerSpec 结构块)
|
|
3
|
-
* 车道坐标的空白判官 `isBlankCoordinate`),零依赖(叶模块:本文件不 import 任何东西,`types.ts` 反过来引它)。
|
|
2
|
+
* 执行车道 + 存储后端的**词表正本**(7.0.0,M-R2 WorkerSpec 结构块)。纯数据常量,外加三只纯判官函数(退役车道词的拒句 `retiredLaneWordRefusal`、
|
|
3
|
+
* 车道坐标的空白判官 `isBlankCoordinate`、车道表合法性的唯一判官 `laneSetFlaws`〔18.0.0〕),零依赖(叶模块:本文件不 import 任何东西,`types.ts` 反过来引它)。
|
|
4
4
|
*
|
|
5
5
|
* ## 为什么在这里
|
|
6
6
|
* 车道词、每条车道读哪些 env、哪条车道分租户、存储后端词 —— 这几张表以前在四处各抄一份(引擎的能力表、
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* 写闸与起服读同一张表 ⇒ 不会分叉。
|
|
13
13
|
*
|
|
14
14
|
* ## 行内容的出处(逐行抄自引擎真码,坐标 = server 7.112.0 树)
|
|
15
|
-
* ·
|
|
16
|
-
* `
|
|
15
|
+
* · 车道词与次序:前七词抄自 `src/execution-lane-caps.ts` `REMOTE_EXEC_PROVIDER_WORDS`(:366)。次序照抄,于是引擎改派生之后,拒启句里的 `valid:` 列表与出路列表逐字不变。
|
|
16
|
+
* `none`(18.0.0)尾插:它的出处就是本表(见下「`none`」一节),引擎提货本版后从本表派生词表与拒句。
|
|
17
17
|
* · `tenantSeparation`:同文件 `executionLaneCaps` 每臂的 `tenantSeparation` 位(:209 host / :230 e2b / :249 k8s /
|
|
18
18
|
* :269 ssh / :288 adb / :308 local-docker / :327 device)。`tenantSeparationBasis`(11.0.0):分租户的那几臂凭什么分 ——
|
|
19
19
|
* e2b / k8s / local-docker 每任务一只隔离目标(`isolation`),device 是发起者自己的设备(`principal-binding`)。
|
|
@@ -30,15 +30,22 @@
|
|
|
30
30
|
* 收进车道栏会把它们保留成「k8s 专属」,别的车道就再也设不了快照对象存储。也**不收**臂外的适配器调参键
|
|
31
31
|
* (`HOST_BG_*` / `E2B_BG_*` / `K8S_BG_*` / `HOST_SHELL_PATH` …):它们不是车道坐标,照旧走 `env` 逃生口。
|
|
32
32
|
*
|
|
33
|
+
* ## `none`:不给智能体的工具提供执行环境(18.0.0)
|
|
34
|
+
* 每个部署都点名自己的执行车道;没有执行环境的部署点名 `none` —— 这是一个声明,不是「没写车道」的副作用。用户面可观察的事实:
|
|
35
|
+
* · 每个 run:工具的手不挂(两个执行环境座都缺席;引擎的装配清单报 hands 未挂、原因是没有执行环境);
|
|
36
|
+
* · 部署级:执行车道读数是 `none`、工具不在本机执行、没有隔离读数;引擎能力表的 `none` 行除分租户外整排不支持;
|
|
37
|
+
* · 分租户(依据 `no-execution-target`):没有执行目标,也就没有跨租户共享的目标;不挂在副本上(`singleReplica: false`);四栏 env 全空(没有要配的坐标与密钥);
|
|
38
|
+
* · 只能独成一集:含依据为 `no-execution-target` 的车道的车道表恰好一项 —— 判官 {@link laneSetFlaws} 按依据列判(拒因 `not_alone`),不点名车道词。
|
|
39
|
+
* 不在它的射程内(各有自己的属主轴,不随车道):请求体里的 hook 命令条目与 stdio MCP 服务器条目在 worker 宿主上起进程,它们的闸是多租户姿态 / 锁键 / 合规档。
|
|
40
|
+
* 它取代引擎内部「没有声明车道」那个状态的名字 `in-process`(那从来不是可声明的词,本表也从未收过);引擎侧的改名随它提货本版的那一版。
|
|
41
|
+
*
|
|
33
42
|
* ## 不在表里的词
|
|
34
|
-
* · `in-process`:引擎内部「没有 remoteExec」这个状态的名字,不是可声明的车道 —— 显式「无手」的 worker 在模型要用工具时
|
|
35
|
-
* 仍回 completed + 零工具,就是那个病换了个合法名字。要无手 worker 先另立设计、定用户面行为再给词。
|
|
36
43
|
* · `remote-docker`:引擎有一只没接线的适配器工厂,但没有任何读点能把这个词变成一条在跑的车道
|
|
37
44
|
* (`REMOTE_EXEC=remote-docker` 起服即拒;远端 docker 守护进程今天的真形 = `local-docker` + `DOCKER_HOST`)。
|
|
38
45
|
* 它在退役词墓碑 {@link RETIRED_LANE_WORDS} 里:读到即拒,拒句带出路。
|
|
39
46
|
*/
|
|
40
|
-
/** 可声明的执行车道闭集(= 引擎 `REMOTE_EXEC`
|
|
41
|
-
export declare const EXECUTION_LANE_WORDS: readonly ["host", "e2b", "k8s", "ssh", "adb", "local-docker", "device"];
|
|
47
|
+
/** 可声明的执行车道闭集(= 引擎 `REMOTE_EXEC` 收的词,逐字同序;18.0.0 尾插 `none`)。 */
|
|
48
|
+
export declare const EXECUTION_LANE_WORDS: readonly ["host", "e2b", "k8s", "ssh", "adb", "local-docker", "device", "none"];
|
|
42
49
|
export type ExecutionLane = (typeof EXECUTION_LANE_WORDS)[number];
|
|
43
50
|
/**
|
|
44
51
|
* 已退役的车道**值** —— 墓碑(与退役 env 名的墓碑表 `RETIRED_ENVS` 同一条线:永久、只增不减、一跳 —— 去向恒是现行车道词)。
|
|
@@ -53,9 +60,10 @@ export declare function retiredLaneWordRefusal(word: unknown): string | undefine
|
|
|
53
60
|
* `supported` = 每个租户的命令落在各自的目标上;`single-user-only` = 所有任务落同一个共享目标 ⇒ 只许单用户 worker。 */
|
|
54
61
|
export declare const TENANT_SEPARATION_WORDS: readonly ["supported", "single-user-only"];
|
|
55
62
|
export type TenantSeparation = (typeof TENANT_SEPARATION_WORDS)[number];
|
|
56
|
-
/** 分租户车道**凭什么**分租户(
|
|
57
|
-
* 发起者身上(设备 ↔ principal 绑定)
|
|
58
|
-
|
|
63
|
+
/** 分租户车道**凭什么**分租户(三档):`isolation` = 每个任务一只隔离的目标(microVM / pod / 容器);`principal-binding` = 目标绑在
|
|
64
|
+
* 发起者身上(设备 ↔ principal 绑定),目标本身不隔离;`no-execution-target`(18.0.0)= 根本没有执行目标(工具没有执行环境),也就没有跨租户共享的目标 ——
|
|
65
|
+
* 这一档还带一条集合规则:含这档车道的车道表只能有它这一项(判官 {@link laneSetFlaws} 读这一列)。只有 `tenantSeparation: "supported"` 的车道有依据。 */
|
|
66
|
+
export declare const TENANT_SEPARATION_BASES: readonly ["isolation", "principal-binding", "no-execution-target"];
|
|
59
67
|
export type TenantSeparationBasis = (typeof TENANT_SEPARATION_BASES)[number];
|
|
60
68
|
/** 车道的租户分离位与它的依据 —— 判别联合:分租户 ⇔ 依据在场(类型保证,不靠一句注释)。消费方的规则读依据列,不点名车道。 */
|
|
61
69
|
export type LaneTenancy = {
|
|
@@ -78,6 +86,102 @@ export type ExecutionLaneRow = {
|
|
|
78
86
|
readonly optionalEnv: readonly string[];
|
|
79
87
|
readonly optionalSecretEnv: readonly string[];
|
|
80
88
|
} & LaneTenancy;
|
|
89
|
+
/** 逐车道一行。`satisfies Record<ExecutionLane, …>` = 词表加词而这里不加行 ⇒ 编译红。 */
|
|
90
|
+
declare const LANE_ROWS: {
|
|
91
|
+
/** server `config.ts` :4014 臂(无必需键);`execution-lane-caps.ts` :209 `single-user-only`(所有任务落 worker 宿主)。 */
|
|
92
|
+
readonly host: {
|
|
93
|
+
readonly tenantSeparation: "single-user-only";
|
|
94
|
+
readonly singleReplica: true;
|
|
95
|
+
readonly requiredEnv: readonly [];
|
|
96
|
+
readonly requiredSecretEnv: readonly [];
|
|
97
|
+
readonly optionalEnv: readonly ["HOST_WORKSPACE_BASE", "HOST_COMMAND_TIMEOUT_MS"];
|
|
98
|
+
readonly optionalSecretEnv: readonly [];
|
|
99
|
+
};
|
|
100
|
+
/** server `config.ts` :3925 臂;`E2B_API_KEY` 目录 :351 类型 `secret`、`E2B_SANDBOX_ENV` :359 类型 `secret`;
|
|
101
|
+
* `execution-lane-caps.ts` :230 `supported`(每任务一只 microVM)。 */
|
|
102
|
+
readonly e2b: {
|
|
103
|
+
readonly tenantSeparation: "supported";
|
|
104
|
+
readonly tenantSeparationBasis: "isolation";
|
|
105
|
+
readonly singleReplica: false;
|
|
106
|
+
readonly requiredEnv: readonly [];
|
|
107
|
+
readonly requiredSecretEnv: readonly ["E2B_API_KEY"];
|
|
108
|
+
readonly optionalEnv: readonly ["E2B_TEMPLATE", "E2B_TIMEOUT_MS", "E2B_LIVENESS_MS", "E2B_ALLOW_NET", "E2B_MOUNT_PATH", "E2B_ORPHAN_RECLAIM"];
|
|
109
|
+
readonly optionalSecretEnv: readonly ["E2B_SANDBOX_ENV"];
|
|
110
|
+
};
|
|
111
|
+
/** server `config.ts` :3957 臂;`K8S_TOKEN` 目录 :412 类型 `secret`、`K8S_CA_CERT_B64` :403 类型 `opaque`;
|
|
112
|
+
* `execution-lane-caps.ts` :249 `supported`(每任务一只 pod)。`MINIO_*` 刻意不收(见文件头)。
|
|
113
|
+
* `K8S_NAMESPACE`(沙箱 pod 所在的命名空间)是**必需**坐标:pod 住哪是部署自己的声明,表不替它留缺省;服务端的必需 env 门按本行 `requiredEnv` 拒启,
|
|
114
|
+
* 所以这里没有「可选」一说。 */
|
|
115
|
+
readonly k8s: {
|
|
116
|
+
readonly tenantSeparation: "supported";
|
|
117
|
+
readonly tenantSeparationBasis: "isolation";
|
|
118
|
+
readonly singleReplica: false;
|
|
119
|
+
readonly requiredEnv: readonly ["K8S_SANDBOX_IMAGE", "K8S_NAMESPACE"];
|
|
120
|
+
readonly requiredSecretEnv: readonly [];
|
|
121
|
+
readonly optionalEnv: readonly ["K8S_API_URL", "K8S_INSECURE_TLS", "K8S_RUNTIME_CLASS", "K8S_MOUNT_PATH", "K8S_TIMEOUT_MS", "K8S_MEMORY", "K8S_CPU", "WORKSPACE_SNAPSHOT_BUCKET", "WORKSPACE_SNAPSHOT_PREFIX", "WORKSPACE_SNAPSHOT_TTL_SEC"];
|
|
122
|
+
readonly optionalSecretEnv: readonly ["K8S_TOKEN", "K8S_CA_CERT_B64"];
|
|
123
|
+
};
|
|
124
|
+
/** server `config.ts` :3991 臂 + `parseSshHostKeyEnv` :1521;`SSH_PRIVATE_KEY` 目录 :687 类型 `secret`;
|
|
125
|
+
* `execution-lane-caps.ts` :269 `single-user-only`(一台跨任务共享的常驻真机)。 */
|
|
126
|
+
readonly ssh: {
|
|
127
|
+
readonly tenantSeparation: "single-user-only";
|
|
128
|
+
readonly singleReplica: false;
|
|
129
|
+
readonly requiredEnv: readonly ["SSH_HOST", "SSH_USER"];
|
|
130
|
+
readonly requiredSecretEnv: readonly ["SSH_PRIVATE_KEY"];
|
|
131
|
+
readonly optionalEnv: readonly ["SSH_PORT", "SSH_MOUNT_PATH", "SSH_HOST_FINGERPRINT", "SSH_KNOWN_HOSTS"];
|
|
132
|
+
readonly optionalSecretEnv: readonly [];
|
|
133
|
+
};
|
|
134
|
+
/** server `config.ts` :4006 臂;`execution-lane-caps.ts` :288 `single-user-only`(一台跨任务共享的设备)。 */
|
|
135
|
+
readonly adb: {
|
|
136
|
+
readonly tenantSeparation: "single-user-only";
|
|
137
|
+
readonly singleReplica: false;
|
|
138
|
+
readonly requiredEnv: readonly ["ADB_SERIAL"];
|
|
139
|
+
readonly requiredSecretEnv: readonly [];
|
|
140
|
+
readonly optionalEnv: readonly ["ADB_PATH", "ADB_MOUNT_PATH"];
|
|
141
|
+
readonly optionalSecretEnv: readonly [];
|
|
142
|
+
};
|
|
143
|
+
/** server `config.ts` :4026 臂;`DOCKER_SANDBOX_ENV` 目录 :345 类型 `secret`;`execution-lane-caps.ts` :308 `supported`
|
|
144
|
+
* (每任务一只容器)。`DOCKER_HOST` 在本行:远端 docker 守护进程 = 本车道 + `coords.DOCKER_HOST`。 */
|
|
145
|
+
readonly "local-docker": {
|
|
146
|
+
readonly tenantSeparation: "supported";
|
|
147
|
+
readonly tenantSeparationBasis: "isolation";
|
|
148
|
+
readonly singleReplica: false;
|
|
149
|
+
readonly requiredEnv: readonly ["DOCKER_IMAGE"];
|
|
150
|
+
readonly requiredSecretEnv: readonly [];
|
|
151
|
+
readonly optionalEnv: readonly ["DOCKER_MOUNT_PATH", "DOCKER_PATH", "DOCKER_HOST", "DOCKER_MEMORY", "DOCKER_CPUS", "DOCKER_PIDS_LIMIT", "DOCKER_DROP_CAPS", "DOCKER_NETWORK", "DOCKER_COMMAND_TIMEOUT_MS"];
|
|
152
|
+
readonly optionalSecretEnv: readonly ["DOCKER_SANDBOX_ENV"];
|
|
153
|
+
};
|
|
154
|
+
/** server `config.ts` :4055 臂 + `parseDevicePreAuthPerRemoteEnv` :871 / `parseDeviceEnrollTokenTtlEnv` :857;`execution-lane-caps.ts` :327
|
|
155
|
+
* `supported`(发起者自己的设备)。16.0.0:`DEVICE_RELAY_URL`(设备拨哪里)是**必需**坐标 —— 引擎的 device 臂缺它即拒启
|
|
156
|
+
* (`parseDeviceRelayUrlEnv`;此前它是 device 臂读而本表漏登记的键),值只有两种:ws(s) 绝对 URL 或字面 `none`(值的文法见 `./device-relay`)。
|
|
157
|
+
* 17.1.0:`DEVICE_TRUSTED_PROXY_CIDRS`(可选)= 设备 WS 未鉴权握手 per-remote 帽键的可信代理名单(CIDR 闭集,缺省空 = 不读任何代理头);值文法由引擎起服判。 */
|
|
158
|
+
readonly device: {
|
|
159
|
+
readonly tenantSeparation: "supported";
|
|
160
|
+
readonly tenantSeparationBasis: "principal-binding";
|
|
161
|
+
readonly singleReplica: true;
|
|
162
|
+
readonly requiredEnv: readonly ["DEVICE_RELAY_URL"];
|
|
163
|
+
readonly requiredSecretEnv: readonly [];
|
|
164
|
+
readonly optionalEnv: readonly ["DEVICE_DELIVERY_TIMEOUT_MS", "DEVICE_RECONNECT_GRACE_MS", "DEVICE_EXEC_TIMEOUT_MS", "DEVICE_MAX_INFLIGHT_PER_DEVICE", "DEVICE_MAX_PREAUTH_PER_REMOTE", "DEVICE_ENROLL_TOKEN_TTL_SEC", "DEVICE_TRUSTED_PROXY_CIDRS", "DEVICE_SUPERSEDE"];
|
|
165
|
+
readonly optionalSecretEnv: readonly [];
|
|
166
|
+
};
|
|
167
|
+
/** 18.0.0:没有执行环境(见文件头「`none`」一节)。分租户,依据 `no-execution-target`(没有执行目标,就没有跨租户共享的目标);不挂在副本上;
|
|
168
|
+
* 四栏全空(没有要配的坐标与密钥)。本行先于引擎:引擎提货本版后它的能力表 / 必需键门 / 拒句从本行派生。 */
|
|
169
|
+
readonly none: {
|
|
170
|
+
readonly tenantSeparation: "supported";
|
|
171
|
+
readonly tenantSeparationBasis: "no-execution-target";
|
|
172
|
+
readonly singleReplica: false;
|
|
173
|
+
readonly requiredEnv: readonly [];
|
|
174
|
+
readonly requiredSecretEnv: readonly [];
|
|
175
|
+
readonly optionalEnv: readonly [];
|
|
176
|
+
readonly optionalSecretEnv: readonly [];
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
/** 依据为 `no-execution-target` 的车道(型从表行的依据列派生,不点名车道词;今天 = `none`):声明了它的车道表只能有它这一项。 */
|
|
180
|
+
export type StandaloneLane = {
|
|
181
|
+
[L in ExecutionLane]: (typeof LANE_ROWS)[L] extends {
|
|
182
|
+
readonly tenantSeparationBasis: "no-execution-target";
|
|
183
|
+
} ? L : never;
|
|
184
|
+
}[ExecutionLane];
|
|
81
185
|
/** 车道表(次序 = {@link EXECUTION_LANE_WORDS})。整张表深冻结 —— 它是唯一正本,消费方拿到的不许被改。 */
|
|
82
186
|
export declare const EXECUTION_LANES: readonly ExecutionLaneRow[];
|
|
83
187
|
/**
|
|
@@ -90,6 +194,48 @@ export declare const EXECUTION_LANES: readonly ExecutionLaneRow[];
|
|
|
90
194
|
* 车道表的派生索引与写闸也从这里 import,全包只有这一处函数体。
|
|
91
195
|
*/
|
|
92
196
|
export declare function isBlankCoordinate(value: string): boolean;
|
|
197
|
+
/**
|
|
198
|
+
* 一张车道表**不合法**的拒因 —— 闭集,判别字段 `kind`(消费方穷举 `switch`:加一种拒因 ⇒ 消费方编译红,不会静默落进「别的」)。`at` = 那一项在表里的下标(从 0 起)。
|
|
199
|
+
* · `empty_set`:表是空的(一项都没有);
|
|
200
|
+
* · `blank_entry`:那一项是空串或只含空白(判官 {@link isBlankCoordinate});
|
|
201
|
+
* · `unknown`:那一项不是车道词({@link EXECUTION_LANE_WORDS};逐字比:不 trim、不折大小写),也不是车道值墓碑里的旧词 —— 包括根本不是字符串的项(数、`null`、对象 …:
|
|
202
|
+
* 读 JSON 的写闸会见到;`word` 是那一项的原值,判官只比较、不读它的任何属性,渲染给人看时由调用方自己描述它的形);
|
|
203
|
+
* · `retired`:那一项是车道值墓碑 {@link RETIRED_LANE_WORDS} 里的旧词(出路取 {@link retiredLaneWordRefusal},一句);
|
|
204
|
+
* · `duplicate`:那一项是车道词,但表里更早已经有它了(报在第二次及以后出现的那一格;不是车道词的重复不报这一条 —— 它们各自已是拒因);
|
|
205
|
+
* · `not_alone`(18.0.0):表里有独占车道({@link StandaloneLane},依据列为 `no-execution-target`),却还有不是它的项 —— 独占车道只能独成一集。
|
|
206
|
+
* 这是整张表的拒因(没有 `at`);独占车道自己的重复只报 `duplicate`。
|
|
207
|
+
*/
|
|
208
|
+
export type LaneSetFlaw = {
|
|
209
|
+
readonly kind: "empty_set";
|
|
210
|
+
} | {
|
|
211
|
+
readonly kind: "blank_entry";
|
|
212
|
+
readonly at: number;
|
|
213
|
+
} | {
|
|
214
|
+
readonly kind: "unknown";
|
|
215
|
+
readonly at: number;
|
|
216
|
+
readonly word: unknown;
|
|
217
|
+
} | {
|
|
218
|
+
readonly kind: "retired";
|
|
219
|
+
readonly at: number;
|
|
220
|
+
readonly word: string;
|
|
221
|
+
} | {
|
|
222
|
+
readonly kind: "duplicate";
|
|
223
|
+
readonly at: number;
|
|
224
|
+
readonly lane: ExecutionLane;
|
|
225
|
+
} | {
|
|
226
|
+
readonly kind: "not_alone";
|
|
227
|
+
readonly lane: StandaloneLane;
|
|
228
|
+
};
|
|
229
|
+
/** 车道表的规则句(不含值,与 `DEVICE_RELAY_RULE` 同形):写闸的拒句、引擎的拒启句、表单的提示读这一句,句子只在这里写。 */
|
|
230
|
+
export declare const LANE_SET_RULE: string;
|
|
231
|
+
/**
|
|
232
|
+
* 车道表合不合法的**唯一判官**:合法 ⇒ `[]`;否则按表的次序交回每一条拒因({@link LaneSetFlaw})。纯函数,不抛。
|
|
233
|
+
* 谁问它:写闸(`WorkerSpec` 的 `runtime.execution.lanes`)逐条映射成 issue;引擎把 `REMOTE_EXEC` 按逗号切段后交给它(引擎只留切段);web-admin 表单同问。
|
|
234
|
+
* 入参是任意值的表(读 JSON 的写闸原样交进来;引擎切段后交的是字符串):不是字符串的项不是车道词 ⇒ `unknown`,与写错的词同一条拒因 —— 「每一项都是车道词」只有这一处判。
|
|
235
|
+
* 按下标读(`0 … length-1`):稀疏表的空洞读成 `undefined`,是一项不是字符串的项 —— 与写闸的下标快照同答(`forEach` / `some` 会跳过空洞)。
|
|
236
|
+
* 只判「这张表合不合法」;每条车道缺不缺必需坐标、本引擎版本服务不服务这条车道,是调用方各自的门。
|
|
237
|
+
*/
|
|
238
|
+
export declare function laneSetFlaws(lanes: readonly unknown[]): readonly LaneSetFlaw[];
|
|
93
239
|
/** 存储后端(→ `DB_BACKEND`)。= server `src/config-types.ts` `DB_BACKEND_WORDS`(:67)逐字同序。 */
|
|
94
240
|
export declare const STORE_BACKENDS: readonly ["mysql", "pg", "local", "memory"];
|
|
95
241
|
export type StoreBackend = (typeof STORE_BACKENDS)[number];
|
|
@@ -101,3 +247,4 @@ export type SessionBackend = (typeof SESSION_BACKENDS)[number];
|
|
|
101
247
|
* 收成一个字,与 {@link STORE_BACKENDS} 同字;硬破坏,`tidb` 读写两面拒、指路一次性迁移 SS-M12)。次序 file → pg → mysql。 */
|
|
102
248
|
export declare const MEMORY_ENGINE_BACKENDS: readonly ["file", "pg", "mysql"];
|
|
103
249
|
export type MemoryEngineBackend = (typeof MEMORY_ENGINE_BACKENDS)[number];
|
|
250
|
+
export {};
|
package/dist/execution-lanes.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 执行车道 + 存储后端的**词表正本**(7.0.0,M-R2 WorkerSpec 结构块)
|
|
3
|
-
* 车道坐标的空白判官 `isBlankCoordinate`),零依赖(叶模块:本文件不 import 任何东西,`types.ts` 反过来引它)。
|
|
2
|
+
* 执行车道 + 存储后端的**词表正本**(7.0.0,M-R2 WorkerSpec 结构块)。纯数据常量,外加三只纯判官函数(退役车道词的拒句 `retiredLaneWordRefusal`、
|
|
3
|
+
* 车道坐标的空白判官 `isBlankCoordinate`、车道表合法性的唯一判官 `laneSetFlaws`〔18.0.0〕),零依赖(叶模块:本文件不 import 任何东西,`types.ts` 反过来引它)。
|
|
4
4
|
*
|
|
5
5
|
* ## 为什么在这里
|
|
6
6
|
* 车道词、每条车道读哪些 env、哪条车道分租户、存储后端词 —— 这几张表以前在四处各抄一份(引擎的能力表、
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* 写闸与起服读同一张表 ⇒ 不会分叉。
|
|
13
13
|
*
|
|
14
14
|
* ## 行内容的出处(逐行抄自引擎真码,坐标 = server 7.112.0 树)
|
|
15
|
-
* ·
|
|
16
|
-
* `
|
|
15
|
+
* · 车道词与次序:前七词抄自 `src/execution-lane-caps.ts` `REMOTE_EXEC_PROVIDER_WORDS`(:366)。次序照抄,于是引擎改派生之后,拒启句里的 `valid:` 列表与出路列表逐字不变。
|
|
16
|
+
* `none`(18.0.0)尾插:它的出处就是本表(见下「`none`」一节),引擎提货本版后从本表派生词表与拒句。
|
|
17
17
|
* · `tenantSeparation`:同文件 `executionLaneCaps` 每臂的 `tenantSeparation` 位(:209 host / :230 e2b / :249 k8s /
|
|
18
18
|
* :269 ssh / :288 adb / :308 local-docker / :327 device)。`tenantSeparationBasis`(11.0.0):分租户的那几臂凭什么分 ——
|
|
19
19
|
* e2b / k8s / local-docker 每任务一只隔离目标(`isolation`),device 是发起者自己的设备(`principal-binding`)。
|
|
@@ -30,15 +30,22 @@
|
|
|
30
30
|
* 收进车道栏会把它们保留成「k8s 专属」,别的车道就再也设不了快照对象存储。也**不收**臂外的适配器调参键
|
|
31
31
|
* (`HOST_BG_*` / `E2B_BG_*` / `K8S_BG_*` / `HOST_SHELL_PATH` …):它们不是车道坐标,照旧走 `env` 逃生口。
|
|
32
32
|
*
|
|
33
|
+
* ## `none`:不给智能体的工具提供执行环境(18.0.0)
|
|
34
|
+
* 每个部署都点名自己的执行车道;没有执行环境的部署点名 `none` —— 这是一个声明,不是「没写车道」的副作用。用户面可观察的事实:
|
|
35
|
+
* · 每个 run:工具的手不挂(两个执行环境座都缺席;引擎的装配清单报 hands 未挂、原因是没有执行环境);
|
|
36
|
+
* · 部署级:执行车道读数是 `none`、工具不在本机执行、没有隔离读数;引擎能力表的 `none` 行除分租户外整排不支持;
|
|
37
|
+
* · 分租户(依据 `no-execution-target`):没有执行目标,也就没有跨租户共享的目标;不挂在副本上(`singleReplica: false`);四栏 env 全空(没有要配的坐标与密钥);
|
|
38
|
+
* · 只能独成一集:含依据为 `no-execution-target` 的车道的车道表恰好一项 —— 判官 {@link laneSetFlaws} 按依据列判(拒因 `not_alone`),不点名车道词。
|
|
39
|
+
* 不在它的射程内(各有自己的属主轴,不随车道):请求体里的 hook 命令条目与 stdio MCP 服务器条目在 worker 宿主上起进程,它们的闸是多租户姿态 / 锁键 / 合规档。
|
|
40
|
+
* 它取代引擎内部「没有声明车道」那个状态的名字 `in-process`(那从来不是可声明的词,本表也从未收过);引擎侧的改名随它提货本版的那一版。
|
|
41
|
+
*
|
|
33
42
|
* ## 不在表里的词
|
|
34
|
-
* · `in-process`:引擎内部「没有 remoteExec」这个状态的名字,不是可声明的车道 —— 显式「无手」的 worker 在模型要用工具时
|
|
35
|
-
* 仍回 completed + 零工具,就是那个病换了个合法名字。要无手 worker 先另立设计、定用户面行为再给词。
|
|
36
43
|
* · `remote-docker`:引擎有一只没接线的适配器工厂,但没有任何读点能把这个词变成一条在跑的车道
|
|
37
44
|
* (`REMOTE_EXEC=remote-docker` 起服即拒;远端 docker 守护进程今天的真形 = `local-docker` + `DOCKER_HOST`)。
|
|
38
45
|
* 它在退役词墓碑 {@link RETIRED_LANE_WORDS} 里:读到即拒,拒句带出路。
|
|
39
46
|
*/
|
|
40
|
-
/** 可声明的执行车道闭集(= 引擎 `REMOTE_EXEC`
|
|
41
|
-
export const EXECUTION_LANE_WORDS = ["host", "e2b", "k8s", "ssh", "adb", "local-docker", "device"];
|
|
47
|
+
/** 可声明的执行车道闭集(= 引擎 `REMOTE_EXEC` 收的词,逐字同序;18.0.0 尾插 `none`)。 */
|
|
48
|
+
export const EXECUTION_LANE_WORDS = ["host", "e2b", "k8s", "ssh", "adb", "local-docker", "device", "none"];
|
|
42
49
|
export const RETIRED_LANE_WORDS = Object.freeze([
|
|
43
50
|
Object.freeze(["remote-docker", "local-docker", "point it at the remote docker daemon with DOCKER_HOST (in a worker spec: runtime.execution.coords.DOCKER_HOST)"]),
|
|
44
51
|
]);
|
|
@@ -50,9 +57,10 @@ export function retiredLaneWordRefusal(word) {
|
|
|
50
57
|
/** 车道分不分租户(引擎能力表的 `tenantSeparation` 位,两档,没有「不表态」)。
|
|
51
58
|
* `supported` = 每个租户的命令落在各自的目标上;`single-user-only` = 所有任务落同一个共享目标 ⇒ 只许单用户 worker。 */
|
|
52
59
|
export const TENANT_SEPARATION_WORDS = ["supported", "single-user-only"];
|
|
53
|
-
/** 分租户车道**凭什么**分租户(
|
|
54
|
-
* 发起者身上(设备 ↔ principal 绑定)
|
|
55
|
-
|
|
60
|
+
/** 分租户车道**凭什么**分租户(三档):`isolation` = 每个任务一只隔离的目标(microVM / pod / 容器);`principal-binding` = 目标绑在
|
|
61
|
+
* 发起者身上(设备 ↔ principal 绑定),目标本身不隔离;`no-execution-target`(18.0.0)= 根本没有执行目标(工具没有执行环境),也就没有跨租户共享的目标 ——
|
|
62
|
+
* 这一档还带一条集合规则:含这档车道的车道表只能有它这一项(判官 {@link laneSetFlaws} 读这一列)。只有 `tenantSeparation: "supported"` 的车道有依据。 */
|
|
63
|
+
export const TENANT_SEPARATION_BASES = ["isolation", "principal-binding", "no-execution-target"];
|
|
56
64
|
/** 逐车道一行。`satisfies Record<ExecutionLane, …>` = 词表加词而这里不加行 ⇒ 编译红。 */
|
|
57
65
|
const LANE_ROWS = {
|
|
58
66
|
/** server `config.ts` :4014 臂(无必需键);`execution-lane-caps.ts` :209 `single-user-only`(所有任务落 worker 宿主)。 */
|
|
@@ -161,7 +169,25 @@ const LANE_ROWS = {
|
|
|
161
169
|
],
|
|
162
170
|
optionalSecretEnv: [],
|
|
163
171
|
},
|
|
172
|
+
/** 18.0.0:没有执行环境(见文件头「`none`」一节)。分租户,依据 `no-execution-target`(没有执行目标,就没有跨租户共享的目标);不挂在副本上;
|
|
173
|
+
* 四栏全空(没有要配的坐标与密钥)。本行先于引擎:引擎提货本版后它的能力表 / 必需键门 / 拒句从本行派生。 */
|
|
174
|
+
none: {
|
|
175
|
+
tenantSeparation: "supported",
|
|
176
|
+
tenantSeparationBasis: "no-execution-target",
|
|
177
|
+
singleReplica: false,
|
|
178
|
+
requiredEnv: [],
|
|
179
|
+
requiredSecretEnv: [],
|
|
180
|
+
optionalEnv: [],
|
|
181
|
+
optionalSecretEnv: [],
|
|
182
|
+
},
|
|
164
183
|
};
|
|
184
|
+
/** 一条车道是不是独占车道 —— 读表行的依据列(运行期判据与 {@link StandaloneLane} 的型读同一列)。 */
|
|
185
|
+
function isStandaloneLane(lane) {
|
|
186
|
+
const row = LANE_ROWS[lane];
|
|
187
|
+
return row.tenantSeparation === "supported" && row.tenantSeparationBasis === "no-execution-target";
|
|
188
|
+
}
|
|
189
|
+
/** 独占车道,按词表次序(从依据列现算)。 */
|
|
190
|
+
const STANDALONE_LANES = EXECUTION_LANE_WORDS.filter(isStandaloneLane);
|
|
165
191
|
/** 车道表(次序 = {@link EXECUTION_LANE_WORDS})。整张表深冻结 —— 它是唯一正本,消费方拿到的不许被改。 */
|
|
166
192
|
export const EXECUTION_LANES = Object.freeze(EXECUTION_LANE_WORDS.map((lane) => {
|
|
167
193
|
const row = LANE_ROWS[lane];
|
|
@@ -188,6 +214,45 @@ export const EXECUTION_LANES = Object.freeze(EXECUTION_LANE_WORDS.map((lane) =>
|
|
|
188
214
|
export function isBlankCoordinate(value) {
|
|
189
215
|
return value.trim() === "";
|
|
190
216
|
}
|
|
217
|
+
/** 车道表的规则句(不含值,与 `DEVICE_RELAY_RULE` 同形):写闸的拒句、引擎的拒启句、表单的提示读这一句,句子只在这里写。 */
|
|
218
|
+
export const LANE_SET_RULE = `must be a non-empty list — the ordered execution lane set (the first one is the default) of ${EXECUTION_LANE_WORDS.join(" | ")}, each at most once; a lane set with no execution environment for the agent's tools is ${STANDALONE_LANES.map((lane) => `[${JSON.stringify(lane)}]`).join(" or ")}, alone`;
|
|
219
|
+
/**
|
|
220
|
+
* 车道表合不合法的**唯一判官**:合法 ⇒ `[]`;否则按表的次序交回每一条拒因({@link LaneSetFlaw})。纯函数,不抛。
|
|
221
|
+
* 谁问它:写闸(`WorkerSpec` 的 `runtime.execution.lanes`)逐条映射成 issue;引擎把 `REMOTE_EXEC` 按逗号切段后交给它(引擎只留切段);web-admin 表单同问。
|
|
222
|
+
* 入参是任意值的表(读 JSON 的写闸原样交进来;引擎切段后交的是字符串):不是字符串的项不是车道词 ⇒ `unknown`,与写错的词同一条拒因 —— 「每一项都是车道词」只有这一处判。
|
|
223
|
+
* 按下标读(`0 … length-1`):稀疏表的空洞读成 `undefined`,是一项不是字符串的项 —— 与写闸的下标快照同答(`forEach` / `some` 会跳过空洞)。
|
|
224
|
+
* 只判「这张表合不合法」;每条车道缺不缺必需坐标、本引擎版本服务不服务这条车道,是调用方各自的门。
|
|
225
|
+
*/
|
|
226
|
+
export function laneSetFlaws(lanes) {
|
|
227
|
+
if (lanes.length === 0)
|
|
228
|
+
return [{ kind: "empty_set" }];
|
|
229
|
+
const flaws = [];
|
|
230
|
+
const seen = [];
|
|
231
|
+
const entries = Array.from({ length: lanes.length }, (_, at) => lanes[at]); // 按下标:空洞 ⇒ undefined(见上)
|
|
232
|
+
for (const [at, entry] of entries.entries()) {
|
|
233
|
+
if (typeof entry !== "string") {
|
|
234
|
+
flaws.push({ kind: "unknown", at, word: entry }); // 不是字符串:不是车道词(不读它的属性)
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (isBlankCoordinate(entry)) {
|
|
238
|
+
flaws.push({ kind: "blank_entry", at });
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const lane = EXECUTION_LANE_WORDS.find((w) => w === entry); // 裸比较让编译器收窄(不把开放串断言成闭集词)
|
|
242
|
+
if (lane !== undefined) {
|
|
243
|
+
if (seen.includes(lane))
|
|
244
|
+
flaws.push({ kind: "duplicate", at, lane });
|
|
245
|
+
else
|
|
246
|
+
seen.push(lane);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
flaws.push(retiredLaneWordRefusal(entry) === undefined ? { kind: "unknown", at, word: entry } : { kind: "retired", at, word: entry });
|
|
250
|
+
}
|
|
251
|
+
for (const lane of STANDALONE_LANES)
|
|
252
|
+
if (seen.includes(lane) && entries.some((entry) => entry !== lane))
|
|
253
|
+
flaws.push({ kind: "not_alone", lane });
|
|
254
|
+
return flaws;
|
|
255
|
+
}
|
|
191
256
|
/** 存储后端(→ `DB_BACKEND`)。= server `src/config-types.ts` `DB_BACKEND_WORDS`(:67)逐字同序。 */
|
|
192
257
|
export const STORE_BACKENDS = ["mysql", "pg", "local", "memory"];
|
|
193
258
|
/** session 店(→ `SESSION_BACKEND`)。= server `src/config.ts` :1760 `enumEnv("SESSION_BACKEND", …)` 的词表逐字同序
|
package/dist/file-edit.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export interface RequiredEnvName {
|
|
|
30
30
|
/** true if this env-NAME resolves in the supplied environment (.env merged over process.env). */
|
|
31
31
|
present: boolean;
|
|
32
32
|
}
|
|
33
|
-
/** LIST every env-NAME the current local config requires (across models/workers/mcp + the
|
|
33
|
+
/** LIST every env-NAME the current local config requires (across models/workers/mcp/a2a + the
|
|
34
34
|
* remote-exec backend), marking which are MISSING from the resolved env — the TOC "you still need to set
|
|
35
35
|
* these secrets" panel. Reuses collectEnvRefs for the domain side, then appends the remoteExec secret refs. */
|
|
36
36
|
export declare function listRequiredEnvNames(eff: EffectiveConfig, remoteExec: RemoteExecSpec | undefined, resolvedEnv: Record<string, string | undefined>): RequiredEnvName[];
|
package/dist/file-edit.js
CHANGED
|
@@ -69,7 +69,7 @@ export async function writeDomainFile(root, domain, value) {
|
|
|
69
69
|
writeFileAtomic(path.join(dir, `${domain}.json`), configDDocumentText(parsed), "config-document");
|
|
70
70
|
return parsed;
|
|
71
71
|
}
|
|
72
|
-
/** LIST every env-NAME the current local config requires (across models/workers/mcp + the
|
|
72
|
+
/** LIST every env-NAME the current local config requires (across models/workers/mcp/a2a + the
|
|
73
73
|
* remote-exec backend), marking which are MISSING from the resolved env — the TOC "you still need to set
|
|
74
74
|
* these secrets" panel. Reuses collectEnvRefs for the domain side, then appends the remoteExec secret refs. */
|
|
75
75
|
export function listRequiredEnvNames(eff, remoteExec, resolvedEnv) {
|
|
@@ -108,6 +108,7 @@ export function listRequiredEnvNames(eff, remoteExec, resolvedEnv) {
|
|
|
108
108
|
case "adb":
|
|
109
109
|
case "host":
|
|
110
110
|
case "local-docker":
|
|
111
|
+
case "none":
|
|
111
112
|
break; // these carry no secret env-NAME refs
|
|
112
113
|
default: {
|
|
113
114
|
const unhandled = re;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export * from "./url-shape.js";
|
|
|
9
9
|
export * from "./device-relay.js";
|
|
10
10
|
export * from "./url-credential.js";
|
|
11
11
|
export * from "./default-model.js";
|
|
12
|
-
export { catalogManagesModelPlane, enabledEntryCount } from "./catalog-manages.js";
|
|
12
|
+
export { catalogManagesModelPlane, enabledEntryCount, isExplicitlyDisabledEntry } from "./catalog-manages.js";
|
|
13
13
|
export { DEFAULT_MODEL_KEY, ENV_MODEL_TABLE_KEYS, buildEnvModelBaseline, envModelTableDeclared, envModelTableWriteRefusal, mintedCheapId, planEnvModelTableWrite, readEnvModelSlots, type EnvCheapSlot, type EnvModelBaseline, type EnvModelTableEntry, type EnvModelTableKey, type EnvModelTableLanding, type EnvModelTableReceipt, type EnvModelTableRoleRow, type EnvModelTableTarget, type EnvModelTableWriteInput, type EnvModelTableWriteIntent, type EnvModelTableWritePlan, type EnvRoleBinding, type EnvSnapshot, } from "./env-model-table.js";
|
|
14
14
|
export { CONFIG_ROOT_DOCUMENTS, ENV_MODELS_DECISIONS, ENV_MODELS_DOCUMENT, ROOT_DOCUMENT_UNREADABLE_REASONS, envModelsDecisionTag, type ConfigRootDocument, type EnvModelsDecision, type EnvModelsDecisionWord, type MarkedMigrationId, type MigrationMarker, type RootDocumentUnreadableReason } from "./config-root-documents.js";
|
|
15
15
|
export * from "./loopback.js";
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ export * from "./url-shape.js"; // 11.0.0: THE URL shape judge (httpUrlFlaws / h
|
|
|
9
9
|
export * from "./device-relay.js"; // 16.0.0: THE value grammar of the device lane's DEVICE_RELAY_URL (DEVICE_RELAY_NONE / deviceRelayFlaws / DEVICE_RELAY_RULE), pure/browser-safe
|
|
10
10
|
export * from "./url-credential.js"; // 14.5.0: THE "does this URL carry a credential" judge (findUrlCredential / findUrlUserinfo / URL_CREDENTIAL_REASONS / CREDENTIAL_PARAM_NAMES …), pure/browser-safe
|
|
11
11
|
export * from "./default-model.js"; // 11.0.0: THE catalog-default resolver (roles.default → active tier ladder → fallback), pure/browser-safe
|
|
12
|
-
export { catalogManagesModelPlane, enabledEntryCount } from "./catalog-manages.js"; // THE "does this models document manage the model plane" judge (raw half: at least one entry not explicitly disabled) + the log count it is derived from, pure/browser-safe
|
|
12
|
+
export { catalogManagesModelPlane, enabledEntryCount, isExplicitlyDisabledEntry } from "./catalog-manages.js"; // THE "does this models document manage the model plane" judge (raw half: at least one entry not explicitly disabled) + the log count it is derived from + THE "is this one entry explicitly disabled" predicate they (and every per-entry consumer) read (the three-state `enabled` reading stays package-private), pure/browser-safe
|
|
13
13
|
export { DEFAULT_MODEL_KEY, ENV_MODEL_TABLE_KEYS, buildEnvModelBaseline, envModelTableDeclared, envModelTableWriteRefusal, mintedCheapId, planEnvModelTableWrite, readEnvModelSlots, } from "./env-model-table.js"; // the env model table (MODEL_ID / MODEL_CHEAP_ID) read once: readEnvModelSlots / envModelTableDeclared / buildEnvModelBaseline + the writer's plan planEnvModelTableWrite (receipt by id, confirmKey) + envModelTableWriteRefusal, pure/browser-safe (named: the env snapshot helper stays package-private)
|
|
14
14
|
export { CONFIG_ROOT_DOCUMENTS, ENV_MODELS_DECISIONS, ENV_MODELS_DOCUMENT, ROOT_DOCUMENT_UNREADABLE_REASONS, envModelsDecisionTag } from "./config-root-documents.js"; // the config-root documents (config.env-models.json + the per-id migration marker config.migration.<id>.json): names + closed answer tables + the one tagged identity of a decision reading (envModelsDecisionTag); the readers / writer are in ./node
|
|
15
15
|
export * from "./loopback.js"; // 11.0.0: the two「本机」predicates (auth relaxation — narrow / connection routing — wide), pure/browser-safe
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type McpContentOrigin } from "./types.js";
|
|
2
|
+
import { type ReservedMemberName } from "./reserved-member-name.js";
|
|
2
3
|
/** 值的**种类**(不回显值本身)。总(不抛):形状只问座位,读不出的对象说全包唯一的「检视不了」那一句。 */
|
|
3
4
|
export declare function describeValueShape(v: unknown): string;
|
|
4
5
|
/** 「不是字符串数组」的种类:数组里混了非串元素说那一句,否则回落到 {@link describeValueShape}。总(不抛):`isJsonArray` 是座位的总版。 */
|
|
@@ -12,19 +13,13 @@ export declare function describeNotStringRecord(v: unknown): string;
|
|
|
12
13
|
*/
|
|
13
14
|
export declare function isStringArray(v: unknown): v is string[];
|
|
14
15
|
/**
|
|
15
|
-
* 纯数据的「名 → 串」记录(空对象合法;数组、`Map
|
|
16
|
+
* 纯数据的「名 → 串」记录(空对象合法;数组、`Map`、类实例、有保留名成员({@link isReservedMemberName})、有非串成员的对象都不是)—— 类型守卫,所以是**严归类**:成员经内核的
|
|
16
17
|
* `ownEntriesOf` 读(整容器读的严归类:每个自有串键一份描述符;访问器成员或不可枚举的成员 ⇒ 不是,getter 一次都不调 —— 守卫为真,调用方随后的普通读读到的就是判过的那一份)。
|
|
17
|
-
* 传输读器读 `env` / `headers`({@link readPlainStringRecord})交出去的是**副本**,按宽归类读(不可枚举的成员照读、访问器调一次);值与成员名的判据(
|
|
18
|
+
* 传输读器读 `env` / `headers`({@link readPlainStringRecord})交出去的是**副本**,按宽归类读(不可枚举的成员照读、访问器调一次);值与成员名的判据(是串、不是保留名)两边同一条。
|
|
18
19
|
*/
|
|
19
20
|
export declare function isStringRecord(v: unknown): v is Record<string, string>;
|
|
20
|
-
|
|
21
|
-
export
|
|
22
|
-
/**
|
|
23
|
-
* 这个申报名能用吗。严判:非串、空串、超 {@link TOOL_WIRE_NAME_MAX_CHARS}、**首尾带空白**一律不可用。不截断、不 trim、不规范化 —— 截短或剥掉一个名字就是**换一个身份**,
|
|
24
|
-
* 而被换掉身份的那台 server 上挂的 allowTools / toolFaces 收窄声明会一起对不上号。首尾空白 = 坏名(它不是另一个名字:名字是 `mcp__<server>__<tool>` 的身份片,
|
|
25
|
-
* 带着空白的一端无从与不带的那个对上号);内部空白(`a b`)照旧是合法名,本判官不扩判。
|
|
26
|
-
*/
|
|
27
|
-
export declare function isUsableWireName(v: unknown): v is string;
|
|
21
|
+
export { TOOL_WIRE_NAME_MAX_CHARS, isUsableWireName } from "./wire-name.js";
|
|
22
|
+
export { RESERVED_MEMBER_NAMES, isReservedMemberName, type ReservedMemberName } from "./reserved-member-name.js";
|
|
28
23
|
/**
|
|
29
24
|
* 坏名的**可打印**摘要(进拒句 / 告警元数据):种类、`empty`,或引号形的回显加原因 —— 绝不把任意长度的申报串原样回显。回显口径见 {@link quotedCallerText}
|
|
30
25
|
* (剥控制与双向字符、截 64 字)。串的原因是:超界 ⇒ `N chars > 128`(N 是送来的原长度,不是剥完的);首尾带空白 ⇒ `leading or trailing whitespace`
|
|
@@ -82,7 +77,7 @@ export type RequestMcpTransport = {
|
|
|
82
77
|
* `env` / `headers` 这两张「名 → 串」记录上的坏形另带两格机读位,调用方分流不必解析句子:`fault` = 闭集词({@link PLAIN_STRING_RECORD_FAULTS},与公开的记录读器 {@link readPlainStringRecord} 同一张表)——
|
|
83
78
|
* · `not_plain_record`:这个键的值不是纯数据记录(不是对象 / 数组 / `null`,或不是朴素 JSON 对象 —— 原型链比座位的判据长:`Map`、`Set`、类实例;读形状就抛的对象同);整张记录不交;
|
|
84
79
|
* · `member_not_string`:有一个成员的值不是串,或它读不出(它的访问器抛了,或读它的描述符时代理陷阱抛了);整张记录不交,`member` 点名它,两种情形句子分说;
|
|
85
|
-
* · `member_name_reserved
|
|
80
|
+
* · `member_name_reserved`:有成员叫保留名({@link RESERVED_MEMBER_NAMES}:`__proto__` / `constructor` / `prototype`)。值是串 ⇒ 只剔它、其余照交,每个一条、`path` 是成员级(`transport.env.__proto__`);
|
|
86
81
|
* 成员的值也不是串(或读不出)⇒ 整张记录不交,`path` 是键级,句子一次说全两件事 —— 名坏优先、值坏并列,所以词仍是 `member_name_reserved`。
|
|
87
82
|
* `member` 是成员名的**回显形**(剥控制与双向字符、截 64 字加 `…`),可直接进日志与句子,不是回查原对象的键。其余的坏形(`args` / `url` / `principalHeader` / ……)两格都不带。
|
|
88
83
|
*/
|
|
@@ -107,16 +102,11 @@ export type RequestMcpTransportRead = {
|
|
|
107
102
|
* · 软坏形(`args` 不是串数组 / `env` `headers` 不是纯数据的串记录 / `principalHeader` 非串)⇒ 读器**丢这个键**(重放存量提交体时的升级前读法),并把它记进 `lost`
|
|
108
103
|
* (受理新提交的门据它响亮拒)。`assertionHeader` 不在 `lost` 里:两个身份头的键组合与 `assertionHeader` 的值形由调用方在读之前对原始传输判。
|
|
109
104
|
* · `env` / `headers` 只收**纯数据**的记录({@link readPlainStringRecord}):必须是朴素 JSON 对象(`./plain-json-object` 的判据;`Map`、`Set`、类实例整张不收),每个自有成员的值都是串;
|
|
110
|
-
* 交出的是**副本**(不是调用方的对象,改原对象不影响读后的形)
|
|
105
|
+
* 交出的是**副本**(不是调用方的对象,改原对象不影响读后的形)。名叫保留名({@link RESERVED_MEMBER_NAMES})的成员不进副本、每个单独记进 `lost`。
|
|
111
106
|
* 坏形的 `lost` 条目带机读位(见 {@link McpEntryKeyIssue})。
|
|
112
107
|
* url 的拒句不回显值:它常规地带凭据(userinfo)。
|
|
113
108
|
*/
|
|
114
109
|
export declare function readRequestMcpTransport(t: unknown): RequestMcpTransportRead;
|
|
115
|
-
/**
|
|
116
|
-
* 引擎的声明收据不收的成员名(core `mcp-server-spec`:按赋值拷贝它会变成原型):JSON 文本铸得出这个**自有**键,对象字面量写不出。
|
|
117
|
-
* 公开,因为读器交出 `reservedMember: true` 时消费方要点名它 —— 名字只在这里定一次。
|
|
118
|
-
*/
|
|
119
|
-
export declare const PLAIN_STRING_RECORD_RESERVED_MEMBER = "__proto__";
|
|
120
110
|
/**
|
|
121
111
|
* 「名 → 串」记录读不交(或交时点名保留名)的**原因词**,闭集,三个词、一张表:
|
|
122
112
|
* 整张一词(`not_plain_record`)· 成员级一词(`member_not_string`:值读成了别的种类,或读成员时抛了 —— 句子分说)· 名字级一词(`member_name_reserved`)。
|
|
@@ -127,12 +117,12 @@ export declare const PLAIN_STRING_RECORD_FAULTS: readonly ["not_plain_record", "
|
|
|
127
117
|
export type PlainStringRecordFault = (typeof PLAIN_STRING_RECORD_FAULTS)[number];
|
|
128
118
|
/**
|
|
129
119
|
* {@link readPlainStringRecord} 的读数:`ok:false` = 记录不交(`fault` = 原因词;`detail` 是接在 `must be a plain object of string values — ` 后面的句子;坏在某个成员时 `member` 点名它的回显形);
|
|
130
|
-
* `ok:true` = 交出去的纯数据副本,`
|
|
120
|
+
* `ok:true` = 交出去的纯数据副本,`reservedMembers` = 记录里名叫保留名({@link RESERVED_MEMBER_NAMES})的成员,按自有键序(它们没进副本)。
|
|
131
121
|
*/
|
|
132
122
|
export type PlainStringRecordRead = {
|
|
133
123
|
readonly ok: true;
|
|
134
124
|
readonly record: Record<string, string>;
|
|
135
|
-
readonly
|
|
125
|
+
readonly reservedMembers: readonly ReservedMemberName[];
|
|
136
126
|
} | {
|
|
137
127
|
readonly ok: false;
|
|
138
128
|
readonly detail: string;
|
|
@@ -143,7 +133,7 @@ export type PlainStringRecordRead = {
|
|
|
143
133
|
* 读一份「名 → 串」记录 —— **公开读口**:传输读器读 `env` / `headers` 用的就是它,消费方读自己的「名 → 串」记录(中心名册的引用表)调同一只,不抄镜像。从不抛。记录交不交:是朴素 JSON 对象(座位的判据,见 `./plain-json-object`:原型是 `null`,或原型自己的原型是 `null`;纯数据 —— `Map`、`Set`、类实例、建在原型上的记录都不是),
|
|
144
134
|
* 且每个成员的值都是串。成员 = `Object.getOwnPropertyNames` 的每一个名字(不可枚举的也算 —— 引擎的收据按全部自有属性名读),值经内核 `readKey` 读(一份描述符:数据属性取值,访问器调一次,不问 `get` 陷阱;访问器或描述符 trap 抛了同判为坏 —— 词与「值不是串」同是 `member_not_string`,句子说读不出)。
|
|
145
135
|
* 读原型与成员名时代理 trap 抛了 ⇒ 整张不交(读器对调用方递来的任何对象都不抛;`JSON` 存体里不会有代理,这条只落在直接调读器的嵌入方身上)。
|
|
146
|
-
* 交出去的是副本(原型 `Object.prototype`、成员全可枚举)
|
|
147
|
-
*
|
|
136
|
+
* 交出去的是副本(原型 `Object.prototype`、成员全可枚举),调用方的对象不被交出去、也不被改;名叫保留名({@link isReservedMemberName})的成员不进副本,`reservedMembers` 记下它们。
|
|
137
|
+
* 名叫保留名而值也坏的成员,句子一次说全两件事(名坏在前、值坏并列):调用方照值改完再撞第二条是两步才改对。
|
|
148
138
|
*/
|
|
149
139
|
export declare function readPlainStringRecord(v: unknown): PlainStringRecordRead;
|