惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
F
Fortinet All Blogs
D
Docker
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
罗磊的独立博客
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
J
Java Code Geeks
T
The Blog of Author Tim Ferriss
U
Unit 42
N
Netflix TechBlog - Medium
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
V2EX
云风的 BLOG
云风的 BLOG
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
Hugging Face - Blog
Hugging Face - Blog
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Proofpoint News Feed
G
Google Developers Blog
H
Help Net Security

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix: reuse plugin registry during config validation · ope...
shakkernerd · 2026-04-27 · via Recent Commits to openclaw:main

@@ -227,6 +227,7 @@ export type ReadConfigFileSnapshotForWriteResult = {

227227

};

228228229229

export type ConfigWriteNotification = RuntimeConfigWriteNotification;

230+

export type ConfigSnapshotReadMeasure = <T>(name: string, run: () => T | Promise<T>) => Promise<T>;

230231231232

export class ConfigRuntimeRefreshError extends Error {

232233

constructor(message: string, options?: { cause?: unknown }) {

@@ -903,6 +904,7 @@ export type ConfigIoDeps = {

903904

homedir?: () => string;

904905

configPath?: string;

905906

logger?: Pick<typeof console, "error" | "warn">;

907+

measure?: ConfigSnapshotReadMeasure;

906908

};

907909908910

function warnOnConfigMiskeys(raw: unknown, logger: Pick<typeof console, "warn">): void {

@@ -960,6 +962,7 @@ function normalizeDeps(overrides: ConfigIoDeps = {}): Required<ConfigIoDeps> {

960962

overrides.homedir ?? (() => resolveRequiredHomeDir(overrides.env ?? process.env, os.homedir)),

961963

configPath: overrides.configPath ?? "",

962964

logger: overrides.logger ?? console,

965+

measure: overrides.measure ?? (async (_name, run) => await run()),

963966

};

964967

}

965968

@@ -1637,11 +1640,15 @@ export function createConfigIO(

16371640

let fallbackHash = hashConfigRaw(null);

1638164116391642

try {

1640-

const raw = deps.fs.readFileSync(configPath, "utf-8");

1641-

const rawHash = hashConfigRaw(raw);

1643+

const raw = await deps.measure("config.snapshot.read.file", () =>

1644+

deps.fs.readFileSync(configPath, "utf-8"),

1645+

);

1646+

const rawHash = await deps.measure("config.snapshot.read.hash", () => hashConfigRaw(raw));

16421647

fallbackRaw = raw;

16431648

fallbackHash = rawHash;

1644-

const parsedRes = parseConfigJson5(raw, deps.json5);

1649+

const parsedRes = await deps.measure("config.snapshot.read.parse", () =>

1650+

parseConfigJson5(raw, deps.json5),

1651+

);

16451652

if (!parsedRes.ok) {

16461653

return await finalizeReadConfigSnapshotInternalResult(deps, {

16471654

snapshot: createConfigFileSnapshot({

@@ -1663,12 +1670,14 @@ export function createConfigIO(

16631670

fallbackSourceConfig = coerceConfig(parsedRes.parsed);

1664167116651672

// Resolve $include directives

1666-

const recovered = await maybeRecoverSuspiciousConfigRead({

1667-

deps,

1668-

configPath,

1669-

raw,

1670-

parsed: parsedRes.parsed,

1671-

});

1673+

const recovered = await deps.measure("config.snapshot.read.recovery-check", () =>

1674+

maybeRecoverSuspiciousConfigRead({

1675+

deps,

1676+

configPath,

1677+

raw,

1678+

parsed: parsedRes.parsed,

1679+

}),

1680+

);

16721681

const effectiveRaw = recovered.raw;

16731682

const effectiveParsed = recovered.parsed;

16741683

const hash = hashConfigRaw(effectiveRaw);

@@ -1679,7 +1688,9 @@ export function createConfigIO(

1679168816801689

let resolved: unknown;

16811690

try {

1682-

resolved = resolveConfigIncludesForRead(effectiveParsed, configPath, deps);

1691+

resolved = await deps.measure("config.snapshot.read.includes", () =>

1692+

resolveConfigIncludesForRead(effectiveParsed, configPath, deps),

1693+

);

16831694

} catch (err) {

16841695

const message =

16851696

err instanceof ConfigIncludeError

@@ -1703,7 +1714,9 @@ export function createConfigIO(

17031714

});

17041715

}

170517161706-

const readResolution = resolveConfigForRead(resolved, deps.env);

1717+

const readResolution = await deps.measure("config.snapshot.read.env", () =>

1718+

resolveConfigForRead(resolved, deps.env),

1719+

);

1707172017081721

// Convert missing env var references to config warnings instead of fatal errors.

17091722

// This allows the gateway to start in degraded mode when non-critical config

@@ -1714,13 +1727,16 @@ export function createConfigIO(

17141727

}));

1715172817161729

const resolvedConfigRaw = readResolution.resolvedConfigRaw;

1717-

const legacyResolution = resolveLegacyConfigForRead(resolvedConfigRaw, effectiveParsed);

1718-

const installMigration = migrateAndStripShippedPluginInstallConfigRecords(

1719-

legacyResolution.effectiveConfigRaw,

1720-

{

1721-

persist: options.persistShippedPluginInstallMigration !== false,

1722-

rootConfigRaw: effectiveParsed,

1723-

},

1730+

const legacyResolution = await deps.measure("config.snapshot.read.legacy", () =>

1731+

resolveLegacyConfigForRead(resolvedConfigRaw, effectiveParsed),

1732+

);

1733+

const installMigration = await deps.measure(

1734+

"config.snapshot.read.plugin-install-migration",

1735+

() =>

1736+

migrateAndStripShippedPluginInstallConfigRecords(legacyResolution.effectiveConfigRaw, {

1737+

persist: options.persistShippedPluginInstallMigration !== false,

1738+

rootConfigRaw: effectiveParsed,

1739+

}),

17241740

);

17251741

const effectiveConfigRaw = installMigration.config;

17261742

const snapshotRaw = installMigration.persistedRootRaw ?? effectiveRaw;

@@ -1729,10 +1745,12 @@ export function createConfigIO(

17291745

? hashConfigRaw(installMigration.persistedRootRaw)

17301746

: hash;

17311747

fallbackSourceConfig = coerceConfig(effectiveConfigRaw);

1732-

const validated = validateConfigObjectWithPlugins(effectiveConfigRaw, {

1733-

env: deps.env,

1734-

pluginValidation: overrides.pluginValidation,

1735-

});

1748+

const validated = await deps.measure("config.snapshot.read.validate", () =>

1749+

validateConfigObjectWithPlugins(effectiveConfigRaw, {

1750+

env: deps.env,

1751+

pluginValidation: overrides.pluginValidation,

1752+

}),

1753+

);

17361754

if (!validated.ok) {

17371755

return await finalizeReadConfigSnapshotInternalResult(deps, {

17381756

snapshot: createConfigFileSnapshot({

@@ -1752,25 +1770,29 @@ export function createConfigIO(

17521770

}

1753177117541772

warnIfConfigFromFuture(validated.config, deps.logger);

1755-

const snapshotConfig = materializeRuntimeConfig(validated.config, "snapshot");

1756-

return await finalizeReadConfigSnapshotInternalResult(deps, {

1757-

snapshot: createConfigFileSnapshot({

1758-

path: configPath,

1759-

exists: true,

1760-

raw: snapshotRaw,

1761-

parsed: snapshotParsed,

1762-

// Use resolvedConfigRaw (after $include and ${ENV} substitution but BEFORE runtime defaults)

1763-

// for config set/unset operations (issue #6070)

1764-

sourceConfig: coerceConfig(effectiveConfigRaw),

1765-

valid: true,

1766-

runtimeConfig: snapshotConfig,

1767-

hash: snapshotHash,

1768-

issues: [],

1769-

warnings: [...validated.warnings, ...envVarWarnings],

1770-

legacyIssues: legacyResolution.sourceLegacyIssues,

1773+

const snapshotConfig = await deps.measure("config.snapshot.read.materialize", () =>

1774+

materializeRuntimeConfig(validated.config, "snapshot"),

1775+

);

1776+

return await deps.measure("config.snapshot.read.observe", () =>

1777+

finalizeReadConfigSnapshotInternalResult(deps, {

1778+

snapshot: createConfigFileSnapshot({

1779+

path: configPath,

1780+

exists: true,

1781+

raw: snapshotRaw,

1782+

parsed: snapshotParsed,

1783+

// Use resolvedConfigRaw (after $include and ${ENV} substitution but BEFORE runtime defaults)

1784+

// for config set/unset operations (issue #6070)

1785+

sourceConfig: coerceConfig(effectiveConfigRaw),

1786+

valid: true,

1787+

runtimeConfig: snapshotConfig,

1788+

hash: snapshotHash,

1789+

issues: [],

1790+

warnings: [...validated.warnings, ...envVarWarnings],

1791+

legacyIssues: legacyResolution.sourceLegacyIssues,

1792+

}),

1793+

envSnapshotForRestore: readResolution.envSnapshotForRestore,

17711794

}),

1772-

envSnapshotForRestore: readResolution.envSnapshotForRestore,

1773-

});

1795+

);

17741796

} catch (err) {

17751797

const nodeErr = err as NodeJS.ErrnoException;

17761798

let message: string;

@@ -2304,8 +2326,12 @@ export async function readSourceConfigBestEffort(): Promise<OpenClawConfig> {

23042326

return await createConfigIO().readSourceConfigBestEffort();

23052327

}

230623282307-

export async function readConfigFileSnapshot(): Promise<ConfigFileSnapshot> {

2308-

return await createConfigIO().readConfigFileSnapshot();

2329+

export async function readConfigFileSnapshot(options?: {

2330+

measure?: ConfigSnapshotReadMeasure;

2331+

}): Promise<ConfigFileSnapshot> {

2332+

return await createConfigIO(

2333+

options?.measure ? { measure: options.measure } : {},

2334+

).readConfigFileSnapshot();

23092335

}

2310233623112337

export async function promoteConfigSnapshotToLastKnownGood(