@sema-agent/server 7.53.0 → 7.54.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/USAGE.md +5 -0
- package/dist/boot/config-center.js +2 -2
- package/dist/boot/leader.js +2 -0
- package/dist/boot/resolve-spec.js +1 -3
- package/dist/boot/runner-deps.d.ts +20 -0
- package/dist/boot/runner-deps.js +14 -8
- package/dist/boot/shutdown.js +1 -1
- package/dist/capabilities/team.d.ts +10 -9
- package/dist/config-center/apply-effective.d.ts +25 -26
- package/dist/config-center/apply-effective.js +28 -66
- package/dist/config-center/effective-keys.d.ts +30 -0
- package/dist/config-center/effective-keys.js +49 -0
- package/dist/config-center/facade.d.ts +3 -3
- package/dist/config-center/facade.js +1 -1
- package/dist/config-center/restart-signal.js +3 -9
- package/dist/config-center/types.d.ts +19 -40
- package/dist/config-lkg.js +7 -1
- package/dist/config-provider.js +1 -1
- package/dist/device-enrollment.d.ts +5 -3
- package/dist/device-store.d.ts +15 -1
- package/dist/device-store.js +2 -0
- package/dist/device-ws-hub.d.ts +7 -2
- package/dist/device-ws-hub.js +25 -5
- package/dist/http/server.js +19 -0
- package/dist/http/wire-types.d.ts +19 -0
- package/dist/leader/wire.d.ts +12 -0
- package/dist/leader/wire.js +6 -5
- package/dist/observability/fail-open.d.ts +16 -0
- package/dist/observability/fail-open.js +16 -0
- package/dist/plugins/pg-pool.d.ts +29 -2
- package/dist/plugins/pg-pool.js +45 -2
- package/dist/plugins/remote-env-device.d.ts +4 -2
- package/dist/plugins/remote-env-device.js +4 -1
- package/dist/plugins/roster-store-sql.d.ts +1 -3
- package/dist/plugins/store-backend.js +1 -1
- package/dist/plugins/tidb-pool.d.ts +13 -0
- package/dist/runtime-governance.d.ts +4 -0
- package/dist/runtime-governance.js +23 -1
- package/dist/tool-approval.d.ts +21 -28
- package/dist/tool-approval.js +220 -98
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/injection-tier.d.ts +11 -21
- package/dist/trace/injection-tier.js +3 -4
- package/dist/trace/project.d.ts +1 -0
- package/dist/trace/project.js +1 -0
- package/package.json +3 -3
package/USAGE.md
CHANGED
|
@@ -508,6 +508,11 @@ READ_DENY_PATTERNS='[{"pattern":"**/secrets/**"},{"pattern":".ssh","caseSensitiv
|
|
|
508
508
|
一律启动期点名拒——一个手滑的 deny 集比没有 deny 集更糟(以为挡了其实没挡)。
|
|
509
509
|
- **缺席不铸**:两个键不设就**不传给引擎**——引擎抬默认/扩内建集那天,存量部署自动跟上(与重试上限
|
|
510
510
|
同款「引擎当家」纪律)。
|
|
511
|
+
- **leader 车道同席(S-28,7.54 起)**:`LEADER_ENABLED` 的 leader 编排(planner / worker / repair / conflict 四类
|
|
512
|
+
任务)与主车道吃**同一份**四键(连同 `MEMORY_DELEGATION_EVIDENCE` / `MEMORY_PROVENANCE` / `MEMORY_CAPTURE_POLICY`
|
|
513
|
+
与委派入口 caps;取值点唯一 = `buildDeploymentPostureSeats`,leader 不另读 env)。此前(≤7.53)那条腿一席都不带:
|
|
514
|
+
deny 追加对 leader worker **静默不生效**(core 内建 deny 表仍在)。仍缺 tracer / usageWindows / promptSource 三席
|
|
515
|
+
(#311 扩面,另车)。
|
|
511
516
|
- **组织下发腿(config-center,7.29 起)**:四键(`READ_FACE` / `READ_DENY_PATTERNS` /
|
|
512
517
|
`READ_DENY_BUILTIN_TIERS` / `READ_DENY_BUILTIN_EXCLUDE`)也可由 config-center 的 `readFace` 域下发
|
|
513
518
|
(`{face?, denyPatterns?, denyBuiltinTiers?, denyBuiltinExclude?}`)。三条规则:
|
|
@@ -400,7 +400,7 @@ export async function createConfigCenterRuntime(ctx) {
|
|
|
400
400
|
if (effective?.skills && config.configCenter) {
|
|
401
401
|
skills = await applyCenterSkills(skills, effective.skills, config.configCenter.baseUrl, config.configCenter.token, logger, undefined, configLkgEnabled() ? defaultSkillCacheDir() : undefined);
|
|
402
402
|
}
|
|
403
|
-
if (effective?.plugins
|
|
403
|
+
if (effective?.plugins) {
|
|
404
404
|
const pluginOut = await applyCenterPlugins(skills, effective, {
|
|
405
405
|
cacheRoot: join(config.localDataRoot ?? join(homedir(), ".ai-agent"), "plugin-cache"),
|
|
406
406
|
allowHosts: config.pluginsAllowHosts,
|
|
@@ -618,7 +618,7 @@ export async function createConfigCenterRuntime(ctx) {
|
|
|
618
618
|
}
|
|
619
619
|
logger.info("sema_registry_refreshed", {
|
|
620
620
|
version: r.effective.version,
|
|
621
|
-
note: "
|
|
621
|
+
note: "collab + runtime governance + limits + models/roles/roster hot-applied; skills/mcp/runtime-gates(approvalRequire)/scenarios are restart-to-apply",
|
|
622
622
|
...(pendingRestart ? { restartRequired: true, restartReasons: pendingRestart.reasons } : {}),
|
|
623
623
|
});
|
|
624
624
|
latestEffective = r.effective;
|
package/dist/boot/leader.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createLeaderEndpoint } from "../leader/endpoint.js";
|
|
2
2
|
import { createLeaderRunner } from "../leader/wire.js";
|
|
3
|
+
import { buildDeploymentPostureSeats } from "./runner-deps.js";
|
|
3
4
|
export function leaderK8sMinioGap(leaderEnabled, leaderProvider, hasS3) {
|
|
4
5
|
if (!(leaderEnabled && leaderProvider === "k8s" && !hasS3))
|
|
5
6
|
return null;
|
|
@@ -49,6 +50,7 @@ export function createLeaderFace(ctx) {
|
|
|
49
50
|
lockedConfig: governanceSeams.lockedConfig,
|
|
50
51
|
retentionPolicy: governanceSeams.retentionPolicy,
|
|
51
52
|
},
|
|
53
|
+
deploymentPosture: buildDeploymentPostureSeats(config),
|
|
52
54
|
fanoutEnabled: config.leaderFanoutEnabled,
|
|
53
55
|
...((process.env.MODEL_ROUTER_ID || process.env.MODEL_CHEAP_ID)
|
|
54
56
|
? { routerModel: (process.env.MODEL_ROUTER_ID || process.env.MODEL_CHEAP_ID) }
|
|
@@ -289,9 +289,7 @@ export function createResolveSpec(ctx) {
|
|
|
289
289
|
...(() => { const v = toolNameListFromBody(body.deferTools); return v ? { deferTools: v } : {}; })(),
|
|
290
290
|
...(() => { const v = promptProfileFromBody(body.promptProfile); return v ? { promptProfile: v } : {}; })(),
|
|
291
291
|
...(() => { const v = toolMaterializeStrategyFromBody(body.toolMaterializeStrategy); return v ? { toolMaterializeStrategy: v } : {}; })(),
|
|
292
|
-
...(typeof body.interactiveTools === "boolean"
|
|
293
|
-
? { interactiveTools: body.interactiveTools }
|
|
294
|
-
: {}),
|
|
292
|
+
...(typeof body.interactiveTools === "boolean" ? { interactiveTools: body.interactiveTools } : {}),
|
|
295
293
|
...(declaresInteractivePosture(body, req, opts) ? { interactionPosture: "interactive" } : {}),
|
|
296
294
|
...(typeof body.oneShot === "boolean" ? { oneShot: body.oneShot } : {}),
|
|
297
295
|
resilience: normalizeResilience(body.resilience, explicitOperatorOk(auth?.principal, config.operatorPrincipals)),
|
|
@@ -230,6 +230,26 @@ export declare function createEngineNoticeSeat(logger: {
|
|
|
230
230
|
} | undefined, router?: EngineNoticeRouter): {
|
|
231
231
|
onNotice?: NonNullable<RunnerDeps["onNotice"]>;
|
|
232
232
|
};
|
|
233
|
+
/**
|
|
234
|
+
* [ref](黑板 [ref],[ref] 登记)—— **部署姿态座席族**:运维在配置面写下的姿态(READ 面四席 + 记忆三席 +
|
|
235
|
+
* 委派入口 caps)。core 明写「每个 run 读**准备它的那只 Runner** 的 deps」⇒ 一台部署里跑任务的**每一只**
|
|
236
|
+
* Runner 都必须带同一份:主 runner / subRunner / run-local(经 {@link createSharedRunnerDeps} 展开)+
|
|
237
|
+
* **leader lane 五只**(`boot/leader.ts` → `LeaderWireConfig.deploymentPosture` → `src/leader/wire.ts`
|
|
238
|
+
* 五处 `...deploymentPostureSeat`)。
|
|
239
|
+
*
|
|
240
|
+
* 🔴 本函数是这一族**唯一**的取值点。两处各读一遍 config 就是 [ref]§三族A「主挂了、副漏挂」的病族形——
|
|
241
|
+
* [ref] 正是 leader 那条腿漏了**全族**(修前 wire.ts 五处一席都没有;边界曾靠
|
|
242
|
+
* `test/memory-delegation-evidence-lane.test.ts` ⑤ 组的机器门如实登记,现已翻成正向门)。leader 不许自己
|
|
243
|
+
* 再读 config 铸一份,只吃本函数经 cfg 递过去的产物(`test/leader-deployment-posture-seats.test.ts` ③ 钉)。
|
|
244
|
+
*
|
|
245
|
+
* 纯数据(键值全是 config 透传,无闭包)⇒ `build*`(CLAUDE.md 工厂律)。键**恒在场**、缺席 = `undefined`
|
|
246
|
+
* ([ref] S4 house style;core 消费点全按 `!== undefined` / `??` 判 —— dist
|
|
247
|
+
* `prepare-hands-readface.js:96-97`、`prepare-config-doors.js:199/215/229`、`prepare-task.js:1487` 亲读,
|
|
248
|
+
* 「键为 undefined」与「键缺席」对引擎逐字等价)。**不复制引擎缺省**(`roots`/`static-face`/`carry`/`open`/
|
|
249
|
+
* CC parity 20/200 一个都不抄):上游改缺省之日起本仓不会成为第二份真源。
|
|
250
|
+
*/
|
|
251
|
+
export type DeploymentPostureSeats = Pick<RunnerDeps, "readFace" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "delegationEntryCaps">;
|
|
252
|
+
export declare function buildDeploymentPostureSeats(config: Pick<ServiceConfig, keyof DeploymentPostureSeats>): DeploymentPostureSeats;
|
|
233
253
|
export declare function createSharedRunnerDeps(ctx: SharedRunnerDepsCtx): SharedRunnerDeps;
|
|
234
254
|
export declare function createRunnerDeps(ctx: RunnerDepsCtx): RunnerDeps;
|
|
235
255
|
//# sourceMappingURL=runner-deps.d.ts.map
|
package/dist/boot/runner-deps.js
CHANGED
|
@@ -25,6 +25,19 @@ export function createEngineNoticeSeat(logger, router = defaultEngineNoticeRoute
|
|
|
25
25
|
const warn = logger?.warn?.bind(logger);
|
|
26
26
|
return warn ? { onNotice: createEngineNoticeForwarder({ warn }, router) } : {};
|
|
27
27
|
}
|
|
28
|
+
export function buildDeploymentPostureSeats(config) {
|
|
29
|
+
const seats = {
|
|
30
|
+
readFace: config.readFace ? config.readFace : undefined,
|
|
31
|
+
readDenyPatterns: config.readDenyPatterns ? config.readDenyPatterns : undefined,
|
|
32
|
+
readDenyBuiltinTiers: config.readDenyBuiltinTiers ?? undefined,
|
|
33
|
+
readDenyBuiltinExclude: config.readDenyBuiltinExclude ?? undefined,
|
|
34
|
+
memoryDelegationEvidence: config.memoryDelegationEvidence ?? undefined,
|
|
35
|
+
memoryProvenance: config.memoryProvenance ?? undefined,
|
|
36
|
+
memoryCapturePolicy: config.memoryCapturePolicy ?? undefined,
|
|
37
|
+
delegationEntryCaps: config.delegationEntryCaps ?? undefined,
|
|
38
|
+
};
|
|
39
|
+
return seats;
|
|
40
|
+
}
|
|
28
41
|
export function createSharedRunnerDeps(ctx) {
|
|
29
42
|
const shared = {
|
|
30
43
|
brain: ctx.brain,
|
|
@@ -35,14 +48,7 @@ export function createSharedRunnerDeps(ctx) {
|
|
|
35
48
|
pricing: ctx.pricing,
|
|
36
49
|
tracer: ctx.tracer,
|
|
37
50
|
promptSource: ctx.promptSource,
|
|
38
|
-
|
|
39
|
-
readDenyPatterns: ctx.config.readDenyPatterns ? ctx.config.readDenyPatterns : undefined,
|
|
40
|
-
readDenyBuiltinTiers: ctx.config.readDenyBuiltinTiers ?? undefined,
|
|
41
|
-
readDenyBuiltinExclude: ctx.config.readDenyBuiltinExclude ?? undefined,
|
|
42
|
-
memoryDelegationEvidence: ctx.config.memoryDelegationEvidence ?? undefined,
|
|
43
|
-
memoryProvenance: ctx.config.memoryProvenance ?? undefined,
|
|
44
|
-
memoryCapturePolicy: ctx.config.memoryCapturePolicy ?? undefined,
|
|
45
|
-
delegationEntryCaps: ctx.config.delegationEntryCaps ?? undefined,
|
|
51
|
+
...buildDeploymentPostureSeats(ctx.config),
|
|
46
52
|
executionEnvFactory: ctx.executionEnvFactory ? ctx.executionEnvFactory : undefined,
|
|
47
53
|
lspManager: ctx.lspManager ? ctx.lspManager : undefined,
|
|
48
54
|
backgroundAgentStore: ctx.backgroundAgentStore ? ctx.backgroundAgentStore : undefined,
|
package/dist/boot/shutdown.js
CHANGED
|
@@ -108,7 +108,7 @@ export function installShutdownHandlers(ctx) {
|
|
|
108
108
|
}
|
|
109
109
|
draining = true;
|
|
110
110
|
drainState.draining = true;
|
|
111
|
-
deviceHub?.beginDrain();
|
|
111
|
+
deviceHub?.beginDrain({ graceMs: () => config.drainGraceMs });
|
|
112
112
|
drainState.since = Date.now();
|
|
113
113
|
void fleetClient?.announceNow();
|
|
114
114
|
const inflight = drainState.inflight?.() ?? 0;
|
|
@@ -8,17 +8,18 @@ import type { Logger } from "../observability/logger.js";
|
|
|
8
8
|
* ── 词汇([ref] / [ref],clay 直裁 [ref])──────────────────────────────────────────────────────
|
|
9
9
|
* 「team」= agent-teams(持久具名团队)专用词;一次性多 agent 讨论叫「discuss」。所以**面向调用方/
|
|
10
10
|
* 模型的名字**全部是 discussion:场景 `discuss`、工具 `run_discussion`、协调者提示词。
|
|
11
|
-
* 而**模板注册面**(`BUILTIN_TEAMS` / `registerTeams` / `getTeam`
|
|
12
|
-
*
|
|
13
|
-
* 同改要另立件+center 侧同款 alias;本批刻意不单方面改一半(半改的配置键比不改更坏)。
|
|
11
|
+
* 而**模板注册面**(`BUILTIN_TEAMS` / `registerTeams` / `getTeam`)保留 team 词汇(历史命名,注册表是本仓
|
|
12
|
+
* 自己的模块级单例,不再对应任何中心配置键——见下段)。
|
|
14
13
|
*
|
|
15
|
-
* HYBRID layering
|
|
16
|
-
*
|
|
17
|
-
* (
|
|
14
|
+
* HYBRID layering: the TEMPLATE here carries only the GENERIC orchestration skeleton (member roles + generic
|
|
15
|
+
* personas, rounds, synthesizer); the CONSUMER (OA) injects the business prompt/context at call time
|
|
16
|
+
* (`businessContext`); this service composes them.
|
|
18
17
|
*
|
|
19
|
-
* Templates: BUILTIN_TEAMS are the defaults
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
* Templates: BUILTIN_TEAMS are the defaults. ⚠️ 中心的 `teams` 配置域自 settings-schema 0.7 **已删除**
|
|
19
|
+
* (DOMAIN_SCHEMAS 无此域、FileConfigStore 不读、/effective 不铸),[ref] 件3 又拆掉了本仓 `applyEffective →
|
|
20
|
+
* registerTeams` 那条消费腿——本文件旧注里「registry pushes more at runtime via GET /api/config/effective → teams」
|
|
21
|
+
* 是 doc-rot。今天 `registerTeams` 只剩公共信任边界这一层意义(调用方=测试),注册表在生产上恒等于 BUILTIN_TEAMS;
|
|
22
|
+
* 中心侧的多 agent 讨论配置面是 `collab` 域(0.7 继任者),投影成命名 workflow(capabilities/collab-workflows.ts)。
|
|
22
23
|
*/
|
|
23
24
|
type TeamFn = typeof runTeamDiscussion;
|
|
24
25
|
export interface TeamMemberTemplate {
|
|
@@ -63,14 +63,12 @@ export declare function applyEffective(config: ServiceConfig, eff: EffectiveConf
|
|
|
63
63
|
}) => void;
|
|
64
64
|
}): boolean;
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* UNIFORM presence semantics across all 6 gates (center `f95438a` adopted this from our sentinel flag —
|
|
69
|
-
* SERVICE-INTEGRATION「Runtime 治理/限额闸」): all six fields are center `.optional()`, so
|
|
66
|
+
* UNIFORM presence semantics across the center gates (center `f95438a` adopted this from our sentinel flag —
|
|
67
|
+
* SERVICE-INTEGRATION「Runtime 治理/限额闸」): every gate field is center `.optional()`, so
|
|
70
68
|
* `undefined` = center isn't managing it → KEEP env;
|
|
71
69
|
* present (any value, INCLUDING an explicit 0 / [] = "publish the gate OFF") → OVERRIDE env.
|
|
72
70
|
* (Earlier center had `rateLimitPerMin`/`approvalRequire` as `.default(0/[])`, which would have let a default
|
|
73
|
-
* silently disable an env-set gate — we flagged it, center made
|
|
71
|
+
* silently disable an env-set gate — we flagged it, center made them optional, so a plain presence rule is
|
|
74
72
|
* now both correct and uniform. No sentinel special-casing.)
|
|
75
73
|
*
|
|
76
74
|
* Only guard: `costQuotaWindowSec` must be `> 0` (a 0 window is nonsensical — core divides by it). Center's
|
|
@@ -79,22 +77,21 @@ export declare function applyEffective(config: ServiceConfig, eff: EffectiveConf
|
|
|
79
77
|
* Per-worker overrides ride the per-worker `/effective?worker=` response (center merges WorkerSpec.runtime over
|
|
80
78
|
* the fleet default server-side), so this single "effective beats env" rule already honors per-worker > fleet.
|
|
81
79
|
*/
|
|
82
|
-
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
|
|
87
|
-
export declare const RUNTIME_GATE_KEYS: readonly ["rateLimitPerMin", "approvalRequire", "maxTaskCostUsd", "maxTaskTokens", "maxPrincipalCostUsd", "costQuotaWindowSec"];
|
|
80
|
+
/** `runtime` 域的限额五闸(= settings-schema `RuntimeConfig` 的全部键,[ref] 件3 对账门钉集合等式),ONE place:
|
|
81
|
+
* legacy 位的 presence 判据({@link runtimeGatePresent} → stage-limits 的 `legacyGates`)、config-catalog 的
|
|
82
|
+
* center 在管键、dry-run 现值快照都从这一张表派生。[ref] 批1 起五键**全热**(属主 stage-limits,boot+refresh
|
|
83
|
+
* 双腿),所以本表与 restart-to-apply 再无关系——审批闸不在这里:它住 governance 域({@link BOOT_GATE_KEYS})。 */
|
|
84
|
+
export declare const RUNTIME_GATE_KEYS: readonly ["rateLimitPerMin", "maxTaskCostUsd", "maxTaskTokens", "maxPrincipalCostUsd", "costQuotaWindowSec"];
|
|
88
85
|
export type RuntimeGateKey = (typeof RUNTIME_GATE_KEYS)[number];
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
*
|
|
97
|
-
*
|
|
86
|
+
/** boot-only(restart-to-apply)的治理闸:今天只有 `governance.approvalRequire` 一键——它被 main.ts 在本函数之后
|
|
87
|
+
* 用 `config` 构造进 approval gate,refresh 腿(teamsOnly)不写,变更由 restart-signal 的 `runtime-gates` 片通告。
|
|
88
|
+
* ([ref] 批2 若把它转热,这张表清空、那个片随之退役——一处改动。) */
|
|
89
|
+
export declare const BOOT_GATE_KEYS: readonly ["approvalRequire"];
|
|
90
|
+
export type BootGateKey = (typeof BOOT_GATE_KEYS)[number];
|
|
91
|
+
/** Uniform presence rule (center f95438a) for the `runtime` limit gates: "managed" when the field is present —
|
|
92
|
+
* any number (incl. 0). Sole guard: costQuotaWindowSec must be > 0 (a 0 window is nonsensical — core divides by
|
|
93
|
+
* it; center's `.positive()` already enforces, belt-and-suspenders here). The approval gate's presence rule
|
|
94
|
+
* (`Array.isArray`) lives with its owner, {@link stageApprovalGate}. */
|
|
98
95
|
/**
|
|
99
96
|
* DESIGN-278 §5 S2([ref])—— center 这份 effective **当前在管**哪些 `ServiceConfig` 键(配置目录端点
|
|
100
97
|
* `GET /v1/config/catalog` 判 `effectiveLane` 的 center 半场)。
|
|
@@ -109,8 +106,13 @@ export declare const HOT_RUNTIME_GATE_KEYS: ReadonlySet<string>;
|
|
|
109
106
|
*/
|
|
110
107
|
export declare function centerManagedConfigKeys(eff: EffectiveConfig | undefined): ReadonlySet<string>;
|
|
111
108
|
export declare function runtimeGatePresent(rt: NonNullable<EffectiveConfig["runtime"]>, key: RuntimeGateKey): boolean;
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
/** 独立调用面的兼容壳(测试/外部):stage → 就地赋值 → 通知。applyEffective 不走这里——它把
|
|
110
|
+
* assignments 并进自己的 commit 段以保住整世代原子性([ref]②)。入参是 eff 的两个域([ref] 件3:审批闸
|
|
111
|
+
* 住 governance,限额五闸住 runtime——两位各自的属主判据,这里不再合成视图)。
|
|
112
|
+
* [ref]:限额五闸的属主已移交热腿,所以本壳**同样**要过 stage-limits —— 否则一个仍叫 applyRuntimeGates
|
|
113
|
+
* 的函数会静默漏掉五个限额键(比改名更坏的那种沉默)。 */
|
|
114
|
+
export declare function applyRuntimeGates(config: ServiceConfig, eff: Pick<EffectiveConfig, "runtime" | "governance"> | undefined, logger?: Logger): void;
|
|
115
|
+
export declare function applyRuntimeHot(config: ServiceConfig, gov: EffectiveConfig["governance"], logger?: Logger): void;
|
|
114
116
|
/**
|
|
115
117
|
* [ref]① 显式默认解析——applyEffective 与 dry-run(logEffectiveDiff.wouldDefaultModel)共用的单源。优先级
|
|
116
118
|
* (显式源指向不在目录/未启用的名 ⇒ onDangling 回调后落下一级,绝不静默指错模型):
|
|
@@ -129,10 +131,7 @@ export declare function resolveDefaultModelName(eff: EffectiveConfig, has: (name
|
|
|
129
131
|
/**
|
|
130
132
|
* Read-only comparison (SEMA_REGISTRY_DRY_RUN): log what the center config WOULD change vs the current
|
|
131
133
|
* (env-derived) config, WITHOUT applying it. The safe-rollout step the config-center recommends — verify
|
|
132
|
-
* the center's models/roles/
|
|
134
|
+
* the center's models/roles/collab match (or intentionally differ from) the env baseline before going live.
|
|
133
135
|
*/
|
|
134
136
|
export declare function logEffectiveDiff(config: ServiceConfig, eff: EffectiveConfig, logger?: Logger): void;
|
|
135
|
-
/** True if the center `runtime` carries any managed gate (a PRESENT field) — i.e. a refresh that changed it
|
|
136
|
-
* needs a restart to take effect (restart-to-apply). Same key list + presence rule as applyRuntimeGates. */
|
|
137
|
-
export declare function runtimeHasActiveGate(rt: EffectiveConfig["runtime"]): boolean;
|
|
138
137
|
//# sourceMappingURL=apply-effective.d.ts.map
|
|
@@ -4,7 +4,6 @@ import { sealedKeyPoison } from "../sealed-key.js";
|
|
|
4
4
|
import { applyAutoCompactWindow, findUnmatchableToolNames, formatUnmatchableToolNames, parseAutonomy } from "../config.js";
|
|
5
5
|
import { validateCommandRules } from "../runtime-governance.js";
|
|
6
6
|
import { projectCollabToWorkflows, registerCollabWorkflows } from "../capabilities/collab-workflows.js";
|
|
7
|
-
import { registerTeams } from "../capabilities/team.js";
|
|
8
7
|
import { stageLimits } from "./stage-limits.js";
|
|
9
8
|
import { BATCH1_LIMIT_KEYS } from "./hot-keys-registry.js";
|
|
10
9
|
const asModelThinking = (v) => (v && isThinkingLevel(v) && v !== "off" ? v : undefined);
|
|
@@ -124,7 +123,7 @@ export function applyEffective(config, eff, logger, opts = {}) {
|
|
|
124
123
|
logger?.info("sema_registry_runtime", staged.gatesInfo);
|
|
125
124
|
if (Object.keys(staged.hot.infoLine).length > 0)
|
|
126
125
|
logger?.info("sema_registry_runtime_hot", staged.hot.infoLine);
|
|
127
|
-
for (const n of staged.
|
|
126
|
+
for (const n of staged.collabPlane?.notices ?? []) {
|
|
128
127
|
if (n.level === "warn")
|
|
129
128
|
logger?.warn(n.msg, n.fields);
|
|
130
129
|
else
|
|
@@ -158,11 +157,8 @@ function commitStaged(config, staged) {
|
|
|
158
157
|
config.autonomy = staged.hot.autonomyNext;
|
|
159
158
|
if (staged.hot.setCommandPolicy)
|
|
160
159
|
config.commandPolicy = staged.hot.commandPolicyNext;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
registerTeams(tp.teams);
|
|
164
|
-
registerCollabWorkflows(tp.workflows);
|
|
165
|
-
}
|
|
160
|
+
if (staged.collabPlane)
|
|
161
|
+
registerCollabWorkflows(staged.collabPlane.workflows);
|
|
166
162
|
mutateInPlace(config.projects, staged.projects);
|
|
167
163
|
}
|
|
168
164
|
function stageEffective(config, eff, logger, opts) {
|
|
@@ -267,32 +263,20 @@ function stageEffective(config, eff, logger, opts) {
|
|
|
267
263
|
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 },
|
|
268
264
|
};
|
|
269
265
|
}
|
|
270
|
-
const
|
|
271
|
-
const gates = opts.teamsOnly ? undefined : stageRuntimeGates(gatesView, logger);
|
|
266
|
+
const gates = opts.teamsOnly ? undefined : stageApprovalGate(eff.governance, logger);
|
|
272
267
|
const limits = stageLimits(config, { version: typeof eff.version === "number" ? eff.version : 0, ...("limits" in eff ? { limits: eff.limits } : {}), legacyGates: legacyGateValues(eff.runtime) }, logger);
|
|
273
|
-
const hot = stageRuntimeHot(config,
|
|
274
|
-
let
|
|
268
|
+
const hot = stageRuntimeHot(config, eff.governance, logger);
|
|
269
|
+
let collabPlane;
|
|
275
270
|
if (opts.deferModelPlane !== true) {
|
|
276
|
-
const teams = {};
|
|
277
|
-
for (const t of (eff.teams?.teams ?? []).filter((t) => t.enabled !== false)) {
|
|
278
|
-
teams[t.name] = {
|
|
279
|
-
name: t.name,
|
|
280
|
-
members: t.members.map((mm) => ({ role: mm.role, ...(mm.model ? { model: mm.model } : {}), modelRole: mm.modelRole, systemPrompt: mm.systemPrompt })),
|
|
281
|
-
rounds: t.rounds,
|
|
282
|
-
synthesizer: t.synthesizer ? { role: t.synthesizer.role, modelRole: t.synthesizer.modelRole, systemPrompt: t.synthesizer.systemPrompt } : undefined,
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
271
|
const projected = projectCollabToWorkflows(eff.collab?.templates);
|
|
286
272
|
const notices = [];
|
|
287
|
-
if (Object.keys(teams).length > 0)
|
|
288
|
-
notices.push({ level: "info", msg: "sema_registry_teams", fields: { teams: Object.keys(teams) } });
|
|
289
273
|
if (Object.keys(projected.workflows).length > 0)
|
|
290
274
|
notices.push({ level: "info", msg: "sema_registry_collab_workflows", fields: { workflows: Object.keys(projected.workflows) } });
|
|
291
275
|
if (projected.skipped.length > 0)
|
|
292
276
|
notices.push({ level: "warn", msg: "sema_registry_collab_skipped", fields: { skipped: projected.skipped } });
|
|
293
277
|
if (projected.notes.length > 0)
|
|
294
278
|
notices.push({ level: "info", msg: "sema_registry_collab_notes", fields: { notes: projected.notes } });
|
|
295
|
-
|
|
279
|
+
collabPlane = { workflows: projected.workflows, notices };
|
|
296
280
|
}
|
|
297
281
|
const projDomain = eff.projects;
|
|
298
282
|
const rawProjects = (projDomain && typeof projDomain === "object" && !Array.isArray(projDomain) &&
|
|
@@ -316,12 +300,12 @@ function stageEffective(config, eff, logger, opts) {
|
|
|
316
300
|
...(gates !== undefined ? { gateAssignments: gates.assignments, ...(gates.info !== undefined ? { gatesInfo: gates.info } : {}) } : {}),
|
|
317
301
|
limits,
|
|
318
302
|
hot,
|
|
319
|
-
...(
|
|
303
|
+
...(collabPlane !== undefined ? { collabPlane } : {}),
|
|
320
304
|
projects,
|
|
321
305
|
};
|
|
322
306
|
}
|
|
323
|
-
export const RUNTIME_GATE_KEYS = ["rateLimitPerMin", "
|
|
324
|
-
export const
|
|
307
|
+
export const RUNTIME_GATE_KEYS = ["rateLimitPerMin", "maxTaskCostUsd", "maxTaskTokens", "maxPrincipalCostUsd", "costQuotaWindowSec"];
|
|
308
|
+
export const BOOT_GATE_KEYS = ["approvalRequire"];
|
|
325
309
|
export function centerManagedConfigKeys(eff) {
|
|
326
310
|
const out = new Set();
|
|
327
311
|
if (!eff)
|
|
@@ -337,10 +321,6 @@ export function centerManagedConfigKeys(eff) {
|
|
|
337
321
|
for (const k of RUNTIME_GATE_KEYS)
|
|
338
322
|
if (runtimeGatePresent(rt, k))
|
|
339
323
|
out.add(k);
|
|
340
|
-
if (rt.autonomy !== undefined)
|
|
341
|
-
out.add("autonomy");
|
|
342
|
-
if (rt.commandPolicy !== undefined)
|
|
343
|
-
out.add("commandPolicy");
|
|
344
324
|
}
|
|
345
325
|
if (eff.governance) {
|
|
346
326
|
if (eff.governance.autonomy !== undefined)
|
|
@@ -369,8 +349,6 @@ export function centerManagedConfigKeys(eff) {
|
|
|
369
349
|
}
|
|
370
350
|
export function runtimeGatePresent(rt, key) {
|
|
371
351
|
const v = rt[key];
|
|
372
|
-
if (key === "approvalRequire")
|
|
373
|
-
return Array.isArray(v);
|
|
374
352
|
if (key === "costQuotaWindowSec")
|
|
375
353
|
return typeof v === "number" && v > 0;
|
|
376
354
|
return typeof v === "number";
|
|
@@ -401,43 +379,29 @@ function stageApprovalRequire(raw, logger) {
|
|
|
401
379
|
}
|
|
402
380
|
return { value: names };
|
|
403
381
|
}
|
|
404
|
-
function
|
|
405
|
-
|
|
382
|
+
function stageApprovalGate(gov, logger) {
|
|
383
|
+
const raw = gov?.approvalRequire;
|
|
384
|
+
if (!Array.isArray(raw))
|
|
406
385
|
return { assignments: [] };
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
continue;
|
|
412
|
-
if (!runtimeGatePresent(rt, key))
|
|
413
|
-
continue;
|
|
414
|
-
if (key === "approvalRequire") {
|
|
415
|
-
const staged = stageApprovalRequire(rt[key], logger);
|
|
416
|
-
if (staged.value === undefined)
|
|
417
|
-
continue;
|
|
418
|
-
assignments.push([key, staged.value]);
|
|
419
|
-
applied[key] = staged.value;
|
|
420
|
-
continue;
|
|
421
|
-
}
|
|
422
|
-
assignments.push([key, rt[key]]);
|
|
423
|
-
applied[key] = rt[key];
|
|
424
|
-
}
|
|
425
|
-
return { assignments, ...(Object.keys(applied).length > 0 ? { info: applied } : {}) };
|
|
386
|
+
const staged = stageApprovalRequire(raw, logger);
|
|
387
|
+
if (staged.value === undefined)
|
|
388
|
+
return { assignments: [] };
|
|
389
|
+
return { assignments: [["approvalRequire", staged.value]], info: { approvalRequire: staged.value } };
|
|
426
390
|
}
|
|
427
391
|
function legacyGateValues(rt) {
|
|
428
392
|
const out = {};
|
|
429
393
|
if (!rt)
|
|
430
394
|
return out;
|
|
431
395
|
for (const k of RUNTIME_GATE_KEYS)
|
|
432
|
-
if (
|
|
396
|
+
if (runtimeGatePresent(rt, k))
|
|
433
397
|
out[k] = rt[k];
|
|
434
398
|
return out;
|
|
435
399
|
}
|
|
436
|
-
export function applyRuntimeGates(config,
|
|
437
|
-
const s =
|
|
400
|
+
export function applyRuntimeGates(config, eff, logger) {
|
|
401
|
+
const s = stageApprovalGate(eff?.governance, logger);
|
|
438
402
|
for (const [k, v] of s.assignments)
|
|
439
403
|
config[k] = v;
|
|
440
|
-
const limits = stageLimits(config, { version: 0, legacyGates: legacyGateValues(
|
|
404
|
+
const limits = stageLimits(config, { version: 0, legacyGates: legacyGateValues(eff?.runtime) }, logger);
|
|
441
405
|
for (const [k, v] of limits.assignments)
|
|
442
406
|
config[k] = v;
|
|
443
407
|
for (const k of limits.deletions)
|
|
@@ -473,8 +437,8 @@ function stageRuntimeHot(config, rt, logger) {
|
|
|
473
437
|
}
|
|
474
438
|
return { setAutonomy, autonomyNext, setCommandPolicy, commandPolicyNext, infoLine };
|
|
475
439
|
}
|
|
476
|
-
export function applyRuntimeHot(config,
|
|
477
|
-
const s = stageRuntimeHot(config,
|
|
440
|
+
export function applyRuntimeHot(config, gov, logger) {
|
|
441
|
+
const s = stageRuntimeHot(config, gov, logger);
|
|
478
442
|
if (s.setAutonomy)
|
|
479
443
|
config.autonomy = s.autonomyNext;
|
|
480
444
|
if (s.setCommandPolicy)
|
|
@@ -506,7 +470,6 @@ export function logEffectiveDiff(config, eff, logger) {
|
|
|
506
470
|
const centerModels = enabled.map((m) => ({ name: m.name, id: m.id, provider: m.provider, apiKeyEnv: m.apiKeyEnv ?? null, tier: m.tier ?? null }));
|
|
507
471
|
const envModels = Object.entries(config.models).map(([name, m]) => ({ name, id: m.id, provider: m.provider }));
|
|
508
472
|
const centerRoles = Object.fromEntries(Object.entries(eff.models?.roles ?? {}).map(([r, t]) => [r, "model" in t ? t.model : { select: t.select }]));
|
|
509
|
-
const centerTeams = (eff.teams?.teams ?? []).filter((t) => t.enabled !== false).map((t) => t.name);
|
|
510
473
|
logger?.warn("sema_registry_dry_run", {
|
|
511
474
|
note: "DRY RUN — registry config NOT applied; unset SEMA_REGISTRY_DRY_RUN to go live",
|
|
512
475
|
version: eff.version,
|
|
@@ -515,18 +478,17 @@ export function logEffectiveDiff(config, eff, logger) {
|
|
|
515
478
|
currentDefaultModel: config.model.id,
|
|
516
479
|
models: { center: centerModels, envDerived: envModels },
|
|
517
480
|
roles: { center: centerRoles, current: config.roles },
|
|
518
|
-
|
|
481
|
+
collab: { centerWouldRegister: Object.keys(projectCollabToWorkflows(eff.collab?.templates).workflows) },
|
|
519
482
|
skills: { centerWouldLoad: (eff.skills?.skills ?? []).filter((s) => s.enabled !== false).map((s) => s.name) },
|
|
520
483
|
mcp: { centerWouldRegister: (eff.mcp?.servers ?? []).filter((s) => s.enabled !== false).map((s) => s.name) },
|
|
521
484
|
runtime: {
|
|
522
485
|
center: eff.runtime ?? null,
|
|
523
486
|
current: Object.fromEntries(RUNTIME_GATE_KEYS.map((k) => [k, config[k]])),
|
|
524
487
|
},
|
|
488
|
+
governance: {
|
|
489
|
+
center: eff.governance ?? null,
|
|
490
|
+
current: { autonomy: config.autonomy, commandPolicy: config.commandPolicy?.length ?? 0, approvalRequire: config.approvalRequire },
|
|
491
|
+
},
|
|
525
492
|
});
|
|
526
493
|
}
|
|
527
|
-
export function runtimeHasActiveGate(rt) {
|
|
528
|
-
if (!rt)
|
|
529
|
-
return false;
|
|
530
|
-
return RUNTIME_GATE_KEYS.some((k) => runtimeGatePresent(rt, k));
|
|
531
|
-
}
|
|
532
494
|
//# sourceMappingURL=apply-effective.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [ref] 件5 —— server 的 settings-schema 消费键账本(对账门 test/settings-schema-consumption-gates.test.ts 的本仓侧输入)。
|
|
3
|
+
*
|
|
4
|
+
* 🔴 三条纪律:
|
|
5
|
+
* 1. `EFFECTIVE_CONFIG_KEYS` 与 {@link EffectiveConfig} **类型级**绑定(`satisfies Record<keyof …, true>`):接口加键 /
|
|
6
|
+
* 删键而不动这里 = **编译错**——运行时键表永不与类型面漂移(这不是第二份表,是同一份接口的运行时投影;
|
|
7
|
+
* runtime / governance 两域的键表同法,用于与 schema zod shape 的集合等式墓碑)。
|
|
8
|
+
* 2. 三张登记表(非域白名单 / 不消费表 / 远端专属表)每行**必须带理由**;行的成立性由对账门**双向**钉——登记了
|
|
9
|
+
* 却不成立(死账)与成立了却没登记(半接线)都红,理由失效之日格子自己翻红(墓碑),禁裸豁免。
|
|
10
|
+
* 3. schema 侧的数据(`DOMAINS` / `PORTABLE_DOMAINS` / zod shape)一律由对账门**读 dist**,绝不抄进这里
|
|
11
|
+
* (平行副本病是 DESIGN-282 §0 的病理定性,本文件只登记 server 自己那一侧)。
|
|
12
|
+
*/
|
|
13
|
+
import type { EffectiveConfig } from "./types.js";
|
|
14
|
+
/** EffectiveConfig 的全部顶层键(信封 + 域 + 非域白名单键),类型级绑定见上。 */
|
|
15
|
+
export declare const EFFECTIVE_CONFIG_KEYS: ReadonlyArray<keyof EffectiveConfig>;
|
|
16
|
+
/** 信封键(不是域)。 */
|
|
17
|
+
export declare const EFFECTIVE_ENVELOPE_KEYS: readonly ["version", "updatedAt"];
|
|
18
|
+
/** `runtime` 域(限额残余)的键集——对账门与 schema `RuntimeConfig.shape` 钉集合等式([ref] 件3 退役键墓碑)。 */
|
|
19
|
+
export declare const RUNTIME_DOMAIN_KEYS: readonly string[];
|
|
20
|
+
/** `governance` 域(治理三件)的键集——对账门与 schema `GovernanceConfig.shape` 钉集合等式。 */
|
|
21
|
+
export declare const GOVERNANCE_DOMAIN_KEYS: readonly string[];
|
|
22
|
+
/** EffectiveConfig 上**不是** settings-schema 域的顶层键(键 → 成文理由)。⚠️ 墓碑语义:任一键将来出现在 schema
|
|
23
|
+
* `DOMAINS` 里 ⇒ 对账门红 ⇒ 清本行 + 接本地腿投影(mapToServiceEffective)+ 复核 restart 片归属。 */
|
|
24
|
+
export declare const NON_DOMAIN_EFFECTIVE_KEYS: Readonly<Record<string, string>>;
|
|
25
|
+
/** schema `DOMAINS` 里 server **不消费**的域(域 → 成文理由)。⚠️ 新域(如 presets)到货而不入本表也不入
|
|
26
|
+
* EffectiveConfig ⇒ 对账门红 ⇒ 逼一行显式决定(「加了域没人接」从此机器可见,[ref]③)。 */
|
|
27
|
+
export declare const DOMAINS_NOT_CONSUMED_BY_SERVER: Readonly<Record<string, string>>;
|
|
28
|
+
/** server 消费但**非便携**(∉ PORTABLE_DOMAINS ⇒ 本地腿无 config.d/<域>.json 可读)的域(域 → 成文理由)。 */
|
|
29
|
+
export declare const LOCAL_LANE_REMOTE_ONLY_DOMAINS: Readonly<Record<string, string>>;
|
|
30
|
+
//# sourceMappingURL=effective-keys.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const EFFECTIVE_CONFIG_KEY_TABLE = {
|
|
2
|
+
version: true,
|
|
3
|
+
updatedAt: true,
|
|
4
|
+
models: true,
|
|
5
|
+
collab: true,
|
|
6
|
+
skills: true,
|
|
7
|
+
mcp: true,
|
|
8
|
+
a2a: true,
|
|
9
|
+
scenarios: true,
|
|
10
|
+
runtime: true,
|
|
11
|
+
limits: true,
|
|
12
|
+
projects: true,
|
|
13
|
+
governance: true,
|
|
14
|
+
plugins: true,
|
|
15
|
+
readFace: true,
|
|
16
|
+
prompts: true,
|
|
17
|
+
};
|
|
18
|
+
export const EFFECTIVE_CONFIG_KEYS = Object.keys(EFFECTIVE_CONFIG_KEY_TABLE);
|
|
19
|
+
export const EFFECTIVE_ENVELOPE_KEYS = ["version", "updatedAt"];
|
|
20
|
+
const RUNTIME_DOMAIN_KEY_TABLE = {
|
|
21
|
+
rateLimitPerMin: true,
|
|
22
|
+
maxTaskCostUsd: true,
|
|
23
|
+
maxTaskTokens: true,
|
|
24
|
+
maxPrincipalCostUsd: true,
|
|
25
|
+
costQuotaWindowSec: true,
|
|
26
|
+
};
|
|
27
|
+
export const RUNTIME_DOMAIN_KEYS = Object.keys(RUNTIME_DOMAIN_KEY_TABLE);
|
|
28
|
+
const GOVERNANCE_DOMAIN_KEY_TABLE = {
|
|
29
|
+
autonomy: true,
|
|
30
|
+
commandPolicy: true,
|
|
31
|
+
approvalRequire: true,
|
|
32
|
+
};
|
|
33
|
+
export const GOVERNANCE_DOMAIN_KEYS = Object.keys(GOVERNANCE_DOMAIN_KEY_TABLE);
|
|
34
|
+
export const NON_DOMAIN_EFFECTIVE_KEYS = {
|
|
35
|
+
a2a: "R-15 裁开域([4384]),但 settings-schema 至 1.3.0 未开(DOMAINS 无 a2a)——S-31 件2 BLOCKED on schema:远端腿靠 readEffectiveWire 的 open-world verbatim 透传(DESIGN-269),本地腿不可达(FileConfigStore 只读 PORTABLE_DOMAINS)。schema 开域之日按墓碑流程收线。",
|
|
36
|
+
readFace: "R-15 裁**暂不开域**([4384]:env 逐键恒赢语义下收益薄,⚪ 呈现制过渡)——#A4 的远端腿同靠 open-world 透传;本地腿四键由 env / 引擎默认独占。若来日改裁开域,同上墓碑机制。",
|
|
37
|
+
};
|
|
38
|
+
export const DOMAINS_NOT_CONSUMED_BY_SERVER = {
|
|
39
|
+
rosters: "center 写面域:center 端 resolveEffectiveForWorker 把 roster 解析进 per-worker /effective 的 models 视图——server 消费的是解析产物,不读原始域。",
|
|
40
|
+
systems: "控制面登记簿(系统台账),orchestrator / web 消费;worker /effective 视图不含。",
|
|
41
|
+
workers: "fleet 声明域,orchestrator(reconciler)消费拆建 worker;worker 自身不读。",
|
|
42
|
+
hosts: "主机登记域,orchestrator / 探活面消费;worker /effective 视图不含。",
|
|
43
|
+
entitlement: "租户商务数据:裁定为 per-principal caps view 单源(fetchPrincipalCaps),raw 域刻意不上 worker wire(center resolve-roster strips)。",
|
|
44
|
+
execution: "per-principal 执法面同 entitlement:ruling 骑 caps view(ExecutionRuling),/effective 域面 server 不读。",
|
|
45
|
+
};
|
|
46
|
+
export const LOCAL_LANE_REMOTE_ONLY_DOMAINS = {
|
|
47
|
+
projects: "身份台账(design/142 §1.4,与租户身份同风险模型):settings-schema 便携表刻意排除(file-store.ts 成文)——本地腿无此域文件,mapToServiceEffective 不投影;远端腿 verbatim 消费(applyEffective → config.projects)。",
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=effective-keys.js.map
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* identifier ("config-center") and does not chase the rename.)
|
|
10
10
|
*
|
|
11
11
|
* - the CENTER owns the LOGICAL config: the model roster (names/capabilities/tier), the role map,
|
|
12
|
-
* and
|
|
12
|
+
* and collab (multi-agent discussion) templates;
|
|
13
13
|
* - the SERVICE env still owns the SECRETS: API keys stay in env (the center never stores a secret);
|
|
14
14
|
* keys are per-model via `apiKeyEnv` → `config.modelApiKeyEnv` → the spec's `getApiKeyAndHeaders`
|
|
15
15
|
* (core 1.45), so each model/cascade-rung authenticates with its own upstream key.
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* Hot-reload status (复审 2026-07-29 P1-11 — 亲读判定,取代此处旧的 "models/roles are restart-to-apply"
|
|
21
21
|
* TODO, which went stale when `mutateInPlace` landed):
|
|
22
|
-
* - models/roles/roster/
|
|
22
|
+
* - models/roles/roster/collab/projects/autonomy — **HOT**. `applyEffective` mutates `config.models`/
|
|
23
23
|
* `config.roles` IN PLACE, and core's Runner reads `this.deps.models/roles` per task off that very
|
|
24
24
|
* reference. Both brains re-resolve `model.baseUrl || config.baseUrl` inside `buildRequest()` on every
|
|
25
25
|
* call (core 2.1.0 `brain/openai.js` + `brain/anthropic.js`), so a moved gateway takes effect on the
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
* importers to update, which was done in the same commit.
|
|
42
42
|
*/
|
|
43
43
|
export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
|
|
44
|
-
export { mutateInPlace, applyEffective, type ApplyReport, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff,
|
|
44
|
+
export { mutateInPlace, applyEffective, type ApplyReport, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, } from "./apply-effective.js";
|
|
45
45
|
export { restartReasons, planeHasActiveTiers, modelPlaneChanged, type RestartSlice, type RestartSliceCtx, type RestartSignal, } from "./restart-signal.js";
|
|
46
46
|
export { applyCenterSkills, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
|
|
47
47
|
export { applyCenterReadFace } from "./read-face.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
|
|
2
|
-
export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff,
|
|
2
|
+
export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, } from "./apply-effective.js";
|
|
3
3
|
export { restartReasons, planeHasActiveTiers, modelPlaneChanged, } from "./restart-signal.js";
|
|
4
4
|
export { applyCenterSkills, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
|
|
5
5
|
export { applyCenterReadFace } from "./read-face.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveActiveTiers } from "@sema-agent/settings-schema";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveDefaultModelName } from "./apply-effective.js";
|
|
3
3
|
const RESTART_SLICES = ["skills", "mcp", "a2a", "scenarios", "runtime-gates", "models-tiers", "degrade-route", "read-face"];
|
|
4
4
|
export function stableStringify(v) {
|
|
5
5
|
if (v === null || typeof v !== "object")
|
|
@@ -38,14 +38,8 @@ function restartSliceValue(eff, slice, ctx) {
|
|
|
38
38
|
case "scenarios":
|
|
39
39
|
return enabledOnly(eff.scenarios?.scenarios);
|
|
40
40
|
case "runtime-gates": {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
return null;
|
|
44
|
-
const present = {};
|
|
45
|
-
for (const k of RUNTIME_GATE_KEYS)
|
|
46
|
-
if (!HOT_RUNTIME_GATE_KEYS.has(k) && runtimeGatePresent(rt, k))
|
|
47
|
-
present[k] = rt[k];
|
|
48
|
-
return Object.keys(present).length ? present : null;
|
|
41
|
+
const ar = eff.governance?.approvalRequire;
|
|
42
|
+
return Array.isArray(ar) ? { approvalRequire: ar } : null;
|
|
49
43
|
}
|
|
50
44
|
case "models-tiers": {
|
|
51
45
|
const active = eff.models ? resolveActiveTiers(eff.models) : undefined;
|