fix: repair ci lockfile and boundary drift

This commit is contained in:
Peter Steinberger
2026-04-07 08:58:24 +01:00
parent 01e443755c
commit fd6d3f270d
7 changed files with 348 additions and 240 deletions

View File

@@ -1,4 +1,5 @@
import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../../../src/config/types.js";
import { resolveSecretRefValues } from "../../../src/secrets/resolve.js";
import {
applyResolvedAssignments,
@@ -24,8 +25,8 @@ describe("googlechat secret contract", () => {
},
},
},
};
const resolvedConfig = structuredClone(sourceConfig);
} satisfies OpenClawConfig;
const resolvedConfig: OpenClawConfig = structuredClone(sourceConfig);
const context = createResolverContext({
sourceConfig,
env: {
@@ -52,9 +53,8 @@ describe("googlechat secret contract", () => {
resolved,
});
expect(resolvedConfig.channels.googlechat.accounts.work.serviceAccount).toBe(
'{"client_email":"bot@example.com"}',
);
const workAccount = resolvedConfig.channels?.googlechat?.accounts?.work;
expect(workAccount?.serviceAccount).toBe('{"client_email":"bot@example.com"}');
expect(context.warnings).toEqual([]);
});
});

140
pnpm-lock.yaml generated
View File

@@ -286,7 +286,11 @@ importers:
extensions/anthropic: {}
extensions/anthropic-vertex: {}
extensions/anthropic-vertex:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/arcee: {}
@@ -296,7 +300,11 @@ importers:
specifier: workspace:*
version: link:../..
extensions/brave: {}
extensions/brave:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/browser: {}
@@ -304,15 +312,27 @@ importers:
extensions/chutes: {}
extensions/cloudflare-ai-gateway: {}
extensions/cloudflare-ai-gateway:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/comfy: {}
extensions/copilot-proxy: {}
extensions/copilot-proxy:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/deepgram: {}
extensions/deepseek: {}
extensions/deepseek:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/diagnostics-otel:
dependencies:
@@ -349,6 +369,10 @@ importers:
'@opentelemetry/semantic-conventions':
specifier: ^1.40.0
version: 1.40.0
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/diffs:
dependencies:
@@ -394,11 +418,19 @@ importers:
specifier: ^0.10.0
version: 0.10.0
extensions/duckduckgo: {}
extensions/duckduckgo:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/elevenlabs: {}
extensions/exa: {}
extensions/exa:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/fal: {}
@@ -415,9 +447,17 @@ importers:
specifier: workspace:*
version: link:../..
extensions/firecrawl: {}
extensions/firecrawl:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/fireworks: {}
extensions/fireworks:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/github-copilot: {}
@@ -437,11 +477,19 @@ importers:
specifier: workspace:*
version: link:../..
extensions/groq: {}
extensions/groq:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/huggingface: {}
extensions/image-generation-core: {}
extensions/image-generation-core:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/imessage: {}
@@ -457,7 +505,11 @@ importers:
specifier: workspace:*
version: link:../..
extensions/litellm: {}
extensions/litellm:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/llm-task:
dependencies:
@@ -467,6 +519,10 @@ importers:
ajv:
specifier: ^8.18.0
version: 8.18.0
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/lobster:
dependencies:
@@ -515,7 +571,11 @@ importers:
specifier: workspace:*
version: link:../..
extensions/media-understanding-core: {}
extensions/media-understanding-core:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/memory-core:
devDependencies:
@@ -591,11 +651,19 @@ importers:
specifier: workspace:*
version: link:../..
extensions/nvidia: {}
extensions/nvidia:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/ollama: {}
extensions/open-prose: {}
extensions/open-prose:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/openai:
dependencies:
@@ -611,7 +679,11 @@ importers:
extensions/openshell: {}
extensions/perplexity: {}
extensions/perplexity:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/qa-channel:
devDependencies:
@@ -625,7 +697,11 @@ importers:
specifier: workspace:*
version: link:../..
extensions/qianfan: {}
extensions/qianfan:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/qqbot:
dependencies:
@@ -650,7 +726,11 @@ importers:
extensions/runway: {}
extensions/searxng: {}
extensions/searxng:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/sglang: {}
@@ -671,9 +751,17 @@ importers:
extensions/synology-chat: {}
extensions/synthetic: {}
extensions/synthetic:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/tavily: {}
extensions/tavily:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/telegram:
dependencies:
@@ -720,11 +808,19 @@ importers:
specifier: ^8.1.3
version: 8.1.3(@twurple/auth@8.1.3)
extensions/venice: {}
extensions/venice:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/vercel-ai-gateway: {}
extensions/video-generation-core: {}
extensions/video-generation-core:
devDependencies:
'@openclaw/plugin-sdk':
specifier: workspace:*
version: link:../../packages/plugin-sdk
extensions/vllm: {}

