@sema-agent/server 4.0.0 → 4.1.1

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.
@@ -81,6 +81,12 @@ export function mutateInPlace(target, source) {
81
81
  /** 每个 config 对象上一次 COMMIT 的世代号([2283]③ CAS 的 live 端)。WeakMap——config 回收即回收;
82
82
  * version 0(未发布/本地一次性 lane)不参与登记。 */
83
83
  const appliedGeneration = new WeakMap();
84
+ /** [2311]/[2314] 裁①:env 派生 roles 基线(首次进入模型面 apply 时快照,冻结拷贝)。roles 的 file/center
85
+ * lane 语义=**逐键 override,env 基线为底,非粘**——上游(registry-core resolveEffectiveForWorker)本就是
86
+ * 逐键 merge 链;整表替换会让低信任写者(center 编辑面)静默抹掉 operator 的 env 部署契约(MODEL_VERIFIER
87
+ * 反自评等),且旧守卫 `length>0` 粘住的不是 env 底而是**上一个 center 世代**(applyRuntimeHot 头注
88
+ * NON-STICKY 论证同族,roles 曾漏在纪律外——cli [2311] 实测「用户撤销被静默吞掉」即此)。 */
89
+ const envRolesBaseline = new WeakMap();
84
90
  /** 返回值=是否 COMMIT(false 仅在 [2283]③ 世代序 CAS 拒绝时)。caller 收到 false 必须把**同一世代的
85
91
  * 旁路消费**(prompts 采用/pricing/keyResolver/etag 推进/LKG 落盘)一并跳过——否则 applyEffective 拒了
86
92
  * 主面、旁路却半应用同一个被拒世代,混合世代从侧门回来。首次 apply(live 未登记)恒 true。 */
@@ -122,8 +128,7 @@ function commitStaged(config, staged) {
122
128
  mutateInPlace(config.modelQuotaWeights, mp.quotaWeights);
123
129
  mutateInPlace(config.models, mp.models); // IN PLACE: keep the ref the Runner + /v1/models share (hot-apply)
124
130
  config.model = config.models.default;
125
- if (Object.keys(mp.roles).length > 0)
126
- mutateInPlace(config.roles, mp.roles); // IN PLACE: Runner reads this.deps.roles live
131
+ mutateInPlace(config.roles, mp.roles); // IN PLACE: Runner reads this.deps.roles live([2314] 裁①:staged roles 已是 env 底+center 逐键 merge 的整表,无条件落——旧 `length>0` 守卫=空表粘住上一 center 世代)
127
132
  mutateInPlace(config.tiers, mp.activeTiers);
128
133
  }
129
134
  if (staged.gateAssignments) {
@@ -268,13 +273,20 @@ function stageEffective(config, eff, logger, opts) {
268
273
  quotaWeights[m.id] = qw;
269
274
  }
270
275
  }
271
- const roles = {};
276
+ // [2311]/[2314] 裁①:首次进入模型面 apply 时快照 env 派生基线(此刻 config.roles 尚未被任何 center
277
+ // 世代写过——boot 序=loadConfig→applyEffective;deferModelPlane 跳过的 apply 不进本分支,不污染)。
278
+ if (!envRolesBaseline.has(config))
279
+ envRolesBaseline.set(config, { ...config.roles });
280
+ const centerRoles = {};
272
281
  for (const [role, tgt] of Object.entries(eff.models.roles ?? {})) {
273
282
  if ("model" in tgt)
274
- roles[role] = tgt.model;
283
+ centerRoles[role] = tgt.model;
275
284
  else if ("select" in tgt)
276
- roles[role] = { select: tgt.select };
285
+ centerRoles[role] = { select: tgt.select };
277
286
  }
287
+ // 逐键 override(env 底)+ 非粘:每次 apply 从基线整表重算——center 撤键/发空表 = 该键/整表回 env 底,
288
+ // 上一世代绝不驻留;center 同名键盖 env(operator 两边都配时 center 编辑面可见可审)。
289
+ const roles = { ...envRolesBaseline.get(config), ...centerRoles };
278
290
  // registry-core 0.9.0: tier groups → the engine's single active tier table. `resolveActiveTiers`
279
291
  // is registry-core's ONE resolution point (active group → its bound tiers; no active / dangling / all-unbound
280
292
  // → undefined = INERT). Values are catalog NAME strings (open, not enum'd); dangling bindings were already
@@ -198,6 +198,12 @@ export function mapToServiceEffective(eff, version) {
198
198
  api: m.api,
199
199
  ...(m.baseUrl !== undefined ? { baseUrl: m.baseUrl } : {}),
200
200
  ...(m.apiKeyEnv !== undefined ? { apiKeyEnv: m.apiKeyEnv } : {}),
201
+ // RL-1(P4 A0 发现,2026-08-02;autoCompactTokens/promptGuidance 同类病族):CLOSED 投影剥掉
202
+ // sealedApiKey 会让本地 lane 的 sealed 模型绕过 applyEffective 的毒丸臂(严格互斥纪律)⇒
203
+ // 静默烧网关共享 key——正是毒丸臂声称杜绝的事故。携带它,无 opener 时毒丸自然接管(fail-loud)。
204
+ ...(m.sealedApiKey !== undefined ? { sealedApiKey: m.sealedApiKey } : {}),
205
+ // 同族连带:quotaWeight 被剥 ⇒ 本地 lane 配额倍率静默归 1(weight-at-burn 面失真)。
206
+ ...(m.quotaWeight !== undefined ? { quotaWeight: m.quotaWeight } : {}),
201
207
  tier: m.tier,
202
208
  reasoning: m.reasoning,
203
209
  vision: m.vision,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/server",
3
- "version": "4.0.0",
3
+ "version": "4.1.1",
4
4
  "description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",
@@ -68,7 +68,7 @@
68
68
  "sharp": "^0.35.3"
69
69
  },
70
70
  "devDependencies": {
71
- "@sema-agent/sdk": "^2.3.0",
71
+ "@sema-agent/sdk": "^3.0.0",
72
72
  "@types/libsodium-wrappers": "^0.7.14",
73
73
  "@types/node": "22.10.2",
74
74
  "@types/pg": "^8.20.0",