@sema-agent/server 7.122.0 → 7.124.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.
Files changed (256) hide show
  1. package/MIGRATION.md +209 -0
  2. package/README.md +7 -2
  3. package/README.zh-CN.md +5 -2
  4. package/USAGE.md +76 -56
  5. package/dist/approval-ask-audit-store.d.ts +27 -32
  6. package/dist/approval-ask-audit-store.js +10 -9
  7. package/dist/approval-crash-convergence.d.ts +2 -2
  8. package/dist/approval-crash-convergence.js +5 -5
  9. package/dist/approval-deny-reasons.d.ts +163 -51
  10. package/dist/approval-deny-reasons.js +79 -8
  11. package/dist/approval-policy-settlement.d.ts +4 -1
  12. package/dist/approval-policy-settlement.js +3 -2
  13. package/dist/approval-reconciler.d.ts +3 -3
  14. package/dist/approval-reconciler.js +10 -10
  15. package/dist/approval.d.ts +1 -1
  16. package/dist/approval.js +1 -1
  17. package/dist/audit.d.ts +1 -1
  18. package/dist/audit.js +53 -23
  19. package/dist/auth-bridge.d.ts +8 -8
  20. package/dist/auth-bridge.js +6 -6
  21. package/dist/auth-keys.d.ts +2 -2
  22. package/dist/auto-mode-face.d.ts +13 -9
  23. package/dist/auto-mode-face.js +8 -7
  24. package/dist/boot/budget-tracing.js +1 -1
  25. package/dist/boot/execution-env.js +1 -0
  26. package/dist/boot/leader.d.ts +1 -1
  27. package/dist/boot/memory-consolidation.d.ts +4 -4
  28. package/dist/boot/org-memory.d.ts +3 -3
  29. package/dist/boot/org-memory.js +5 -5
  30. package/dist/boot/resolve-spec.js +7 -7
  31. package/dist/boot/runner-deps.d.ts +1 -1
  32. package/dist/boot/runtime-caps.d.ts +1 -1
  33. package/dist/boot/runtime-caps.js +10 -10
  34. package/dist/boot/shutdown.d.ts +2 -2
  35. package/dist/boot/shutdown.js +2 -2
  36. package/dist/boot/side-query-lane.d.ts +3 -3
  37. package/dist/boot/{stage-02-registry-pull.d.ts → stage-02-web-admin-pull.d.ts} +2 -2
  38. package/dist/boot/{stage-02-registry-pull.js → stage-02-web-admin-pull.js} +4 -4
  39. package/dist/boot/stage-03-store-backend.d.ts +2 -2
  40. package/dist/boot/stage-04-stores.d.ts +1 -1
  41. package/dist/boot/stage-05-execution-env.d.ts +1 -1
  42. package/dist/boot/stage-06-runners.d.ts +2 -2
  43. package/dist/boot/stage-06-runners.js +6 -6
  44. package/dist/boot/stage-07-capability-layer.d.ts +2 -2
  45. package/dist/boot/stage-07-capability-layer.js +6 -5
  46. package/dist/boot/stage-08-reapers.d.ts +3 -3
  47. package/dist/boot/stage-08-reapers.js +3 -3
  48. package/dist/boot/stage-09-leader.d.ts +3 -3
  49. package/dist/boot/stage-09-leader.js +7 -7
  50. package/dist/boot/stage-10-http-server.d.ts +3 -3
  51. package/dist/boot/stage-10-http-server.js +19 -19
  52. package/dist/boot/unpriced-ceiling-verdict.d.ts +1 -1
  53. package/dist/boot/{config-center.d.ts → web-admin.d.ts} +11 -11
  54. package/dist/boot/{config-center.js → web-admin.js} +39 -20
  55. package/dist/boot/webfetch-summarize-lane.d.ts +2 -2
  56. package/dist/brain.d.ts +1 -1
  57. package/dist/brain.js +1 -1
  58. package/dist/budget.d.ts +3 -3
  59. package/dist/canonical-json.d.ts +2 -2
  60. package/dist/capabilities/center-plugins.d.ts +1 -1
  61. package/dist/capabilities/center-wiring.d.ts +12 -5
  62. package/dist/capabilities/center-wiring.js +11 -2
  63. package/dist/capabilities/composite-members.d.ts +1 -1
  64. package/dist/capabilities/composite-members.js +1 -1
  65. package/dist/capabilities/scenarios.js +2 -2
  66. package/dist/capabilities/team.d.ts +1 -1
  67. package/dist/capabilities/tool-defer.d.ts +1 -1
  68. package/dist/center-credential-renewer.d.ts +1 -1
  69. package/dist/center-credential-renewer.js +7 -7
  70. package/dist/center-credential.d.ts +9 -9
  71. package/dist/center-credential.js +6 -6
  72. package/dist/config-catalog.d.ts +7 -10
  73. package/dist/config-catalog.js +16 -16
  74. package/dist/config-d-migration.d.ts +32 -0
  75. package/dist/config-d-migration.js +59 -0
  76. package/dist/config-invariants.d.ts +14 -4
  77. package/dist/config-invariants.js +31 -2
  78. package/dist/config-lkg.d.ts +34 -11
  79. package/dist/config-lkg.js +76 -48
  80. package/dist/config-provider.d.ts +26 -21
  81. package/dist/config-provider.js +25 -27
  82. package/dist/config-types.d.ts +59 -50
  83. package/dist/config.d.ts +17 -54
  84. package/dist/config.js +99 -181
  85. package/dist/execution-lane-caps.d.ts +1 -1
  86. package/dist/fleet/drain-entry.d.ts +1 -1
  87. package/dist/fleet/engine-signal.d.ts +61 -30
  88. package/dist/fleet/engine-signal.js +29 -5
  89. package/dist/fleet/fleet-bus.d.ts +12 -3
  90. package/dist/fleet/fleet-bus.js +13 -9
  91. package/dist/fleet/serving-lease.d.ts +3 -3
  92. package/dist/fleet/serving-lease.js +1 -1
  93. package/dist/fleet-client.d.ts +15 -13
  94. package/dist/fleet-client.js +9 -7
  95. package/dist/fleet-lease.d.ts +3 -3
  96. package/dist/fleet-lease.js +2 -2
  97. package/dist/host-lsp-manager.d.ts +1 -1
  98. package/dist/hosted-posture.d.ts +4 -4
  99. package/dist/http/admission.js +4 -4
  100. package/dist/http/checkpoint-ctx.d.ts +20 -3
  101. package/dist/http/checkpoint-ctx.js +13 -5
  102. package/dist/http/dispatch.js +7 -16
  103. package/dist/http/durable-run-leg.js +2 -1
  104. package/dist/http/health-self-report.d.ts +7 -4
  105. package/dist/http/health-self-report.js +3 -3
  106. package/dist/http/idempotency.d.ts +1 -1
  107. package/dist/http/resume-legs.d.ts +4 -3
  108. package/dist/http/resume-legs.js +31 -18
  109. package/dist/http/route-ctx.d.ts +8 -0
  110. package/dist/http/routes/admin-config-refresh.d.ts +1 -1
  111. package/dist/http/routes/admin-config-refresh.js +1 -1
  112. package/dist/http/routes/admin-drain.d.ts +1 -1
  113. package/dist/http/routes/admin-drain.js +5 -4
  114. package/dist/http/routes/approvals-assistant.js +4 -4
  115. package/dist/http/routes/capabilities.js +6 -5
  116. package/dist/http/routes/config-catalog.js +2 -3
  117. package/dist/http/routes/diagnostics.js +1 -1
  118. package/dist/http/routes/runs.js +8 -4
  119. package/dist/http/routes/sessions-list.js +2 -1
  120. package/dist/http/routes/sessions.js +2 -5
  121. package/dist/http/routes/side-query.js +3 -3
  122. package/dist/http/routes/tasks.js +3 -2
  123. package/dist/http/run-meta.d.ts +1 -1
  124. package/dist/http/run-meta.js +2 -2
  125. package/dist/http/server.d.ts +7 -7
  126. package/dist/http/server.js +1 -1
  127. package/dist/http/stored-body-replay.d.ts +4 -3
  128. package/dist/http/stored-body-replay.js +5 -5
  129. package/dist/index.d.ts +2 -1
  130. package/dist/index.js +1 -1
  131. package/dist/key-resolver.d.ts +1 -1
  132. package/dist/leader/leader.d.ts +7 -6
  133. package/dist/leader/leader.js +3 -1
  134. package/dist/leader/run-entry.d.ts +2 -2
  135. package/dist/leader/run-entry.js +3 -3
  136. package/dist/leader/wire.d.ts +4 -4
  137. package/dist/leader/wire.js +2 -1
  138. package/dist/main.js +1 -1
  139. package/dist/mcp-tool-faces.d.ts +2 -2
  140. package/dist/model-entry-refusal.d.ts +20 -11
  141. package/dist/model-entry-refusal.js +22 -17
  142. package/dist/model-provider.d.ts +2 -2
  143. package/dist/model-route-endpoint.d.ts +22 -2
  144. package/dist/model-route-endpoint.js +9 -3
  145. package/dist/model-route-gap.d.ts +103 -0
  146. package/dist/model-route-gap.js +80 -0
  147. package/dist/model-route-url.d.ts +1 -1
  148. package/dist/model-route-url.js +2 -1
  149. package/dist/model-select.d.ts +24 -21
  150. package/dist/model-select.js +22 -17
  151. package/dist/namespaced-rule-name.d.ts +16 -30
  152. package/dist/namespaced-rule-name.js +2 -20
  153. package/dist/observability/fail-open.d.ts +0 -4
  154. package/dist/observability/fail-open.js +0 -4
  155. package/dist/observability/metrics.d.ts +1 -1
  156. package/dist/org-memory-admission.d.ts +1 -1
  157. package/dist/plugins/approval-ask-store-file.d.ts +4 -2
  158. package/dist/plugins/approval-ask-store-file.js +3 -3
  159. package/dist/plugins/approval-ask-store-memory.d.ts +4 -3
  160. package/dist/plugins/approval-ask-store-memory.js +10 -4
  161. package/dist/plugins/approval-ask-store-sql.d.ts +16 -2
  162. package/dist/plugins/approval-ask-store-sql.js +20 -13
  163. package/dist/plugins/caching-session-store.d.ts +0 -10
  164. package/dist/plugins/caching-session-store.js +0 -3
  165. package/dist/plugins/file-run-store.js +9 -3
  166. package/dist/plugins/leader-run-store-sql.d.ts +3 -2
  167. package/dist/plugins/leader-run-store-sql.js +3 -2
  168. package/dist/plugins/local-session-store.d.ts +20 -27
  169. package/dist/plugins/local-session-store.js +19 -17
  170. package/dist/plugins/memory-run-store.js +9 -3
  171. package/dist/plugins/one-time-migrations.js +51 -0
  172. package/dist/plugins/scheduler-support.d.ts +26 -7
  173. package/dist/plugins/scheduler-support.js +96 -53
  174. package/dist/plugins/session-policy-store-sql.js +1 -2
  175. package/dist/plugins/store-backend.js +1 -1
  176. package/dist/plugins/store-contracts.d.ts +20 -4
  177. package/dist/plugins/web-search.d.ts +1 -1
  178. package/dist/plugins/web-search.js +2 -1
  179. package/dist/plugins/workflow-run-store-sql.d.ts +4 -2
  180. package/dist/posture-source.d.ts +1 -1
  181. package/dist/read-face-posture.d.ts +3 -3
  182. package/dist/read-face-posture.js +1 -1
  183. package/dist/rule-entry-list.d.ts +3 -13
  184. package/dist/rule-entry-list.js +1 -12
  185. package/dist/run-local.js +10 -7
  186. package/dist/runtime-caps-resolver.d.ts +4 -4
  187. package/dist/runtime-caps-resolver.js +2 -2
  188. package/dist/runtime-governance.d.ts +36 -13
  189. package/dist/runtime-governance.js +7 -2
  190. package/dist/sealed-key.d.ts +4 -4
  191. package/dist/sealed-key.js +3 -2
  192. package/dist/security.d.ts +3 -3
  193. package/dist/service-version.d.ts +1 -1
  194. package/dist/service-version.js +5 -0
  195. package/dist/session-policy-wire.d.ts +47 -49
  196. package/dist/session-policy-wire.js +41 -36
  197. package/dist/session-sync.d.ts +5 -1
  198. package/dist/session-sync.js +2 -1
  199. package/dist/session-titler.d.ts +0 -11
  200. package/dist/session-titler.js +3 -5
  201. package/dist/shared-memory-scope-authorizer.d.ts +4 -4
  202. package/dist/spec-fields.d.ts +4 -4
  203. package/dist/spec-fields.js +1 -4
  204. package/dist/task-a2a.d.ts +1 -1
  205. package/dist/task-settings.d.ts +4 -5
  206. package/dist/task-settings.js +5 -8
  207. package/dist/tool-approval.d.ts +43 -4
  208. package/dist/tool-approval.js +147 -98
  209. package/dist/trace/core-keyset-guard.d.ts +1 -1
  210. package/dist/trace/project.d.ts +3 -3
  211. package/dist/trace/redact.d.ts +2 -23
  212. package/dist/trace/redact.js +1 -6
  213. package/dist/trace/self-minted-wire.d.ts +147 -3
  214. package/dist/trace/self-minted-wire.js +50 -9
  215. package/dist/unattended-permission-mode.d.ts +3 -3
  216. package/dist/unattended-permission-mode.js +2 -2
  217. package/dist/url-refusal.d.ts +35 -0
  218. package/dist/url-refusal.js +15 -0
  219. package/dist/user-authored-text.d.ts +31 -0
  220. package/dist/user-authored-text.js +18 -0
  221. package/dist/{config-center → web-admin-client}/apply-effective.d.ts +13 -70
  222. package/dist/{config-center → web-admin-client}/apply-effective.js +104 -121
  223. package/dist/{config-center → web-admin-client}/apply-ledger.d.ts +2 -2
  224. package/dist/{config-center → web-admin-client}/center-request.d.ts +7 -7
  225. package/dist/{config-center → web-admin-client}/center-request.js +5 -4
  226. package/dist/{config-center → web-admin-client}/effective-keys.d.ts +1 -3
  227. package/dist/{config-center → web-admin-client}/effective-keys.js +0 -9
  228. package/dist/{config-center → web-admin-client}/facade.d.ts +6 -6
  229. package/dist/{config-center → web-admin-client}/facade.js +2 -2
  230. package/dist/{config-center → web-admin-client}/http-client.d.ts +6 -10
  231. package/dist/{config-center → web-admin-client}/http-client.js +15 -15
  232. package/dist/{config-center → web-admin-client}/pull-state.d.ts +1 -1
  233. package/dist/{config-center → web-admin-client}/read-face.js +4 -4
  234. package/dist/web-admin-client/read-warnings.d.ts +137 -0
  235. package/dist/web-admin-client/read-warnings.js +168 -0
  236. package/dist/{config-center → web-admin-client}/restart-signal.d.ts +5 -3
  237. package/dist/{config-center → web-admin-client}/restart-signal.js +3 -4
  238. package/dist/{config-center → web-admin-client}/skills-mcp.d.ts +1 -1
  239. package/dist/{config-center → web-admin-client}/skills-mcp.js +13 -13
  240. package/dist/{config-center → web-admin-client}/stage-limits.d.ts +1 -7
  241. package/dist/{config-center → web-admin-client}/stage-limits.js +6 -7
  242. package/dist/{config-center → web-admin-client}/types.d.ts +19 -47
  243. package/package.json +3 -3
  244. package/skills/find-skills.md +2 -2
  245. package/dist/config-center/read-warnings.d.ts +0 -109
  246. package/dist/config-center/read-warnings.js +0 -110
  247. package/dist/url-shape.d.ts +0 -31
  248. package/dist/url-shape.js +0 -41
  249. /package/dist/{config-center → web-admin-client}/apply-ledger.js +0 -0
  250. /package/dist/{config-center → web-admin-client}/hot-keys-registry.d.ts +0 -0
  251. /package/dist/{config-center → web-admin-client}/hot-keys-registry.js +0 -0
  252. /package/dist/{config-center → web-admin-client}/mcp-revocation.d.ts +0 -0
  253. /package/dist/{config-center → web-admin-client}/mcp-revocation.js +0 -0
  254. /package/dist/{config-center → web-admin-client}/pull-state.js +0 -0
  255. /package/dist/{config-center → web-admin-client}/read-face.d.ts +0 -0
  256. /package/dist/{config-center → web-admin-client}/types.js +0 -0