View File

@@ -7,6 +7,7 @@ const TEST_LIKE_SEGMENT_RE =
const TEST_LIKE_FILENAME_RE =
/(^|\/)[^/]*test-(?:support|helpers|fixtures|harness)\.(?:[cm]?ts|[cm]?js|tsx|jsx)$/u;
const TEST_SHARED_FILENAME_RE = /(^|\/)[^/]*\.test-[^/]*\.(?:[cm]?ts|[cm]?js|tsx|jsx)$/u;
const TEST_CANARY_FILENAME_RE = /(^|\/)__rootdir_boundary_canary__\.(?:[cm]?ts|[cm]?js|tsx|jsx)$/u;
const SNAPSHOT_FILE_RE = /\.snap$/u;
const SUFFIX_SKIP_RE = /\.(?:test|spec|fixture)\./u;
const INFRA_DIR_RE = /(^|\/)(?:coverage|dist|node_modules)(?:\/|$)/u;
@@ -25,6 +26,7 @@ export function classifyBundledExtensionSourcePath(filePath) {
TEST_LIKE_SEGMENT_RE.test(normalizedPath) ||
TEST_LIKE_FILENAME_RE.test(normalizedPath) ||
TEST_SHARED_FILENAME_RE.test(normalizedPath) ||
TEST_CANARY_FILENAME_RE.test(normalizedPath) ||
SUFFIX_SKIP_RE.test(normalizedPath) ||
SNAPSHOT_FILE_RE.test(normalizedPath) ||
INFRA_NAME_RE.test(normalizedPath);

View File

@@ -609,56 +609,58 @@ async function maybeRecoverSuspiciousConfigRead(params: {
fs: params.deps.fs,
env: params.deps.env,
homedir: params.deps.homedir,
ts: now,
source: "config-io",
event: "config.observe",
phase: "read",
configPath: params.configPath,
pid: process.pid,
ppid: process.ppid,
cwd: process.cwd(),
argv: process.argv.slice(0, 8),
execArgv: process.execArgv.slice(0, 8),
exists: true,
valid: true,
hash: current.hash,
bytes: current.bytes,
mtimeMs: current.mtimeMs,
ctimeMs: current.ctimeMs,
dev: current.dev,
ino: current.ino,
mode: current.mode,
nlink: current.nlink,
uid: current.uid,
gid: current.gid,
hasMeta: current.hasMeta,
gatewayMode: current.gatewayMode,
suspicious,
lastKnownGoodHash: entry.lastKnownGood?.hash ?? null,
lastKnownGoodBytes: entry.lastKnownGood?.bytes ?? null,
lastKnownGoodMtimeMs: entry.lastKnownGood?.mtimeMs ?? null,
lastKnownGoodCtimeMs: entry.lastKnownGood?.ctimeMs ?? null,
lastKnownGoodDev: entry.lastKnownGood?.dev ?? null,
lastKnownGoodIno: entry.lastKnownGood?.ino ?? null,
lastKnownGoodMode: entry.lastKnownGood?.mode ?? null,
lastKnownGoodNlink: entry.lastKnownGood?.nlink ?? null,
lastKnownGoodUid: entry.lastKnownGood?.uid ?? null,
lastKnownGoodGid: entry.lastKnownGood?.gid ?? null,
lastKnownGoodGatewayMode: entry.lastKnownGood?.gatewayMode ?? null,
backupHash: backup?.hash ?? null,
backupBytes: backup?.bytes ?? null,
backupMtimeMs: backup?.mtimeMs ?? null,
backupCtimeMs: backup?.ctimeMs ?? null,
backupDev: backup?.dev ?? null,
backupIno: backup?.ino ?? null,
backupMode: backup?.mode ?? null,
backupNlink: backup?.nlink ?? null,
backupUid: backup?.uid ?? null,
backupGid: backup?.gid ?? null,
backupGatewayMode: backup?.gatewayMode ?? null,
clobberedPath,
restoredFromBackup,
restoredBackupPath: backupPath,
record: {
ts: now,
source: "config-io",
event: "config.observe",
phase: "read",
configPath: params.configPath,
pid: process.pid,
ppid: process.ppid,
cwd: process.cwd(),
argv: process.argv.slice(0, 8),
execArgv: process.execArgv.slice(0, 8),
exists: true,
valid: true,
hash: current.hash,
bytes: current.bytes,
mtimeMs: current.mtimeMs,
ctimeMs: current.ctimeMs,
dev: current.dev,
ino: current.ino,
mode: current.mode,
nlink: current.nlink,
uid: current.uid,
gid: current.gid,
hasMeta: current.hasMeta,
gatewayMode: current.gatewayMode,
suspicious,
lastKnownGoodHash: entry.lastKnownGood?.hash ?? null,
lastKnownGoodBytes: entry.lastKnownGood?.bytes ?? null,
lastKnownGoodMtimeMs: entry.lastKnownGood?.mtimeMs ?? null,
lastKnownGoodCtimeMs: entry.lastKnownGood?.ctimeMs ?? null,
lastKnownGoodDev: entry.lastKnownGood?.dev ?? null,
lastKnownGoodIno: entry.lastKnownGood?.ino ?? null,
lastKnownGoodMode: entry.lastKnownGood?.mode ?? null,
lastKnownGoodNlink: entry.lastKnownGood?.nlink ?? null,
lastKnownGoodUid: entry.lastKnownGood?.uid ?? null,
lastKnownGoodGid: entry.lastKnownGood?.gid ?? null,
lastKnownGoodGatewayMode: entry.lastKnownGood?.gatewayMode ?? null,
backupHash: backup?.hash ?? null,
backupBytes: backup?.bytes ?? null,
backupMtimeMs: backup?.mtimeMs ?? null,
backupCtimeMs: backup?.ctimeMs ?? null,
backupDev: backup?.dev ?? null,
backupIno: backup?.ino ?? null,
backupMode: backup?.mode ?? null,
backupNlink: backup?.nlink ?? null,
backupUid: backup?.uid ?? null,
backupGid: backup?.gid ?? null,
backupGatewayMode: backup?.gatewayMode ?? null,
clobberedPath,
restoredFromBackup,
restoredBackupPath: backupPath,
},
});
healthState = setConfigHealthEntry(healthState, params.configPath, {
@@ -742,56 +744,58 @@ function maybeRecoverSuspiciousConfigReadSync(params: {
fs: params.deps.fs,
env: params.deps.env,
homedir: params.deps.homedir,
ts: now,
source: "config-io",
event: "config.observe",
phase: "read",
configPath: params.configPath,
pid: process.pid,
ppid: process.ppid,
cwd: process.cwd(),
argv: process.argv.slice(0, 8),
execArgv: process.execArgv.slice(0, 8),
exists: true,
valid: true,
hash: current.hash,
bytes: current.bytes,
mtimeMs: current.mtimeMs,
ctimeMs: current.ctimeMs,
dev: current.dev,
ino: current.ino,
mode: current.mode,
nlink: current.nlink,
uid: current.uid,
gid: current.gid,
hasMeta: current.hasMeta,
gatewayMode: current.gatewayMode,
suspicious,
lastKnownGoodHash: entry.lastKnownGood?.hash ?? null,
lastKnownGoodBytes: entry.lastKnownGood?.bytes ?? null,
lastKnownGoodMtimeMs: entry.lastKnownGood?.mtimeMs ?? null,
lastKnownGoodCtimeMs: entry.lastKnownGood?.ctimeMs ?? null,
lastKnownGoodDev: entry.lastKnownGood?.dev ?? null,
lastKnownGoodIno: entry.lastKnownGood?.ino ?? null,
lastKnownGoodMode: entry.lastKnownGood?.mode ?? null,
lastKnownGoodNlink: entry.lastKnownGood?.nlink ?? null,
lastKnownGoodUid: entry.lastKnownGood?.uid ?? null,
lastKnownGoodGid: entry.lastKnownGood?.gid ?? null,
lastKnownGoodGatewayMode: entry.lastKnownGood?.gatewayMode ?? null,
backupHash: backup?.hash ?? null,
backupBytes: backup?.bytes ?? null,
backupMtimeMs: backup?.mtimeMs ?? null,
backupCtimeMs: backup?.ctimeMs ?? null,
backupDev: backup?.dev ?? null,
backupIno: backup?.ino ?? null,
backupMode: backup?.mode ?? null,
backupNlink: backup?.nlink ?? null,
backupUid: backup?.uid ?? null,
backupGid: backup?.gid ?? null,
backupGatewayMode: backup?.gatewayMode ?? null,
clobberedPath,
restoredFromBackup,
restoredBackupPath: backupPath,
record: {
ts: now,
source: "config-io",
event: "config.observe",
phase: "read",
configPath: params.configPath,
pid: process.pid,
ppid: process.ppid,
cwd: process.cwd(),
argv: process.argv.slice(0, 8),
execArgv: process.execArgv.slice(0, 8),
exists: true,
valid: true,
hash: current.hash,
bytes: current.bytes,
mtimeMs: current.mtimeMs,
ctimeMs: current.ctimeMs,
dev: current.dev,
ino: current.ino,
mode: current.mode,
nlink: current.nlink,
uid: current.uid,
gid: current.gid,
hasMeta: current.hasMeta,
gatewayMode: current.gatewayMode,
suspicious,
lastKnownGoodHash: entry.lastKnownGood?.hash ?? null,
lastKnownGoodBytes: entry.lastKnownGood?.bytes ?? null,
lastKnownGoodMtimeMs: entry.lastKnownGood?.mtimeMs ?? null,
lastKnownGoodCtimeMs: entry.lastKnownGood?.ctimeMs ?? null,
lastKnownGoodDev: entry.lastKnownGood?.dev ?? null,
lastKnownGoodIno: entry.lastKnownGood?.ino ?? null,
lastKnownGoodMode: entry.lastKnownGood?.mode ?? null,
lastKnownGoodNlink: entry.lastKnownGood?.nlink ?? null,
lastKnownGoodUid: entry.lastKnownGood?.uid ?? null,
lastKnownGoodGid: entry.lastKnownGood?.gid ?? null,
lastKnownGoodGatewayMode: entry.lastKnownGood?.gatewayMode ?? null,
backupHash: backup?.hash ?? null,
backupBytes: backup?.bytes ?? null,
backupMtimeMs: backup?.mtimeMs ?? null,
backupCtimeMs: backup?.ctimeMs ?? null,
backupDev: backup?.dev ?? null,
backupIno: backup?.ino ?? null,
backupMode: backup?.mode ?? null,
backupNlink: backup?.nlink ?? null,
backupUid: backup?.uid ?? null,
backupGid: backup?.gid ?? null,
backupGatewayMode: backup?.gatewayMode ?? null,
clobberedPath,
restoredFromBackup,
restoredBackupPath: backupPath,
},
});
healthState = setConfigHealthEntry(healthState, params.configPath, {
@@ -897,56 +901,58 @@ async function observeConfigSnapshot(
fs: deps.fs,
env: deps.env,
homedir: deps.homedir,
ts: now,
source: "config-io",
event: "config.observe",
phase: "read",
configPath: snapshot.path,
pid: process.pid,
ppid: process.ppid,
cwd: process.cwd(),
argv: process.argv.slice(0, 8),
execArgv: process.execArgv.slice(0, 8),
exists: true,
valid: snapshot.valid,
hash: current.hash,
bytes: current.bytes,
mtimeMs: current.mtimeMs,
ctimeMs: current.ctimeMs,
dev: current.dev,
ino: current.ino,
mode: current.mode,
nlink: current.nlink,
uid: current.uid,
gid: current.gid,
hasMeta: current.hasMeta,
gatewayMode: current.gatewayMode,
suspicious,
lastKnownGoodHash: entry.lastKnownGood?.hash ?? null,
lastKnownGoodBytes: entry.lastKnownGood?.bytes ?? null,
lastKnownGoodMtimeMs: entry.lastKnownGood?.mtimeMs ?? null,
lastKnownGoodCtimeMs: entry.lastKnownGood?.ctimeMs ?? null,
lastKnownGoodDev: entry.lastKnownGood?.dev ?? null,
lastKnownGoodIno: entry.lastKnownGood?.ino ?? null,
lastKnownGoodMode: entry.lastKnownGood?.mode ?? null,
lastKnownGoodNlink: entry.lastKnownGood?.nlink ?? null,
lastKnownGoodUid: entry.lastKnownGood?.uid ?? null,
lastKnownGoodGid: entry.lastKnownGood?.gid ?? null,
lastKnownGoodGatewayMode: entry.lastKnownGood?.gatewayMode ?? null,
backupHash: backup?.hash ?? null,
backupBytes: backup?.bytes ?? null,
backupMtimeMs: backup?.mtimeMs ?? null,
backupCtimeMs: backup?.ctimeMs ?? null,
backupDev: backup?.dev ?? null,
backupIno: backup?.ino ?? null,
backupMode: backup?.mode ?? null,
backupNlink: backup?.nlink ?? null,
backupUid: backup?.uid ?? null,
backupGid: backup?.gid ?? null,
backupGatewayMode: backup?.gatewayMode ?? null,
clobberedPath,
restoredFromBackup: false,
restoredBackupPath: null,
record: {
ts: now,
source: "config-io",
event: "config.observe",
phase: "read",
configPath: snapshot.path,
pid: process.pid,
ppid: process.ppid,
cwd: process.cwd(),
argv: process.argv.slice(0, 8),
execArgv: process.execArgv.slice(0, 8),
exists: true,
valid: snapshot.valid,
hash: current.hash,
bytes: current.bytes,
mtimeMs: current.mtimeMs,
ctimeMs: current.ctimeMs,
dev: current.dev,
ino: current.ino,
mode: current.mode,
nlink: current.nlink,
uid: current.uid,
gid: current.gid,
hasMeta: current.hasMeta,
gatewayMode: current.gatewayMode,
suspicious,
lastKnownGoodHash: entry.lastKnownGood?.hash ?? null,
lastKnownGoodBytes: entry.lastKnownGood?.bytes ?? null,
lastKnownGoodMtimeMs: entry.lastKnownGood?.mtimeMs ?? null,
lastKnownGoodCtimeMs: entry.lastKnownGood?.ctimeMs ?? null,
lastKnownGoodDev: entry.lastKnownGood?.dev ?? null,
lastKnownGoodIno: entry.lastKnownGood?.ino ?? null,
lastKnownGoodMode: entry.lastKnownGood?.mode ?? null,
lastKnownGoodNlink: entry.lastKnownGood?.nlink ?? null,
lastKnownGoodUid: entry.lastKnownGood?.uid ?? null,
lastKnownGoodGid: entry.lastKnownGood?.gid ?? null,
lastKnownGoodGatewayMode: entry.lastKnownGood?.gatewayMode ?? null,
backupHash: backup?.hash ?? null,
backupBytes: backup?.bytes ?? null,
backupMtimeMs: backup?.mtimeMs ?? null,
backupCtimeMs: backup?.ctimeMs ?? null,
backupDev: backup?.dev ?? null,
backupIno: backup?.ino ?? null,
backupMode: backup?.mode ?? null,
backupNlink: backup?.nlink ?? null,
backupUid: backup?.uid ?? null,
backupGid: backup?.gid ?? null,
backupGatewayMode: backup?.gatewayMode ?? null,
clobberedPath,
restoredFromBackup: false,
restoredBackupPath: null,
},
});
healthState = setConfigHealthEntry(healthState, snapshot.path, {
@@ -1028,56 +1034,58 @@ function observeConfigSnapshotSync(
fs: deps.fs,
env: deps.env,
homedir: deps.homedir,
ts: now,
source: "config-io",
event: "config.observe",
phase: "read",
configPath: snapshot.path,
pid: process.pid,
ppid: process.ppid,
cwd: process.cwd(),
argv: process.argv.slice(0, 8),
execArgv: process.execArgv.slice(0, 8),
exists: true,
valid: snapshot.valid,
hash: current.hash,
bytes: current.bytes,
mtimeMs: current.mtimeMs,
ctimeMs: current.ctimeMs,
dev: current.dev,
ino: current.ino,
mode: current.mode,
nlink: current.nlink,
uid: current.uid,
gid: current.gid,
hasMeta: current.hasMeta,
gatewayMode: current.gatewayMode,
suspicious,
lastKnownGoodHash: entry.lastKnownGood?.hash ?? null,
lastKnownGoodBytes: entry.lastKnownGood?.bytes ?? null,
lastKnownGoodMtimeMs: entry.lastKnownGood?.mtimeMs ?? null,
lastKnownGoodCtimeMs: entry.lastKnownGood?.ctimeMs ?? null,
lastKnownGoodDev: entry.lastKnownGood?.dev ?? null,
lastKnownGoodIno: entry.lastKnownGood?.ino ?? null,
lastKnownGoodMode: entry.lastKnownGood?.mode ?? null,
lastKnownGoodNlink: entry.lastKnownGood?.nlink ?? null,
lastKnownGoodUid: entry.lastKnownGood?.uid ?? null,
lastKnownGoodGid: entry.lastKnownGood?.gid ?? null,
lastKnownGoodGatewayMode: entry.lastKnownGood?.gatewayMode ?? null,
backupHash: backup?.hash ?? null,
backupBytes: backup?.bytes ?? null,
backupMtimeMs: backup?.mtimeMs ?? null,
backupCtimeMs: backup?.ctimeMs ?? null,
backupDev: backup?.dev ?? null,
backupIno: backup?.ino ?? null,
backupMode: backup?.mode ?? null,
backupNlink: backup?.nlink ?? null,
backupUid: backup?.uid ?? null,
backupGid: backup?.gid ?? null,
backupGatewayMode: backup?.gatewayMode ?? null,
clobberedPath,
restoredFromBackup: false,
restoredBackupPath: null,
record: {
ts: now,
source: "config-io",
event: "config.observe",
phase: "read",
configPath: snapshot.path,
pid: process.pid,
ppid: process.ppid,
cwd: process.cwd(),
argv: process.argv.slice(0, 8),
execArgv: process.execArgv.slice(0, 8),
exists: true,
valid: snapshot.valid,
hash: current.hash,
bytes: current.bytes,
mtimeMs: current.mtimeMs,
ctimeMs: current.ctimeMs,
dev: current.dev,
ino: current.ino,
mode: current.mode,
nlink: current.nlink,
uid: current.uid,
gid: current.gid,
hasMeta: current.hasMeta,
gatewayMode: current.gatewayMode,
suspicious,
lastKnownGoodHash: entry.lastKnownGood?.hash ?? null,
lastKnownGoodBytes: entry.lastKnownGood?.bytes ?? null,
lastKnownGoodMtimeMs: entry.lastKnownGood?.mtimeMs ?? null,
lastKnownGoodCtimeMs: entry.lastKnownGood?.ctimeMs ?? null,
lastKnownGoodDev: entry.lastKnownGood?.dev ?? null,
lastKnownGoodIno: entry.lastKnownGood?.ino ?? null,
lastKnownGoodMode: entry.lastKnownGood?.mode ?? null,
lastKnownGoodNlink: entry.lastKnownGood?.nlink ?? null,
lastKnownGoodUid: entry.lastKnownGood?.uid ?? null,
lastKnownGoodGid: entry.lastKnownGood?.gid ?? null,
lastKnownGoodGatewayMode: entry.lastKnownGood?.gatewayMode ?? null,
backupHash: backup?.hash ?? null,
backupBytes: backup?.bytes ?? null,
backupMtimeMs: backup?.mtimeMs ?? null,
backupCtimeMs: backup?.ctimeMs ?? null,
backupDev: backup?.dev ?? null,
backupIno: backup?.ino ?? null,
backupMode: backup?.mode ?? null,
backupNlink: backup?.nlink ?? null,
backupUid: backup?.uid ?? null,
backupGid: backup?.gid ?? null,
backupGatewayMode: backup?.gatewayMode ?? null,
clobberedPath,
restoredFromBackup: false,
restoredBackupPath: null,
},
});
healthState = setConfigHealthEntry(healthState, snapshot.path, {

View File

@@ -17,7 +17,9 @@ const mockLoadPluginManifestRegistry = vi.hoisted(() =>
}),
),
);
const mockMaintainConfigBackups = vi.hoisted(() => vi.fn(async () => {}));
const mockMaintainConfigBackups = vi.hoisted(() =>
vi.fn<typeof import("./backup-rotation.js").maintainConfigBackups>(async () => {}),
);
vi.mock("../plugins/manifest-registry.js", () => ({
loadPluginManifestRegistry: mockLoadPluginManifestRegistry,
@@ -27,8 +29,7 @@ vi.mock("./backup-rotation.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("./backup-rotation.js")>();
return {
...actual,
maintainConfigBackups: (..._args: Parameters<typeof actual.maintainConfigBackups>) =>
mockMaintainConfigBackups(),
maintainConfigBackups: mockMaintainConfigBackups,
};
});

View File

@@ -65,7 +65,7 @@ describe("config io write prepare", () => {
const input: OpenClawConfig = {
gateway: { mode: "local" },
commands: { ownerDisplay: "hash" },
};
} satisfies OpenClawConfig;
const next = unsetPathForWrite(input, ["commands", "ownerDisplay"]);
@@ -80,7 +80,7 @@ describe("config io write prepare", () => {
const input: OpenClawConfig = {
gateway: { mode: "local" },
tools: { alsoAllow: ["exec", "fetch", "read"] },
};
} satisfies OpenClawConfig;
const next = unsetPathForWrite(input, ["tools", "alsoAllow", "1"]);
@@ -95,7 +95,7 @@ describe("config io write prepare", () => {
const input: OpenClawConfig = {
gateway: { mode: "local" },
commands: { ownerDisplay: "hash" },
};
} satisfies OpenClawConfig;
const next = unsetPathForWrite(input, ["commands", "missingKey"]);
@@ -111,7 +111,7 @@ describe("config io write prepare", () => {
const input: OpenClawConfig = {
gateway: { mode: "local" },
commands: { ownerDisplay: "hash" },
};
} satisfies OpenClawConfig;
const blocked = [
["commands", "__proto__"],
@@ -279,7 +279,7 @@ describe("config io write prepare", () => {
password: "test-password",
},
},
};
} satisfies OpenClawConfig;
const runtimeConfig: OpenClawConfig = {
gateway: { port: 18789 },
@@ -290,9 +290,9 @@ describe("config io write prepare", () => {
enrichGroupParticipantsFromContacts: true,
},
},
};
} satisfies OpenClawConfig;
const nextConfig = structuredClone(runtimeConfig);
const nextConfig: OpenClawConfig = structuredClone(runtimeConfig);
nextConfig.gateway = {
...nextConfig.gateway,
auth: { mode: "token" },
@@ -328,7 +328,7 @@ describe("config io write prepare", () => {
},
},
gateway: { port: 18789 },
};
} satisfies OpenClawConfig;
const nextConfig = structuredClone(sourceConfig);
delete (nextConfig.channels?.discord?.dm as { enabled?: boolean; policy?: string } | undefined)
@@ -382,9 +382,9 @@ describe("config io write prepare", () => {
},
},
},
};
} satisfies OpenClawConfig;
const nextConfig = {
const nextConfig: OpenClawConfig = {
...structuredClone(sourceConfig),
gateway: {
auth: { mode: "token" },

View File

@@ -19,6 +19,7 @@ const allowedNonExtensionTests = new Set<string>([
"src/commands/onboard-channels.e2e.test.ts",
"src/gateway/hooks.test.ts",
"src/infra/outbound/deliver.test.ts",
"src/media-generation/provider-capabilities.contract.test.ts",
"src/plugins/interactive.test.ts",
"src/plugins/contracts/discovery.contract.test.ts",
"src/plugin-sdk/telegram-command-config.test.ts",