@sema-agent/settings-schema 1.8.0 → 1.10.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 +34 -0
- package/dist/hash.d.ts +7 -3
- package/dist/hash.js +7 -3
- package/dist/types.d.ts +106 -0
- package/dist/types.js +75 -27
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,40 @@
|
|
|
6
6
|
> `@sema-agent/registry-core`(更早还曾是 `@sema-ai/registry-core`)。本档 `0.19.0` 以下各节里的
|
|
7
7
|
> 包名是**历史记录**,如实保留不追改。
|
|
8
8
|
|
|
9
|
+
## 1.10.0 — 2026-09-09 — `models.models[].compat` 引擎兼容声明席(镜像 `OpenAICompletionsCompat`;新键=minor)
|
|
10
|
+
|
|
11
|
+
- 引擎 `OpenAICompletionsCompat`(五键 `thinkingFormat` / `reasoningEffortLevels` / `maxTokensField` /
|
|
12
|
+
`requiresReasoningContentOnAssistantMessages` / `supportsReasoningEffort`)早就能按模型发兼容声明,但 `ModelEntry`
|
|
13
|
+
没有这个键 ⇒ 目录条目写了 `compat` 在 parse 期被 strip 剥掉,声明**根本到不了引擎**;`extraBody` 也穿不过(引擎的
|
|
14
|
+
OpenAI 保留键表拦下 `chat_template_kwargs` / `enable_thinking`)。1.10.0 起 `ModelEntry.compat?`
|
|
15
|
+
(`z.unknown().optional()`)。
|
|
16
|
+
- **三问**:①谁需要 —— vLLM / Qwen 类**缺省开思考**的网关(关思考只能靠 `chat_template_kwargs.enable_thinking=false`),
|
|
17
|
+
以及任何要按模型钉 `max_tokens` 拼写 / reasoning 档位的部署;②谁受伤 —— 无:additive 可选键,缺席 = 键不铸 = 今日行为,
|
|
18
|
+
存量配置零迁移;③补偿 —— 不加旋钮(不写就没有这个键)。
|
|
19
|
+
- **解析透明**,与 1.7.2 `source` / 1.9.0 `toolFaces` 同一条规矩:形与词表(`thinkingFormat` 有哪几个词)的校验归
|
|
20
|
+
消费方摄入侧**单点**,本仓刻意不复述那张表 —— 本域整域 all-or-nothing,一次形/词拒会把整套模型目录抹掉(1.7.1 升级
|
|
21
|
+
回归的形)。
|
|
22
|
+
- 唯一保留的解析拒 = 与兄弟字段 `extraBody` **同一只**自由形安全判据(secret 形键/值、访问器、循环、非 JSON、过深):
|
|
23
|
+
1.10.0 把这条流水线从 `extraBody` 里抽成共用的 `vetFreeFormJson(v, field)`(getter-free 描述符走查 → 单次
|
|
24
|
+
`JSON.stringify` → 复扫的 clone 即持久值),两个字段同调一处,不留第二份判据。`extraBody` 的「必须是 plain JSON
|
|
25
|
+
对象」形门是它自己的(它要被摊进请求体),行为逐字不变(消息文本与判定结果均未变)。深度上限仍是 `MAX_EXTRA_BODY_DEPTH`
|
|
26
|
+
(`./hash` 上的已发布导出,不改名 —— 改名是 BREAKING,收益纯属观感),其 JSDoc 已改写成「所有自由形字段共用的一只上限」。
|
|
27
|
+
- 红先:`test/model-compat-1.10.test.ts` 七格(①原样保留 ①b 五键全量 ②缺席不铸 ③坏形不整域默认 ④安全判据拒
|
|
28
|
+
⑤`loadLocalConfig` 全链到 `effective.models.models[].compat` ⑤b `readEffectiveWire` wire 腿同样透传且不降级整域)。
|
|
29
|
+
- 消费方点名(能力显式表态制):**worker 服务**(投影/env/读面,随其 7.69.0)、**CLI**(探针写目录条目)、
|
|
30
|
+
**config-center 产品**(models 域透传)。
|
|
31
|
+
- 顺带:`package-lock.json` 的 `packages[""].version` 自 1.6.0 起停在 `1.5.0`(历次发版只改了顶层 `version`),
|
|
32
|
+
本节一并对齐到 1.10.0。
|
|
33
|
+
|
|
34
|
+
## 1.9.0 — 2026-09-08 — `mcp.servers[].toolFaces` 覆盖层声明面(core 7.8.0 design/388 片 1 F7;新键=minor)
|
|
35
|
+
|
|
36
|
+
- core 7.8.0 起 `McpServerSpec.toolFaces?: Record<remoteToolName, { family?, pathTarget?: {param, aliases?, access, skillScopeEligible?}, renderHints?, ruleFace? }>`
|
|
37
|
+
是工具名册的 face 覆盖层。本仓只加**解析透明**的键(`z.unknown().optional()`),与 1.7.2 `source` 同一条规矩:形的校验属 core 摄入侧
|
|
38
|
+
(不合 schema 的工具**不挂**并通告一次 `config.tool_face_invalid`),本仓不复述那张表——这一域 all-or-nothing,任一字段解析拒都会让整套
|
|
39
|
+
mcp 服务器静默消失(S-144 类病)。缺席 = 不铸键。
|
|
40
|
+
- 红先:`test/mcp-tool-faces-1.9.test.ts`(1.8.0 上「带 toolFaces 的 server 键原样到消费方」红)。
|
|
41
|
+
- 消费方:sema-server(MCP 配置面三腿透传,随 7.66.0)、cli(settings 面)。
|
|
42
|
+
|
|
9
43
|
## 1.8.0 — 2026-09-07 — `ModelRole` 闭集对齐 core:加 `classifier` / `consolidate`(新词=minor)
|
|
10
44
|
|
|
11
45
|
- cli [6554] 真案:core `ModelRole` 早有 `classifier`(auto 权限分类器,FALLBACK classifier→summarize→default、tier 缺省 flash)
|
package/dist/hash.d.ts
CHANGED
|
@@ -20,9 +20,13 @@ export declare const MAX_HASH_DEPTH = 200;
|
|
|
20
20
|
* getVersion/getEffective (hard-DoS poison pill) — the two caps were each hardened in isolation but never
|
|
21
21
|
* reconciled (R18). The real max wrapper is ~4–6; 32 is a deliberate ≫ margin. */
|
|
22
22
|
export declare const MAX_HASH_WRAPPER_RESERVE = 32;
|
|
23
|
-
/** Depth cap for a standalone
|
|
24
|
-
* ANYTHING the validator accepts is guaranteed hashable in every context it's later hashed in. 168 ≫ any
|
|
25
|
-
*
|
|
23
|
+
/** Depth cap for a standalone FREE-FORM config value, reconciled with the hash cap MINUS the wrapper reserve so
|
|
24
|
+
* that ANYTHING the validator accepts is guaranteed hashable in every context it's later hashed in. 168 ≫ any
|
|
25
|
+
* real free-form value (OpenAI-style request params nest <10 deep).
|
|
26
|
+
* Scope: the ONE cap for EVERY free-form field vetted by `vetFreeFormJson` (`ModelEntry.extraBody` and, since
|
|
27
|
+
* 1.10.0, `ModelEntry.compat`) — they sit at the SAME wrapper depth (`{models:{models:[{…}]}}`), so one cap
|
|
28
|
+
* serves both. The `EXTRA_BODY` spelling is kept because this is a published export on the `./hash` subpath
|
|
29
|
+
* (renaming it would be a BREAKING change for a purely cosmetic gain). */
|
|
26
30
|
export declare const MAX_EXTRA_BODY_DEPTH: number;
|
|
27
31
|
/** Deterministic JSON with sorted object keys (so key order never affects the hash). */
|
|
28
32
|
export declare function stableStringify(v: unknown, depth?: number): string;
|
package/dist/hash.js
CHANGED
|
@@ -20,9 +20,13 @@ export const MAX_HASH_DEPTH = 200;
|
|
|
20
20
|
* getVersion/getEffective (hard-DoS poison pill) — the two caps were each hardened in isolation but never
|
|
21
21
|
* reconciled (R18). The real max wrapper is ~4–6; 32 is a deliberate ≫ margin. */
|
|
22
22
|
export const MAX_HASH_WRAPPER_RESERVE = 32;
|
|
23
|
-
/** Depth cap for a standalone
|
|
24
|
-
* ANYTHING the validator accepts is guaranteed hashable in every context it's later hashed in. 168 ≫ any
|
|
25
|
-
*
|
|
23
|
+
/** Depth cap for a standalone FREE-FORM config value, reconciled with the hash cap MINUS the wrapper reserve so
|
|
24
|
+
* that ANYTHING the validator accepts is guaranteed hashable in every context it's later hashed in. 168 ≫ any
|
|
25
|
+
* real free-form value (OpenAI-style request params nest <10 deep).
|
|
26
|
+
* Scope: the ONE cap for EVERY free-form field vetted by `vetFreeFormJson` (`ModelEntry.extraBody` and, since
|
|
27
|
+
* 1.10.0, `ModelEntry.compat`) — they sit at the SAME wrapper depth (`{models:{models:[{…}]}}`), so one cap
|
|
28
|
+
* serves both. The `EXTRA_BODY` spelling is kept because this is a published export on the `./hash` subpath
|
|
29
|
+
* (renaming it would be a BREAKING change for a purely cosmetic gain). */
|
|
26
30
|
export const MAX_EXTRA_BODY_DEPTH = MAX_HASH_DEPTH - MAX_HASH_WRAPPER_RESERVE;
|
|
27
31
|
/** Deterministic JSON with sorted object keys (so key order never affects the hash). */
|
|
28
32
|
export function stableStringify(v, depth = 0) {
|
package/dist/types.d.ts
CHANGED
|
@@ -184,6 +184,24 @@ export declare const ModelEntry: z.ZodEffects<z.ZodObject<{
|
|
|
184
184
|
* through), e.g. {frequency_penalty:0.5, presence_penalty:0.3}. Non-secret model metadata — same class
|
|
185
185
|
* as cost/tier. Shipped on /effective.models.models[].extraBody; the service merges it into the request. */
|
|
186
186
|
extraBody: z.ZodEffects<z.ZodOptional<z.ZodUnknown>, Record<string, unknown> | undefined, unknown>;
|
|
187
|
+
/** Per-model wire-compat declaration for the OpenAI-completions lane — mirrors the engine's
|
|
188
|
+
* `OpenAICompletionsCompat` (five keys: `thinkingFormat` / `reasoningEffortLevels` / `maxTokensField` /
|
|
189
|
+
* `requiresReasoningContentOnAssistantMessages` / `supportsReasoningEffort`). Real need: a vLLM/Qwen-class
|
|
190
|
+
* gateway that thinks by DEFAULT can only be turned off with `chat_template_kwargs.enable_thinking=false`,
|
|
191
|
+
* which `extraBody` cannot carry (the engine reserves those request keys) — and without this key a catalog
|
|
192
|
+
* entry that declares it is stripped at parse, so the declaration never reaches the engine at all.
|
|
193
|
+
*
|
|
194
|
+
* **Parse-transparent** (`z.unknown()`), same rule as `McpServerSpec.source` (1.7.2) and `.toolFaces` (1.9.0):
|
|
195
|
+
* the SHAPE and the VOCABULARY (which `thinkingFormat` words exist) are the consuming side's single point —
|
|
196
|
+
* this package deliberately does NOT restate that table. This domain parses all-or-nothing, so a shape/word
|
|
197
|
+
* rejection HERE would blank the entire model catalog over one bad key (the 1.7.1 upgrade regression). ABSENT
|
|
198
|
+
* = key not minted = today's behaviour, zero migration.
|
|
199
|
+
*
|
|
200
|
+
* The ONE rejection that remains is the free-form SAFETY judgment shared with `extraBody`
|
|
201
|
+
* ({@link vetFreeFormJson}): a secret-shaped key/value, an accessor, a cycle, non-JSON, or too deep to hash
|
|
202
|
+
* later. That is not shape validation — it is the boundary every free-form value must clear to enter the
|
|
203
|
+
* persisted config and `stableHash` (R18). */
|
|
204
|
+
compat: z.ZodEffects<z.ZodOptional<z.ZodUnknown>, unknown, unknown>;
|
|
187
205
|
/** 配额倍率(EXPERT-REDESIGN §4-1):该模型烧 token 双窗额度的倍率,默认 1。折算时点=weight-at-burn
|
|
188
206
|
* (记账时固化到 UsageEntry.quotaWeightAtUse/weightedTokens):改倍率只影响此后记账,不回算窗口内历史。 */
|
|
189
207
|
quotaWeight: z.ZodDefault<z.ZodNumber>;
|
|
@@ -219,6 +237,7 @@ export declare const ModelEntry: z.ZodEffects<z.ZodObject<{
|
|
|
219
237
|
cacheWrite: number;
|
|
220
238
|
} | undefined;
|
|
221
239
|
extraBody?: Record<string, unknown> | undefined;
|
|
240
|
+
compat?: unknown;
|
|
222
241
|
notes?: string | undefined;
|
|
223
242
|
}, {
|
|
224
243
|
id: string;
|
|
@@ -248,6 +267,7 @@ export declare const ModelEntry: z.ZodEffects<z.ZodObject<{
|
|
|
248
267
|
cacheWrite?: number | undefined;
|
|
249
268
|
} | undefined;
|
|
250
269
|
extraBody?: unknown;
|
|
270
|
+
compat?: unknown;
|
|
251
271
|
quotaWeight?: number | undefined;
|
|
252
272
|
enabled?: boolean | undefined;
|
|
253
273
|
notes?: string | undefined;
|
|
@@ -281,6 +301,7 @@ export declare const ModelEntry: z.ZodEffects<z.ZodObject<{
|
|
|
281
301
|
cacheWrite: number;
|
|
282
302
|
} | undefined;
|
|
283
303
|
extraBody?: Record<string, unknown> | undefined;
|
|
304
|
+
compat?: unknown;
|
|
284
305
|
notes?: string | undefined;
|
|
285
306
|
}, {
|
|
286
307
|
id: string;
|
|
@@ -310,6 +331,7 @@ export declare const ModelEntry: z.ZodEffects<z.ZodObject<{
|
|
|
310
331
|
cacheWrite?: number | undefined;
|
|
311
332
|
} | undefined;
|
|
312
333
|
extraBody?: unknown;
|
|
334
|
+
compat?: unknown;
|
|
313
335
|
quotaWeight?: number | undefined;
|
|
314
336
|
enabled?: boolean | undefined;
|
|
315
337
|
notes?: string | undefined;
|
|
@@ -504,6 +526,24 @@ export declare const ModelsConfig: z.ZodEffects<z.ZodObject<{
|
|
|
504
526
|
* through), e.g. {frequency_penalty:0.5, presence_penalty:0.3}. Non-secret model metadata — same class
|
|
505
527
|
* as cost/tier. Shipped on /effective.models.models[].extraBody; the service merges it into the request. */
|
|
506
528
|
extraBody: z.ZodEffects<z.ZodOptional<z.ZodUnknown>, Record<string, unknown> | undefined, unknown>;
|
|
529
|
+
/** Per-model wire-compat declaration for the OpenAI-completions lane — mirrors the engine's
|
|
530
|
+
* `OpenAICompletionsCompat` (five keys: `thinkingFormat` / `reasoningEffortLevels` / `maxTokensField` /
|
|
531
|
+
* `requiresReasoningContentOnAssistantMessages` / `supportsReasoningEffort`). Real need: a vLLM/Qwen-class
|
|
532
|
+
* gateway that thinks by DEFAULT can only be turned off with `chat_template_kwargs.enable_thinking=false`,
|
|
533
|
+
* which `extraBody` cannot carry (the engine reserves those request keys) — and without this key a catalog
|
|
534
|
+
* entry that declares it is stripped at parse, so the declaration never reaches the engine at all.
|
|
535
|
+
*
|
|
536
|
+
* **Parse-transparent** (`z.unknown()`), same rule as `McpServerSpec.source` (1.7.2) and `.toolFaces` (1.9.0):
|
|
537
|
+
* the SHAPE and the VOCABULARY (which `thinkingFormat` words exist) are the consuming side's single point —
|
|
538
|
+
* this package deliberately does NOT restate that table. This domain parses all-or-nothing, so a shape/word
|
|
539
|
+
* rejection HERE would blank the entire model catalog over one bad key (the 1.7.1 upgrade regression). ABSENT
|
|
540
|
+
* = key not minted = today's behaviour, zero migration.
|
|
541
|
+
*
|
|
542
|
+
* The ONE rejection that remains is the free-form SAFETY judgment shared with `extraBody`
|
|
543
|
+
* ({@link vetFreeFormJson}): a secret-shaped key/value, an accessor, a cycle, non-JSON, or too deep to hash
|
|
544
|
+
* later. That is not shape validation — it is the boundary every free-form value must clear to enter the
|
|
545
|
+
* persisted config and `stableHash` (R18). */
|
|
546
|
+
compat: z.ZodEffects<z.ZodOptional<z.ZodUnknown>, unknown, unknown>;
|
|
507
547
|
/** 配额倍率(EXPERT-REDESIGN §4-1):该模型烧 token 双窗额度的倍率,默认 1。折算时点=weight-at-burn
|
|
508
548
|
* (记账时固化到 UsageEntry.quotaWeightAtUse/weightedTokens):改倍率只影响此后记账,不回算窗口内历史。 */
|
|
509
549
|
quotaWeight: z.ZodDefault<z.ZodNumber>;
|
|
@@ -539,6 +579,7 @@ export declare const ModelsConfig: z.ZodEffects<z.ZodObject<{
|
|
|
539
579
|
cacheWrite: number;
|
|
540
580
|
} | undefined;
|
|
541
581
|
extraBody?: Record<string, unknown> | undefined;
|
|
582
|
+
compat?: unknown;
|
|
542
583
|
notes?: string | undefined;
|
|
543
584
|
}, {
|
|
544
585
|
id: string;
|
|
@@ -568,6 +609,7 @@ export declare const ModelsConfig: z.ZodEffects<z.ZodObject<{
|
|
|
568
609
|
cacheWrite?: number | undefined;
|
|
569
610
|
} | undefined;
|
|
570
611
|
extraBody?: unknown;
|
|
612
|
+
compat?: unknown;
|
|
571
613
|
quotaWeight?: number | undefined;
|
|
572
614
|
enabled?: boolean | undefined;
|
|
573
615
|
notes?: string | undefined;
|
|
@@ -601,6 +643,7 @@ export declare const ModelsConfig: z.ZodEffects<z.ZodObject<{
|
|
|
601
643
|
cacheWrite: number;
|
|
602
644
|
} | undefined;
|
|
603
645
|
extraBody?: Record<string, unknown> | undefined;
|
|
646
|
+
compat?: unknown;
|
|
604
647
|
notes?: string | undefined;
|
|
605
648
|
}, {
|
|
606
649
|
id: string;
|
|
@@ -630,6 +673,7 @@ export declare const ModelsConfig: z.ZodEffects<z.ZodObject<{
|
|
|
630
673
|
cacheWrite?: number | undefined;
|
|
631
674
|
} | undefined;
|
|
632
675
|
extraBody?: unknown;
|
|
676
|
+
compat?: unknown;
|
|
633
677
|
quotaWeight?: number | undefined;
|
|
634
678
|
enabled?: boolean | undefined;
|
|
635
679
|
notes?: string | undefined;
|
|
@@ -753,6 +797,7 @@ export declare const ModelsConfig: z.ZodEffects<z.ZodObject<{
|
|
|
753
797
|
cacheWrite: number;
|
|
754
798
|
} | undefined;
|
|
755
799
|
extraBody?: Record<string, unknown> | undefined;
|
|
800
|
+
compat?: unknown;
|
|
756
801
|
notes?: string | undefined;
|
|
757
802
|
}[];
|
|
758
803
|
roles: Partial<Record<"default" | "summarize" | "subagent" | "team" | "synthesize" | "verifier" | "classifier" | "consolidate", {
|
|
@@ -808,6 +853,7 @@ export declare const ModelsConfig: z.ZodEffects<z.ZodObject<{
|
|
|
808
853
|
cacheWrite?: number | undefined;
|
|
809
854
|
} | undefined;
|
|
810
855
|
extraBody?: unknown;
|
|
856
|
+
compat?: unknown;
|
|
811
857
|
quotaWeight?: number | undefined;
|
|
812
858
|
enabled?: boolean | undefined;
|
|
813
859
|
notes?: string | undefined;
|
|
@@ -865,6 +911,7 @@ export declare const ModelsConfig: z.ZodEffects<z.ZodObject<{
|
|
|
865
911
|
cacheWrite: number;
|
|
866
912
|
} | undefined;
|
|
867
913
|
extraBody?: Record<string, unknown> | undefined;
|
|
914
|
+
compat?: unknown;
|
|
868
915
|
notes?: string | undefined;
|
|
869
916
|
}[];
|
|
870
917
|
roles: Partial<Record<"default" | "summarize" | "subagent" | "team" | "synthesize" | "verifier" | "classifier" | "consolidate", {
|
|
@@ -920,6 +967,7 @@ export declare const ModelsConfig: z.ZodEffects<z.ZodObject<{
|
|
|
920
967
|
cacheWrite?: number | undefined;
|
|
921
968
|
} | undefined;
|
|
922
969
|
extraBody?: unknown;
|
|
970
|
+
compat?: unknown;
|
|
923
971
|
quotaWeight?: number | undefined;
|
|
924
972
|
enabled?: boolean | undefined;
|
|
925
973
|
notes?: string | undefined;
|
|
@@ -7334,6 +7382,12 @@ export declare const McpServerSpec: z.ZodObject<{
|
|
|
7334
7382
|
* both legs stripped it (default-strip object); this is the declaration half of the consumer-side fix
|
|
7335
7383
|
* (ticket B-036 / S-143), the projection half lives in the consumer. */
|
|
7336
7384
|
source: z.ZodOptional<z.ZodUnknown>;
|
|
7385
|
+
/** 1.9.0 —— core 7.8.0(design/388 片 1 F7)`toolFaces` 覆盖层:按远端工具名 key 的 face 声明
|
|
7386
|
+
* (`{ family?, pathTarget?: {param, aliases?, access, skillScopeEligible?}, renderHints?, ruleFace? }`)。
|
|
7387
|
+
* 与 `source` 同一条规矩:**解析透明**(`z.unknown()`),形的校验属 core 摄入侧(不合 schema 的工具**不挂**并
|
|
7388
|
+
* 通告一次 `config.tool_face_invalid`);本仓不复述那张表 —— 这一域 all-or-nothing,任一字段解析拒都会
|
|
7389
|
+
* 让整套 mcp 服务器静默消失。缺席 = 不铸键。 */
|
|
7390
|
+
toolFaces: z.ZodOptional<z.ZodUnknown>;
|
|
7337
7391
|
notes: z.ZodOptional<z.ZodString>;
|
|
7338
7392
|
}, "strip", z.ZodTypeAny, {
|
|
7339
7393
|
name: string;
|
|
@@ -7356,6 +7410,7 @@ export declare const McpServerSpec: z.ZodObject<{
|
|
|
7356
7410
|
allowTools?: string[] | undefined;
|
|
7357
7411
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
7358
7412
|
source?: unknown;
|
|
7413
|
+
toolFaces?: unknown;
|
|
7359
7414
|
}, {
|
|
7360
7415
|
name: string;
|
|
7361
7416
|
transport: {
|
|
@@ -7377,6 +7432,7 @@ export declare const McpServerSpec: z.ZodObject<{
|
|
|
7377
7432
|
elicitation?: boolean | undefined;
|
|
7378
7433
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
7379
7434
|
source?: unknown;
|
|
7435
|
+
toolFaces?: unknown;
|
|
7380
7436
|
}>;
|
|
7381
7437
|
export type McpServerSpec = z.infer<typeof McpServerSpec>;
|
|
7382
7438
|
export declare const McpConfig: z.ZodEffects<z.ZodObject<{
|
|
@@ -7465,6 +7521,12 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
|
|
|
7465
7521
|
* both legs stripped it (default-strip object); this is the declaration half of the consumer-side fix
|
|
7466
7522
|
* (ticket B-036 / S-143), the projection half lives in the consumer. */
|
|
7467
7523
|
source: z.ZodOptional<z.ZodUnknown>;
|
|
7524
|
+
/** 1.9.0 —— core 7.8.0(design/388 片 1 F7)`toolFaces` 覆盖层:按远端工具名 key 的 face 声明
|
|
7525
|
+
* (`{ family?, pathTarget?: {param, aliases?, access, skillScopeEligible?}, renderHints?, ruleFace? }`)。
|
|
7526
|
+
* 与 `source` 同一条规矩:**解析透明**(`z.unknown()`),形的校验属 core 摄入侧(不合 schema 的工具**不挂**并
|
|
7527
|
+
* 通告一次 `config.tool_face_invalid`);本仓不复述那张表 —— 这一域 all-or-nothing,任一字段解析拒都会
|
|
7528
|
+
* 让整套 mcp 服务器静默消失。缺席 = 不铸键。 */
|
|
7529
|
+
toolFaces: z.ZodOptional<z.ZodUnknown>;
|
|
7468
7530
|
notes: z.ZodOptional<z.ZodString>;
|
|
7469
7531
|
}, "strip", z.ZodTypeAny, {
|
|
7470
7532
|
name: string;
|
|
@@ -7487,6 +7549,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
|
|
|
7487
7549
|
allowTools?: string[] | undefined;
|
|
7488
7550
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
7489
7551
|
source?: unknown;
|
|
7552
|
+
toolFaces?: unknown;
|
|
7490
7553
|
}, {
|
|
7491
7554
|
name: string;
|
|
7492
7555
|
transport: {
|
|
@@ -7508,6 +7571,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
|
|
|
7508
7571
|
elicitation?: boolean | undefined;
|
|
7509
7572
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
7510
7573
|
source?: unknown;
|
|
7574
|
+
toolFaces?: unknown;
|
|
7511
7575
|
}>, "many">>;
|
|
7512
7576
|
}, "strip", z.ZodTypeAny, {
|
|
7513
7577
|
servers: {
|
|
@@ -7531,6 +7595,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
|
|
|
7531
7595
|
allowTools?: string[] | undefined;
|
|
7532
7596
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
7533
7597
|
source?: unknown;
|
|
7598
|
+
toolFaces?: unknown;
|
|
7534
7599
|
}[];
|
|
7535
7600
|
}, {
|
|
7536
7601
|
servers?: {
|
|
@@ -7554,6 +7619,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
|
|
|
7554
7619
|
elicitation?: boolean | undefined;
|
|
7555
7620
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
7556
7621
|
source?: unknown;
|
|
7622
|
+
toolFaces?: unknown;
|
|
7557
7623
|
}[] | undefined;
|
|
7558
7624
|
}>, {
|
|
7559
7625
|
servers: {
|
|
@@ -7577,6 +7643,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
|
|
|
7577
7643
|
allowTools?: string[] | undefined;
|
|
7578
7644
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
7579
7645
|
source?: unknown;
|
|
7646
|
+
toolFaces?: unknown;
|
|
7580
7647
|
}[];
|
|
7581
7648
|
}, {
|
|
7582
7649
|
servers?: {
|
|
@@ -7600,6 +7667,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
|
|
|
7600
7667
|
elicitation?: boolean | undefined;
|
|
7601
7668
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
7602
7669
|
source?: unknown;
|
|
7670
|
+
toolFaces?: unknown;
|
|
7603
7671
|
}[] | undefined;
|
|
7604
7672
|
}>;
|
|
7605
7673
|
export type McpConfig = z.infer<typeof McpConfig>;
|
|
@@ -9379,6 +9447,24 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
9379
9447
|
* through), e.g. {frequency_penalty:0.5, presence_penalty:0.3}. Non-secret model metadata — same class
|
|
9380
9448
|
* as cost/tier. Shipped on /effective.models.models[].extraBody; the service merges it into the request. */
|
|
9381
9449
|
extraBody: z.ZodEffects<z.ZodOptional<z.ZodUnknown>, Record<string, unknown> | undefined, unknown>;
|
|
9450
|
+
/** Per-model wire-compat declaration for the OpenAI-completions lane — mirrors the engine's
|
|
9451
|
+
* `OpenAICompletionsCompat` (five keys: `thinkingFormat` / `reasoningEffortLevels` / `maxTokensField` /
|
|
9452
|
+
* `requiresReasoningContentOnAssistantMessages` / `supportsReasoningEffort`). Real need: a vLLM/Qwen-class
|
|
9453
|
+
* gateway that thinks by DEFAULT can only be turned off with `chat_template_kwargs.enable_thinking=false`,
|
|
9454
|
+
* which `extraBody` cannot carry (the engine reserves those request keys) — and without this key a catalog
|
|
9455
|
+
* entry that declares it is stripped at parse, so the declaration never reaches the engine at all.
|
|
9456
|
+
*
|
|
9457
|
+
* **Parse-transparent** (`z.unknown()`), same rule as `McpServerSpec.source` (1.7.2) and `.toolFaces` (1.9.0):
|
|
9458
|
+
* the SHAPE and the VOCABULARY (which `thinkingFormat` words exist) are the consuming side's single point —
|
|
9459
|
+
* this package deliberately does NOT restate that table. This domain parses all-or-nothing, so a shape/word
|
|
9460
|
+
* rejection HERE would blank the entire model catalog over one bad key (the 1.7.1 upgrade regression). ABSENT
|
|
9461
|
+
* = key not minted = today's behaviour, zero migration.
|
|
9462
|
+
*
|
|
9463
|
+
* The ONE rejection that remains is the free-form SAFETY judgment shared with `extraBody`
|
|
9464
|
+
* ({@link vetFreeFormJson}): a secret-shaped key/value, an accessor, a cycle, non-JSON, or too deep to hash
|
|
9465
|
+
* later. That is not shape validation — it is the boundary every free-form value must clear to enter the
|
|
9466
|
+
* persisted config and `stableHash` (R18). */
|
|
9467
|
+
compat: z.ZodEffects<z.ZodOptional<z.ZodUnknown>, unknown, unknown>;
|
|
9382
9468
|
/** 配额倍率(EXPERT-REDESIGN §4-1):该模型烧 token 双窗额度的倍率,默认 1。折算时点=weight-at-burn
|
|
9383
9469
|
* (记账时固化到 UsageEntry.quotaWeightAtUse/weightedTokens):改倍率只影响此后记账,不回算窗口内历史。 */
|
|
9384
9470
|
quotaWeight: z.ZodDefault<z.ZodNumber>;
|
|
@@ -9414,6 +9500,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
9414
9500
|
cacheWrite: number;
|
|
9415
9501
|
} | undefined;
|
|
9416
9502
|
extraBody?: Record<string, unknown> | undefined;
|
|
9503
|
+
compat?: unknown;
|
|
9417
9504
|
notes?: string | undefined;
|
|
9418
9505
|
}, {
|
|
9419
9506
|
id: string;
|
|
@@ -9443,6 +9530,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
9443
9530
|
cacheWrite?: number | undefined;
|
|
9444
9531
|
} | undefined;
|
|
9445
9532
|
extraBody?: unknown;
|
|
9533
|
+
compat?: unknown;
|
|
9446
9534
|
quotaWeight?: number | undefined;
|
|
9447
9535
|
enabled?: boolean | undefined;
|
|
9448
9536
|
notes?: string | undefined;
|
|
@@ -9476,6 +9564,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
9476
9564
|
cacheWrite: number;
|
|
9477
9565
|
} | undefined;
|
|
9478
9566
|
extraBody?: Record<string, unknown> | undefined;
|
|
9567
|
+
compat?: unknown;
|
|
9479
9568
|
notes?: string | undefined;
|
|
9480
9569
|
}, {
|
|
9481
9570
|
id: string;
|
|
@@ -9505,6 +9594,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
9505
9594
|
cacheWrite?: number | undefined;
|
|
9506
9595
|
} | undefined;
|
|
9507
9596
|
extraBody?: unknown;
|
|
9597
|
+
compat?: unknown;
|
|
9508
9598
|
quotaWeight?: number | undefined;
|
|
9509
9599
|
enabled?: boolean | undefined;
|
|
9510
9600
|
notes?: string | undefined;
|
|
@@ -9628,6 +9718,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
9628
9718
|
cacheWrite: number;
|
|
9629
9719
|
} | undefined;
|
|
9630
9720
|
extraBody?: Record<string, unknown> | undefined;
|
|
9721
|
+
compat?: unknown;
|
|
9631
9722
|
notes?: string | undefined;
|
|
9632
9723
|
}[];
|
|
9633
9724
|
roles: Partial<Record<"default" | "summarize" | "subagent" | "team" | "synthesize" | "verifier" | "classifier" | "consolidate", {
|
|
@@ -9683,6 +9774,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
9683
9774
|
cacheWrite?: number | undefined;
|
|
9684
9775
|
} | undefined;
|
|
9685
9776
|
extraBody?: unknown;
|
|
9777
|
+
compat?: unknown;
|
|
9686
9778
|
quotaWeight?: number | undefined;
|
|
9687
9779
|
enabled?: boolean | undefined;
|
|
9688
9780
|
notes?: string | undefined;
|
|
@@ -9740,6 +9832,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
9740
9832
|
cacheWrite: number;
|
|
9741
9833
|
} | undefined;
|
|
9742
9834
|
extraBody?: Record<string, unknown> | undefined;
|
|
9835
|
+
compat?: unknown;
|
|
9743
9836
|
notes?: string | undefined;
|
|
9744
9837
|
}[];
|
|
9745
9838
|
roles: Partial<Record<"default" | "summarize" | "subagent" | "team" | "synthesize" | "verifier" | "classifier" | "consolidate", {
|
|
@@ -9795,6 +9888,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
9795
9888
|
cacheWrite?: number | undefined;
|
|
9796
9889
|
} | undefined;
|
|
9797
9890
|
extraBody?: unknown;
|
|
9891
|
+
compat?: unknown;
|
|
9798
9892
|
quotaWeight?: number | undefined;
|
|
9799
9893
|
enabled?: boolean | undefined;
|
|
9800
9894
|
notes?: string | undefined;
|
|
@@ -10138,6 +10232,12 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
10138
10232
|
* both legs stripped it (default-strip object); this is the declaration half of the consumer-side fix
|
|
10139
10233
|
* (ticket B-036 / S-143), the projection half lives in the consumer. */
|
|
10140
10234
|
source: z.ZodOptional<z.ZodUnknown>;
|
|
10235
|
+
/** 1.9.0 —— core 7.8.0(design/388 片 1 F7)`toolFaces` 覆盖层:按远端工具名 key 的 face 声明
|
|
10236
|
+
* (`{ family?, pathTarget?: {param, aliases?, access, skillScopeEligible?}, renderHints?, ruleFace? }`)。
|
|
10237
|
+
* 与 `source` 同一条规矩:**解析透明**(`z.unknown()`),形的校验属 core 摄入侧(不合 schema 的工具**不挂**并
|
|
10238
|
+
* 通告一次 `config.tool_face_invalid`);本仓不复述那张表 —— 这一域 all-or-nothing,任一字段解析拒都会
|
|
10239
|
+
* 让整套 mcp 服务器静默消失。缺席 = 不铸键。 */
|
|
10240
|
+
toolFaces: z.ZodOptional<z.ZodUnknown>;
|
|
10141
10241
|
notes: z.ZodOptional<z.ZodString>;
|
|
10142
10242
|
}, "strip", z.ZodTypeAny, {
|
|
10143
10243
|
name: string;
|
|
@@ -10160,6 +10260,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
10160
10260
|
allowTools?: string[] | undefined;
|
|
10161
10261
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
10162
10262
|
source?: unknown;
|
|
10263
|
+
toolFaces?: unknown;
|
|
10163
10264
|
}, {
|
|
10164
10265
|
name: string;
|
|
10165
10266
|
transport: {
|
|
@@ -10181,6 +10282,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
10181
10282
|
elicitation?: boolean | undefined;
|
|
10182
10283
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
10183
10284
|
source?: unknown;
|
|
10285
|
+
toolFaces?: unknown;
|
|
10184
10286
|
}>, "many">>;
|
|
10185
10287
|
}, "strip", z.ZodTypeAny, {
|
|
10186
10288
|
servers: {
|
|
@@ -10204,6 +10306,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
10204
10306
|
allowTools?: string[] | undefined;
|
|
10205
10307
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
10206
10308
|
source?: unknown;
|
|
10309
|
+
toolFaces?: unknown;
|
|
10207
10310
|
}[];
|
|
10208
10311
|
}, {
|
|
10209
10312
|
servers?: {
|
|
@@ -10227,6 +10330,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
10227
10330
|
elicitation?: boolean | undefined;
|
|
10228
10331
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
10229
10332
|
source?: unknown;
|
|
10333
|
+
toolFaces?: unknown;
|
|
10230
10334
|
}[] | undefined;
|
|
10231
10335
|
}>, {
|
|
10232
10336
|
servers: {
|
|
@@ -10250,6 +10354,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
10250
10354
|
allowTools?: string[] | undefined;
|
|
10251
10355
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
10252
10356
|
source?: unknown;
|
|
10357
|
+
toolFaces?: unknown;
|
|
10253
10358
|
}[];
|
|
10254
10359
|
}, {
|
|
10255
10360
|
servers?: {
|
|
@@ -10273,6 +10378,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
10273
10378
|
elicitation?: boolean | undefined;
|
|
10274
10379
|
contentOrigin?: "local" | "execution" | "external" | undefined;
|
|
10275
10380
|
source?: unknown;
|
|
10381
|
+
toolFaces?: unknown;
|
|
10276
10382
|
}[] | undefined;
|
|
10277
10383
|
}>;
|
|
10278
10384
|
readonly plugins: z.ZodEffects<z.ZodObject<{
|
package/dist/types.js
CHANGED
|
@@ -209,6 +209,40 @@ export function extraBodyUnsafe(v) {
|
|
|
209
209
|
}
|
|
210
210
|
return false;
|
|
211
211
|
}
|
|
212
|
+
/** THE vetting pipeline for every FREE-FORM JSON value that lands in the persisted config — `ModelEntry.extraBody`
|
|
213
|
+
* and `ModelEntry.compat` share this ONE function (1.10.0; before that it was inline in `extraBody` and a second
|
|
214
|
+
* free-form field would have copied it). The judgment is identical for every such field, so it lives in one place:
|
|
215
|
+
*
|
|
216
|
+
* 1. getter-free descriptor walk ({@link extraBodyUnsafe}) over the RAW value — never invokes a getter, and any
|
|
217
|
+
* reflective throw (a hostile Proxy trap could throw a secret-bearing message) collapses into a FIXED message;
|
|
218
|
+
* 2. a SINGLE `JSON.stringify` — its clone is re-scanned, so a Proxy that fakes its descriptors still can't ship
|
|
219
|
+
* a secret, and that same clone IS what we return to persist, so a non-idempotent `toJSON` cannot validate one
|
|
220
|
+
* serialization and persist another (the pre-R10 superRefine+transform stringified TWICE).
|
|
221
|
+
*
|
|
222
|
+
* `field` only NAMES the field in the message — it never changes the judgment. What this does NOT do is validate
|
|
223
|
+
* SHAPE: a field's shape/vocabulary is the consumer's single point (1.7.2 / 1.9.0 rule), and this domain parses
|
|
224
|
+
* all-or-nothing, so a shape rejection here would blank the whole catalog. */
|
|
225
|
+
function vetFreeFormJson(v, field) {
|
|
226
|
+
let rawUnsafe;
|
|
227
|
+
try {
|
|
228
|
+
rawUnsafe = extraBodyUnsafe(v);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return { ok: false, message: `${field} could not be validated (reflective access threw)` }; // R11
|
|
232
|
+
}
|
|
233
|
+
if (rawUnsafe)
|
|
234
|
+
return { ok: false, message: `${field}: a key/value is a secret shape, non-JSON (Infinity/function/Map), an accessor, cyclic, or too deep` };
|
|
235
|
+
let clone;
|
|
236
|
+
try {
|
|
237
|
+
clone = JSON.parse(JSON.stringify(v)); // the ONLY serialization — its result is what we scan AND persist
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return { ok: false, message: `${field} is not JSON-serializable` };
|
|
241
|
+
}
|
|
242
|
+
if (extraBodyUnsafe(clone))
|
|
243
|
+
return { ok: false, message: `${field}: its serialized form carries a secret` };
|
|
244
|
+
return { ok: true, value: clone };
|
|
245
|
+
}
|
|
212
246
|
/** A k8s resource quantity ("250m", "1", "0.5", "512Mi", "1Gi", "128M") — catches garbage at config-submit
|
|
213
247
|
* rather than surfacing as a reconcile ApplyError at the apiserver (consistent with ENV_NAME/DURATION guards). */
|
|
214
248
|
export const K8S_QUANTITY = z.string().regex(/^\d+(\.\d+)?(m|[kKMGTPE]i?)?$/, 'must be a k8s quantity like "250m", "512Mi", "1Gi"');
|
|
@@ -313,10 +347,9 @@ export const ModelEntry = z.object({
|
|
|
313
347
|
extraBody: z
|
|
314
348
|
.unknown()
|
|
315
349
|
.optional()
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
//
|
|
319
|
-
// BEFORE the stringify; the clone is re-scanned so a Proxy that fakes its descriptors still can't ship a secret.
|
|
350
|
+
// The SHAPE gate (plain JSON object) is extraBody's OWN — it is spread into a request body, so a non-object
|
|
351
|
+
// is meaningless here; the SAFETY judgment is the shared vetFreeFormJson pipeline (see its doc: getter-free
|
|
352
|
+
// walk → single stringify → re-scanned clone IS the persisted value).
|
|
320
353
|
.transform((v, ctx) => {
|
|
321
354
|
if (v === undefined)
|
|
322
355
|
return undefined;
|
|
@@ -325,33 +358,42 @@ export const ModelEntry = z.object({
|
|
|
325
358
|
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "extraBody must be a plain JSON object" });
|
|
326
359
|
return z.NEVER;
|
|
327
360
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
try {
|
|
332
|
-
rawUnsafe = extraBodyUnsafe(v);
|
|
333
|
-
}
|
|
334
|
-
catch {
|
|
335
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "extraBody could not be validated (reflective access threw)" });
|
|
361
|
+
const vetted = vetFreeFormJson(v, "extraBody");
|
|
362
|
+
if (!vetted.ok) {
|
|
363
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: vetted.message });
|
|
336
364
|
return z.NEVER;
|
|
337
365
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
366
|
+
return vetted.value;
|
|
367
|
+
}),
|
|
368
|
+
/** Per-model wire-compat declaration for the OpenAI-completions lane — mirrors the engine's
|
|
369
|
+
* `OpenAICompletionsCompat` (five keys: `thinkingFormat` / `reasoningEffortLevels` / `maxTokensField` /
|
|
370
|
+
* `requiresReasoningContentOnAssistantMessages` / `supportsReasoningEffort`). Real need: a vLLM/Qwen-class
|
|
371
|
+
* gateway that thinks by DEFAULT can only be turned off with `chat_template_kwargs.enable_thinking=false`,
|
|
372
|
+
* which `extraBody` cannot carry (the engine reserves those request keys) — and without this key a catalog
|
|
373
|
+
* entry that declares it is stripped at parse, so the declaration never reaches the engine at all.
|
|
374
|
+
*
|
|
375
|
+
* **Parse-transparent** (`z.unknown()`), same rule as `McpServerSpec.source` (1.7.2) and `.toolFaces` (1.9.0):
|
|
376
|
+
* the SHAPE and the VOCABULARY (which `thinkingFormat` words exist) are the consuming side's single point —
|
|
377
|
+
* this package deliberately does NOT restate that table. This domain parses all-or-nothing, so a shape/word
|
|
378
|
+
* rejection HERE would blank the entire model catalog over one bad key (the 1.7.1 upgrade regression). ABSENT
|
|
379
|
+
* = key not minted = today's behaviour, zero migration.
|
|
380
|
+
*
|
|
381
|
+
* The ONE rejection that remains is the free-form SAFETY judgment shared with `extraBody`
|
|
382
|
+
* ({@link vetFreeFormJson}): a secret-shaped key/value, an accessor, a cycle, non-JSON, or too deep to hash
|
|
383
|
+
* later. That is not shape validation — it is the boundary every free-form value must clear to enter the
|
|
384
|
+
* persisted config and `stableHash` (R18). */
|
|
385
|
+
compat: z
|
|
386
|
+
.unknown()
|
|
387
|
+
.optional()
|
|
388
|
+
.transform((v, ctx) => {
|
|
389
|
+
if (v === undefined)
|
|
390
|
+
return undefined;
|
|
391
|
+
const vetted = vetFreeFormJson(v, "compat");
|
|
392
|
+
if (!vetted.ok) {
|
|
393
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: vetted.message });
|
|
352
394
|
return z.NEVER;
|
|
353
395
|
}
|
|
354
|
-
return
|
|
396
|
+
return vetted.value;
|
|
355
397
|
}),
|
|
356
398
|
/** 配额倍率(EXPERT-REDESIGN §4-1):该模型烧 token 双窗额度的倍率,默认 1。折算时点=weight-at-burn
|
|
357
399
|
* (记账时固化到 UsageEntry.quotaWeightAtUse/weightedTokens):改倍率只影响此后记账,不回算窗口内历史。 */
|
|
@@ -1912,6 +1954,12 @@ export const McpServerSpec = z.object({
|
|
|
1912
1954
|
* both legs stripped it (default-strip object); this is the declaration half of the consumer-side fix
|
|
1913
1955
|
* (ticket B-036 / S-143), the projection half lives in the consumer. */
|
|
1914
1956
|
source: z.unknown().optional(),
|
|
1957
|
+
/** 1.9.0 —— core 7.8.0(design/388 片 1 F7)`toolFaces` 覆盖层:按远端工具名 key 的 face 声明
|
|
1958
|
+
* (`{ family?, pathTarget?: {param, aliases?, access, skillScopeEligible?}, renderHints?, ruleFace? }`)。
|
|
1959
|
+
* 与 `source` 同一条规矩:**解析透明**(`z.unknown()`),形的校验属 core 摄入侧(不合 schema 的工具**不挂**并
|
|
1960
|
+
* 通告一次 `config.tool_face_invalid`);本仓不复述那张表 —— 这一域 all-or-nothing,任一字段解析拒都会
|
|
1961
|
+
* 让整套 mcp 服务器静默消失。缺席 = 不铸键。 */
|
|
1962
|
+
toolFaces: z.unknown().optional(),
|
|
1915
1963
|
notes: z.string().optional(),
|
|
1916
1964
|
});
|
|
1917
1965
|
export const McpConfig = z
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/settings-schema",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Sema settings schema — pure config contract (zod domains + effective-config + roster resolution + ref-integrity + remoteExec) shared by sema-registry, sema-server, and the TOC desktop/CLI. One source of truth. (Renamed at 1.0.0 from @sema-agent/registry-core — name and docs only, no behavior change; note the range moves 0.19.0 -> 1.0.0, so a dependency must become ^1.0.0. The old names @sema-agent/registry-core <=0.19.0 and @sema-ai/registry-core remain published, frozen, for migration.)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|