@sema-agent/server 7.121.0 → 7.123.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +175 -0
- package/README.md +6 -1
- package/README.zh-CN.md +6 -1
- package/USAGE.md +57 -18
- package/dist/approval-reconciler.d.ts +8 -0
- package/dist/approval-reconciler.js +72 -52
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +52 -22
- package/dist/auto-mode-face.d.ts +16 -5
- package/dist/auto-mode-face.js +7 -4
- package/dist/bench/s1/live-deps.js +1 -0
- package/dist/boot/config-center.js +3 -0
- package/dist/boot/leader.js +1 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +2 -1
- package/dist/boot/resolve-spec.js +1 -4
- package/dist/boot/shutdown.js +6 -1
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/capabilities/memory-notice.d.ts +1 -1
- package/dist/config-catalog.js +4 -4
- package/dist/config-center/apply-effective.d.ts +1 -1
- package/dist/config-center/apply-effective.js +5 -3
- package/dist/config-center/center-request.d.ts +6 -9
- package/dist/config-center/center-request.js +11 -27
- package/dist/config-center/http-client.js +3 -3
- package/dist/config-center/read-warnings.d.ts +56 -35
- package/dist/config-center/read-warnings.js +67 -19
- package/dist/config-center/types.d.ts +7 -8
- package/dist/config-lkg.d.ts +12 -9
- package/dist/config-lkg.js +38 -39
- package/dist/config-provider.d.ts +3 -2
- package/dist/config-provider.js +2 -2
- package/dist/config-types.d.ts +20 -9
- package/dist/config-types.js +1 -1
- package/dist/config.d.ts +10 -10
- package/dist/config.js +92 -127
- package/dist/fleet/drain-entry.d.ts +28 -3
- package/dist/fleet/drain-entry.js +3 -0
- package/dist/fleet/engine-signal.d.ts +54 -23
- package/dist/fleet/engine-signal.js +29 -5
- package/dist/fleet/serving-lease.js +13 -15
- package/dist/fleet-client.d.ts +8 -6
- package/dist/fleet-client.js +4 -3
- package/dist/governance-overrides.d.ts +7 -2
- package/dist/http/admission.js +7 -5
- package/dist/http/approval-sweeps.js +2 -2
- package/dist/http/checkpoint-ctx.d.ts +60 -11
- package/dist/http/checkpoint-ctx.js +23 -9
- package/dist/http/dispatch.js +22 -19
- package/dist/http/health-self-report.d.ts +3 -0
- package/dist/http/resume-legs.js +8 -8
- package/dist/http/route-ctx.d.ts +19 -3
- package/dist/http/route-table.d.ts +3 -0
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/admin-drain.d.ts +5 -2
- package/dist/http/routes/admin-drain.js +14 -2
- package/dist/http/routes/approvals-assistant.d.ts +1 -0
- package/dist/http/routes/approvals-assistant.js +6 -6
- package/dist/http/routes/capabilities.js +7 -5
- package/dist/http/routes/fleet.d.ts +1 -0
- package/dist/http/routes/fleet.js +1 -1
- package/dist/http/routes/images.d.ts +1 -0
- package/dist/http/routes/images.js +1 -1
- package/dist/http/routes/leader.js +6 -0
- package/dist/http/routes/runs.d.ts +2 -0
- package/dist/http/routes/runs.js +5 -4
- package/dist/http/routes/sessions.d.ts +1 -0
- package/dist/http/routes/sessions.js +2 -5
- package/dist/http/routes/trace-usage.d.ts +1 -0
- package/dist/http/routes/trace-usage.js +1 -1
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +1 -1
- package/dist/http/send.d.ts +13 -0
- package/dist/http/send.js +9 -0
- package/dist/http/server.d.ts +3 -0
- package/dist/http/stored-body-replay.d.ts +28 -0
- package/dist/http/stored-body-replay.js +22 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/leader/leader.d.ts +23 -1
- package/dist/leader/leader.js +6 -1
- package/dist/leader/repair-wire.d.ts +1 -1
- package/dist/leader/repair-wire.js +2 -2
- package/dist/leader/run-entry.d.ts +27 -0
- package/dist/leader/run-entry.js +29 -0
- package/dist/leader/wire.d.ts +10 -0
- package/dist/leader/wire.js +15 -10
- package/dist/model-entry-refusal.d.ts +18 -9
- package/dist/model-entry-refusal.js +19 -14
- package/dist/model-route-endpoint.d.ts +21 -1
- package/dist/model-route-endpoint.js +9 -3
- package/dist/model-route-gap.d.ts +103 -0
- package/dist/model-route-gap.js +80 -0
- package/dist/model-route-url.d.ts +13 -20
- package/dist/model-route-url.js +28 -24
- package/dist/namespaced-rule-name.d.ts +16 -30
- package/dist/namespaced-rule-name.js +2 -20
- package/dist/observability/fail-open.d.ts +23 -10
- package/dist/observability/fail-open.js +8 -8
- package/dist/plugins/approval-ask-store-file.d.ts +1 -0
- package/dist/plugins/approval-ask-store-file.js +3 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +1 -0
- package/dist/plugins/approval-ask-store-memory.js +6 -0
- package/dist/plugins/approval-ask-store-sql.d.ts +12 -0
- package/dist/plugins/approval-ask-store-sql.js +4 -0
- package/dist/plugins/one-time-migrations.js +40 -0
- package/dist/plugins/park-commit-watch.d.ts +19 -5
- package/dist/plugins/park-commit-watch.js +24 -17
- package/dist/plugins/session-policy-store-sql.js +1 -2
- package/dist/plugins/workflow-run-store-sql.d.ts +4 -2
- package/dist/router/route-orchestration.d.ts +4 -2
- package/dist/router/route-orchestration.js +2 -1
- package/dist/rule-entry-list.d.ts +3 -13
- package/dist/rule-entry-list.js +1 -12
- package/dist/run-local.js +4 -2
- package/dist/runtime-governance.d.ts +67 -32
- package/dist/runtime-governance.js +28 -9
- package/dist/session-policy-wire.d.ts +47 -49
- package/dist/session-policy-wire.js +41 -36
- package/dist/session-sync.d.ts +5 -1
- package/dist/session-sync.js +2 -1
- package/dist/sighup-idle.d.ts +7 -1
- package/dist/sighup-idle.js +4 -4
- package/dist/spec-fields.d.ts +4 -4
- package/dist/spec-fields.js +1 -4
- package/dist/task-settings.d.ts +36 -14
- package/dist/task-settings.js +20 -23
- package/dist/tool-approval.d.ts +6 -0
- package/dist/tool-approval.js +13 -1
- package/dist/trace/redact.d.ts +3 -3
- package/dist/unattended-permission-mode.d.ts +17 -13
- package/dist/unattended-permission-mode.js +3 -1
- package/dist/url-shape.d.ts +31 -0
- package/dist/url-shape.js +41 -0
- package/package.json +3 -3
- package/scripts/drain-check-local.mjs +1 -1
package/dist/config-lkg.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { promises as fs
|
|
2
|
-
import {
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { join, dirname, resolve } from "node:path";
|
|
3
3
|
import { randomBytes } from "node:crypto";
|
|
4
4
|
import { validatePromptsDomain } from "./prompts-domain-validate.js";
|
|
5
5
|
import { centerStateBin, pullTokenIdentity } from "./center-credential.js";
|
|
6
6
|
import { configRootOf } from "./sema-config-dir.js";
|
|
7
|
-
import { recordFailOpen } from "./observability/fail-open.js";
|
|
8
7
|
export function defaultSkillCacheDir(config) {
|
|
9
8
|
return join(configRootOf(config), "skill-cache");
|
|
10
9
|
}
|
|
@@ -23,41 +22,10 @@ export function lkgPathOverrideOf(raw) {
|
|
|
23
22
|
export function lkgReadDenyRows(configLkgPath) {
|
|
24
23
|
if (configLkgPath === undefined)
|
|
25
24
|
return [];
|
|
26
|
-
return [
|
|
27
|
-
}
|
|
28
|
-
function landedPathOf(p) {
|
|
29
|
-
const rest = [];
|
|
30
|
-
let landed = p;
|
|
31
|
-
let unresolved;
|
|
32
|
-
for (let head = p;; head = dirname(head)) {
|
|
33
|
-
try {
|
|
34
|
-
landed = join(realpathSync(head), ...rest);
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
if (unresolved === undefined && head !== p && segmentPresent(head))
|
|
39
|
-
unresolved = head;
|
|
40
|
-
if (dirname(head) === head)
|
|
41
|
-
break;
|
|
42
|
-
rest.unshift(basename(head));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
if (unresolved !== undefined)
|
|
46
|
-
recordFailOpen("server.config-lkg.landed-path-unresolved", `segment=${unresolved}`);
|
|
47
|
-
return landed;
|
|
48
|
-
}
|
|
49
|
-
function segmentPresent(p) {
|
|
50
|
-
try {
|
|
51
|
-
lstatSync(p);
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
catch (e) {
|
|
55
|
-
const code = e.code;
|
|
56
|
-
return code !== "ENOENT" && code !== "ENOTDIR";
|
|
57
|
-
}
|
|
25
|
+
return [{ pattern: configLkgPath, caseSensitive: false }];
|
|
58
26
|
}
|
|
59
27
|
export async function saveLkg(path, worker, identity, effective, etag) {
|
|
60
|
-
const body = { formatVersion:
|
|
28
|
+
const body = { formatVersion: 3, savedAt: new Date().toISOString(), worker: worker ?? "global", identity, ...(etag !== undefined ? { etag } : {}), effective };
|
|
61
29
|
const tmp = `${path}.${randomBytes(6).toString("hex")}.tmp`;
|
|
62
30
|
await fs.mkdir(dirname(path), { recursive: true });
|
|
63
31
|
await fs.writeFile(tmp, JSON.stringify(body), { mode: 0o600 });
|
|
@@ -84,14 +52,45 @@ export async function loadLkg(path, worker, identity) {
|
|
|
84
52
|
const formatVersion = p.formatVersion;
|
|
85
53
|
if (formatVersion === 1)
|
|
86
54
|
return { reason: "pre-identity LKG (formatVersion 1) — not read back: it cannot prove whose credential fetched it (S-651); the next clean candidate rewrites it" };
|
|
87
|
-
if (formatVersion !== 2)
|
|
55
|
+
if (formatVersion !== 2 && formatVersion !== 3)
|
|
88
56
|
return { reason: `unknown formatVersion ${String(formatVersion)}` };
|
|
89
57
|
if (typeof p.worker !== "string" || p.worker !== (worker ?? "global"))
|
|
90
58
|
return { reason: `worker mismatch (file=${String(p.worker)})` };
|
|
91
59
|
if (typeof p.identity !== "string" || p.identity !== identity)
|
|
92
60
|
return { reason: "credential identity mismatch (the LKG was fetched under another credential identity — not read back)" };
|
|
93
61
|
const problem = lkgPayloadProblem(p.effective, p.etag);
|
|
94
|
-
|
|
62
|
+
if (problem !== undefined)
|
|
63
|
+
return { reason: problem };
|
|
64
|
+
return formatVersion === 2 ? migrateV2Lkg(p) : { lkg: p };
|
|
65
|
+
}
|
|
66
|
+
const RETIRED_CATALOG_COORDINATE = /^models\.(0|[1-9][0-9]*)$/;
|
|
67
|
+
function migrateDroppedIdentityRow(row) {
|
|
68
|
+
if (row === null || typeof row !== "object")
|
|
69
|
+
return row;
|
|
70
|
+
const r = row;
|
|
71
|
+
const at = typeof r.entry === "string" ? RETIRED_CATALOG_COORDINATE.exec(r.entry) : null;
|
|
72
|
+
const fields = r.fields;
|
|
73
|
+
if (at === null || typeof r.name !== "string" || (r.id !== undefined && typeof r.id !== "string") || !Array.isArray(fields) || !fields.every((f) => typeof f === "string") || typeof r.issues !== "string")
|
|
74
|
+
return row;
|
|
75
|
+
return { index: Number(at[1]), reasonCode: "entry-schema-invalid", identity: { name: r.name, ...(typeof r.id === "string" ? { id: r.id } : {}) }, fields: [...fields], issues: r.issues };
|
|
76
|
+
}
|
|
77
|
+
function migrateV2Lkg(lkg) {
|
|
78
|
+
const { etag: _incompleteCarrierValidator, ...envelope } = lkg;
|
|
79
|
+
const models = lkg.effective.models;
|
|
80
|
+
const hasRetired = models !== undefined && models !== null && typeof models === "object" && Object.hasOwn(models, "droppedIdentities");
|
|
81
|
+
let effective = lkg.effective;
|
|
82
|
+
if (hasRetired) {
|
|
83
|
+
const { droppedIdentities: retired, ...rest } = models;
|
|
84
|
+
if (Object.hasOwn(rest, "droppedCatalogEntries")) {
|
|
85
|
+
return { reason: "both the retired dropped-entry carrier (models.droppedIdentities) and its successor (models.droppedCatalogEntries) are present — no writer produces that shape; not read back" };
|
|
86
|
+
}
|
|
87
|
+
effective = { ...lkg.effective, models: { ...rest, droppedCatalogEntries: Array.isArray(retired) ? retired.map(migrateDroppedIdentityRow) : retired } };
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
lkg: { ...envelope, formatVersion: 3, effective },
|
|
91
|
+
migrated: "formatVersion 2 → 3 (one-time): this LKG was written before every dropped catalog entry was recorded, so its etag is not reused — the next pull re-reads the whole candidate and re-mints the full record" +
|
|
92
|
+
(hasRetired ? "; the retired carrier models.droppedIdentities was moved to models.droppedCatalogEntries" : ""),
|
|
93
|
+
};
|
|
95
94
|
}
|
|
96
95
|
function lkgPayloadProblem(effective, etag) {
|
|
97
96
|
if (effective === null || typeof effective !== "object")
|
|
@@ -183,7 +182,7 @@ export async function migrateV1Lkg(o) {
|
|
|
183
182
|
}
|
|
184
183
|
}
|
|
185
184
|
try {
|
|
186
|
-
await saveLkg(o.binPath, o.worker, o.identity, v1.effective,
|
|
185
|
+
await saveLkg(o.binPath, o.worker, o.identity, v1.effective, undefined);
|
|
187
186
|
}
|
|
188
187
|
catch (err) {
|
|
189
188
|
return refuse(`writing it into this credential identity's bin failed (${String(err)}) — the old file is left in place and the migration retries on the next LKG read`);
|
|
@@ -22,8 +22,9 @@ import type { ConfigProviderWord } from "./config-types.js";
|
|
|
22
22
|
* 路由进日志/审计流的消费者必须自己先脱敏。 */
|
|
23
23
|
/** `credentialIdentity`(S-651 / [ref] E-15):远程腿恒在场 = 这次拉取所用凭证的身份(分箱键来源);本地腿
|
|
24
24
|
* 缺席(没有凭证 —— config.d 就在本机盘上)。 */
|
|
25
|
-
/** `droppedEntries`(S-704 ②):schema 逐条丢掉的条目(坐标 +
|
|
26
|
-
*
|
|
25
|
+
/** `droppedEntries`(S-704 ②):schema 逐条丢掉的条目(坐标 + 字段诊断,已脱敏;S-1295 起每行带闭集词 `reasonCode`)—— **不**进候选门,
|
|
26
|
+
* 调用方逐条响亮点名、其余照用;缺席 = 这次读零逐条丢弃(与 `domainErrors` 同一种缺席即无的形)。其中的目录条目同一次折叠另记进
|
|
27
|
+
* `effective.models.droppedCatalogEntries`(`GET /v1/models.droppedEntries` 的源,与 `models` 同世代)。 */
|
|
27
28
|
export type FetchEffectiveResult = {
|
|
28
29
|
effective: EffectiveConfig;
|
|
29
30
|
etag?: string;
|
package/dist/config-provider.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readMcpSourceLabel } from "./mcp-source-label.js";
|
|
2
2
|
import { createHmac, randomBytes } from "node:crypto";
|
|
3
|
-
import { splitFoldedReadWarnings,
|
|
3
|
+
import { splitFoldedReadWarnings, withDroppedCatalogEntries } from "./config-center/read-warnings.js";
|
|
4
4
|
import { FileConfigStore } from "@sema-agent/settings-schema/node";
|
|
5
5
|
import { findSkillContent, skillContentHash, refIntegrityIssues, createSiblingResolver, formatConfigPath, REF_CHECKED_DOMAINS, } from "@sema-agent/settings-schema";
|
|
6
6
|
import { redactSecrets } from "./trace/redact.js";
|
|
@@ -96,7 +96,7 @@ export class LocalConfigProvider {
|
|
|
96
96
|
const droppedEntries = folded.droppedEntries.map((d) => ({ ...d, error: redactConfigError(d.error) }));
|
|
97
97
|
const errors = [...domainErrors.map((de) => ({ domain: de.domain, error: redactConfigError(de.error) })), ...parseErrors, ...refErrors];
|
|
98
98
|
return {
|
|
99
|
-
effective:
|
|
99
|
+
effective: withDroppedCatalogEntries(mapToServiceEffective(eff, eff.version), folded.droppedCatalogEntries),
|
|
100
100
|
etag: tag,
|
|
101
101
|
readWarnings,
|
|
102
102
|
...(errors.length > 0 ? { domainErrors: errors } : {}),
|
package/dist/config-types.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type { ReadFaceSource } from "./read-face-posture.js";
|
|
|
9
9
|
import type { PostureSource } from "./posture-source.js";
|
|
10
10
|
import type { SealedCustodyPoison } from "./key-resolver.js";
|
|
11
11
|
import type { ModelEntryRefusal } from "./model-entry-refusal.js";
|
|
12
|
+
import type { DroppedCatalogEntry } from "./config-center/read-warnings.js";
|
|
12
13
|
import type { A2aServerSpec, CompliancePosture, CrossSessionDialogExpiry, CrossSessionInboundSetting, FileHistoryRetentionPolicy, LockedKey, McpServerSpec, Model, ModelRoles, RetentionPolicy, ShellGateDoctrine, WriteProtectedEntry } from "@sema-agent/core";
|
|
13
14
|
import type { ApprovalHmacKey, PrincipalJwtKey } from "./auth-keys.js";
|
|
14
15
|
import type { ElicitationThrottle } from "./elicitation.js";
|
|
@@ -127,8 +128,8 @@ export declare const DRAIN_SECOND_SIGNAL_MIN_GAP_DEFAULT_MS = 250;
|
|
|
127
128
|
* 住在本叶(而不在 `fleet/drain-entry.ts`):`config.ts` 读它,而 drain-entry 值引 `plugins/store-contracts.ts`,config 不值引 plugins 层。
|
|
128
129
|
*/
|
|
129
130
|
export declare function fleetScopeOf(raw: string | undefined): string;
|
|
130
|
-
/** 中心基址三席(`SEMA_REGISTRY_URL` / `SEMA_REGISTRY_LIVE_URL` / `SEMA_REGISTRY_WEB_URL`)
|
|
131
|
-
export declare const CENTER_BASE_URL_RULE = "\u8BBE\u4E86\u5C31\u5FC5\u987B\u662F\u53EF\u89E3\u6790\u7684 http(s) URL,\u4E14\u4E0D\u5E26\u51ED\u636E / query / fragment(\u57FA\u5740\u540E\u9762\u8981\u62FC\u8DEF\u5F84);\u574F\u5F62\u62D2\u542F(\u6CA1\u63A5\u4E2D\u5FC3\u4E5F\u62D2)";
|
|
131
|
+
/** 中心基址三席(`SEMA_REGISTRY_URL` / `SEMA_REGISTRY_LIVE_URL` / `SEMA_REGISTRY_WEB_URL`)与公告地址的形句 —— 判官 `config-center/center-request.ts` `pathBaseUrlRefusal` 一只(形判 = `url-shape.ts`),配置目录四行同读这一句。 */
|
|
132
|
+
export declare const CENTER_BASE_URL_RULE = "\u8BBE\u4E86\u5C31\u5FC5\u987B\u662F\u53EF\u89E3\u6790\u7684 http(s) URL,\u4E14\u4E0D\u5E26\u51ED\u636E / query / fragment(\u57FA\u5740\u540E\u9762\u8981\u62FC\u8DEF\u5F84);\u574F\u5F62\u62D2\u542F(\u6CA1\u63A5\u4E2D\u5FC3\u4E5F\u62D2),\u62D2\u53E5\u53EA\u70B9\u540D\u89C4\u5219,\u4E0D\u56DE\u663E scheme";
|
|
132
133
|
/** 编排器片 2:`FLEET_LEASE_OUTAGE_MAX_MS` 的缺省(24 h)—— 中心 / 库故障、中心降级在今天都靠 LKG 无限期容忍,10 分钟级的窗会把它们变成数据面停服。 */
|
|
133
134
|
export declare const FLEET_LEASE_OUTAGE_MAX_DEFAULT_MS = 86400000;
|
|
134
135
|
/**
|
|
@@ -572,6 +573,13 @@ export interface ServiceConfigFlat {
|
|
|
572
573
|
* 「没这模型」。env 腿恒空;只由 applyEffective 与 `models` **同世代同 commit** 整表重赋值(非粘)。
|
|
573
574
|
*/
|
|
574
575
|
modelRefusals: Readonly<Record<string, ModelEntryRefusal>>;
|
|
576
|
+
/**
|
|
577
|
+
* S-1295 —— **本世代目录里被读腿逐条丢掉的条目**(载体 `EffectiveConfig.models.droppedCatalogEntries` 经模型面判据判过形的行,保序;
|
|
578
|
+
* 下标 + settings-schema 闭集词 + 身份 + 字段诊断)。`GET /v1/models` 的 `droppedEntries` 唯一的源(出口投影 `buildDroppedEntriesWire`:
|
|
579
|
+
* 只投词与可披露身份)。env 腿恒空(没有目录读);只由 applyEffective 与 `models` **同世代同 commit** 整表重赋值(非粘)—— 模型面这一组
|
|
580
|
+
* 被拒时它与目录一起停在上一代。墓碑(`modelRefusals` 里的 `entry_invalid` 行)是同一份载体的另一种读法,不是第二份记录。
|
|
581
|
+
*/
|
|
582
|
+
droppedCatalogEntries: readonly DroppedCatalogEntry[];
|
|
575
583
|
/** 配额倍率表(name+id 双键→ModelEntry.quotaWeight):weight-at-burn 的运行时源——tracer 在
|
|
576
584
|
* brain.call 记账点读它算 weightedTokens(lease 双轴+usage 批报)。registry apply IN-PLACE hot-apply;
|
|
577
585
|
* env lane 恒空(无倍率概念,weight=1 兜底)。 */
|
|
@@ -1479,8 +1487,9 @@ export interface ServiceConfigFlat {
|
|
|
1479
1487
|
* `TaskSpec.enablePlanMode:true` but NOT `handsReadOnly` (writable-start) → core auto-mounts `enter_plan_mode`
|
|
1480
1488
|
* (+ `present_plan`) so the model can self-call `enter_plan_mode` at ANY time it judges a task needs planning
|
|
1481
1489
|
* (CC EnterPlanMode parity). 🆕 DEFAULT ON (clay: model-driven plan is resident — the model decides when to plan);
|
|
1482
|
-
* set `PLAN_MODE_ENABLED=false` to opt out. USER-driven plan (`body.permissionMode=plan
|
|
1483
|
-
*
|
|
1490
|
+
* set `PLAN_MODE_ENABLED=false` to opt out. A USER-driven plan (`body.permissionMode=plan`, bundle `defaultMode`, or
|
|
1491
|
+
* `AUTONOMY=plan`) is the same engine mode word, independent of this knob: the engine's mode table mounts the plan
|
|
1492
|
+
* tools for a declared `plan` itself, and no plan entry clamps the hands (only `AUTONOMY=read-only` does). */
|
|
1484
1493
|
planModeEnabled: boolean;
|
|
1485
1494
|
/**
|
|
1486
1495
|
* [ref]⑥(core 5.56 `Hooks.timeoutMs` 座)—— **每一只 hook 席位单次调用的时间上限**(ms)。
|
|
@@ -2134,10 +2143,12 @@ export interface ServiceConfigFlat {
|
|
|
2134
2143
|
* `loadConfig` **无条件**解析一次:未设 / 空串 ⇒ 缺席(公告环不装);在场必须是可解析的 http(s) URL,否则拒启。读者:fleet 公告环、
|
|
2135
2144
|
* 围栏判官 `fleetFenceLaneOf`、`/health.center.sessionsVisible`、启动日志 —— 都读这一席,不读 env。 */
|
|
2136
2145
|
fleetAdvertiseAddress?: string;
|
|
2137
|
-
/** 编排器片 2
|
|
2138
|
-
*
|
|
2139
|
-
*
|
|
2140
|
-
*
|
|
2146
|
+
/** 编排器片 2:一台实例「活着而不服务」的最长时长 `T_max`(ms;env `FLEET_LEASE_OUTAGE_MAX_MS`)。缺省 86 400 000(24 h);地板 = 服务租约
|
|
2147
|
+
* TTL 地板(settings-schema `SERVING_LEASE_TTL_FLOOR_MS`,60 s);不许 0 / 无穷,坏值拒启。`loadConfig` 无条件解析(成员与非成员同读)。两个读者:
|
|
2148
|
+
* ① 服务租约**中心不可达的容忍上限**(`fleet/serving-lease.ts`;只在 fleet 成员 ∧ 中心宣告了 `servingLease` 能力位时生效):租约过期(中心
|
|
2149
|
+
* 不可达 / 答 unknown)之后照常服务,直到过期满这么久 ⇒ 新计费提交 503 `state.lease_expired`(取消 / HITL 应答 / 续跑 / 读面照放行),在飞不动、
|
|
2150
|
+
* 不自停;中心恢复授予即恢复。② 排空口 `POST /v1/admin/drain` 的**期限准入上界**(`fleet/drain-entry.ts` 规则 2):`deadlineAt` 离此刻超过它 ⇒
|
|
2151
|
+
* 400 `request.field_invalid`。 */
|
|
2141
2152
|
fleetLeaseOutageMaxMs: number;
|
|
2142
2153
|
/** S-698(design-325 §2):中心凭证**续签提前量**(ms)—— `SEMA_REGISTRY_TOKEN_FILE` 指向人的登录会话信封
|
|
2143
2154
|
* (`kind:"user-session"`)时,访问令牌离到期 ≤ 本值即由引擎续签并原子改写同一文件(`center-credential-renewer.ts`)。
|
|
@@ -2156,7 +2167,7 @@ export interface ServiceConfigFlat {
|
|
|
2156
2167
|
/** 组:store(持久化)—— DB 引擎三态、session 后端、SQL coords、快照 BLOB / SendUserFile 对象存储。 */
|
|
2157
2168
|
export type ServiceStoreConfig = Pick<ServiceConfigFlat, "sessionBackend" | "sessionCacheTtlSec" | "storeProbeIntervalMs" | "storeLockWaitMs" | "dbBackend" | "dbBackendExplicit" | "localDataRoot" | "runStoreStrictHydrate" | "tidb" | "pg" | "dbQueryTimeoutMs" | "snapshotBlobStore" | "snapshotBlobSqlMaxBytes" | "snapshotBlobAllowSql" | "fileHistory" | "fileHistoryCapture" | "sendUserFile">;
|
|
2158
2169
|
/** 组:modelPlane(模型面)—— 网关坐标、Anthropic 路线、韧性旋钮、主/廉价 model entry、role 表、降级梯。 */
|
|
2159
|
-
export type ServiceModelPlaneConfig = Pick<ServiceConfigFlat, "gatewayBaseUrl" | "gatewayApiKey" | "gatewayFallbackUrls" | "gatewayMaxRetries" | "anthropic" | "resilience" | "model" | "envModel" | "models" | "modelApiKeyEnv" | "modelApiKeys" | "modelRefusals" | "modelQuotaWeights" | "tiers" | "projects" | "roles" | "atModelAllowlist" | "cascadeLadder" | "degrade">;
|
|
2170
|
+
export type ServiceModelPlaneConfig = Pick<ServiceConfigFlat, "gatewayBaseUrl" | "gatewayApiKey" | "gatewayFallbackUrls" | "gatewayMaxRetries" | "anthropic" | "resilience" | "model" | "envModel" | "models" | "modelApiKeyEnv" | "modelApiKeys" | "modelRefusals" | "droppedCatalogEntries" | "modelQuotaWeights" | "tiers" | "projects" | "roles" | "atModelAllowlist" | "cascadeLadder" | "degrade">;
|
|
2160
2171
|
/** 组:approval(审批 / HITL 门)。`directDoorActive` 无 env 解析腿(装配层三域合取的产物),但语义上
|
|
2161
2172
|
* 就是本组的门状态,故进组;`parseApprovalDomain` 的返回类型相应是 `Omit<…, "directDoorActive">`。 */
|
|
2162
2173
|
export type ServiceApprovalConfig = Pick<ServiceConfigFlat, "approvalRequire" | "approvalDeny" | "approvalTimeoutSec" | "approvalAutoBudget" | "approvalNeverAuto" | "approvalGrant" | "approvalHmacKeys" | "durableApproval" | "durableApprovalSource" | "streamAskWindowMsSource" | "directApprovalDoor" | "directDoorActive" | "resourceSuspend" | "resourceSuspendTtlSec" | "resourceSuspendTotalTokens" | "resourceSuspendTotalBudgetUsd" | "resourceSuspendMaxSlices" | "askQuestionEnabled" | "questionThrottle" | "toolApprovalEnabled" | "permissionRulesEnabled" | "permissionRulesEnabledExplicit" | "streamAskWindowMarginMs" | "streamApproval" | "unattendedApprovalPolicy" | "mcpElicitation" | "sensitiveWritePatterns" | "writeProtectedPaths" | "manualModeShellGate" | "permissionsDisableAutoMode" | "autoModeClassifierFallback" | "autoModeClassifierTimeoutMs" | "crossSessionInbound" | "crossSessionDialogExpiry">;
|
package/dist/config-types.js
CHANGED
|
@@ -12,7 +12,7 @@ export const DRAIN_SECOND_SIGNAL_MIN_GAP_DEFAULT_MS = 250;
|
|
|
12
12
|
export function fleetScopeOf(raw) {
|
|
13
13
|
return raw ?? GLOBAL_SCOPE;
|
|
14
14
|
}
|
|
15
|
-
export const CENTER_BASE_URL_RULE = "设了就必须是可解析的 http(s) URL,且不带凭据 / query / fragment(基址后面要拼路径);坏形拒启(没接中心也拒)";
|
|
15
|
+
export const CENTER_BASE_URL_RULE = "设了就必须是可解析的 http(s) URL,且不带凭据 / query / fragment(基址后面要拼路径);坏形拒启(没接中心也拒),拒句只点名规则,不回显 scheme";
|
|
16
16
|
export const FLEET_LEASE_OUTAGE_MAX_DEFAULT_MS = 86_400_000;
|
|
17
17
|
export const FIRST_BYTE_TIMEOUT_BOUNDS = { minMs: 0, maxMs: MAX_TIMER_DELAY_MS };
|
|
18
18
|
export const RESILIENCE_DEFAULTS = {
|
package/dist/config.d.ts
CHANGED
|
@@ -211,7 +211,7 @@ export declare function buildUnpricedCeilingNotice(models: Record<string, Model>
|
|
|
211
211
|
fields: Record<string, string>;
|
|
212
212
|
} | undefined;
|
|
213
213
|
/** [ref] N8/N9 — the BOOLEAN member of this module's env-parser family (`env`/`env2`/`numEnv`/
|
|
214
|
-
* `numEnvBounded`/`optFinitePositiveEnv`/`enumEnv`/`headerNameEnv
|
|
214
|
+
* `numEnvBounded`/`optFinitePositiveEnv`/`enumEnv`/`headerNameEnv`). Until now booleans were the
|
|
215
215
|
* one type parsed by a hand-written literal comparison at every single site, and that is exactly why the same
|
|
216
216
|
* `*_ENABLED` suffix grew FOUR incompatible polarities (opt-in `=== "true"`, opt-out `!== "false"`, the posture
|
|
217
217
|
* tri-state, and negative `*_DISABLED` names): with no shared helper there was nowhere for the default to be
|
|
@@ -298,10 +298,10 @@ export declare function isRosterGateArmed(configCenter: ServiceConfig["configCen
|
|
|
298
298
|
* - 够不着挂载工具的协议名:**对端段铸不出**(`mcp__github.com`、`mcp__github.com__*`、`mcp__*`、超长 / 归一后带连串下划线的服务器段、对端段为空的
|
|
299
299
|
* `mcp__` / `mcp____x`)—— 前缀对,但引擎铸注册名时归一对端段,而规则对对端段逐字比,永不匹配。判官是引擎的 `judgeRuleToolName`(core 7.43.0 #1355 (b)
|
|
300
300
|
* 的判词 `unmintable_segment`,句子带它的 guidance 与 1:1 现名);本仓 7.116.0–7.117.x 那只自比 `mintNamespacePrefix` 的对照随之退役。
|
|
301
|
-
*
|
|
301
|
+
* **工具段为空**(`mcp__srv__`)core 7.48.0 #1400 起也是这一判词(7.116.0–7.122.x 由本仓自答,随之退役)。
|
|
302
302
|
* ⚠️ 两段覆盖形 `mcp__<server>`(服务器段是自铸形)够得着(S-1047 收掉的分叉,见下)。
|
|
303
|
-
* - **core
|
|
304
|
-
*
|
|
303
|
+
* - **core 的文法编不出来的串**:判词取自 core 自己的 `validatePermissionRules`,射程与指引见 {@link uncompilableRuleGuidance}
|
|
304
|
+
* (名表消费者只递得来名字里带反斜杠、单条 >512 字符、空串三种;规则编译器消费者递来的每一条内容形都走这里)。[ref]①([ref])补齐 ——
|
|
305
305
|
* 此前只有 `ask` 腿(经 `createPermissionRulePolicy` 的 throw)拒得出这一族,`deny` 静默 no-op。
|
|
306
306
|
*
|
|
307
307
|
* 已接受的权衡(与退役表墓碑同一条):部署自有工具真叫 `figma__x` 的极端形会被误拒——boot 期无 roster 可
|
|
@@ -337,8 +337,8 @@ export interface UnmatchableToolName {
|
|
|
337
337
|
* (S-177 / core 7.9.0 起)。引擎**真的按内容匹配** deny / ask 的内容形(`Bash(rm -r:*)` / `Edit(~/.sema/**)`),所以本仓不许再替它拒 ——
|
|
338
338
|
* 判据整条交回 core 的 `validatePermissionRules`,按这张表自己的 behavior 问。core 7.42.0 起策略只说 deny / ask(allow 表不再是本消费者)。
|
|
339
339
|
* (7.117.0 有过第三种 `"allow-layer"` —— 请求的 `settings.permissions.allow` 只判名字。7.118.0 / core 7.43.0 #1358 起引擎的 allow 层自己按名册读条目名并通告
|
|
340
|
-
* (`permission.allowed_tool_not_granted`,`reason: "tool_name"` / `near_miss`)⇒ 本仓的名字判退役,allow
|
|
341
|
-
*
|
|
340
|
+
* (`permission.allowed_tool_not_granted`,`reason: "tool_name"` / `near_miss`)⇒ 本仓的名字判退役,allow 侧整只交引擎;7.116.0–7.122.x 另拒的「工具段为空」
|
|
341
|
+
* 一形随 core 7.48.0 #1400 也交引擎。)
|
|
342
342
|
*/
|
|
343
343
|
export type RuleEntryConsumer = "tool-name-table" | "rule-policy";
|
|
344
344
|
/**
|
|
@@ -369,10 +369,10 @@ export declare function unmatchableToolNamesRefusal(source: string, names: reado
|
|
|
369
369
|
* 7.117.0(core 7.42.0)起这张表整份投 `RunnerDeps.allowedTools`(引擎 allow 层的部署成员,构造时读一次),判据是**引擎的读法**,与请求的两张
|
|
370
370
|
* allow 表同一份(`rule-entry-list.ts`):
|
|
371
371
|
* ① 值不是字符串表 ⇒ 拒(env 的 CSV 恒给字符串表;判在这里是为了「值一旦换了来源,第一道判仍在」);
|
|
372
|
-
* ②
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
* 该怎么写。请求的 allow 侧对
|
|
372
|
+
* ② 引擎读成空的条目(`compileAllowList(names, "allow", 名册 = 空集).inert` 非空 —— `*`、`mcp__*`、写路径 / 域名形、带空白或畸形的名字,以及
|
|
373
|
+
* core 7.43.0 起条目名过引擎判官读成 `tool_name` 的退役名 / 无前缀短名 / 对端段铸不出,core 7.48.0 #1400 起含工具段为空的 `mcp__<srv>__`;
|
|
374
|
+
* 7.116.0–7.122.x 那一形由本仓先拒,随之退役)⇒ 拒,句子点名条目、引擎给的原因词(名字层带判词与现名)、
|
|
375
|
+
* 该怎么写。请求的 allow 侧对 ② 只收通告;运维这一侧拒启:这是运维自己的配置,写错了当场改,而引擎对读成空的部署条目只在每一跑发一条通告。
|
|
376
376
|
* 文法随引擎:工具名、协议名覆盖形、`Bash(...)` 命令规则、`Read(//dir/**)` 读目录都收(内容形里带逗号的写不进 CSV —— 这张表的分隔符就是逗号)。
|
|
377
377
|
*/
|
|
378
378
|
export declare function approvalGrantRefusal(names: unknown): string | undefined;
|