@@ -1,10 +1,11 @@
1
- import { promises as fs, lstatSync, realpathSync } from "node:fs";
2
- import { basename, join, dirname, resolve } from "node:path";
1
+ import { promises as fs } from "node:fs";
2
+ import { migrateEffectiveSnapshot } from "@sema-agent/settings-schema/one-time-migrations";
3
+ import { formatConfigPath } from "@sema-agent/settings-schema";
4
+ import { join, dirname, resolve } from "node:path";
3
5
  import { randomBytes } from "node:crypto";
4
6
  import { validatePromptsDomain } from "./prompts-domain-validate.js";
5
7
  import { centerStateBin, pullTokenIdentity } from "./center-credential.js";
6
8
  import { configRootOf } from "./sema-config-dir.js";
7
- import { recordFailOpen } from "./observability/fail-open.js";
8
9
  export function defaultSkillCacheDir(config) {
9
10
  return join(configRootOf(config), "skill-cache");
10
11
  }
@@ -23,41 +24,10 @@ export function lkgPathOverrideOf(raw) {
23
24
  export function lkgReadDenyRows(configLkgPath) {
24
25
  if (configLkgPath === undefined)
25
26
  return [];
26
- return [...new Set([configLkgPath, landedPathOf(configLkgPath)])].map((pattern) => ({ pattern, caseSensitive: false }));
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
- }
27
+ return [{ pattern: configLkgPath, caseSensitive: false }];
58
28
  }
