@sema-agent/server 1.222.0 → 1.224.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/dist/capabilities/center-prompts.d.ts.map +1 -1
- package/dist/capabilities/center-prompts.js +6 -2
- package/dist/capabilities/center-prompts.js.map +1 -1
- package/dist/config-lkg.d.ts +17 -0
- package/dist/config-lkg.d.ts.map +1 -0
- package/dist/config-lkg.js +72 -0
- package/dist/config-lkg.js.map +1 -0
- package/dist/main.js +115 -8
- package/dist/main.js.map +1 -1
- package/dist/plugins/roster-store-sql.d.ts +28 -0
- package/dist/plugins/roster-store-sql.d.ts.map +1 -0
- package/dist/plugins/roster-store-sql.js +137 -0
- package/dist/plugins/roster-store-sql.js.map +1 -0
- package/dist/sema-registry.d.ts +2 -2
- package/dist/sema-registry.d.ts.map +1 -1
- package/dist/sema-registry.js +38 -6
- package/dist/sema-registry.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"center-prompts.d.ts","sourceRoot":"","sources":["../../src/capabilities/center-prompts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"center-prompts.d.ts","sourceRoot":"","sources":["../../src/capabilities/center-prompts.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAI9E,MAAM,WAAW,sBAAsB;IAErC,MAAM,EAAE,MAAM,CAAC;IAEf,aAAa,EAAE,MAAM,CAAC;IAEtB,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAElC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;CAC7D;AA4BD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,sBAAsB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAmC9H;AAOD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,GAAG,cAAc,CAK1G"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
const ID_RE = /^[a-z0-9][a-z0-9/._-]*$/;
|
|
2
3
|
const SLOTS = new Set(["identity", "scenario", "behavior"]);
|
|
3
4
|
const HASH_RE = /^sha256:[0-9a-f]{64}$/;
|
|
@@ -13,8 +14,11 @@ function declarationIssue(d, where) {
|
|
|
13
14
|
return `${where}: bad slot`;
|
|
14
15
|
if (typeof o.text !== "string" || o.text.length === 0)
|
|
15
16
|
return `${where}: text must be a non-empty string`;
|
|
16
|
-
if (
|
|
17
|
-
return `${where}:
|
|
17
|
+
if (typeof o.contentHash !== "string" || !HASH_RE.test(o.contentHash))
|
|
18
|
+
return `${where}: contentHash is required (sha256:<64hex> — the epoch declaration axis needs it for byte-level change detection)`;
|
|
19
|
+
const expected = `sha256:${createHash("sha256").update(o.text).digest("hex")}`;
|
|
20
|
+
if (o.contentHash !== expected)
|
|
21
|
+
return `${where}: contentHash does not match sha256(text) — stale or tampered declaration`;
|
|
18
22
|
return undefined;
|
|
19
23
|
}
|
|
20
24
|
export function validateCenterPrompts(raw) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"center-prompts.js","sourceRoot":"","sources":["../../src/capabilities/center-prompts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"center-prompts.js","sourceRoot":"","sources":["../../src/capabilities/center-prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface PersistedLkg {
|
|
2
|
+
formatVersion: 1;
|
|
3
|
+
savedAt: string;
|
|
4
|
+
worker: string;
|
|
5
|
+
etag?: string;
|
|
6
|
+
effective: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export declare function defaultSkillCacheDir(): string;
|
|
9
|
+
export declare function defaultLkgPath(worker: string | undefined): string;
|
|
10
|
+
export declare function saveLkg(path: string, worker: string | undefined, effective: Record<string, unknown>, etag: string | undefined): Promise<void>;
|
|
11
|
+
export declare function loadLkg(path: string, worker: string | undefined): Promise<{
|
|
12
|
+
lkg: PersistedLkg;
|
|
13
|
+
} | {
|
|
14
|
+
lkg?: undefined;
|
|
15
|
+
reason: string;
|
|
16
|
+
}>;
|
|
17
|
+
//# sourceMappingURL=config-lkg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-lkg.d.ts","sourceRoot":"","sources":["../src/config-lkg.ts"],"names":[],"mappings":"AA2BA,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,CAAC,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAKD,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAID,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAIjE;AAID,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAMnJ;AAMD,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,GAAG,CAAC,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA0C5I"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, dirname } from "node:path";
|
|
4
|
+
import { randomBytes } from "node:crypto";
|
|
5
|
+
import { validateCenterPrompts } from "./capabilities/center-prompts.js";
|
|
6
|
+
export function defaultSkillCacheDir() {
|
|
7
|
+
return join(process.env.SEMA_CONFIG_DIR ?? join(homedir(), ".sema"), "skill-cache");
|
|
8
|
+
}
|
|
9
|
+
export function defaultLkgPath(worker) {
|
|
10
|
+
const dir = process.env.SEMA_CONFIG_DIR ?? join(homedir(), ".sema");
|
|
11
|
+
const key = (worker ?? "global").replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 64);
|
|
12
|
+
return join(dir, `config-lkg-${key}.json`);
|
|
13
|
+
}
|
|
14
|
+
export async function saveLkg(path, worker, effective, etag) {
|
|
15
|
+
const body = { formatVersion: 1, savedAt: new Date().toISOString(), worker: worker ?? "global", ...(etag !== undefined ? { etag } : {}), effective };
|
|
16
|
+
const tmp = `${path}.${randomBytes(6).toString("hex")}.tmp`;
|
|
17
|
+
await fs.mkdir(dirname(path), { recursive: true });
|
|
18
|
+
await fs.writeFile(tmp, JSON.stringify(body), { mode: 0o600 });
|
|
19
|
+
await fs.rename(tmp, path);
|
|
20
|
+
}
|
|
21
|
+
export async function loadLkg(path, worker) {
|
|
22
|
+
let text;
|
|
23
|
+
try {
|
|
24
|
+
text = await fs.readFile(path, "utf8");
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return { reason: "absent" };
|
|
28
|
+
}
|
|
29
|
+
let parsed;
|
|
30
|
+
try {
|
|
31
|
+
parsed = JSON.parse(text);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { reason: "corrupt json" };
|
|
35
|
+
}
|
|
36
|
+
if (parsed === null || typeof parsed !== "object")
|
|
37
|
+
return { reason: "bad envelope" };
|
|
38
|
+
const p = parsed;
|
|
39
|
+
if (p.formatVersion !== 1)
|
|
40
|
+
return { reason: `unknown formatVersion ${String(p.formatVersion)}` };
|
|
41
|
+
if (typeof p.worker !== "string" || p.worker !== (worker ?? "global"))
|
|
42
|
+
return { reason: `worker mismatch (file=${String(p.worker)})` };
|
|
43
|
+
if (p.effective === null || typeof p.effective !== "object")
|
|
44
|
+
return { reason: "bad effective" };
|
|
45
|
+
if (p.etag !== undefined && typeof p.etag !== "string")
|
|
46
|
+
return { reason: "bad etag" };
|
|
47
|
+
const eff = p.effective;
|
|
48
|
+
if (typeof eff.version !== "number")
|
|
49
|
+
return { reason: "bad effective.version" };
|
|
50
|
+
for (const [domain, arrayKey] of [["models", "models"], ["teams", null], ["skills", "skills"], ["mcp", "servers"], ["scenarios", "scenarios"], ["runtime", null]]) {
|
|
51
|
+
const v = eff[domain];
|
|
52
|
+
if (v === undefined)
|
|
53
|
+
continue;
|
|
54
|
+
if (domain === "teams") {
|
|
55
|
+
if (!Array.isArray(v))
|
|
56
|
+
return { reason: "bad effective.teams" };
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (v === null || typeof v !== "object" || Array.isArray(v))
|
|
60
|
+
return { reason: `bad effective.${domain}` };
|
|
61
|
+
if (arrayKey !== null) {
|
|
62
|
+
const arr = v[arrayKey];
|
|
63
|
+
if (arr !== undefined && !Array.isArray(arr))
|
|
64
|
+
return { reason: `bad effective.${domain}.${arrayKey}` };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const promptsRaw = p.effective.prompts;
|
|
68
|
+
if (promptsRaw !== undefined && !validateCenterPrompts(promptsRaw).ok)
|
|
69
|
+
return { reason: "prompts face fails re-validation" };
|
|
70
|
+
return { lkg: p };
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=config-lkg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-lkg.js","sourceRoot":"","sources":["../src/config-lkg.ts"],"names":[],"mappings":"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"}
|
package/dist/main.js
CHANGED
|
@@ -2,7 +2,7 @@ import { readFileSync, existsSync, realpathSync } from "node:fs";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { loadRemoteExec } from "@sema-agent/registry-core/node";
|
|
5
|
-
import { Runner, TtlSessionStore, uuidv7, defaultTaskRegistry, combinePolicies, createDurableQuestionPolicy, createAllowDenyPolicy, tightenTaskSpec, isThinkingLevel, QUESTION_AWAITS_RESUME, FileWorkflowRunStore, InMemoryWorkflowRunStore, workflowsCapability, NodeLspManager, createFileWorkflowScriptStore, expandTiers, NodeExecutionEnv } from "@sema-agent/core";
|
|
5
|
+
import { Runner, TtlSessionStore, uuidv7, FileRosterStore, defaultTaskRegistry, combinePolicies, createDurableQuestionPolicy, createAllowDenyPolicy, tightenTaskSpec, isThinkingLevel, QUESTION_AWAITS_RESUME, FileWorkflowRunStore, InMemoryWorkflowRunStore, workflowsCapability, NodeLspManager, createFileWorkflowScriptStore, expandTiers, NodeExecutionEnv } from "@sema-agent/core";
|
|
6
6
|
import { PgMemoryEngineBackend, ensurePgMemoryEngineSchema } from "./plugins/memory-engine-pg.js";
|
|
7
7
|
import { TiDBMemoryEngineBackend, ensureTiDBMemoryEngineSchema } from "./plugins/memory-engine-tidb.js";
|
|
8
8
|
import { PgMemoryHistoryStore, ensurePgMemoryHistorySchema, PgMemorySyncStore, ensurePgMemorySyncSchema } from "./plugins/memory-sync-store-pg.js";
|
|
@@ -71,6 +71,8 @@ import { applyEffective, mutateInPlace, logEffectiveDiff, applyCenterSkills, res
|
|
|
71
71
|
import { ensureSealedKeyStore, reportExecutionPublicKey } from "./sealed-key.js";
|
|
72
72
|
import { createConfigProvider, raceBootFetch, BOOT_FETCH_DEFERRED } from "./config-provider.js";
|
|
73
73
|
import { validateCenterPrompts, centerPromptProvider } from "./capabilities/center-prompts.js";
|
|
74
|
+
import { defaultLkgPath, defaultSkillCacheDir, saveLkg, loadLkg } from "./config-lkg.js";
|
|
75
|
+
import { TiDBRosterStore, PgRosterStore, ensureTiDBRosterSchema, ensurePgRosterSchema } from "./plugins/roster-store-sql.js";
|
|
74
76
|
import { createPrincipalCapsClient, gateExecutionLane, scopedTokenNeedsWorker, applyObserverEnvOptIn } from "./runtime-caps-resolver.js";
|
|
75
77
|
import { applyRuntimeGovernance, stripDelegationTools } from "./runtime-governance.js";
|
|
76
78
|
import { parseTaskSettings, applyTaskSettings, coercePermissionMode, withPermissionMode, effectiveThinking } from "./task-settings.js";
|
|
@@ -175,20 +177,75 @@ async function main() {
|
|
|
175
177
|
centerPrompts = v.value;
|
|
176
178
|
};
|
|
177
179
|
let bootConfigPending;
|
|
180
|
+
const lkgEnabled = configProvider?.kind === "remote" && process.env.CONFIG_LKG_DISABLED !== "true";
|
|
181
|
+
const lkgPath = process.env.CONFIG_LKG_PATH ?? defaultLkgPath(cc?.worker);
|
|
182
|
+
let lkgBooted = false;
|
|
183
|
+
let bootLkgCandidate;
|
|
184
|
+
const persistLkgDurable = async (effectiveObj, etag) => {
|
|
185
|
+
if (!lkgEnabled)
|
|
186
|
+
return;
|
|
187
|
+
try {
|
|
188
|
+
if (effectiveObj.skills && config.configCenter) {
|
|
189
|
+
await applyCenterSkills([], effectiveObj.skills, config.configCenter.baseUrl, config.configCenter.token, logger, undefined, defaultSkillCacheDir());
|
|
190
|
+
}
|
|
191
|
+
await saveLkg(lkgPath, cc?.worker, effectiveObj, etag);
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
logger.warn("config_lkg_save_failed", { path: lkgPath, err: String(err), note: "durable persist failed — restart signal proceeds anyway (a dead disk + dead center double-fault can re-loop; fix the disk)" });
|
|
195
|
+
}
|
|
196
|
+
};
|
|
178
197
|
if (configProvider) {
|
|
179
198
|
const dryRun = cc?.dryRun ?? false;
|
|
199
|
+
const bootFromLkg = async (why) => {
|
|
200
|
+
if (!lkgEnabled || dryRun)
|
|
201
|
+
return null;
|
|
202
|
+
const read = await loadLkg(lkgPath, cc?.worker);
|
|
203
|
+
if (!read.lkg) {
|
|
204
|
+
if (read.reason !== "absent")
|
|
205
|
+
logger.warn("config_lkg_unusable", { path: lkgPath, reason: read.reason, note: "ignoring the on-disk LKG — env fallback serves; the cache rewrites on the next clean candidate" });
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
logger.info("config_loaded_lkg", { path: lkgPath, savedAt: read.lkg.savedAt, why, note: "booting from the persisted last-known-good (all restart-to-apply faces included) — the live pull continues in the background and reconciles on arrival" });
|
|
209
|
+
return { effective: read.lkg.effective, ...(read.lkg.etag !== undefined ? { etag: read.lkg.etag } : {}) };
|
|
210
|
+
};
|
|
211
|
+
const bootApplyLkgInline = (lkgR) => {
|
|
212
|
+
applyEffective(config, lkgR.effective, logger, { sealedKeys });
|
|
213
|
+
adoptCenterPrompts(lkgR.effective, "boot-lkg");
|
|
214
|
+
markRosterLanded(lkgR.effective);
|
|
215
|
+
effective = lkgR.effective;
|
|
216
|
+
latestEffective = lkgR.effective;
|
|
217
|
+
if (lkgR.etag !== undefined)
|
|
218
|
+
ccEtag = lkgR.etag;
|
|
219
|
+
const cfgModels = (lkgR.effective.models?.models ?? []).filter((m) => m.enabled !== false).length;
|
|
220
|
+
logger.info("config_loaded", { source: "lkg", version: lkgR.effective.version, worker: cc?.worker ?? "(global)", models: cfgModels });
|
|
221
|
+
};
|
|
180
222
|
try {
|
|
181
223
|
const bootFetch = configProvider.fetchEffective(undefined);
|
|
182
224
|
const raced = await raceBootFetch(bootFetch, config.configBootFetchBudgetMs);
|
|
225
|
+
let lkgFallback = null;
|
|
183
226
|
if (raced === BOOT_FETCH_DEFERRED) {
|
|
184
227
|
bootConfigPending = bootFetch;
|
|
185
228
|
bootFetch.catch(() => { });
|
|
229
|
+
lkgFallback = await bootFromLkg("boot fetch deferred (budget exceeded)");
|
|
230
|
+
lkgBooted = lkgFallback !== null;
|
|
186
231
|
logger.warn("config_boot_fetch_deferred", {
|
|
187
232
|
source: configProvider.kind,
|
|
188
233
|
budgetMs: config.configBootFetchBudgetMs,
|
|
189
|
-
|
|
234
|
+
lkg: lkgBooted,
|
|
235
|
+
note: lkgBooted
|
|
236
|
+
? "center slow — booting from the persisted LKG; the pull continues in the background and reconciles via the refresh path on arrival"
|
|
237
|
+
: "center slow/unreachable and no usable LKG — serving on the env fallback; the pull continues in the background (late-boot adoption on arrival). Raise CONFIG_BOOT_FETCH_BUDGET_MS to block boot instead.",
|
|
190
238
|
});
|
|
191
239
|
}
|
|
240
|
+
if (raced === BOOT_FETCH_DEFERRED && lkgFallback) {
|
|
241
|
+
try {
|
|
242
|
+
bootApplyLkgInline(lkgFallback);
|
|
243
|
+
}
|
|
244
|
+
catch (applyErr) {
|
|
245
|
+
lkgBooted = false;
|
|
246
|
+
logger.warn("config_lkg_apply_failed", { err: String(applyErr), note: "persisted LKG failed to apply — env fallback serves; the cache rewrites on the next clean candidate" });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
192
249
|
const r = raced === BOOT_FETCH_DEFERRED ? null : raced;
|
|
193
250
|
if (r) {
|
|
194
251
|
const bootPromptsRaw = r.effective.prompts;
|
|
@@ -208,6 +265,8 @@ async function main() {
|
|
|
208
265
|
effective = r.effective;
|
|
209
266
|
if (bootClean)
|
|
210
267
|
latestEffective = r.effective;
|
|
268
|
+
if (bootClean && !lkgBooted)
|
|
269
|
+
bootLkgCandidate = { effective: r.effective, etag: r.etag };
|
|
211
270
|
const cfgModels = (r.effective.models?.models ?? []).filter((m) => m.enabled !== false).length;
|
|
212
271
|
const cfgDir = configProvider.kind === "local" ? { dir: configProvider.root } : {};
|
|
213
272
|
logger.info("config_loaded", { source: configProvider.kind, version: r.effective.version, worker: cc?.worker ?? "(global)", models: cfgModels, ...cfgDir });
|
|
@@ -218,6 +277,17 @@ async function main() {
|
|
|
218
277
|
}
|
|
219
278
|
catch (err) {
|
|
220
279
|
logger.warn("config_source_unreachable_using_env", { source: configProvider.kind, err: String(err) });
|
|
280
|
+
const lkgFallback = await bootFromLkg(`boot fetch failed: ${String(err).slice(0, 120)}`);
|
|
281
|
+
if (lkgFallback) {
|
|
282
|
+
lkgBooted = true;
|
|
283
|
+
try {
|
|
284
|
+
bootApplyLkgInline(lkgFallback);
|
|
285
|
+
}
|
|
286
|
+
catch (applyErr) {
|
|
287
|
+
lkgBooted = false;
|
|
288
|
+
logger.warn("config_lkg_apply_failed", { err: String(applyErr), note: "persisted LKG failed to apply — env fallback serves" });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
221
291
|
}
|
|
222
292
|
}
|
|
223
293
|
if (!modelReadyState.ready)
|
|
@@ -333,6 +403,25 @@ async function main() {
|
|
|
333
403
|
else {
|
|
334
404
|
memoryEngine = memoryEngineBackendFor(config);
|
|
335
405
|
}
|
|
406
|
+
let rosterStore;
|
|
407
|
+
{
|
|
408
|
+
const mysqlPool = backend?.mysqlPool?.();
|
|
409
|
+
const pgPool = backend?.pgPool?.();
|
|
410
|
+
if (pgPool) {
|
|
411
|
+
const q = async (text, params) => { const r = await pgPool.query(text, params); return { rows: r.rows }; };
|
|
412
|
+
await ensurePgRosterSchema(q);
|
|
413
|
+
rosterStore = new PgRosterStore(q);
|
|
414
|
+
}
|
|
415
|
+
else if (mysqlPool) {
|
|
416
|
+
await ensureTiDBRosterSchema(mysqlPool);
|
|
417
|
+
rosterStore = new TiDBRosterStore(mysqlPool);
|
|
418
|
+
}
|
|
419
|
+
else if (backend?.kind === "local") {
|
|
420
|
+
rosterStore = new FileRosterStore(join(config.localDataRoot ?? localRoot, "roster.json"));
|
|
421
|
+
}
|
|
422
|
+
if (rosterStore)
|
|
423
|
+
logger.info("roster_store_enabled", { backend: pgPool ? "pg" : mysqlPool ? "tidb" : "file" });
|
|
424
|
+
}
|
|
336
425
|
const memoryExportBackend = config.memoryEngineBackend !== "file" ? memoryEngine?.backend : undefined;
|
|
337
426
|
const memoryLane = memoryEngineRemoteLanePosture(config);
|
|
338
427
|
if (config.memoryEngineBackend === "file" || !config.memoryEngineEnabled) {
|
|
@@ -725,6 +814,7 @@ async function main() {
|
|
|
725
814
|
warn: (msg, fields) => logger.warn(msg, fields),
|
|
726
815
|
});
|
|
727
816
|
const runnerDeps = {
|
|
817
|
+
...(rosterStore ? { rosterStore } : {}),
|
|
728
818
|
brain,
|
|
729
819
|
models: config.models,
|
|
730
820
|
roles: config.roles,
|
|
@@ -971,7 +1061,10 @@ async function main() {
|
|
|
971
1061
|
: undefined;
|
|
972
1062
|
let skills = loadSkills(config.skillsDir);
|
|
973
1063
|
if (effective?.skills && config.configCenter) {
|
|
974
|
-
skills = await applyCenterSkills(skills, effective.skills, config.configCenter.baseUrl, config.configCenter.token, logger);
|
|
1064
|
+
skills = await applyCenterSkills(skills, effective.skills, config.configCenter.baseUrl, config.configCenter.token, logger, undefined, process.env.CONFIG_LKG_DISABLED !== "true" ? defaultSkillCacheDir() : undefined);
|
|
1065
|
+
}
|
|
1066
|
+
if (bootLkgCandidate && lkgEnabled) {
|
|
1067
|
+
await saveLkg(lkgPath, cc?.worker, bootLkgCandidate.effective, bootLkgCandidate.etag).catch((err) => logger.warn("config_lkg_save_failed", { path: lkgPath, err: String(err), note: "boot LKG persist failed — next clean candidate rewrites" }));
|
|
975
1068
|
}
|
|
976
1069
|
if (effective?.mcp)
|
|
977
1070
|
config.mcpServers = resolveMcpServers(effective.mcp, logger);
|
|
@@ -1077,12 +1170,12 @@ async function main() {
|
|
|
1077
1170
|
if (configProvider) {
|
|
1078
1171
|
const ccRef = config.configCenter;
|
|
1079
1172
|
let refreshInFlight = false;
|
|
1080
|
-
const refreshTick = async () => {
|
|
1173
|
+
const refreshTick = async (prefetched) => {
|
|
1081
1174
|
if (refreshInFlight)
|
|
1082
1175
|
return;
|
|
1083
1176
|
refreshInFlight = true;
|
|
1084
1177
|
try {
|
|
1085
|
-
const r = await configProvider.fetchEffective(ccEtag);
|
|
1178
|
+
const r = prefetched !== undefined ? prefetched : await configProvider.fetchEffective(ccEtag);
|
|
1086
1179
|
if (r) {
|
|
1087
1180
|
const promptsRaw = r.effective.prompts;
|
|
1088
1181
|
const promptsGate = promptsRaw !== undefined ? validateCenterPrompts(promptsRaw) : { ok: true };
|
|
@@ -1114,9 +1207,11 @@ async function main() {
|
|
|
1114
1207
|
}
|
|
1115
1208
|
else {
|
|
1116
1209
|
applyEffective(config, r.effective, logger, { teamsOnly: true, sealedKeys });
|
|
1210
|
+
adoptCenterPrompts(r.effective, "refresh");
|
|
1117
1211
|
markRosterLanded(r.effective);
|
|
1118
1212
|
mutateInPlace(pricing, buildPricing(config.models));
|
|
1119
1213
|
keyResolver = buildKeyResolver(config.modelApiKeyEnv, process.env, config.modelApiKeys);
|
|
1214
|
+
await persistLkgDurable(r.effective, r.etag);
|
|
1120
1215
|
const reasons = restartReasons(effective, r.effective);
|
|
1121
1216
|
if (reasons.length === 0) {
|
|
1122
1217
|
pendingRestart = undefined;
|
|
@@ -1146,9 +1241,20 @@ async function main() {
|
|
|
1146
1241
|
};
|
|
1147
1242
|
const ccTimer = setInterval(() => void refreshTick(), 60_000);
|
|
1148
1243
|
ccTimer.unref?.();
|
|
1149
|
-
const deferredBootApply = (r) => {
|
|
1244
|
+
const deferredBootApply = async (r) => {
|
|
1150
1245
|
if (!r)
|
|
1151
1246
|
return;
|
|
1247
|
+
if (refreshInFlight)
|
|
1248
|
+
return;
|
|
1249
|
+
refreshInFlight = true;
|
|
1250
|
+
try {
|
|
1251
|
+
await deferredBootApplyInner(r);
|
|
1252
|
+
}
|
|
1253
|
+
finally {
|
|
1254
|
+
refreshInFlight = false;
|
|
1255
|
+
}
|
|
1256
|
+
};
|
|
1257
|
+
const deferredBootApplyInner = async (r) => {
|
|
1152
1258
|
const promptsRaw = r.effective.prompts;
|
|
1153
1259
|
const promptsGate = promptsRaw !== undefined ? validateCenterPrompts(promptsRaw) : { ok: true };
|
|
1154
1260
|
if ((r.domainErrors ?? []).length > 0 || !promptsGate.ok) {
|
|
@@ -1172,13 +1278,14 @@ async function main() {
|
|
|
1172
1278
|
effective = r.effective;
|
|
1173
1279
|
latestEffective = r.effective;
|
|
1174
1280
|
ccEtag = r.etag;
|
|
1175
|
-
|
|
1281
|
+
await persistLkgDurable(r.effective, r.etag);
|
|
1282
|
+
const reasons = restartReasons(undefined, r.effective);
|
|
1176
1283
|
if (reasons.length > 0)
|
|
1177
1284
|
pendingRestart = { restartRequired: true, reasons, version: r.effective.version, since: Date.now() };
|
|
1178
1285
|
logger.info("config_loaded_deferred", { source: configProvider.kind, version: r.effective.version, models: (r.effective.models?.models ?? []).filter((m) => m.enabled !== false).length, ...(reasons.length > 0 ? { restartRequired: true, restartReasons: reasons } : {}) });
|
|
1179
1286
|
};
|
|
1180
1287
|
if (bootConfigPending)
|
|
1181
|
-
void bootConfigPending.then((r) => deferredBootApply(r), () => { });
|
|
1288
|
+
void bootConfigPending.then((r) => (lkgBooted ? refreshTick(r) : deferredBootApply(r)), () => { });
|
|
1182
1289
|
}
|
|
1183
1290
|
let keyResolver = buildKeyResolver(config.modelApiKeyEnv, process.env, config.modelApiKeys);
|
|
1184
1291
|
const mysqlPool = backend?.mysqlPool();
|