@sema-agent/settings-schema 14.7.0 → 15.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 +306 -0
- package/README.md +80 -3
- package/conformance/VERSION +1 -1
- package/conformance/cases/c59-s784-g3-k8s-missing-image/input.json +4 -1
- package/conformance/cases/c61-s784-g3-other-lane-key/input.json +1 -0
- package/conformance/cases/c64-s784-multitenant-local-store/input.json +2 -1
- package/dist/atomic-write.d.ts +15 -0
- package/dist/atomic-write.js +109 -5
- package/dist/catalog-manages.d.ts +15 -0
- package/dist/catalog-manages.js +60 -0
- package/dist/center-refs.d.ts +68 -0
- package/dist/center-refs.js +70 -0
- package/dist/config-dir-migration.js +1 -0
- package/dist/config-fns.js +5 -3
- package/dist/config-root-documents.d.ts +106 -0
- package/dist/config-root-documents.js +93 -0
- package/dist/config-root-node.d.ts +117 -0
- package/dist/config-root-node.js +260 -0
- package/dist/conformance/run.d.ts +3 -0
- package/dist/conformance/run.js +10 -6
- package/dist/conformance/temp-roots.d.ts +31 -0
- package/dist/conformance/temp-roots.js +184 -0
- package/dist/default-model.d.ts +1 -1
- package/dist/default-model.js +5 -4
- package/dist/env-model-table.d.ts +163 -0
- package/dist/env-model-table.js +257 -0
- package/dist/execution-lane-index.d.ts +6 -0
- package/dist/execution-lane-index.js +8 -0
- package/dist/execution-lanes.d.ts +2 -1
- package/dist/execution-lanes.js +6 -4
- package/dist/fleet.d.ts +25 -7
- package/dist/fleet.js +24 -6
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/mcp-request-entry.d.ts +58 -6
- package/dist/mcp-request-entry.js +45 -13
- package/dist/mcp-server-name.d.ts +17 -0
- package/dist/mcp-server-name.js +19 -0
- package/dist/migration-receipt.d.ts +10 -6
- package/dist/migration-receipt.js +5 -3
- package/dist/node.d.ts +1 -0
- package/dist/node.js +2 -0
- package/dist/one-time-migrations.d.ts +4 -2
- package/dist/one-time-migrations.js +29 -1
- package/dist/own-key-read.d.ts +1 -1
- package/dist/remote-exec.d.ts +1 -1
- package/dist/remote-exec.js +4 -2
- package/dist/retired-form.d.ts +19 -0
- package/dist/retired-form.js +24 -1
- package/dist/safety-merge-spec.d.ts +6 -6
- package/dist/tier-words.d.ts +33 -0
- package/dist/tier-words.js +43 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +29 -5
- package/dist/worker-row-verdict.js +7 -1
- package/docs/API-SURFACE.md +68 -4
- package/docs/CONSUMER-INTEGRATION.md +72 -2
- package/llms-full.txt +8 -3
- package/llms.txt +9 -3
- package/package.json +2 -2
|
@@ -11,7 +11,13 @@
|
|
|
11
11
|
* **迁移只认形、不认义**:每一步的输入形在新契约下非法、输出形合法 ⇒ 重跑恒等,新写入的数据永远不会被当成旧数据再改一次,不需要版本围栏;
|
|
12
12
|
* 同一串字节换意思的改动一律**换表示**(SS-M6 因此是「`atModelAllowlist` → `atMention`」换字段,而不是翻 `[]` 的义)。
|
|
13
13
|
*
|
|
14
|
-
* ##
|
|
14
|
+
* ## 第二种机制:在配置根上铸一次事实(只有 SS-M11)
|
|
15
|
+
* 上面的「只认形」律管的是**改写存储文档**的迁移。SS-M11 不改写任何存储形:它在一份文档**缺席**处铸一份部署决定(配置根的 `config.env-models.json`,收据词 `minted`),
|
|
16
|
+
* 而「缺席」本身没有形可认 —— 所以它不归上面的律,另有三条:① 它读 env、碰文件系统,住 `./node`(`migrateEnvModelsDecision`),不在下面的纯函数入口里;
|
|
17
|
+
* ② 它靠**按 id 一份的运行记录**(`config.migration.SS-M11.json`,「不存在才建」)跑恰一次,建成运行记录的进程是本根唯一的执行者;
|
|
18
|
+
* ③ 它的旧形待遇是 `read-as-default`(缺席按读者的缺省 `kept` 读,没有拒句可点名)。窗、删法与删后由谁接住照样只写在登记表那一行。
|
|
19
|
+
*
|
|
20
|
+
* ## 入口(纯函数:不读环境、不读墙钟、不改入参、**不抬任何版本号**;SS-M11 除外,见上一节)
|
|
15
21
|
* · {@link migrateStoredDocuments} —— 一组**存储文档**(域名 → 文档;还有本机的 `remote-exec` —— `config.d/remote-exec.json`,
|
|
16
22
|
* 只有 SS-M7 的座位走查读它)。一个 scope 的全部草稿、一个 principal 层(个人 models / mcp / skills / plugins)、回滚史里的一条单域行,各调一次;`coverage` 说这组文档是不是一个 scope 的全集(只有 SS-M1 要知道:缺席的
|
|
17
23
|
* `governance` 是「从未设过」还是「没给」)。缺的域 = 不动。
|
|
@@ -176,6 +182,28 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
176
182
|
afterRemoval: "the prompts `bindings` / `catalog` tombstone fields (permanent): a residual key is refused on read and write (the prompts domain degrades " +
|
|
177
183
|
"to its default — no center layer is served)",
|
|
178
184
|
},
|
|
185
|
+
{
|
|
186
|
+
id: "SS-M11",
|
|
187
|
+
oldForm: "read-as-default",
|
|
188
|
+
introducedIn: "14.8.0",
|
|
189
|
+
releasedOn: "2026-10-27",
|
|
190
|
+
removableAfter: "2026-11-26",
|
|
191
|
+
rewrites: "nothing stored is rewritten — the config root's env-model-table decision is minted once (migrateEnvModelsDecision, ./node): when the run " +
|
|
192
|
+
"marker config.migration.SS-M11.json is absent (a marker that does not read counts as run), the decision and whether config.d/models.json " +
|
|
193
|
+
"manages the model plane (catalogManagesModelPlane) are read first; then the marker is created exclusively — the one process that creates " +
|
|
194
|
+
"it is the only one that may mint on this root, any other stops for good — and that minter creates {\"envModels\":\"replaced\"} " +
|
|
195
|
+
"exclusively only when the decision it read before the election is absent and the catalog manages the model plane (whether an env model " +
|
|
196
|
+
"table is declared does not matter: the env only names the replaced env models) — the reading before the decision existed (a managing " +
|
|
197
|
+
"catalog replaced the env model table). Outcomes: minted / exists (only EEXIST) / failed (errno + a manual way out); an interruption after the marker is " +
|
|
198
|
+
"never retried. An absent root is created owner-only, holding only the marker; config.d is never created",
|
|
199
|
+
removal: "the next major after the window: delete migrateEnvModelsDecision (the SS-M11 body), this row, SS-M11 from ONE_TIME_MIGRATION_IDS, the " +
|
|
200
|
+
"`minted` receipt word and the `read-as-default` oldForm word; the marker then has no reader — readMigrationMarker and the marker's " +
|
|
201
|
+
"entry in CONFIG_ROOT_DOCUMENTS go with it (a marker left on disk is inert)",
|
|
202
|
+
afterRemoval: "an absent decision reads as kept — the reading the group-refusal code config.catalog_replaces_env_models is for: this package exports " +
|
|
203
|
+
"that code constant and the decision document for the engine to read, enforcing it is the engine's side, and the engine does not " +
|
|
204
|
+
"refuse on it today. Where the engine refuses, the way out is to write config.env-models.json = {\"envModels\":\"replaced\"} in the " +
|
|
205
|
+
"config root; no signpost in this package",
|
|
206
|
+
},
|
|
179
207
|
{
|
|
180
208
|
// 一条 wire 位的删码登记,不是数据迁移(id 在 WIRE_RETIREMENT_IDS,不在收据闭集)。
|
|
181
209
|
id: "SS-W1",
|
package/dist/own-key-read.d.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* 以及交回原引用 / 作类型守卫 / 对原值下判决的读口:`isStringArray` / `isStringRecord` / `isSchedulerRecord`、`readSettingsUnit` 的列表单元与环境变量表、比较器的串集合(`tightenVerdict` 的集合规则)。
|
|
25
25
|
* 内核覆盖声明键读与整容器读;**仍自带读法的读者按名登记**(各自写明契约;普查钉按「文件 → 函数 → 读法 API」逐处数,登记外出现即红):
|
|
26
26
|
* 既有、未经内核的数据读者:`tightenVerdict` 的 `none` 规则(`strictJsonCopy`:对象的不可枚举键跳过、访问器 ⇒ 整份 `unreadable`;数组按 `length` 逐位读描述符 —— `length` 走一次 `[[Get]]`、不可枚举的下标照读)·
|
|
27
|
-
* 被丢条目的身份(`readEntryIdentity
|
|
27
|
+
* 被丢条目的身份(`readEntryIdentity` 读 `name` / `id`,它调的 `ownEnabledFlag`(`./catalog-manages`,与原文判官共用)读 `enabled` —— 同一读法:访问器 ⇒ 当缺席,从不调)· 传输记录读法(`readPlainStringRecord`:自己枚举成员名 `getOwnPropertyNames`,值经 {@link readKey});
|
|
28
28
|
* 不是数据读的:安全判官 `extraBodyUnsafe` 的审计读(`./types`:问「任何自有键上有没有可疑」,含符号键与会抛的描述符,访问器 ⇒ 判不安全,从不调)。
|
|
29
29
|
* 直接用 `[[Get]]` 的几处(不经内核,按名登记):hooks 分类器(`Object.keys` + 成员读;闭包可抄的内建写法,随闭包契约变更收)· `collectDropped` / `collectionSlots`(`./config-fns`:
|
|
30
30
|
* 未知键扫描与条目集合的位置表,自己枚举容器再 `[[Get]]`;既有)· http hook 名单读器与判官的**普通读对拍**(安全轴的名单、判官的 `layers` / `hookVars` 要描述符视图
|
package/dist/remote-exec.d.ts
CHANGED
|
@@ -63,7 +63,7 @@ export declare const RemoteExecSpec: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
63
63
|
tokenEnv: z.ZodOptional<z.ZodString>;
|
|
64
64
|
caCertEnv: z.ZodOptional<z.ZodString>;
|
|
65
65
|
insecureTls: z.ZodOptional<z.ZodBoolean>;
|
|
66
|
-
namespace: z.
|
|
66
|
+
namespace: z.ZodString;
|
|
67
67
|
runtimeClass: z.ZodOptional<z.ZodString>;
|
|
68
68
|
mountPath: z.ZodOptional<z.ZodString>;
|
|
69
69
|
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
package/dist/remote-exec.js
CHANGED
|
@@ -84,7 +84,7 @@ export const RemoteExecSpec = z.discriminatedUnion("provider", [
|
|
|
84
84
|
/** Which of THIS process's env-NAMEs to forward into the sandbox (service: E2B_SANDBOX_ENV, a CSV of NAMEs). */
|
|
85
85
|
sandboxEnv: z.array(ENV_NAME).optional(),
|
|
86
86
|
}),
|
|
87
|
-
// ── k8s: per-task Kata pod (service provider "k8s"; REMOTE_EXEC=k8s + K8S_SANDBOX_IMAGE).
|
|
87
|
+
// ── k8s: per-task Kata pod (service provider "k8s"; REMOTE_EXEC=k8s + K8S_SANDBOX_IMAGE + K8S_NAMESPACE).
|
|
88
88
|
z.object({
|
|
89
89
|
provider: z.literal("k8s"),
|
|
90
90
|
/** Sandbox container image (service: K8S_SANDBOX_IMAGE). Required so a run is reproducible. */
|
|
@@ -97,7 +97,9 @@ export const RemoteExecSpec = z.discriminatedUnion("provider", [
|
|
|
97
97
|
/** env-NAME holding the base64 CA cert (service: K8S_CA_CERT_B64). NEVER the cert bytes. */
|
|
98
98
|
caCertEnv: ENV_NAME.optional(),
|
|
99
99
|
insecureTls: z.boolean().optional(),
|
|
100
|
-
namespace:
|
|
100
|
+
/** The namespace the sandbox pods live in (service: K8S_NAMESPACE). Required — the deployment declares where its pods run and nothing here guesses one;
|
|
101
|
+
* the execution-lane table lists K8S_NAMESPACE as a required coordinate of the k8s lane, and this file contract says the same. */
|
|
102
|
+
namespace: execStr,
|
|
101
103
|
runtimeClass: execStr.optional(),
|
|
102
104
|
mountPath: execStr.optional(),
|
|
103
105
|
timeoutMs: INTEGER.positive().optional(),
|
package/dist/retired-form.d.ts
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 墓碑是**拒**,不是第二种读法:它不把旧形读成任何值,只说「这里有一份没迁的旧形」以及去哪儿迁。迁移族按登记表的窗整族删,
|
|
9
9
|
* 墓碑留下 —— 到那时拒句里的迁移 id 由删码那一车改写(登记表那一行的 `removal` 点名了这件事)。
|
|
10
|
+
*
|
|
11
|
+
* **墓碑表**:每个 {@link retiredKey} 铸出的墓碑在铸造时登记一行({@link RetiredKeyRow}:键名、形、整句)。表的读者两个 —— 读面的终判
|
|
12
|
+
* ({@link retiredKeyOfSentence}:一条 zod issue 的 message 恰是某个墓碑的整句 ⇒ 这是一条墓碑 issue)与测试({@link retiredKeyTable}:从表读名单,不手抄)。
|
|
10
13
|
*/
|
|
11
14
|
import { z } from "zod";
|
|
12
15
|
/** 迁移命令行的唯一拼写:`npx` 全名形 —— 没装本包的运维粘贴即可跑(裸 bin 名在没装本包的机器上是 `command not found`)。参数是一个 `config.d` 目录。
|
|
@@ -29,8 +32,24 @@ export interface RetiredForm {
|
|
|
29
32
|
readonly migration: string;
|
|
30
33
|
}
|
|
31
34
|
export declare function retiredFormSentence(form: string, t: RetiredForm): string;
|
|
35
|
+
/** 墓碑表的一行:`key` 是墓碑字段在它所在对象里的点路径(例:`runtime.sessionBackend`),`sentence` 是它的拒句整句(= 那条 zod issue 的 message)。 */
|
|
36
|
+
export interface RetiredKeyRow {
|
|
37
|
+
readonly key: string;
|
|
38
|
+
readonly form: RetiredForm;
|
|
39
|
+
readonly sentence: string;
|
|
40
|
+
}
|
|
32
41
|
/**
|
|
33
42
|
* retired**键**的墓碑字段:放在该键原来所在的对象形里,键缺席 = 合法,键在场(任何值)= 一条 issue(路径就是那个键、句子点名迁移)。
|
|
34
43
|
* 输出形里它恒缺席(型上是 `?: undefined`),JSON Schema 上是 `not: {}`(「不许出现」)—— 墓碑写在旧键原来的位置上,schema 自己说明它retired了。
|
|
35
44
|
*/
|
|
36
45
|
export declare function retiredKey(key: string, t: RetiredForm): z.ZodOptional<z.ZodNever>;
|
|
46
|
+
/** 墓碑表(一份副本,按铸造次序)。 */
|
|
47
|
+
export declare function retiredKeyTable(): readonly RetiredKeyRow[];
|
|
48
|
+
/** 一条 zod issue 的 message 恰是某个墓碑的整句 ⇒ 那一行;否则 `undefined`。 */
|
|
49
|
+
export declare function retiredKeyOfSentence(message: string): RetiredKeyRow | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* 墓碑在**读面**(终判扣下一行时的拒句)的说法:不点名那个旧字段的名字 —— 它就在盘上那一行里,结构化的坐标(`field`)已经指到它;
|
|
52
|
+
* 文字说现行位、迁移是一条出路,以及「迁移拒过这一行」的出路。读面是纯函数、无 I/O,不知道这一行跑没跑过迁移,所以两种情形都要成立:
|
|
53
|
+
* 没跑过 ⇒ 跑迁移;跑过且拒了(迁移不写回半成品,原行留在盘上)⇒ 手写现行形、删掉旧字段。
|
|
54
|
+
*/
|
|
55
|
+
export declare function retiredKeyHeldSentence(t: RetiredForm): string;
|
package/dist/retired-form.js
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 墓碑是**拒**,不是第二种读法:它不把旧形读成任何值,只说「这里有一份没迁的旧形」以及去哪儿迁。迁移族按登记表的窗整族删,
|
|
9
9
|
* 墓碑留下 —— 到那时拒句里的迁移 id 由删码那一车改写(登记表那一行的 `removal` 点名了这件事)。
|
|
10
|
+
*
|
|
11
|
+
* **墓碑表**:每个 {@link retiredKey} 铸出的墓碑在铸造时登记一行({@link RetiredKeyRow}:键名、形、整句)。表的读者两个 —— 读面的终判
|
|
12
|
+
* ({@link retiredKeyOfSentence}:一条 zod issue 的 message 恰是某个墓碑的整句 ⇒ 这是一条墓碑 issue)与测试({@link retiredKeyTable}:从表读名单,不手抄)。
|
|
10
13
|
*/
|
|
11
14
|
import { z } from "zod";
|
|
12
15
|
import { shellQuote } from "./shell-quote.js";
|
|
@@ -27,10 +30,30 @@ export function migrationSignpost(migration, before) {
|
|
|
27
30
|
export function retiredFormSentence(form, t) {
|
|
28
31
|
return `${form} was retired in ${t.retiredIn} — now ${t.now}; ${migrationSignpost(t.migration, t.retiredIn)}`;
|
|
29
32
|
}
|
|
33
|
+
/** 整句 → 行。同一个键在两处 schema 里以同一个形退役(整句逐字同)只占一行。 */
|
|
34
|
+
const TOMBSTONES = new Map();
|
|
30
35
|
/**
|
|
31
36
|
* retired**键**的墓碑字段:放在该键原来所在的对象形里,键缺席 = 合法,键在场(任何值)= 一条 issue(路径就是那个键、句子点名迁移)。
|
|
32
37
|
* 输出形里它恒缺席(型上是 `?: undefined`),JSON Schema 上是 `not: {}`(「不许出现」)—— 墓碑写在旧键原来的位置上,schema 自己说明它retired了。
|
|
33
38
|
*/
|
|
34
39
|
export function retiredKey(key, t) {
|
|
35
|
-
|
|
40
|
+
const sentence = retiredFormSentence(key, t);
|
|
41
|
+
TOMBSTONES.set(sentence, Object.freeze({ key, form: t, sentence }));
|
|
42
|
+
return z.never({ error: sentence }).optional();
|
|
43
|
+
}
|
|
44
|
+
/** 墓碑表(一份副本,按铸造次序)。 */
|
|
45
|
+
export function retiredKeyTable() {
|
|
46
|
+
return [...TOMBSTONES.values()];
|
|
47
|
+
}
|
|
48
|
+
/** 一条 zod issue 的 message 恰是某个墓碑的整句 ⇒ 那一行;否则 `undefined`。 */
|
|
49
|
+
export function retiredKeyOfSentence(message) {
|
|
50
|
+
return TOMBSTONES.get(message);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 墓碑在**读面**(终判扣下一行时的拒句)的说法:不点名那个旧字段的名字 —— 它就在盘上那一行里,结构化的坐标(`field`)已经指到它;
|
|
54
|
+
* 文字说现行位、迁移是一条出路,以及「迁移拒过这一行」的出路。读面是纯函数、无 I/O,不知道这一行跑没跑过迁移,所以两种情形都要成立:
|
|
55
|
+
* 没跑过 ⇒ 跑迁移;跑过且拒了(迁移不写回半成品,原行留在盘上)⇒ 手写现行形、删掉旧字段。
|
|
56
|
+
*/
|
|
57
|
+
export function retiredKeyHeldSentence(t) {
|
|
58
|
+
return `a field retired in ${t.retiredIn} is still in the row — now ${t.now}; ${migrationSignpost(t.migration, t.retiredIn)}; if that migration already refused this row, write the current form by hand and delete the old field`;
|
|
36
59
|
}
|
|
@@ -92,8 +92,8 @@ export declare const MIN_TRUST_WORDS: readonly ["local", "session", "project", "
|
|
|
92
92
|
export declare const MinTrust: z.ZodEnum<{
|
|
93
93
|
local: "local";
|
|
94
94
|
session: "session";
|
|
95
|
-
project: "project";
|
|
96
95
|
global: "global";
|
|
96
|
+
project: "project";
|
|
97
97
|
managed: "managed";
|
|
98
98
|
task: "task";
|
|
99
99
|
}>;
|
|
@@ -151,8 +151,8 @@ export declare const MemberAdmission: z.ZodObject<{
|
|
|
151
151
|
minTrust: z.ZodOptional<z.ZodEnum<{
|
|
152
152
|
local: "local";
|
|
153
153
|
session: "session";
|
|
154
|
-
project: "project";
|
|
155
154
|
global: "global";
|
|
155
|
+
project: "project";
|
|
156
156
|
managed: "managed";
|
|
157
157
|
task: "task";
|
|
158
158
|
}>>;
|
|
@@ -161,8 +161,8 @@ export declare const MemberAdmission: z.ZodObject<{
|
|
|
161
161
|
minTrust: z.ZodEnum<{
|
|
162
162
|
local: "local";
|
|
163
163
|
session: "session";
|
|
164
|
-
project: "project";
|
|
165
164
|
global: "global";
|
|
165
|
+
project: "project";
|
|
166
166
|
managed: "managed";
|
|
167
167
|
task: "task";
|
|
168
168
|
}>;
|
|
@@ -264,8 +264,8 @@ export declare const MergeCategorySpec: z.ZodObject<{
|
|
|
264
264
|
minTrust: z.ZodEnum<{
|
|
265
265
|
local: "local";
|
|
266
266
|
session: "session";
|
|
267
|
-
project: "project";
|
|
268
267
|
global: "global";
|
|
268
|
+
project: "project";
|
|
269
269
|
managed: "managed";
|
|
270
270
|
task: "task";
|
|
271
271
|
}>;
|
|
@@ -314,8 +314,8 @@ export declare const MergeCategorySpec: z.ZodObject<{
|
|
|
314
314
|
minTrust: z.ZodOptional<z.ZodEnum<{
|
|
315
315
|
local: "local";
|
|
316
316
|
session: "session";
|
|
317
|
-
project: "project";
|
|
318
317
|
global: "global";
|
|
318
|
+
project: "project";
|
|
319
319
|
managed: "managed";
|
|
320
320
|
task: "task";
|
|
321
321
|
}>>;
|
|
@@ -324,8 +324,8 @@ export declare const MergeCategorySpec: z.ZodObject<{
|
|
|
324
324
|
minTrust: z.ZodEnum<{
|
|
325
325
|
local: "local";
|
|
326
326
|
session: "session";
|
|
327
|
-
project: "project";
|
|
328
327
|
global: "global";
|
|
328
|
+
project: "project";
|
|
329
329
|
managed: "managed";
|
|
330
330
|
task: "task";
|
|
331
331
|
}>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 档位词(纯、零 I/O、浏览器安全;**包内叶子模块,不出包**):引擎的档序与 CC 档位别名、从某档起向低档的梯,与「一个目录词在档位展开之后落到哪条条目」。
|
|
3
|
+
* 本包里档位词的唯一一处:default 角色的档梯(`./default-model`)与写者计划助手的落点(`./env-model-table`)都从这里取。
|
|
4
|
+
* 镜像 core(`DEFAULT_TIER_ORDER` / `CC_MODEL_TIER_ALIASES` / `expandTiers`):`test/tier-words-parity-14.8.0` 对 devDependency 里精确钉住的那一版 core 对拍。
|
|
5
|
+
*/
|
|
6
|
+
/** 引擎的档序(高 → 低)。 */
|
|
7
|
+
export declare const TIER_ORDER: readonly ["ultra", "max", "pro", "flash", "lite"];
|
|
8
|
+
/** 一个档位词。 */
|
|
9
|
+
export type TierWord = (typeof TIER_ORDER)[number];
|
|
10
|
+
/** CC 档位词 → 引擎档位。 */
|
|
11
|
+
export declare const CC_TIER_ALIASES: {
|
|
12
|
+
readonly fable: "max";
|
|
13
|
+
readonly mythos: "max";
|
|
14
|
+
readonly opus: "pro";
|
|
15
|
+
readonly sonnet: "flash";
|
|
16
|
+
readonly haiku: "lite";
|
|
17
|
+
};
|
|
18
|
+
/** 档序里从 `S` 起(含)向低档的那一段,字面元组型。 */
|
|
19
|
+
type LadderFrom<S extends TierWord, T extends readonly TierWord[] = typeof TIER_ORDER> = T extends readonly [infer H, ...infer R extends readonly TierWord[]] ? H extends S ? Readonly<T> : LadderFrom<S, R> : readonly [];
|
|
20
|
+
/** 一档的梯:档序里从它起(含)向低档的那一段(没绑的档沿它往下落)。 */
|
|
21
|
+
export declare function tierLadderFrom<S extends TierWord>(tier: S): LadderFrom<S>;
|
|
22
|
+
/**
|
|
23
|
+
* 一个目录词(条目名 / 档位词 / CC 档位别名 / `best`)在**档位展开之后**落到哪条目录条目名 —— 与引擎装配档位表的两步同答:
|
|
24
|
+
* 先摘掉活跃组里绑定目标不可服务的档(引擎的生效装配在交给 core 之前做这一步,并 warn 点名),再按 core `expandTiers` 展开
|
|
25
|
+
* (对拍 devDependency 那一版 core 的「摘后表」)。所以这里只有一条绑定规则:**一档的绑定只在它点名一条可服务条目时算数**,否则当作没绑。展开规则:
|
|
26
|
+
* · 目录自己的键先赢(`has(word)`;一条就叫 `flash` 的条目遮住档位词);
|
|
27
|
+
* · 档位词 ⇒ 它的梯({@link tierLadderFrom})上第一个有绑定的档;摘完没有任何绑定 ⇒ 只认目录键;
|
|
28
|
+
* · CC 档位别名 ⇒ 经它对应的档位;`best` ⇒ 档序里第一个有绑定的档;别的词 ⇒ 落不到。
|
|
29
|
+
* `has` = 调用方的「这个名是目录里一条可服务(启用)的条目」;`tiers` = `resolveActiveTiers` 的读数(原表,未摘)—— 它的键只有五个档位词
|
|
30
|
+
* (档位组的绑定表在 schema 里只收这五个键,别的键被剥掉),所以只按档位词读表。
|
|
31
|
+
*/
|
|
32
|
+
export declare function landCatalogWord(word: string, has: (name: string) => boolean, tiers: Readonly<Partial<Record<TierWord, string>>> | undefined): string | undefined;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 档位词(纯、零 I/O、浏览器安全;**包内叶子模块,不出包**):引擎的档序与 CC 档位别名、从某档起向低档的梯,与「一个目录词在档位展开之后落到哪条条目」。
|
|
3
|
+
* 本包里档位词的唯一一处:default 角色的档梯(`./default-model`)与写者计划助手的落点(`./env-model-table`)都从这里取。
|
|
4
|
+
* 镜像 core(`DEFAULT_TIER_ORDER` / `CC_MODEL_TIER_ALIASES` / `expandTiers`):`test/tier-words-parity-14.8.0` 对 devDependency 里精确钉住的那一版 core 对拍。
|
|
5
|
+
*/
|
|
6
|
+
/** 引擎的档序(高 → 低)。 */
|
|
7
|
+
export const TIER_ORDER = ["ultra", "max", "pro", "flash", "lite"];
|
|
8
|
+
/** CC 档位词 → 引擎档位。 */
|
|
9
|
+
export const CC_TIER_ALIASES = { fable: "max", mythos: "max", opus: "pro", sonnet: "flash", haiku: "lite" };
|
|
10
|
+
/** 一档的梯:档序里从它起(含)向低档的那一段(没绑的档沿它往下落)。 */
|
|
11
|
+
export function tierLadderFrom(tier) {
|
|
12
|
+
return TIER_ORDER.slice(TIER_ORDER.indexOf(tier));
|
|
13
|
+
}
|
|
14
|
+
const isTierWord = (word) => TIER_ORDER.includes(word);
|
|
15
|
+
/**
|
|
16
|
+
* 一个目录词(条目名 / 档位词 / CC 档位别名 / `best`)在**档位展开之后**落到哪条目录条目名 —— 与引擎装配档位表的两步同答:
|
|
17
|
+
* 先摘掉活跃组里绑定目标不可服务的档(引擎的生效装配在交给 core 之前做这一步,并 warn 点名),再按 core `expandTiers` 展开
|
|
18
|
+
* (对拍 devDependency 那一版 core 的「摘后表」)。所以这里只有一条绑定规则:**一档的绑定只在它点名一条可服务条目时算数**,否则当作没绑。展开规则:
|
|
19
|
+
* · 目录自己的键先赢(`has(word)`;一条就叫 `flash` 的条目遮住档位词);
|
|
20
|
+
* · 档位词 ⇒ 它的梯({@link tierLadderFrom})上第一个有绑定的档;摘完没有任何绑定 ⇒ 只认目录键;
|
|
21
|
+
* · CC 档位别名 ⇒ 经它对应的档位;`best` ⇒ 档序里第一个有绑定的档;别的词 ⇒ 落不到。
|
|
22
|
+
* `has` = 调用方的「这个名是目录里一条可服务(启用)的条目」;`tiers` = `resolveActiveTiers` 的读数(原表,未摘)—— 它的键只有五个档位词
|
|
23
|
+
* (档位组的绑定表在 schema 里只收这五个键,别的键被剥掉),所以只按档位词读表。
|
|
24
|
+
*/
|
|
25
|
+
export function landCatalogWord(word, has, tiers) {
|
|
26
|
+
if (has(word))
|
|
27
|
+
return word;
|
|
28
|
+
if (tiers === undefined)
|
|
29
|
+
return undefined;
|
|
30
|
+
/** 一档的绑定:只在它点名一条可服务条目时算数(否则引擎已摘掉它)。 */
|
|
31
|
+
const bound = (tier) => {
|
|
32
|
+
const target = Object.hasOwn(tiers, tier) ? tiers[tier] : undefined;
|
|
33
|
+
return target !== undefined && has(target) ? target : undefined;
|
|
34
|
+
};
|
|
35
|
+
const firstBound = (ladder) => ladder.map(bound).find((landed) => landed !== undefined);
|
|
36
|
+
if (isTierWord(word))
|
|
37
|
+
return firstBound(tierLadderFrom(word));
|
|
38
|
+
if (Object.hasOwn(CC_TIER_ALIASES, word))
|
|
39
|
+
return firstBound(tierLadderFrom(CC_TIER_ALIASES[word]));
|
|
40
|
+
if (word === "best")
|
|
41
|
+
return firstBound(TIER_ORDER);
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1885,6 +1885,8 @@ export declare const McpServerSpec: z.ZodObject<{
|
|
|
1885
1885
|
local: "local";
|
|
1886
1886
|
execution: "execution";
|
|
1887
1887
|
}>>;
|
|
1888
|
+
sessionMetaKey: z.ZodOptional<z.ZodUnknown>;
|
|
1889
|
+
startupTimeoutMs: z.ZodOptional<z.ZodUnknown>;
|
|
1888
1890
|
source: z.ZodOptional<z.ZodUnknown>;
|
|
1889
1891
|
toolFaces: z.ZodOptional<z.ZodUnknown>;
|
|
1890
1892
|
toolAxes: z.ZodOptional<z.ZodUnknown>;
|
|
@@ -1918,6 +1920,8 @@ export declare const McpConfig: z.ZodObject<{
|
|
|
1918
1920
|
local: "local";
|
|
1919
1921
|
execution: "execution";
|
|
1920
1922
|
}>>;
|
|
1923
|
+
sessionMetaKey: z.ZodOptional<z.ZodUnknown>;
|
|
1924
|
+
startupTimeoutMs: z.ZodOptional<z.ZodUnknown>;
|
|
1921
1925
|
source: z.ZodOptional<z.ZodUnknown>;
|
|
1922
1926
|
toolFaces: z.ZodOptional<z.ZodUnknown>;
|
|
1923
1927
|
toolAxes: z.ZodOptional<z.ZodUnknown>;
|
|
@@ -2520,6 +2524,8 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
2520
2524
|
local: "local";
|
|
2521
2525
|
execution: "execution";
|
|
2522
2526
|
}>>;
|
|
2527
|
+
sessionMetaKey: z.ZodOptional<z.ZodUnknown>;
|
|
2528
|
+
startupTimeoutMs: z.ZodOptional<z.ZodUnknown>;
|
|
2523
2529
|
source: z.ZodOptional<z.ZodUnknown>;
|
|
2524
2530
|
toolFaces: z.ZodOptional<z.ZodUnknown>;
|
|
2525
2531
|
toolAxes: z.ZodOptional<z.ZodUnknown>;
|
package/dist/types.js
CHANGED
|
@@ -30,7 +30,7 @@ import { PREVIOUS_WEB_ADMIN_ENV } from "./previous-web-admin-env.js"; // the pre
|
|
|
30
30
|
import { retiredEnvRefusal } from "./retired-envs.js"; // the worker env write gate asks the retired-env tombstone table too (one table, one refusal sentence)
|
|
31
31
|
import { Sha256Digest } from "./sha256.js"; // the one `sha256:<hex>` digest form
|
|
32
32
|
import { EXECUTION_LANES, EXECUTION_LANE_WORDS, MEMORY_ENGINE_BACKENDS, SESSION_BACKENDS, STORE_BACKENDS, retiredLaneWordRefusal } from "./execution-lanes.js"; // 7.0.0 M-R2: the lane / store vocabulary (one exported table)
|
|
33
|
-
import { LANE_ENV_OWNER, isMigratableEnvKey, laneEnvSeat, laneRowOf } from "./execution-lane-index.js"; // package-private indexes derived from that table (not in the barrel)
|
|
33
|
+
import { LANE_ENV_OWNER, isBlankCoordinate, isMigratableEnvKey, laneEnvSeat, laneRowOf } from "./execution-lane-index.js"; // package-private indexes derived from that table (not in the barrel)
|
|
34
34
|
import { migrationSignpost, retiredFormSentence, retiredKey } from "./retired-form.js"; // 11.0.0: the ONE retired-form sentence + key tombstone (package-private)
|
|
35
35
|
import { retiredRoleWordsRefusal } from "./retired-role-words.js"; // 12.0.0: the retired role-word tombstone (package-private; SS-M8)
|
|
36
36
|
import { buildQuotedIssue, fixed } from "./quoted-issue.js"; // THE minting point of custom issues (package-private)
|
|
@@ -456,6 +456,20 @@ export const PARSE_TRANSPARENT_KEYS = [
|
|
|
456
456
|
validatedBy: "consumer",
|
|
457
457
|
why: "它的形由同一条 override 的 `key` 决定(一个 key 一种形),执法点在读那个 key 的消费方;在这里写死形等于把所有可覆盖键的形表搬进本包。",
|
|
458
458
|
},
|
|
459
|
+
{
|
|
460
|
+
domain: "mcp",
|
|
461
|
+
path: "servers[].sessionMetaKey",
|
|
462
|
+
since: "14.8.0",
|
|
463
|
+
validatedBy: "engine-ingest",
|
|
464
|
+
why: "引擎在发给这台服务器的请求 `_meta` 里放发送腿会话 id 的那把键;它只有一只判官 = 引擎根导出 `judgeSessionMetaKey`(类型、非空、上界、MCP `_meta` 键名文法、MCP 保留前缀、`progressToken`、引擎的 `sema/` 命名空间一并判;坏键在引擎的准备门整条拒、点名这把键),投影它的消费方在交给引擎之前可调同一只;本包只承载 —— 这里哪怕只判类型与长度,也是第二只判官的一部分,与引擎那只各答各的。",
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
domain: "mcp",
|
|
468
|
+
path: "servers[].startupTimeoutMs",
|
|
469
|
+
since: "14.8.0",
|
|
470
|
+
validatedBy: "engine-ingest",
|
|
471
|
+
why: "引擎的逐服务器启动界(握手与首次工具列举各带它);它只有一只判官 = 引擎根导出的 `mcpStartupTimeoutMs`(是不是数、整数性、范围一并判;坏值在引擎的拨号门拒这一台服务器、点名 `config.mcp_startup_timeout_invalid`,其余服务器照挂),投影它的消费方在交给引擎之前可调同一只;本包只承载 —— 这里哪怕只判「是不是数」,也是第二只判官的一部分,与引擎那只各答各的。",
|
|
472
|
+
},
|
|
459
473
|
];
|
|
460
474
|
/** A catalog model's price / capability tier — fuels core 1.25 `selectModel({ tier })` role resolution. ONE closed set for both
|
|
461
475
|
* places that name it (`ModelEntry.tier`, `RoleTarget.select.tier`). Not the tier-group ladder of {@link TierBindings}
|
|
@@ -1875,8 +1889,8 @@ const nonSecretLiteral = (minLength) => z
|
|
|
1875
1889
|
/**
|
|
1876
1890
|
* `runtime.execution` —— 这台 worker 的执行车道(渲染:`REMOTE_EXEC=<lane>` + `REQUIRE_EXECUTION_LANE=true` + coords / secretRefs 逐键)。
|
|
1877
1891
|
* - `lane`:{@link EXECUTION_LANE_WORDS} 之一。没有「无手」词。
|
|
1878
|
-
* - `coords`:该车道的**非密坐标**(服务变量名 → 字面值),键 ⊆ 表[lane] 的 `requiredEnv ∪ optionalEnv
|
|
1879
|
-
* (
|
|
1892
|
+
* - `coords`:该车道的**非密坐标**(服务变量名 → 字面值),键 ⊆ 表[lane] 的 `requiredEnv ∪ optionalEnv`;必需键在场且不是空白
|
|
1893
|
+
* (空串或只含空白按缺 —— 唯一判官 `isBlankCoordinate`)。可选键的空串照收(例:`K8S_RUNTIME_CLASS=""` 在引擎里是「不用 Kata」)。
|
|
1880
1894
|
* - `secretRefs`:该车道的**密钥**(服务变量名 → 宿主 env-NAME),键 ⊆ 表[lane] 的 `requiredSecretEnv ∪ optionalSecretEnv`,必需键在场。
|
|
1881
1895
|
* 别车道的键 ⇒ 拒并点名它属于哪条车道;本车道的密钥写进 coords / 坐标写进 secretRefs ⇒ 拒并指路另一栏。
|
|
1882
1896
|
*/
|
|
@@ -1911,8 +1925,8 @@ const ExecutionBlock = z
|
|
|
1911
1925
|
return true;
|
|
1912
1926
|
};
|
|
1913
1927
|
for (const [key, value] of Object.entries(x.coords)) {
|
|
1914
|
-
if (judgeKey("coords", key) && value
|
|
1915
|
-
issue("coords", key, buildQuotedIssue `required coordinate ${key} of lane "${x.lane}" is empty
|
|
1928
|
+
if (judgeKey("coords", key) && isBlankCoordinate(value) && LANE_ENV_OWNER.get(key)?.required === true) {
|
|
1929
|
+
issue("coords", key, buildQuotedIssue `required coordinate ${key} of lane "${x.lane}" is empty or whitespace-only — it counts as absent, and the engine refuses to start without it`);
|
|
1916
1930
|
}
|
|
1917
1931
|
}
|
|
1918
1932
|
for (const key of Object.keys(x.secretRefs))
|
|
@@ -2486,6 +2500,16 @@ export const McpServerSpec = z.object({
|
|
|
2486
2500
|
* declared `"local"`, the engine read ABSENT. A value outside the table is REJECTED at parse — a mistyped trust
|
|
2487
2501
|
* word must never be read as a legal one (the consumer's gate is equally severe: no case-folding). */
|
|
2488
2502
|
contentOrigin: z.enum(MCP_CONTENT_ORIGINS).optional(),
|
|
2503
|
+
/** 引擎在发给这台服务器的每个 `tools/call` / `resources/read` 的 `params._meta[key]` 里放发送腿自己的会话 id 的那把键 —— 一一对应引擎的
|
|
2504
|
+
* `McpServerSpec.sessionMetaKey`。缺席 = 什么都不送(`.optional()`,不铸默认:会话 id 出进程是部署自己选的关联)。
|
|
2505
|
+
*
|
|
2506
|
+
* **解析透明** —— 形归谁校验、为什么不放这里:{@link PARSE_TRANSPARENT_KEYS}(`mcp.servers[].sessionMetaKey`)。 */
|
|
2507
|
+
sessionMetaKey: z.unknown().optional(),
|
|
2508
|
+
/** 这一台服务器自己的启动界(整数毫秒):握手(连接 + initialize)与首次工具列举各带它 —— 一一对应引擎的 `McpServerSpec.startupTimeoutMs`。
|
|
2509
|
+
* 缺席 = 引擎读进程级的缺省界(`.optional()`,不铸默认:没声明就是没声明);它只界启动阶段,不动单次调用的超时。
|
|
2510
|
+
*
|
|
2511
|
+
* **解析透明** —— 形归谁校验、为什么不放这里:{@link PARSE_TRANSPARENT_KEYS}(`mcp.servers[].startupTimeoutMs`)。 */
|
|
2512
|
+
startupTimeoutMs: z.unknown().optional(),
|
|
2489
2513
|
/** Declaration-plane GROUPING LABEL for this server — maps 1:1 onto the engine's `McpServerSpec.source`
|
|
2490
2514
|
* (core ≥7.5.0 echoes it verbatim on `wiring_manifest.mcp[].source`, single-line + 80-char cap, so a
|
|
2491
2515
|
* consumer can group servers by where they were declared). An OPEN set: CC's `plugin` / `user` /
|
|
@@ -10,6 +10,7 @@ import { formatConfigPath, outgoingPath } from "./config-fns.js";
|
|
|
10
10
|
import { issuePath } from "./issue-path.js";
|
|
11
11
|
import { guardedSafeParse } from "./own-key-read.js";
|
|
12
12
|
import { jsonShapeOf } from "./plain-json-object.js";
|
|
13
|
+
import { retiredKeyHeldSentence, retiredKeyOfSentence } from "./retired-form.js";
|
|
13
14
|
import { WorkersConfig } from "./types.js";
|
|
14
15
|
/** 每一形的拒句主语 —— 穷举映射型:加一形不补这里即编译红。 */
|
|
15
16
|
const SUBJECT = {
|
|
@@ -63,6 +64,11 @@ export function safeIssueMessage(issue) {
|
|
|
63
64
|
function rowRelative(path) {
|
|
64
65
|
return path[0] === "workers" && path[1] === 0 ? path.slice(2) : path;
|
|
65
66
|
}
|
|
67
|
+
/** 一条 issue 在拒句里的样子:`<坐标>: <句子>`;墓碑 issue(旧形字段还在盘上)换成读面的说法 —— 坐标就是退役键名,拒句的文字里不点名它(结构化的 `field` 已经指到它),指现行位与出路。 */
|
|
68
|
+
function issueText(i) {
|
|
69
|
+
const tombstone = retiredKeyOfSentence(i.message);
|
|
70
|
+
return tombstone !== undefined ? retiredKeyHeldSentence(tombstone.form) : `${formatConfigPath(outgoingPath(rowRelative(issuePath(i))))}: ${i.message}`;
|
|
71
|
+
}
|
|
66
72
|
/** 一行的终判:读得进 ⇒ `undefined`;读不进 ⇒ 第一条 issue 的路径(相对该行)+ 拒句(见文件头)。 */
|
|
67
73
|
export function workerRowVerdict(row, form) {
|
|
68
74
|
// 校验过程抛(会抛的 getter / 陷阱:读侧交进来的是调用方的活对象;zod 4.6 首读 `error` 时拼句子抛 —— 被污染的运行时、另一 realm 的怪形值)⇒ 这一行判「读不出」
|
|
@@ -74,7 +80,7 @@ export function workerRowVerdict(row, form) {
|
|
|
74
80
|
if (verdict.success)
|
|
75
81
|
return undefined;
|
|
76
82
|
const issues = verdict.error.issues;
|
|
77
|
-
const shown = issues.slice(0, 3).map(
|
|
83
|
+
const shown = issues.slice(0, 3).map(issueText);
|
|
78
84
|
const more = issues.length > shown.length ? ` (+${issues.length - shown.length} more)` : "";
|
|
79
85
|
const first = issues[0];
|
|
80
86
|
return { field: first === undefined ? [] : rowRelative(issuePath(first)), reason: `${SUBJECT[form]} is not a valid WorkerSpec — ${shown.join("; ")}${more}` };
|