@sema-agent/server 7.98.0 → 7.100.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 +19 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +86 -60
- package/deploy/sema-up/lib/envf.sh +110 -42
- package/deploy/sema-up/sema-up.sh +76 -34
- package/dist/approval-ask-machine.d.ts +10 -0
- package/dist/approval-ask-machine.js +3 -0
- package/dist/approval-card.d.ts +74 -1
- package/dist/approval-card.js +41 -8
- package/dist/approval.d.ts +44 -20
- package/dist/approval.js +14 -6
- package/dist/boot/config-center.d.ts +16 -8
- package/dist/boot/config-center.js +206 -103
- package/dist/boot/execution-env.d.ts +1 -2
- package/dist/boot/execution-env.js +2 -2
- package/dist/boot/leader.js +12 -9
- package/dist/boot/memory-consolidation.d.ts +38 -0
- package/dist/boot/memory-consolidation.js +35 -0
- package/dist/boot/org-memory.d.ts +2 -1
- package/dist/boot/org-memory.js +9 -5
- package/dist/boot/resolve-spec.d.ts +0 -1
- package/dist/boot/resolve-spec.js +4 -3
- package/dist/boot/runner-deps.d.ts +2 -2
- package/dist/boot/runtime-caps.js +4 -4
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +3 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -3
- package/dist/boot/stage-07-capability-layer.js +6 -6
- package/dist/boot/stage-08-reapers.d.ts +3 -4
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +2 -3
- package/dist/boot/stage-10-http-server.d.ts +2 -3
- package/dist/boot/stage-10-http-server.js +2 -2
- package/dist/capabilities/center-plugins.d.ts +14 -2
- package/dist/capabilities/center-plugins.js +13 -5
- package/dist/capabilities/center-prompts.d.ts +3 -0
- package/dist/capabilities/center-prompts.js +1 -1
- package/dist/capabilities/hands-lane.js +2 -1
- package/dist/capabilities/scenarios.js +18 -5
- package/dist/capabilities/tool-defer.d.ts +2 -2
- package/dist/center-credential.d.ts +112 -0
- package/dist/center-credential.js +131 -0
- package/dist/config-catalog.d.ts +2 -2
- package/dist/config-catalog.js +15 -15
- package/dist/config-center/apply-effective.d.ts +34 -39
- package/dist/config-center/apply-effective.js +100 -64
- package/dist/config-center/apply-ledger.d.ts +35 -16
- package/dist/config-center/apply-ledger.js +25 -18
- package/dist/config-center/center-request.d.ts +60 -0
- package/dist/config-center/center-request.js +71 -0
- package/dist/config-center/facade.d.ts +11 -5
- package/dist/config-center/facade.js +1 -1
- package/dist/config-center/hot-keys-registry.d.ts +11 -4
- package/dist/config-center/hot-keys-registry.js +11 -7
- package/dist/config-center/http-client.d.ts +17 -9
- package/dist/config-center/http-client.js +27 -36
- package/dist/config-center/restart-signal.d.ts +21 -14
- package/dist/config-center/restart-signal.js +16 -22
- package/dist/config-center/skills-mcp.d.ts +4 -1
- package/dist/config-center/skills-mcp.js +2 -2
- package/dist/config-center/types.d.ts +3 -3
- package/dist/config-invariants.d.ts +2 -2
- package/dist/config-invariants.js +0 -8
- package/dist/config-lkg.d.ts +47 -8
- package/dist/config-lkg.js +107 -20
- package/dist/config-provider.d.ts +8 -7
- package/dist/config-provider.js +5 -5
- package/dist/config-types.d.ts +30 -11
- package/dist/config.js +11 -13
- package/dist/cross-session-settings.js +1 -1
- package/dist/fleet-client.d.ts +8 -8
- package/dist/fleet-client.js +7 -7
- package/dist/fleet-lease.d.ts +11 -11
- package/dist/fleet-lease.js +17 -13
- package/dist/host-lsp-manager.d.ts +29 -0
- package/dist/host-lsp-manager.js +14 -0
- package/dist/hosted-posture.d.ts +49 -93
- package/dist/hosted-posture.js +1 -25
- package/dist/http/active-run-conflict.d.ts +2 -12
- package/dist/http/active-run-conflict.js +1 -6
- package/dist/http/admission.js +8 -0
- package/dist/http/resume-legs.d.ts +1 -1
- package/dist/http/resume-legs.js +14 -10
- package/dist/http/route-ctx.d.ts +2 -2
- package/dist/http/routes/approvals-assistant.d.ts +1 -1
- package/dist/http/routes/approvals-assistant.js +2 -2
- package/dist/http/routes/memory-compliance.js +5 -0
- package/dist/http/routes/memory-origin.js +5 -0
- package/dist/http/routes/sessions.js +6 -0
- package/dist/http/routes/tasks.js +7 -6
- package/dist/http/server.d.ts +6 -5
- package/dist/http/wire-types.d.ts +6 -3
- package/dist/leader/wire.d.ts +20 -12
- package/dist/leader/wire.js +7 -6
- package/dist/memory-layer-preflight.d.ts +46 -0
- package/dist/memory-layer-preflight.js +121 -0
- package/dist/memory-operator-faces.js +17 -1
- package/dist/observability/corrupt-read-seat.d.ts +21 -4
- package/dist/observability/corrupt-read-seat.js +31 -0
- package/dist/observability/fail-open.d.ts +8 -4
- package/dist/observability/fail-open.js +8 -4
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +3 -26
- package/dist/observability/secret-env-scrub.js +3 -2
- package/dist/orchestration/workflow-completion-inbox.d.ts +31 -23
- package/dist/orchestration/workflow-completion-inbox.js +8 -3
- package/dist/plugins/approval-ask-store-file.d.ts +20 -2
- package/dist/plugins/approval-ask-store-file.js +21 -3
- package/dist/plugins/approval-ask-store-memory.d.ts +2 -0
- package/dist/plugins/approval-ask-store-memory.js +39 -13
- package/dist/plugins/approval-ask-store-sql.d.ts +24 -5
- package/dist/plugins/approval-ask-store-sql.js +27 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +9 -3
- package/dist/plugins/checkpoint-store-sql.js +19 -2
- package/dist/plugins/local-checkpoint-store.js +2 -0
- package/dist/plugins/mailbox-store-sql.d.ts +7 -5
- package/dist/plugins/mailbox-store-sql.js +6 -4
- package/dist/plugins/permission-rule-store-file.js +3 -2
- package/dist/plugins/remote-env-host.d.ts +3 -1
- package/dist/plugins/remote-env-host.js +3 -2
- package/dist/plugins/sql-json-column.d.ts +16 -3
- package/dist/plugins/sql-json-column.js +15 -4
- package/dist/plugins/web-search.d.ts +42 -22
- package/dist/plugins/web-search.js +141 -49
- package/dist/project-memory.d.ts +28 -1
- package/dist/project-memory.js +22 -22
- package/dist/run-local.js +6 -7
- package/dist/runs.js +6 -5
- package/dist/runtime-caps-resolver.d.ts +8 -8
- package/dist/runtime-caps-resolver.js +16 -14
- package/dist/runtime-governance.d.ts +50 -3
- package/dist/runtime-governance.js +5 -0
- package/dist/sealed-key.js +3 -7
- package/dist/server-secret-env.d.ts +43 -0
- package/dist/server-secret-env.js +18 -0
- package/dist/task-settings.d.ts +1 -1
- package/dist/tool-approval.d.ts +144 -9
- package/dist/tool-approval.js +74 -18
- package/dist/trace/core-keyset-guard.d.ts +5 -5
- package/dist/trace/ledger-sink.js +2 -2
- package/dist/trace/project.d.ts +13 -0
- package/dist/trace/project.js +22 -5
- package/dist/trace/projection-drop.d.ts +2 -0
- package/dist/trace/projection-drop.js +6 -0
- package/dist/trace/sema-provenance.d.ts +4 -1
- package/dist/trace/sema-provenance.js +1 -1
- package/dist/trace/task-notification-facets.d.ts +65 -0
- package/dist/trace/task-notification-facets.js +31 -0
- package/dist/trace/wire-projection-faces.d.ts +3 -3
- package/dist/trace/wire-projection-faces.js +3 -3
- package/package.json +5 -4
|
@@ -5,9 +5,11 @@ import { buildModelCompat, readModelCompat } from "../model-compat.js";
|
|
|
5
5
|
import { validateCommandRules } from "../runtime-governance.js";
|
|
6
6
|
import { projectCollabToWorkflows, registerCollabWorkflows } from "../capabilities/collab-workflows.js";
|
|
7
7
|
import { stageLimits } from "./stage-limits.js";
|
|
8
|
-
import { BATCH1_LIMIT_KEYS } from "./hot-keys-registry.js";
|
|
8
|
+
import { APPROVAL_GROUP_KEYS, BATCH1_LIMIT_KEYS } from "./hot-keys-registry.js";
|
|
9
9
|
import { buildDisplaySafeUrl } from "../trace/redact.js";
|
|
10
10
|
import { crossInvariant } from "../config-invariants.js";
|
|
11
|
+
import { gateIntentUnserviceableReason } from "../approval.js";
|
|
12
|
+
import { refusedGroups } from "./apply-ledger.js";
|
|
11
13
|
const charsPerTokenOf = (v) => (typeof v === "number" && Number.isFinite(v) && v > 0 ? v : undefined);
|
|
12
14
|
function envDerivedModel(config) {
|
|
13
15
|
const m = config.envModel;
|
|
@@ -93,7 +95,7 @@ function stageAtModelAllowlist(raw, models, logger) {
|
|
|
93
95
|
}
|
|
94
96
|
return names;
|
|
95
97
|
}
|
|
96
|
-
export function applyEffective(config, eff, logger, opts
|
|
98
|
+
export function applyEffective(config, eff, logger, opts) {
|
|
97
99
|
const staged = stageEffective(config, eff, logger, opts);
|
|
98
100
|
const gen = opts.generation ?? staged.version;
|
|
99
101
|
const live = appliedGeneration.get(config);
|
|
@@ -118,25 +120,30 @@ export function applyEffective(config, eff, logger, opts = {}) {
|
|
|
118
120
|
commitStaged(config, staged);
|
|
119
121
|
if (ordered)
|
|
120
122
|
appliedGeneration.set(config, gen);
|
|
121
|
-
opts.report
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
123
|
+
if (opts.report) {
|
|
124
|
+
const report = {
|
|
125
|
+
version: staged.version,
|
|
126
|
+
...(opts.generation !== undefined ? { ordinal: opts.generation } : {}),
|
|
127
|
+
groups: {
|
|
128
|
+
limitsHttp: {
|
|
129
|
+
applied: staged.limits.changed,
|
|
130
|
+
...(staged.limits.deferred.length > 0 ? { deferred: staged.limits.deferred } : {}),
|
|
131
|
+
...(staged.limits.rejected ? { rejected: staged.limits.rejected } : {}),
|
|
132
|
+
},
|
|
133
|
+
approvalGate: groupReportOf(staged.approvalGate),
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
opts.report({ ...report, fullyApplied: refusedGroups(report).length === 0 });
|
|
137
|
+
}
|
|
131
138
|
if (staged.limits.changed.length > 0)
|
|
132
139
|
logger?.info("sema_registry_limits", { version: staged.version, keys: staged.limits.changed });
|
|
133
140
|
if (staged.modelPlane)
|
|
134
141
|
logger?.info("sema_registry_models", staged.modelPlane.infoLine);
|
|
135
|
-
if (staged.
|
|
136
|
-
logger?.info("sema_registry_runtime", staged.
|
|
142
|
+
if (staged.approvalGate.next !== undefined)
|
|
143
|
+
logger?.info("sema_registry_runtime", { version: staged.version, approvalRequire: staged.approvalGate.next });
|
|
137
144
|
if (Object.keys(staged.hot.infoLine).length > 0)
|
|
138
145
|
logger?.info("sema_registry_runtime_hot", staged.hot.infoLine);
|
|
139
|
-
for (const n of staged.collabPlane
|
|
146
|
+
for (const n of staged.collabPlane.notices) {
|
|
140
147
|
if (n.level === "warn")
|
|
141
148
|
logger?.warn(n.msg, n.fields);
|
|
142
149
|
else
|
|
@@ -158,10 +165,8 @@ function commitStaged(config, staged) {
|
|
|
158
165
|
mutateInPlace(config.tiers, mp.activeTiers);
|
|
159
166
|
config.atModelAllowlist = mp.atModelAllowlist;
|
|
160
167
|
}
|
|
161
|
-
if (staged.
|
|
162
|
-
|
|
163
|
-
config[k] = v;
|
|
164
|
-
}
|
|
168
|
+
if (staged.approvalGate.next !== undefined)
|
|
169
|
+
config.approvalRequire = staged.approvalGate.next;
|
|
165
170
|
for (const [k, v] of staged.limits.assignments)
|
|
166
171
|
config[k] = v;
|
|
167
172
|
for (const k of staged.limits.deletions)
|
|
@@ -170,12 +175,11 @@ function commitStaged(config, staged) {
|
|
|
170
175
|
config.autonomy = staged.hot.autonomyNext;
|
|
171
176
|
if (staged.hot.setCommandPolicy)
|
|
172
177
|
config.commandPolicy = staged.hot.commandPolicyNext;
|
|
173
|
-
|
|
174
|
-
registerCollabWorkflows(staged.collabPlane.workflows);
|
|
178
|
+
registerCollabWorkflows(staged.collabPlane.workflows);
|
|
175
179
|
mutateInPlace(config.projects, staged.projects);
|
|
176
180
|
}
|
|
177
181
|
function stageEffective(config, eff, logger, opts) {
|
|
178
|
-
if (
|
|
182
|
+
if (opts.leg === "boot" && !eff.version) {
|
|
179
183
|
logger?.warn("sema_registry_unpublished", {
|
|
180
184
|
version: eff.version,
|
|
181
185
|
note: "empty/unpublished effective config — using env + built-in fallback; publish a config or unset CONFIG_PUBLISH_MODE",
|
|
@@ -183,7 +187,7 @@ function stageEffective(config, eff, logger, opts) {
|
|
|
183
187
|
}
|
|
184
188
|
const enabled = (eff.models?.models ?? []).filter((m) => m.enabled !== false);
|
|
185
189
|
let modelPlane;
|
|
186
|
-
if (enabled.length > 0
|
|
190
|
+
if (enabled.length > 0) {
|
|
187
191
|
const models = {};
|
|
188
192
|
const modelApiKeyEnv = {};
|
|
189
193
|
const modelApiKeys = {};
|
|
@@ -282,21 +286,18 @@ function stageEffective(config, eff, logger, opts) {
|
|
|
282
286
|
infoLine: { count: enabled.length, default: models.default.id, defaultSource: picked.source, roles: Object.keys(roles), tiers: Object.keys(activeTiers), atModelAllowlist: atModelAllowlist.length, sealedKeys: Object.values(modelApiKeys).filter((v) => typeof v === "string").length, sealedPoisoned: Object.values(modelApiKeys).filter((v) => typeof v !== "string").length },
|
|
283
287
|
};
|
|
284
288
|
}
|
|
285
|
-
const
|
|
289
|
+
const approvalGate = stageApprovalGate(config, eff.governance, opts, logger);
|
|
286
290
|
const limits = stageLimits(config, { version: typeof eff.version === "number" ? eff.version : 0, ...("limits" in eff ? { limits: eff.limits } : {}), legacyGates: legacyGateValues(eff.runtime) }, logger);
|
|
287
291
|
const hot = stageRuntimeHot(config, eff.governance, logger);
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
notices.push({ level: "info", msg: "sema_registry_collab_notes", fields: { notes: projected.notes } });
|
|
298
|
-
collabPlane = { workflows: projected.workflows, notices };
|
|
299
|
-
}
|
|
292
|
+
const projected = projectCollabToWorkflows(eff.collab?.templates);
|
|
293
|
+
const collabNotices = [];
|
|
294
|
+
if (Object.keys(projected.workflows).length > 0)
|
|
295
|
+
collabNotices.push({ level: "info", msg: "sema_registry_collab_workflows", fields: { workflows: Object.keys(projected.workflows) } });
|
|
296
|
+
if (projected.skipped.length > 0)
|
|
297
|
+
collabNotices.push({ level: "warn", msg: "sema_registry_collab_skipped", fields: { skipped: projected.skipped } });
|
|
298
|
+
if (projected.notes.length > 0)
|
|
299
|
+
collabNotices.push({ level: "info", msg: "sema_registry_collab_notes", fields: { notes: projected.notes } });
|
|
300
|
+
const collabPlane = { workflows: projected.workflows, notices: collabNotices };
|
|
300
301
|
const projDomain = eff.projects;
|
|
301
302
|
const rawProjects = (projDomain && typeof projDomain === "object" && !Array.isArray(projDomain) &&
|
|
302
303
|
"projects" in projDomain && typeof projDomain.projects === "object"
|
|
@@ -316,15 +317,14 @@ function stageEffective(config, eff, logger, opts) {
|
|
|
316
317
|
return {
|
|
317
318
|
version: typeof eff.version === "number" && Number.isFinite(eff.version) ? eff.version : 0,
|
|
318
319
|
...(modelPlane !== undefined ? { modelPlane } : {}),
|
|
319
|
-
|
|
320
|
+
approvalGate,
|
|
320
321
|
limits,
|
|
321
322
|
hot,
|
|
322
|
-
|
|
323
|
+
collabPlane,
|
|
323
324
|
projects,
|
|
324
325
|
};
|
|
325
326
|
}
|
|
326
327
|
export const RUNTIME_GATE_KEYS = ["rateLimitPerMin", "maxTaskCostUsd", "maxTaskTokens", "maxPrincipalCostUsd", "costQuotaWindowSec"];
|
|
327
|
-
export const BOOT_GATE_KEYS = ["approvalRequire"];
|
|
328
328
|
export function centerManagedConfigKeys(eff) {
|
|
329
329
|
const out = new Set();
|
|
330
330
|
if (!eff)
|
|
@@ -372,40 +372,76 @@ export function runtimeGatePresent(rt, key) {
|
|
|
372
372
|
return typeof v === "number" && v > 0;
|
|
373
373
|
return typeof v === "number";
|
|
374
374
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
};
|
|
380
|
-
const KEPT_WOULD_MATCH_NOTHING = "the prior approvalRequire is unchanged — the published list would have silently matched nothing";
|
|
381
|
-
const KEPT_WOULD_REMOVE_GATE = "the prior approvalRequire is unchanged — coercing this malformed value would have silently REMOVED the approval gate";
|
|
375
|
+
const KEPT_WOULD_MATCH_NOTHING = "the prior approvalRequire is unchanged — the published list would have silently matched nothing";
|
|
376
|
+
const KEPT_WOULD_REMOVE_GATE = "the prior approvalRequire is unchanged — coercing this malformed value would have silently REMOVED the approval gate";
|
|
377
|
+
const KEPT_WOULD_NEVER_PARK = "the prior approvalRequire is unchanged — this deployment has nowhere to park a gated call, so applying the list would leave it silently unenforced";
|
|
378
|
+
function stageApprovalRequire(raw) {
|
|
382
379
|
if (!Array.isArray(raw)) {
|
|
383
|
-
|
|
384
|
-
`Refusing the
|
|
380
|
+
const detail = `published governance.approvalRequire must be an ARRAY of whole tool names — got ${raw === null ? "null" : typeof raw}. ` +
|
|
381
|
+
`Refusing the group instead of coercing it: an empty list means "no approval gate", so coercing a malformed value would SILENTLY remove the gate.`;
|
|
382
|
+
return { ok: false, detail, reason: detail, names: [], kept: KEPT_WOULD_REMOVE_GATE };
|
|
385
383
|
}
|
|
386
384
|
const nonString = raw
|
|
387
385
|
.map((n, i) => (typeof n === "string" ? undefined : { i, t: n === null ? "null" : typeof n }))
|
|
388
386
|
.filter((e) => e !== undefined);
|
|
389
387
|
if (nonString.length > 0) {
|
|
390
|
-
|
|
388
|
+
const detail = `published governance.approvalRequire contains ${nonString.length} non-string entr${nonString.length === 1 ? "y" : "ies"} ` +
|
|
391
389
|
`(${nonString.map((e) => `[${e.i}]:${e.t}`).join(", ")}) — every entry must be a whole tool name string. ` +
|
|
392
|
-
`Refusing the
|
|
390
|
+
`Refusing the group instead of dropping them: dropping every entry would SILENTLY remove the approval gate.`;
|
|
391
|
+
return { ok: false, detail, reason: detail, names: nonString.map((e) => `[${e.i}]`), kept: KEPT_WOULD_REMOVE_GATE };
|
|
393
392
|
}
|
|
394
393
|
const names = raw.filter((n) => typeof n === "string").map((n) => n.trim()).filter((n) => n.length > 0);
|
|
395
394
|
const bad = findUnmatchableToolNames(names, { consumer: "tool-name-table", behavior: "deny" });
|
|
396
395
|
if (bad.length > 0) {
|
|
397
|
-
return
|
|
396
|
+
return {
|
|
397
|
+
ok: false,
|
|
398
|
+
detail: formatUnmatchableToolNames("published governance.approvalRequire", bad),
|
|
399
|
+
reason: `published governance.approvalRequire has ${bad.length} entr${bad.length === 1 ? "y" : "ies"} that match no live tool (retired name / incomplete MCP name / CC-form rule) — the offending entries are named in the sema_registry_approval_require_invalid log line`,
|
|
400
|
+
names: bad.map((b) => b.name),
|
|
401
|
+
kept: KEPT_WOULD_MATCH_NOTHING,
|
|
402
|
+
};
|
|
398
403
|
}
|
|
399
|
-
return { value: names };
|
|
404
|
+
return { ok: true, value: names };
|
|
400
405
|
}
|
|
401
|
-
function
|
|
406
|
+
function unserviceableOnLeg(leg, candidate) {
|
|
407
|
+
switch (leg.leg) {
|
|
408
|
+
case "boot":
|
|
409
|
+
return undefined;
|
|
410
|
+
case "hot":
|
|
411
|
+
return gateIntentUnserviceableReason(candidate, leg.checkpointStorePresent);
|
|
412
|
+
default: {
|
|
413
|
+
const unknownLeg = leg;
|
|
414
|
+
throw new Error(`applyEffective: unknown apply leg ${JSON.stringify(unknownLeg)}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function groupReportOf(g) {
|
|
419
|
+
return { applied: g.next !== undefined ? [...APPROVAL_GROUP_KEYS] : [], ...(g.rejected ? { rejected: g.rejected } : {}) };
|
|
420
|
+
}
|
|
421
|
+
const approvalEnvBaseline = new WeakMap();
|
|
422
|
+
function stageApprovalGate(config, gov, leg, logger) {
|
|
423
|
+
if (!approvalEnvBaseline.has(config))
|
|
424
|
+
approvalEnvBaseline.set(config, Object.freeze([...config.approvalRequire]));
|
|
425
|
+
const refuse = (r) => {
|
|
426
|
+
logger?.warn("sema_registry_approval_require_invalid", { keys: [...APPROVAL_GROUP_KEYS], detail: r.detail, names: [...r.names], kept: r.kept });
|
|
427
|
+
return { rejected: { keys: [...APPROVAL_GROUP_KEYS], reason: r.reason } };
|
|
428
|
+
};
|
|
402
429
|
const raw = gov?.approvalRequire;
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
430
|
+
let next;
|
|
431
|
+
if (raw === undefined) {
|
|
432
|
+
next = [...approvalEnvBaseline.get(config)];
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
const verdict = stageApprovalRequire(raw);
|
|
436
|
+
if (!verdict.ok)
|
|
437
|
+
return refuse(verdict);
|
|
438
|
+
next = verdict.value;
|
|
439
|
+
}
|
|
440
|
+
const unserviceable = unserviceableOnLeg(leg, { ...config, approvalRequire: next });
|
|
441
|
+
if (unserviceable !== undefined)
|
|
442
|
+
return refuse({ detail: unserviceable, reason: unserviceable, names: next, kept: KEPT_WOULD_NEVER_PARK });
|
|
443
|
+
const same = next.length === config.approvalRequire.length && next.every((n, i) => n === config.approvalRequire[i]);
|
|
444
|
+
return same ? {} : { next };
|
|
409
445
|
}
|
|
410
446
|
function legacyGateValues(rt) {
|
|
411
447
|
const out = {};
|
|
@@ -416,16 +452,16 @@ function legacyGateValues(rt) {
|
|
|
416
452
|
out[k] = rt[k];
|
|
417
453
|
return out;
|
|
418
454
|
}
|
|
419
|
-
export function applyRuntimeGates(config, eff, logger) {
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
config
|
|
455
|
+
export function applyRuntimeGates(config, eff, leg, logger) {
|
|
456
|
+
const approval = stageApprovalGate(config, eff?.governance, leg, logger);
|
|
457
|
+
if (approval.next !== undefined)
|
|
458
|
+
config.approvalRequire = approval.next;
|
|
423
459
|
const limits = stageLimits(config, { version: 0, legacyGates: legacyGateValues(eff?.runtime) }, logger);
|
|
424
460
|
for (const [k, v] of limits.assignments)
|
|
425
461
|
config[k] = v;
|
|
426
462
|
for (const k of limits.deletions)
|
|
427
463
|
delete config[k];
|
|
428
|
-
const info = { ...
|
|
464
|
+
const info = { ...(approval.next !== undefined ? { approvalRequire: approval.next } : {}), ...Object.fromEntries(limits.assignments) };
|
|
429
465
|
if (Object.keys(info).length > 0)
|
|
430
466
|
logger?.info("sema_registry_runtime", info);
|
|
431
467
|
}
|
|
@@ -20,7 +20,16 @@
|
|
|
20
20
|
* 🔴 原子承诺的**域**是单进程(§2):本账记的是「本副本的收敛状态」,不是 fleet 的。fleet 级判据 = 各副本
|
|
21
21
|
* /health 的 applied == target,拉齐工具归运维面。
|
|
22
22
|
*/
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* 世代账按组记账的**组闭集**(读面 `groups` 的键集;加组 = 这里加词,报告形 `Record<组, …>` 随之编译红)。
|
|
25
|
+
* · `limitsHttp` —— [ref] 批1 限额组(属主 `stage-limits.ts`);
|
|
26
|
+
* · `approvalGate` —— S-668 波 2 审批组(`governance.approvalRequire`;属主 `apply-effective.ts` 的
|
|
27
|
+
* `stageApprovalGate`:坏形 / 工具名匹配不到 / ④ 门意图不可服务 ⇒ 整组拒)。
|
|
28
|
+
* 两组同姿势、各用各的判据表(审批组**不**复用限额组的跨键不变量表 —— 那张表的候选视图只叠限额键)。
|
|
29
|
+
*/
|
|
30
|
+
export declare const CONFIG_APPLY_GROUPS: readonly ["limitsHttp", "approvalGate"];
|
|
31
|
+
export type ConfigApplyGroup = (typeof CONFIG_APPLY_GROUPS)[number];
|
|
32
|
+
/** 一组的收敛状态(读面形对所有组相同)。 */
|
|
24
33
|
export interface ConfigApplyGroupState {
|
|
25
34
|
/** 本组最后一次**真的落地**的源版本(身份标)。 */
|
|
26
35
|
readonly appliedVersion: number;
|
|
@@ -48,27 +57,37 @@ export interface ConfigApplyLedgerView {
|
|
|
48
57
|
readonly configAppliedOrdinal: number;
|
|
49
58
|
/** target≠applied 的**持续**时长(ms);收敛时键缺席(健康面不制造噪音)。 */
|
|
50
59
|
readonly configApplyStaleMs?: number;
|
|
51
|
-
readonly groups: Readonly<Record<
|
|
60
|
+
readonly groups: Readonly<Partial<Record<ConfigApplyGroup, ConfigApplyGroupState>>>;
|
|
61
|
+
}
|
|
62
|
+
/** 一组在一次 apply 里的报告(所有组同形)。 */
|
|
63
|
+
export interface ConfigApplyGroupReport {
|
|
64
|
+
/** 本世代真正换了值的键。 */
|
|
65
|
+
readonly applied: readonly string[];
|
|
66
|
+
/** 值合法但**不热**的键(逐键 defer:变更只能重启生效)。 */
|
|
67
|
+
readonly deferred?: ReadonlyArray<{
|
|
68
|
+
readonly key: string;
|
|
69
|
+
readonly reason: string;
|
|
70
|
+
}>;
|
|
71
|
+
/** 整组被拒时的成因(消毒:键名 + 判据文案,绝不带值)。 */
|
|
72
|
+
readonly rejected?: {
|
|
73
|
+
readonly keys: readonly string[];
|
|
74
|
+
readonly reason: string;
|
|
75
|
+
readonly restartReason?: string;
|
|
76
|
+
};
|
|
52
77
|
}
|
|
53
|
-
/** applyEffective 的 post-commit 报告(见 apply-effective.ts `ApplyReport`)
|
|
78
|
+
/** applyEffective 的 post-commit 报告(见 apply-effective.ts `ApplyReport`)—— **每一组都报**。 */
|
|
54
79
|
export interface ConfigApplyReport {
|
|
55
80
|
readonly version: number;
|
|
56
81
|
/** [ref]:本候选的收货序数(applyEffective opts.generation 原样带回;缺席=version 兼容臂)。 */
|
|
57
82
|
readonly ordinal?: number;
|
|
58
|
-
readonly
|
|
59
|
-
readonly applied: readonly string[];
|
|
60
|
-
readonly deferred?: ReadonlyArray<{
|
|
61
|
-
readonly key: string;
|
|
62
|
-
readonly reason: string;
|
|
63
|
-
}>;
|
|
64
|
-
readonly rejected?: {
|
|
65
|
-
readonly keys: readonly string[];
|
|
66
|
-
readonly reason: string;
|
|
67
|
-
readonly restartReason?: string;
|
|
68
|
-
};
|
|
69
|
-
};
|
|
70
|
-
readonly fullyApplied?: boolean;
|
|
83
|
+
readonly groups: Readonly<Record<ConfigApplyGroup, ConfigApplyGroupReport>>;
|
|
71
84
|
}
|
|
85
|
+
/** 本报告里被整组拒的那些组(按组闭集序)。空 ⇒ 候选完整应用。两条 commit 腿的「部分应用」warn 与世代账共用。 */
|
|
86
|
+
export declare function refusedGroups(report: ConfigApplyReport): Array<{
|
|
87
|
+
readonly group: ConfigApplyGroup;
|
|
88
|
+
readonly keys: readonly string[];
|
|
89
|
+
readonly reason: string;
|
|
90
|
+
}>;
|
|
72
91
|
export interface ConfigApplyLedger {
|
|
73
92
|
/** 拉到一个候选(无论后续是否应用)。ordinal=收货序数,version=身份标。 */
|
|
74
93
|
seenTarget(ordinal: number, version: number): void;
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export const CONFIG_APPLY_GROUPS = ["limitsHttp", "approvalGate"];
|
|
2
|
+
export function refusedGroups(report) {
|
|
3
|
+
return CONFIG_APPLY_GROUPS.flatMap((group) => {
|
|
4
|
+
const r = report.groups[group].rejected;
|
|
5
|
+
return r ? [{ group, keys: r.keys, reason: r.reason }] : [];
|
|
6
|
+
});
|
|
7
|
+
}
|
|
1
8
|
export function createConfigApplyLedger(now = () => Date.now()) {
|
|
2
9
|
let targetOrd = 0;
|
|
3
10
|
let appliedOrd = 0;
|
|
@@ -6,6 +13,21 @@ export function createConfigApplyLedger(now = () => Date.now()) {
|
|
|
6
13
|
const rejectedOrds = new Set();
|
|
7
14
|
let divergedSince;
|
|
8
15
|
const groups = {};
|
|
16
|
+
const nextGroupState = (prev, r, version) => {
|
|
17
|
+
if (r.rejected) {
|
|
18
|
+
return {
|
|
19
|
+
appliedVersion: prev?.appliedVersion ?? 0,
|
|
20
|
+
...(prev?.deferredKeys ? { deferredKeys: prev.deferredKeys } : {}),
|
|
21
|
+
lastRejected: { keys: [...r.rejected.keys], reason: r.rejected.reason, version, at: now() },
|
|
22
|
+
...(r.rejected.restartReason ? { deferredKeys: r.rejected.keys.map((key) => ({ key, reason: r.rejected.restartReason })) } : {}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
appliedVersion: version,
|
|
27
|
+
...(r.deferred && r.deferred.length > 0 ? { deferredKeys: r.deferred.map((d) => ({ key: d.key, reason: d.reason })) } : {}),
|
|
28
|
+
...(prev?.lastRejected ? { lastRejected: prev.lastRejected } : {}),
|
|
29
|
+
};
|
|
30
|
+
};
|
|
9
31
|
const reconcile = () => {
|
|
10
32
|
if (targetOrd === appliedOrd)
|
|
11
33
|
divergedSince = undefined;
|
|
@@ -32,28 +54,13 @@ export function createConfigApplyLedger(now = () => Date.now()) {
|
|
|
32
54
|
reconcile();
|
|
33
55
|
},
|
|
34
56
|
recordApply(report) {
|
|
35
|
-
const prev = groups.limitsHttp;
|
|
36
57
|
const ord = report.ordinal ?? report.version;
|
|
37
|
-
if (report.
|
|
58
|
+
if (refusedGroups(report).length > 0)
|
|
38
59
|
rejectedOrds.add(ord);
|
|
39
60
|
else
|
|
40
61
|
rejectedOrds.delete(ord);
|
|
41
|
-
|
|
42
|
-
groups
|
|
43
|
-
appliedVersion: prev?.appliedVersion ?? 0,
|
|
44
|
-
...(prev?.deferredKeys ? { deferredKeys: prev.deferredKeys } : {}),
|
|
45
|
-
lastRejected: { keys: [...report.limits.rejected.keys], reason: report.limits.rejected.reason, version: report.version, at: now() },
|
|
46
|
-
...(report.limits.rejected.restartReason
|
|
47
|
-
? { deferredKeys: report.limits.rejected.keys.map((key) => ({ key, reason: report.limits.rejected.restartReason })) }
|
|
48
|
-
: {}),
|
|
49
|
-
};
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
groups.limitsHttp = {
|
|
53
|
-
appliedVersion: report.version,
|
|
54
|
-
...(report.limits.deferred && report.limits.deferred.length > 0 ? { deferredKeys: report.limits.deferred.map((d) => ({ key: d.key, reason: d.reason })) } : {}),
|
|
55
|
-
...(prev?.lastRejected ? { lastRejected: prev.lastRejected } : {}),
|
|
56
|
-
};
|
|
62
|
+
for (const g of CONFIG_APPLY_GROUPS)
|
|
63
|
+
groups[g] = nextGroupState(groups[g], report.groups[g], report.version);
|
|
57
64
|
},
|
|
58
65
|
view() {
|
|
59
66
|
const stale = divergedSince !== undefined ? now() - divergedSince : undefined;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type CenterCredentialSource } from "../center-credential.js";
|
|
2
|
+
export declare const SCHEMA_MAJOR_HEADER = "x-sema-schema-major";
|
|
3
|
+
/** 已装 settings-schema 的 major(机器派生)。版本号不成形 ⇒ 模块装载即抛(装坏了的包不该带着一个猜出来的
|
|
4
|
+
* major 去跟中心协商 wire 形)。 */
|
|
5
|
+
export declare const SETTINGS_SCHEMA_MAJOR: string;
|
|
6
|
+
/** 一个中心端点 = 基址 + 凭证来源(`ServiceConfig.configCenter` 结构上满足)。 */
|
|
7
|
+
export interface CenterEndpoint {
|
|
8
|
+
readonly baseUrl: string;
|
|
9
|
+
readonly credential: CenterCredentialSource;
|
|
10
|
+
}
|
|
11
|
+
/** 中心路由闭集。 */
|
|
12
|
+
export type CenterRoute = {
|
|
13
|
+
readonly kind: "effective";
|
|
14
|
+
readonly worker?: string | undefined;
|
|
15
|
+
readonly principal?: string | undefined;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: "skill-content";
|
|
18
|
+
readonly contentHash: string;
|
|
19
|
+
} | {
|
|
20
|
+
readonly kind: "prompt-artifact";
|
|
21
|
+
readonly digest: string;
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: "prompt-blob";
|
|
24
|
+
readonly digest: string;
|
|
25
|
+
} | {
|
|
26
|
+
readonly kind: "fleet-leases";
|
|
27
|
+
} | {
|
|
28
|
+
readonly kind: "fleet-instances";
|
|
29
|
+
} | {
|
|
30
|
+
readonly kind: "fleet-usage";
|
|
31
|
+
} | {
|
|
32
|
+
readonly kind: "execution-keys";
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* 拉取视图(`/api/config/effective`)查询串的**唯一拼装点**:`?principal=`(per-principal 视图)、`?worker=`
|
|
36
|
+
* (worker 作用域视图;对 `wpt_<self>` 是授权必需,对全量令牌无害)。
|
|
37
|
+
* [ref] E-15:执行体绑 scope 的参数将来加在这里(契约字段 settings-schema 6.0.0;本批不铸)。
|
|
38
|
+
*/
|
|
39
|
+
export declare function pullViewQuery(view: {
|
|
40
|
+
readonly worker?: string | undefined;
|
|
41
|
+
readonly principal?: string | undefined;
|
|
42
|
+
}): string;
|
|
43
|
+
export interface CenterRequestInit {
|
|
44
|
+
readonly method?: "GET" | "POST" | "DELETE";
|
|
45
|
+
/** JSON 请求体(在场 ⇒ `content-type: application/json`)。 */
|
|
46
|
+
readonly json?: unknown;
|
|
47
|
+
/** 条件请求(`if-none-match`)。 */
|
|
48
|
+
readonly etag?: string | undefined;
|
|
49
|
+
readonly timeoutMs: number;
|
|
50
|
+
readonly fetchImpl?: typeof fetch;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 对中心发一条请求。返回响应与**这次请求所用凭证的身份**(调用方据此给拿回来的候选打分箱标记,
|
|
54
|
+
* 见 `boot/config-center.ts` 的 LKG / prompt 状态分箱)。
|
|
55
|
+
*/
|
|
56
|
+
export declare function centerFetch(center: CenterEndpoint, route: CenterRoute, init: CenterRequestInit): Promise<{
|
|
57
|
+
res: Response;
|
|
58
|
+
identity: string;
|
|
59
|
+
}>;
|
|
60
|
+
//# sourceMappingURL=center-request.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import settingsSchemaPackage from "@sema-agent/settings-schema/package.json" with { type: "json" };
|
|
2
|
+
import { CenterCredentialUnavailableError } from "../center-credential.js";
|
|
3
|
+
export const SCHEMA_MAJOR_HEADER = "x-sema-schema-major";
|
|
4
|
+
export const SETTINGS_SCHEMA_MAJOR = (() => {
|
|
5
|
+
const version = settingsSchemaPackage.version;
|
|
6
|
+
const m = /^(\d+)\.\d+\.\d+/.exec(version);
|
|
7
|
+
if (m === null)
|
|
8
|
+
throw new Error(`cannot derive ${SCHEMA_MAJOR_HEADER}: @sema-agent/settings-schema package.json has version ${JSON.stringify(version)}`);
|
|
9
|
+
return m[1];
|
|
10
|
+
})();
|
|
11
|
+
export function pullViewQuery(view) {
|
|
12
|
+
const parts = [];
|
|
13
|
+
if (view.principal !== undefined)
|
|
14
|
+
parts.push(`principal=${encodeURIComponent(view.principal)}`);
|
|
15
|
+
if (view.worker)
|
|
16
|
+
parts.push(`worker=${encodeURIComponent(view.worker)}`);
|
|
17
|
+
return parts.length === 0 ? "" : `?${parts.join("&")}`;
|
|
18
|
+
}
|
|
19
|
+
function contentRoot(kind) {
|
|
20
|
+
switch (kind) {
|
|
21
|
+
case "user-jwt":
|
|
22
|
+
return "/api/v1/me";
|
|
23
|
+
case "pull-token":
|
|
24
|
+
case "none":
|
|
25
|
+
return "/api/config";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function routePath(route, kind) {
|
|
29
|
+
switch (route.kind) {
|
|
30
|
+
case "effective":
|
|
31
|
+
return `/api/config/effective${pullViewQuery(route)}`;
|
|
32
|
+
case "skill-content":
|
|
33
|
+
return `${contentRoot(kind)}/skills/content/${encodeURIComponent(route.contentHash)}`;
|
|
34
|
+
case "prompt-artifact":
|
|
35
|
+
return `${contentRoot(kind)}/prompts/epoch-artifacts/${encodeURIComponent(route.digest)}`;
|
|
36
|
+
case "prompt-blob":
|
|
37
|
+
return `${contentRoot(kind)}/prompts/blobs/${encodeURIComponent(route.digest)}`;
|
|
38
|
+
case "fleet-leases":
|
|
39
|
+
return "/api/fleet/leases";
|
|
40
|
+
case "fleet-instances":
|
|
41
|
+
return "/api/fleet/instances";
|
|
42
|
+
case "fleet-usage":
|
|
43
|
+
return "/api/fleet/usage";
|
|
44
|
+
case "execution-keys":
|
|
45
|
+
return "/api/config/execution-keys";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export async function centerFetch(center, route, init) {
|
|
49
|
+
const scheme = new URL(center.baseUrl).protocol;
|
|
50
|
+
if (scheme !== "http:" && scheme !== "https:")
|
|
51
|
+
throw new Error(`SEMA_REGISTRY_URL must be http(s), got "${scheme}"`);
|
|
52
|
+
const cred = center.credential.read();
|
|
53
|
+
if (!cred.ok)
|
|
54
|
+
throw new CenterCredentialUnavailableError(cred.reason);
|
|
55
|
+
const headers = { [SCHEMA_MAJOR_HEADER]: SETTINGS_SCHEMA_MAJOR };
|
|
56
|
+
if (cred.kind !== "none")
|
|
57
|
+
headers.authorization = `Bearer ${cred.bearer}`;
|
|
58
|
+
if (init.json !== undefined)
|
|
59
|
+
headers["content-type"] = "application/json";
|
|
60
|
+
if (init.etag)
|
|
61
|
+
headers["if-none-match"] = init.etag;
|
|
62
|
+
const url = `${center.baseUrl.replace(/\/+$/, "")}${routePath(route, cred.kind)}`;
|
|
63
|
+
const res = await (init.fetchImpl ?? fetch)(url, {
|
|
64
|
+
method: init.method ?? "GET",
|
|
65
|
+
headers,
|
|
66
|
+
...(init.json !== undefined ? { body: JSON.stringify(init.json) } : {}),
|
|
67
|
+
signal: AbortSignal.timeout(init.timeoutMs),
|
|
68
|
+
});
|
|
69
|
+
return { res, identity: cred.identity };
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=center-request.js.map
|
|
@@ -25,14 +25,20 @@
|
|
|
25
25
|
* reference. Both brains re-resolve `model.baseUrl || config.baseUrl` inside `buildRequest()` on every
|
|
26
26
|
* call (core 2.1.0 `brain/openai.js` + `brain/anthropic.js`), so a moved gateway takes effect on the
|
|
27
27
|
* next task with no restart.
|
|
28
|
-
* - the
|
|
29
|
-
* at construction,
|
|
30
|
-
*
|
|
28
|
+
* - tiers (and the whole plane under an active tier table) — **HOT** as well: core expands a PRIVATE catalog
|
|
29
|
+
* copy at Runner construction, and the refresh loop swaps every changed plane into all boot Runners before
|
|
30
|
+
* commit (`Runner.swapDeps`, core 7.10.0; production always wires it). The old "tier-frozen ⇒ defer to restart"
|
|
31
|
+
* arm and its `models-tiers` restart slice retired in S-668 波 0 — `/v1/models` and tier-word routing move on
|
|
32
|
+
* the same tick.
|
|
33
|
+
* - **`degrade-route`** — one of the two genuinely boot-frozen catalog consumers left (the other is the
|
|
34
|
+
* memory-consolidation driver seat, last bullet): reactive degrade
|
|
31
35
|
* (`MODEL_DEGRADE_REACTIVE`) bakes the target Model + its gateway + its key into the brain composition
|
|
32
36
|
* at boot. It cannot be hot-applied without rebuilding the brain, so it is registered on the existing
|
|
33
37
|
* restartRequired /health contract instead (see `restart-signal.ts`). Fail-loud beats serving a stale
|
|
34
38
|
* gateway silently on the rate-limit path.
|
|
35
|
-
* - skills/mcp/scenarios
|
|
39
|
+
* - skills(+plugins)/mcp/a2a/scenarios — restart-to-apply by construction (baked into the boot
|
|
40
|
+
* wiring); so is the memory-consolidation driver's model seat (`memory-consolidation` slice, S-668 波 0).
|
|
41
|
+
* (`governance.approvalRequire` left this list in S-668 波 2 — its own staged group, hot on both legs.)
|
|
36
42
|
*
|
|
37
43
|
* ([ref] A13, internal-lossless) This module is now a FACADE: the implementation lives
|
|
38
44
|
* alongside it in `src/config-center/` split by responsibility group (HTTP client / EffectiveConfig
|
|
@@ -43,7 +49,7 @@
|
|
|
43
49
|
*/
|
|
44
50
|
export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
|
|
45
51
|
export { mutateInPlace, applyEffective, type ApplyReport, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, } from "./apply-effective.js";
|
|
46
|
-
export { restartReasons,
|
|
52
|
+
export { restartReasons, modelPlaneChanged, type RestartSlice, type RestartSliceCtx, type RestartSignal, } from "./restart-signal.js";
|
|
47
53
|
export { applyCenterSkills, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
|
|
48
54
|
export { applyCenterReadFace, CENTER_READ_FACE_LIVE_KEYS, type CenterReadFaceApply, type CenterReadFaceReport, type ReadFaceBaseline } from "./read-face.js";
|
|
49
55
|
export type { CenterSkillManifest, CenterMcpServer, CenterA2aPeer, CenterModel, CenterReadFace, EffectiveConfig, ExecutionRuling, SessionMirrorRuling, } from "./types.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
|
|
2
2
|
export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, } from "./apply-effective.js";
|
|
3
|
-
export { restartReasons,
|
|
3
|
+
export { restartReasons, modelPlaneChanged, } from "./restart-signal.js";
|
|
4
4
|
export { applyCenterSkills, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
|
|
5
5
|
export { applyCenterReadFace, CENTER_READ_FACE_LIVE_KEYS } from "./read-face.js";
|
|
6
6
|
//# sourceMappingURL=facade.js.map
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* 键 → 组 → 换代手法 → **参数化用例 ID**(不是文件名——文件名粒度挡不住「文件在、用例没了」)。
|
|
7
7
|
*
|
|
8
8
|
* 机器门在 test/config-hot/batch1-hot-keys-registry.test.ts:登记为热却没有三断言用例 = 红;
|
|
9
|
-
* 表的键集与 stage 真正消费的键集(`BATCH1_LIMIT_KEYS`)不等 = 红。
|
|
9
|
+
* 表的键集与 stage 真正消费的键集(`BATCH1_LIMIT_KEYS` ∪ `APPROVAL_GROUP_KEYS`)不等 = 红。
|
|
10
10
|
*
|
|
11
11
|
* ⚠️ 本表**只登记已落地的批**。批2-4 的键在各自批次里追加(设计稿 §6),不提前写进来 —— 一个「登记为热
|
|
12
12
|
* 但没接线」的条目正是本表要消灭的那种谎。
|
|
@@ -27,8 +27,8 @@ export interface HotKeyEntry {
|
|
|
27
27
|
readonly key: keyof ServiceConfigFlat;
|
|
28
28
|
readonly group: keyof ServiceConfigGroups;
|
|
29
29
|
readonly form: HotKeyForm;
|
|
30
|
-
/**
|
|
31
|
-
readonly batch: 1;
|
|
30
|
+
/** 落地批次:1 = [ref] 批1(limitsHttp 组);2 = S-668 波 2(审批组 —— [ref] §6 原排的「批2」)。 */
|
|
31
|
+
readonly batch: 1 | 2;
|
|
32
32
|
readonly cases: HotKeyCases;
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
@@ -57,6 +57,13 @@ export declare const DEFERRED_LIMIT_KEYS: ReadonlyArray<{
|
|
|
57
57
|
readonly restartReason: string;
|
|
58
58
|
readonly why: string;
|
|
59
59
|
}>;
|
|
60
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* S-668 波 2([ref] §3)—— **审批组**真正接线的键:`apply-effective.ts` 的 `stageApprovalGate` 消费、报告(世代账
|
|
62
|
+
* `groups.approvalGate`)与拒绝(拒因的键名)都取这一张表。换代手法 A′:消费点本就逐请求现读活 config(审批基线 /
|
|
63
|
+
* SendUserFile 子代闸 / 会话与记忆读面 / parked 赎回),leader 腿与单用户基线改成现读之后,热只差 refresh 腿的写口。
|
|
64
|
+
*/
|
|
65
|
+
export declare const APPROVAL_GROUP_KEYS: readonly ["approvalRequire"];
|
|
66
|
+
export type ApprovalGroupKey = (typeof APPROVAL_GROUP_KEYS)[number];
|
|
67
|
+
/** 热键表 = 批1 消费键集**减去**显式 deferred 的那些 + 审批组(表只登记真的热的键)。 */
|
|
61
68
|
export declare const HOT_KEYS_REGISTRY: readonly HotKeyEntry[];
|
|
62
69
|
//# sourceMappingURL=hot-keys-registry.d.ts.map
|
|
@@ -29,11 +29,15 @@ export const DEFERRED_LIMIT_KEYS = [
|
|
|
29
29
|
},
|
|
30
30
|
];
|
|
31
31
|
const DEFERRED_KEYS = new Set(DEFERRED_LIMIT_KEYS.map((d) => d.key));
|
|
32
|
-
export const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
export const APPROVAL_GROUP_KEYS = ["approvalRequire"];
|
|
33
|
+
export const HOT_KEYS_REGISTRY = [
|
|
34
|
+
...BATCH1_LIMIT_KEYS.filter((key) => !DEFERRED_KEYS.has(key)).map((key) => ({
|
|
35
|
+
key,
|
|
36
|
+
group: "limitsHttp",
|
|
37
|
+
form: (B_SETTER_KEYS.includes(key) ? "B-setter" : "A-prime"),
|
|
38
|
+
batch: 1,
|
|
39
|
+
cases: cases(key),
|
|
40
|
+
})),
|
|
41
|
+
...APPROVAL_GROUP_KEYS.map((key) => ({ key, group: "approval", form: "A-prime", batch: 2, cases: cases(key) })),
|
|
42
|
+
];
|
|
39
43
|
//# sourceMappingURL=hot-keys-registry.js.map
|