59
29
  export async function saveLkg(path, worker, identity, effective, etag) {
60
- const body = { formatVersion: 2, savedAt: new Date().toISOString(), worker: worker ?? "global", identity, ...(etag !== undefined ? { etag } : {}), effective };
30
+ const body = { formatVersion: 4, savedAt: new Date().toISOString(), worker: worker ?? "global", identity, ...(etag !== undefined ? { etag } : {}), effective };
61
31
  const tmp = `${path}.${randomBytes(6).toString("hex")}.tmp`;
62
32
  await fs.mkdir(dirname(path), { recursive: true });
63
33
  await fs.writeFile(tmp, JSON.stringify(body), { mode: 0o600 });
@@ -84,14 +54,73 @@ export async function loadLkg(path, worker, identity) {
84
54
  const formatVersion = p.formatVersion;
85
55
  if (formatVersion === 1)
86
56
  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)
57
+ if (formatVersion !== 2 && formatVersion !== 3 && formatVersion !== 4)
88
58
  return { reason: `unknown formatVersion ${String(formatVersion)}` };
89
59
  if (typeof p.worker !== "string" || p.worker !== (worker ?? "global"))
90
60
  return { reason: `worker mismatch (file=${String(p.worker)})` };
91
61
  if (typeof p.identity !== "string" || p.identity !== identity)
92
62
  return { reason: "credential identity mismatch (the LKG was fetched under another credential identity — not read back)" };
93
- const problem = lkgPayloadProblem(p.effective, p.etag);
94
- return problem === undefined ? { lkg: p } : { reason: problem };
63
+ if (p.effective === null || typeof p.effective !== "object" || Array.isArray(p.effective))
64
+ return { reason: "bad effective" };
65
+ let envelope = p;
66
+ let note;
67
+ if (formatVersion === 2) {
68
+ const v2 = migrateV2Lkg(envelope);
69
+ if (v2.lkg === undefined)
70
+ return v2;
71
+ envelope = v2.lkg;
72
+ note = v2.migrated;
73
+ }
74
+ const payload = migrateLkgPayload(envelope.effective);
75
+ if ("refused" in payload)
76
+ return { reason: payload.refused };
77
+ const problem = lkgPayloadProblem(payload.effective, envelope.etag);
78
+ if (problem !== undefined)
79
+ return { reason: problem };
80
+ const lkg = { ...envelope, formatVersion: 4, effective: payload.effective };
81
+ const migrated = formatVersion !== 4 || payload.receipts.length > 0;
82
+ return migrated ? { lkg, migrated: { fromFormat: formatVersion, ...(note !== undefined ? { note } : {}), receipts: payload.receipts } } : { lkg };
83
+ }
84
+ export function migrateLkgPayload(effective) {
85
+ const m = migrateEffectiveSnapshot(effective);
86
+ const refused = m.receipts.filter((r) => r.appliedAs === "refused");
87
+ if (refused.length > 0) {
88
+ return {
89
+ refused: "settings-schema one-time migration refused part of this LKG's payload (" +
90
+ refused.map((r) => `${r.migration} ${r.document}:${formatConfigPath(r.path)} — ${r.reason}`).join("; ") +
91
+ ") — not read back: the engine applies an LKG without the contract's reader, so a form the migration cannot rewrite would be silently skipped; the next clean candidate rewrites it",
92
+ };
93
+ }
94
+ return { effective: m.effective, receipts: m.receipts };
95
+ }
96
+ const RETIRED_CATALOG_COORDINATE = /^models\.(0|[1-9][0-9]*)$/;
97
+ function migrateDroppedIdentityRow(row) {
98
+ if (row === null || typeof row !== "object")
99
+ return row;
100
+ const r = row;
101
+ const at = typeof r.entry === "string" ? RETIRED_CATALOG_COORDINATE.exec(r.entry) : null;
102
+ const fields = r.fields;
103
+ 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")
104
+ return row;
105
+ 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 };
106
+ }
107
+ function migrateV2Lkg(lkg) {
108
+ const { etag: _incompleteCarrierValidator, ...envelope } = lkg;
109
+ const models = lkg.effective.models;
110
+ const hasRetired = models !== undefined && models !== null && typeof models === "object" && Object.hasOwn(models, "droppedIdentities");
111
+ let effective = lkg.effective;
112
+ if (hasRetired) {
113
+ const { droppedIdentities: retired, ...rest } = models;
114
+ if (Object.hasOwn(rest, "droppedCatalogEntries")) {
115
+ 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" };
116
+ }
117
+ effective = { ...lkg.effective, models: { ...rest, droppedCatalogEntries: Array.isArray(retired) ? retired.map(migrateDroppedIdentityRow) : retired } };
118
+ }
119
+ return {
120
+ lkg: { ...envelope, effective },
121
+ 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" +
122
+ (hasRetired ? "; the retired carrier models.droppedIdentities was moved to models.droppedCatalogEntries" : ""),
123
+ };
95
124
  }
96
125
  function lkgPayloadProblem(effective, etag) {
97
126
  if (effective === null || typeof effective !== "object")
@@ -101,7 +130,7 @@ function lkgPayloadProblem(effective, etag) {
101
130
  const eff = effective;
102
131
  if (typeof eff.version !== "number")
103
132
  return "bad effective.version";
104
- for (const [domain, arrayKey] of [["models", "models"], ["skills", "skills"], ["mcp", "servers"], ["scenarios", "scenarios"], ["runtime", null]]) {
133
+ for (const [domain, arrayKey] of [["models", "models"], ["skills", "skills"], ["mcp", "servers"], ["scenarios", "scenarios"], ["limits", null]]) {
105
134
  const v = eff[domain];
106
135
  if (v === undefined)
107
136
  continue;
@@ -113,12 +142,6 @@ function lkgPayloadProblem(effective, etag) {
113
142
  return `bad effective.${domain}.${arrayKey}`;
114
143
  }
115
144
  }
116
- {
117
- const rt = eff.runtime;
118
- if (rt && (rt.autonomy !== undefined || rt.commandPolicy !== undefined || rt.approvalRequire !== undefined)) {
119
- return "legacy runtime governance keys (pre-0.7.1 mirror shape; no contract producer since LKG shipped) — refusing rather than silently dropping governance";
120
- }
121
- }
122
145
  const promptsRaw = eff.prompts;
123
146
  if (promptsRaw !== undefined && !validatePromptsDomain(promptsRaw).ok)
124
147
  return "prompts face fails re-validation";
@@ -169,7 +192,12 @@ export async function migrateV1Lkg(o) {
169
192
  if (o.identity !== pullTokenIdentity(o.worker)) {
170
193
  return refuse("its envelope records only the worker, and only a pull-token credential's identity (= the worker) can be derived from that — the current credential is not this worker's pull token, so the file cannot prove whose credential fetched it");
171
194
  }
172
- const problem = lkgPayloadProblem(v1.effective, v1.etag);
195
+ if (v1.effective === null || typeof v1.effective !== "object" || Array.isArray(v1.effective))
196
+ return refuse("its payload is unusable (bad effective)");
197
+ const payload = migrateLkgPayload(v1.effective);
198
+ if ("refused" in payload)
199
+ return refuse(`its payload cannot be migrated to the current settings form (${payload.refused})`);
200
+ const problem = lkgPayloadProblem(payload.effective, v1.etag);
173
201
  if (problem !== undefined)
174
202
  return refuse(`its payload is unusable (${problem})`);
175
203
  const retiredTo = `${o.legacyPath}.migrated-v1`;
@@ -183,7 +211,7 @@ export async function migrateV1Lkg(o) {
183
211
  }
184
212
  }
185
213
  try {
186
- await saveLkg(o.binPath, o.worker, o.identity, v1.effective, typeof v1.etag === "string" ? v1.etag : undefined);
214
+ await saveLkg(o.binPath, o.worker, o.identity, payload.effective, undefined);
187
215
  }
188
216
  catch (err) {
189
217
  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`);
@@ -1,10 +1,10 @@
1
- import { type DroppedConfigEntry } from "./config-center/read-warnings.js";
1
+ import { type DroppedConfigEntry } from "./web-admin-client/read-warnings.js";
2
2
  import { FileConfigStore } from "@sema-agent/settings-schema/node";
3
3
  import { type EffectiveConfig as AgentConfigEffective, type EffectiveReadWarning } from "@sema-agent/settings-schema";
4
- import { fetchEffective as remoteFetchEffective, fetchSkillContent as remoteFetchSkillContent, type EffectiveConfig } from "./config-center/facade.js";
5
- import type { CenterEndpoint } from "./config-center/center-request.js";
4
+ import { fetchEffective as remoteFetchEffective, fetchSkillContent as remoteFetchSkillContent, type EffectiveConfig } from "./web-admin-client/facade.js";
5
+ import type { CenterEndpoint } from "./web-admin-client/center-request.js";
6
6
  import type { ConfigProviderWord } from "./config-types.js";
7
- /** Result of a `fetchEffective` — EXACTLY the config-center's return: the effective config + its etag, or
7
+ /** Result of a `fetchEffective` — EXACTLY the web-admin's return: the effective config + its etag, or
8
8
  * `null` for "unchanged" (remote 304; local: the version matched the caller's prior etag).
9
9
  * `domainErrors`([ref] registry-core 0.10.12 tolerant seam,local lane only):catalog 域坏文件不再
10
10
  * 连坐全包回落 env——坏域按该域 schema default 落+错误单列,好域照常生效;caller(main.ts)对每条打
@@ -13,17 +13,16 @@ import type { ConfigProviderWord } from "./config-types.js";
13
13
  /** 壳写在 `config.d/models.json` 条目上的装饰键(`sema*`)自 settings-schema 1.5.0 起是**声明过的扩展命名空间**
14
14
  * (`EXTENSION_NAMESPACES`):schema 照旧 strip、但不再报「未知键」,所以本函数收到的每一个未知键都是拼错/越界 ⇒ 候选门错误。
15
15
  * 此前把这类键当「通知」放行的整套下游机制(域豁免/键路径闭集/满额特判/单独的通知面)已全部撤回——意图在声明处说,消费方不猜。 */
16
- /** `readWarnings`:契约 `onWarning` 流的**原值**(未折叠),两条读腿同键同义。折叠是有损的——
17
- * `hosts-grandfathered` / `legacy-governance-lifted` 按律折成 `null`,只看 `domainErrors` 的人永远看不见
18
- * 兼容臂还开着,而契约铸出 `legacy-governance-lifted` 的理由正是「关窗的前提是有人知道它还开着」
19
- * (`legacyGovernanceFromRuntime` SUNSET 注)。恒在场(空数组 = 这次读零告警),不用缺席表达「没有」
16
+ /** `readWarnings`:契约 `onWarning` 流的**原值**(未折叠),两条读腿同键同义 —— 读者是一致性门的读腿适配器(它要逐条对契约语料的
17
+ * 告警多重集,折叠后的诊断面带不回 `kind` / 坐标段)。恒在场(空数组 = 这次读零告警),不用缺席表达「没有」
20
18
  * ——缺席/空两形并存就是又一处二义。
21
19
  * 🔐 原流的 `error` 未经 {@link redactConfigError}(那道脱敏挂在真正进日志流的 `domainErrors` 产出边界上),
22
20
  * 路由进日志/审计流的消费者必须自己先脱敏。 */
23
21
  /** `credentialIdentity`(S-651 / [ref] E-15):远程腿恒在场 = 这次拉取所用凭证的身份(分箱键来源);本地腿
24
22
  * 缺席(没有凭证 —— config.d 就在本机盘上)。 */
25
- /** `droppedEntries`(S-704 ②):schema 逐条丢掉的条目(坐标 + 字段诊断,已脱敏)—— **不**进候选门,调用方逐条响亮
26
- * 点名、其余照用;缺席 = 这次读零逐条丢弃(与 `domainErrors` 同一种缺席即无的形)。 */
23
+ /** `droppedEntries`(S-704 ②):schema 逐条丢掉的条目(坐标 + 字段诊断,已脱敏;S-1295 起每行带闭集词 `reasonCode`)—— **不**进候选门,
24
+ * 调用方逐条响亮点名、其余照用;缺席 = 这次读零逐条丢弃(与 `domainErrors` 同一种缺席即无的形)。其中的目录条目同一次折叠另记进
25
+ * `effective.models.droppedCatalogEntries`(`GET /v1/models.droppedEntries` 的源,与 `models` 同世代)。 */
27
26
  export type FetchEffectiveResult = {
28
27
  effective: EffectiveConfig;
29
28
  etag?: string;
@@ -51,6 +50,12 @@ export type FetchEffectiveResult = {
51
50
  * 不回声值(上游 settings-schema)。
52
51
  */
53
52
  export declare function redactConfigError(text: string): string;
53
+ /**
54
+ * 一个配置值的单向短指纹(`#` + 8 位十六进制;HMAC 的钥匙每进程一把 —— 只在同一条日志流里可对照,不是一份可查字典的摘要)。
55
+ * 句子由契约从**结构化操作数**铸的地方(settings-schema 11 的 `renderRefIssue(issue, show)`)把它当 `show` 传进去:值逐个换成指纹,
56
+ * 句子的固定词与坐标原样 —— 不需要 {@link redactConfigError} 那种从引号猜值边界的读法。
57
+ */
58
+ export declare function fingerprintConfigOperand(operand: string): string;
54
59
  /** Sentinel returned by {@link raceBootFetch} when the boot pull outlived its budget — the caller
55
60
  * starts serving on the env fallback and the SAME promise settles in the background (never cancelled). */
56
61
  export declare const BOOT_FETCH_DEFERRED: unique symbol;
@@ -70,7 +75,7 @@ export declare function raceBootFetch<T>(fetch: Promise<T>, budgetMs: number): P
70
75
  * et al. (main.ts does not swap on this seam yet — see the NOT-YET-WIRED note at the top of this module).
71
76
  */
72
77
  export interface ConfigProvider {
73
- /** "remote" = config-center HTTP; "local" = on-disk FileConfigStore. */
78
+ /** "remote" = web-admin HTTP; "local" = on-disk FileConfigStore. */
74
79
  readonly kind: "remote" | "local";
75
80
  /**
76
81
  * Pull the effective config. `etag` is the caller's last-seen version token (`if-none-match` on remote;
@@ -89,10 +94,10 @@ export interface ConfigProvider {
89
94
  /** The config-provider knobs read off ServiceConfig (a structural subset — avoids importing the whole
90
95
  * ServiceConfig type and keeps this module testable with a plain object). */
91
96
  export interface ConfigProviderInput {
92
- /** Set when SEMA_REGISTRY_URL (legacy CONFIG_CENTER_URL now boot-rejects, no dual-read) is configured (config.ts `configCenter`). `dryRun` is carried through so a
97
+ /** Set when SEMA_WEB_ADMIN_URL is configured (config.ts `webAdmin`). `dryRun` is carried through so a
93
98
  * remote↔local swap via this seam does NOT drop the dry-run posture main.ts branches on (config.ts
94
- * `configCenter.dryRun`); the provider itself does not consume it (the caller still branches on it). */
95
- configCenter?: CenterEndpoint & {
99
+ * `webAdmin.dryRun`); the provider itself does not consume it (the caller still branches on it). */
100
+ webAdmin?: CenterEndpoint & {
96
101
  worker?: string;
97
102
  dryRun?: boolean;
98
103
  };
@@ -107,10 +112,10 @@ export interface ConfigProviderInput {
107
112
  localDir: string;
108
113
  }
109
114
  /**
110
- * RemoteConfigProvider — DELEGATES to the exported config-center HTTP functions. No HTTP is reimplemented;
115
+ * RemoteConfigProvider — DELEGATES to the exported web-admin HTTP functions. No HTTP is reimplemented;
111
116
  * the center endpoint (baseUrl + credential SOURCE — S-651: read per request, never a bound token) and worker
112
117
  * are passed through. The two delegate fns are injectable (defaulting
113
- * to the real config-center exports) so a unit test can assert delegation without module-mocking.
118
+ * to the real web-admin exports) so a unit test can assert delegation without module-mocking.
114
119
  */
115
120
  export declare class RemoteConfigProvider implements ConfigProvider {
116
121
  private readonly cc;
@@ -155,7 +160,7 @@ export declare class LocalConfigProvider implements ConfigProvider {
155
160
  export declare function mapToServiceEffective(eff: AgentConfigEffective, version: number): EffectiveConfig;
156
161
  /**
157
162
  * Pick the backend off a CLOSED `provider` enum (`local` | `remote` | undefined): LOCAL when
158
- * `CONFIG_PROVIDER=local`, OR when no config-center URL is configured (a lone box with config.d/ on disk
163
+ * `CONFIG_PROVIDER=local`, OR when no web-admin URL is configured (a lone box with config.d/ on disk
159
164
  * and no control plane). REMOTE otherwise (a configured center URL, the default fleet posture). A
160
165
  * `CONFIG_PROVIDER=remote` with no URL is a misconfiguration — we fall through to local rather than
161
166
  * constructing a remote provider with no endpoint (the caller would have skipped the remote pull entirely
@@ -167,7 +172,7 @@ export declare function mapToServiceEffective(eff: AgentConfigEffective, version
167
172
  export declare function createConfigProvider(input: ConfigProviderInput): ConfigProvider;
168
173
  /**
169
174
  * S-841 —— **本地配置根的唯一来源**:`CONFIG_LOCAL_DIR` → `AGENT_DATA_DIR` → `~/.ai-agent`。两个入口(HTTP 服务的第 1 段、
170
- * run-local)各调一次,算出来的那一个值同时交给 config-center 工厂(`createConfigProvider` 的 `localDir`)与执行车道合成步
175
+ * run-local)各调一次,算出来的那一个值同时交给 web-admin 工厂(`createConfigProvider` 的 `localDir`)与执行车道合成步
171
176
  * (`composeExecutionLane` 的 `localRoot`)—— 修前两个入口各写一份这条链(run-local 还多一个与之等价的三元),工厂又在
172
177
  * 字面 `"local"` 之外回落 `process.cwd()`。
173
178
  *
@@ -184,14 +189,14 @@ export declare function configLocalRoot(config: {
184
189
  */
185
190
  export declare function configProviderKind(input: {
186
191
  readonly provider?: ConfigProviderWord | undefined;
187
- readonly configCenter?: unknown;
192
+ readonly webAdmin?: unknown;
188
193
  }): "local" | "remote";
189
194
  /**
190
- * HTTP 服务这一侧的配置源:config-center 工厂**建不建** provider(`CONFIG_PROVIDER=local` 或配了中心才建)、建出来是哪一种。
195
+ * HTTP 服务这一侧的配置源:web-admin 工厂**建不建** provider(`CONFIG_PROVIDER=local` 或配了中心才建)、建出来是哪一种。
191
196
  * `undefined` = 纯 env 部署(没有配置源)。工厂与执行车道合成步读这同一只(车PI 修复轮 ①:合成步排在工厂之前)。
192
197
  */
193
198
  export declare function serviceConfigSourceKind(config: {
194
199
  readonly configProvider?: ConfigProviderWord | undefined;
195
- readonly configCenter?: unknown;
200
+ readonly webAdmin?: unknown;
196
201
  }): "local" | "remote" | undefined;
197
202
  //# sourceMappingURL=config-provider.d.ts.map
@@ -1,10 +1,10 @@
1
1
  import { readMcpSourceLabel } from "./mcp-source-label.js";
2
2
  import { createHmac, randomBytes } from "node:crypto";
3
- import { splitFoldedReadWarnings, withDroppedIdentities } from "./config-center/read-warnings.js";
3
+ import { splitFoldedReadWarnings, withDroppedCatalogEntries } from "./web-admin-client/read-warnings.js";
4
4
  import { FileConfigStore } from "@sema-agent/settings-schema/node";
5
- import { findSkillContent, skillContentHash, refIntegrityIssues, createSiblingResolver, formatConfigPath, REF_CHECKED_DOMAINS, } from "@sema-agent/settings-schema";
5
+ import { danglingRefs, findSkillContent, renderRefIssue, skillContentHash, } from "@sema-agent/settings-schema";
6
6
  import { redactSecrets } from "./trace/redact.js";
7
- import { fetchEffective as remoteFetchEffective, fetchSkillContent as remoteFetchSkillContent, ConfigCenterHttpError, } from "./config-center/facade.js";
7
+ import { fetchEffective as remoteFetchEffective, fetchSkillContent as remoteFetchSkillContent, WebAdminHttpError, } from "./web-admin-client/facade.js";
8
8
  import { homedir } from "node:os";
9
9
  import { join } from "node:path";
10
10
  const OPERAND_FINGERPRINT_KEY = randomBytes(16);
@@ -14,12 +14,16 @@ export function redactConfigError(text) {
14
14
  if (first === -1)
15
15
  return s;
16
16
  const count = (q) => s.split(q).length - 1;
17
- const fingerprint = (operand) => `"#${createHmac("sha256", OPERAND_FINGERPRINT_KEY).update(operand).digest("hex").slice(0, 8)}"`;
17
+ const fingerprint = (operand) => `"${fingerprintConfigOperand(operand)}"`;
18
18
  if (count('"') % 2 === 1 || count("'") % 2 === 1)
19
19
  return `${s.slice(0, first)}${fingerprint(s.slice(first + 1))}`;
20
20
  const last = Math.max(s.lastIndexOf('"'), s.lastIndexOf("'"));
21
21
  return `${s.slice(0, first)}${fingerprint(s.slice(first + 1, last))}${s.slice(last + 1)}`;
22
22
  }
23
+ export function fingerprintConfigOperand(operand) {
24
+ return `#${createHmac("sha256", OPERAND_FINGERPRINT_KEY).update(operand).digest("hex").slice(0, 8)}`;
25
+ }
26
+ const redactDroppedEntry = (d) => ({ ...d, error: redactSecrets(d.error) });
23
27
  export const BOOT_FETCH_DEFERRED = Symbol("boot-fetch-deferred");
24
28
  export function raceBootFetch(fetch, budgetMs) {
25
29
  if (budgetMs <= 0)
@@ -47,7 +51,7 @@ export class RemoteConfigProvider {
47
51
  return {
48
52
  ...r,
49
53
  ...(r.domainErrors !== undefined ? { domainErrors: r.domainErrors.map((de) => ({ domain: de.domain, error: redactConfigError(de.error) })) } : {}),
50
- ...(r.droppedEntries !== undefined ? { droppedEntries: r.droppedEntries.map((d) => ({ ...d, error: redactConfigError(d.error) })) } : {}),
54
+ ...(r.droppedEntries !== undefined ? { droppedEntries: r.droppedEntries.map(redactDroppedEntry) } : {}),
51
55
  };
52
56
  }
53
57
  async fetchSkillContent(contentHash) {
@@ -56,7 +60,7 @@ export class RemoteConfigProvider {
56
60
  return await fn(this.cc, contentHash);
57
61
  }
58
62
  catch (err) {
59
- if (err instanceof ConfigCenterHttpError && err.status === 404)
63
+ if (err instanceof WebAdminHttpError && err.status === 404)
60
64
  return undefined;
61
65
  throw err;
62
66
  }
@@ -85,18 +89,20 @@ export class LocalConfigProvider {
85
89
  if (etag !== undefined && etag === tag)
86
90
  return null;
87
91
  const refErrors = [];
88
- const resolve = createSiblingResolver(store, eff);
89
- for (const d of REF_CHECKED_DOMAINS) {
90
- const issues = await refIntegrityIssues(d, eff[d], resolve);
91
- if (issues.length > 0)
92
- refErrors.push({ domain: d, error: issues.map((i) => `${formatConfigPath(i.path)}: ${redactConfigError(i.message)}`).join("; ") });
92
+ const byReferrer = new Map();
93
+ for (const issue of danglingRefs(eff)) {
94
+ const rows = byReferrer.get(issue.referrer.domain) ?? [];
95
+ rows.push(renderRefIssue(issue, fingerprintConfigOperand));
96
+ byReferrer.set(issue.referrer.domain, rows);
93
97
  }
98
+ for (const [domain, rows] of byReferrer)
99
+ refErrors.push({ domain, error: rows.join("; ") });
94
100
  const folded = splitFoldedReadWarnings(readWarnings);
95
101
  const parseErrors = folded.domainErrors.map((w) => ({ domain: w.domain, error: redactConfigError(w.error) }));
96
- const droppedEntries = folded.droppedEntries.map((d) => ({ ...d, error: redactConfigError(d.error) }));
102
+ const droppedEntries = folded.droppedEntries.map(redactDroppedEntry);
97
103
  const errors = [...domainErrors.map((de) => ({ domain: de.domain, error: redactConfigError(de.error) })), ...parseErrors, ...refErrors];
98
104
  return {
99
- effective: withDroppedIdentities(mapToServiceEffective(eff, eff.version), folded.droppedIdentities),
105
+ effective: withDroppedCatalogEntries(mapToServiceEffective(eff, eff.version), folded.droppedCatalogEntries),
100
106
  etag: tag,
101
107
  readWarnings,
102
108
  ...(errors.length > 0 ? { domainErrors: errors } : {}),
@@ -139,8 +145,7 @@ export function mapToServiceEffective(eff, version) {
139
145
  enabled: m.enabled,
140
146
  })),
141
147
  roles: eff.models.roles ?? {},
142
- ...(eff.models.default !== undefined ? { default: eff.models.default } : {}),
143
- ...(eff.models.atModelAllowlist !== undefined ? { atModelAllowlist: eff.models.atModelAllowlist } : {}),
148
+ atMention: eff.models.atMention,
144
149
  ...(eff.models.tierGroups !== undefined ? { tierGroups: eff.models.tierGroups } : {}),
145
150
  ...(eff.models.activeTierGroup !== undefined ? { activeTierGroup: eff.models.activeTierGroup } : {}),
146
151
  },
@@ -199,13 +204,6 @@ export function mapToServiceEffective(eff, version) {
199
204
  enabled: sc.enabled,
200
205
  })),
201
206
  },
202
- runtime: {
203
- ...(eff.runtime.rateLimitPerMin !== undefined ? { rateLimitPerMin: eff.runtime.rateLimitPerMin } : {}),
204
- ...(eff.runtime.maxTaskCostUsd !== undefined ? { maxTaskCostUsd: eff.runtime.maxTaskCostUsd } : {}),
205
- ...(eff.runtime.maxTaskTokens !== undefined ? { maxTaskTokens: eff.runtime.maxTaskTokens } : {}),
206
- ...(eff.runtime.maxPrincipalCostUsd !== undefined ? { maxPrincipalCostUsd: eff.runtime.maxPrincipalCostUsd } : {}),
207
- ...(eff.runtime.costQuotaWindowSec !== undefined ? { costQuotaWindowSec: eff.runtime.costQuotaWindowSec } : {}),
208
- },
209
207
  ...(eff.limits !== undefined ? { limits: eff.limits } : {}),
210
208
  governance: {
211
209
  ...(eff.governance.autonomy !== undefined ? { autonomy: eff.governance.autonomy } : {}),
@@ -215,21 +213,21 @@ export function mapToServiceEffective(eff, version) {
215
213
  };
216
214
  }
217
215
  export function createConfigProvider(input) {
218
- return configProviderKind(input) === "remote" && input.configCenter !== undefined
219
- ? new RemoteConfigProvider(input.configCenter)
216
+ return configProviderKind(input) === "remote" && input.webAdmin !== undefined
217
+ ? new RemoteConfigProvider(input.webAdmin)
220
218
  : new LocalConfigProvider(input.localDir);
221
219
  }
222
220
  export function configLocalRoot(config) {
223
221
  return config.configLocalDir ?? process.env.AGENT_DATA_DIR ?? join(homedir(), ".ai-agent");
224
222
  }
225
223
  export function configProviderKind(input) {
226
- if (input.provider === "local" || input.configCenter === undefined)
224
+ if (input.provider === "local" || input.webAdmin === undefined)
227
225
  return "local";
228
226
  return "remote";
229
227
  }
230
228
  export function serviceConfigSourceKind(config) {
231
- if (config.configCenter === undefined && config.configProvider !== "local")
229
+ if (config.webAdmin === undefined && config.configProvider !== "local")
232
230
  return undefined;
233
- return configProviderKind({ provider: config.configProvider, configCenter: config.configCenter });
231
+ return configProviderKind({ provider: config.configProvider, webAdmin: config.webAdmin });
234
232
  }
235
233
  //# sourceMappingURL=config-provider.js.map