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

推荐订阅源

美团技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Martin Fowler
Martin Fowler
雷峰网
雷峰网
IT之家
IT之家
小众软件
小众软件
M
MIT News - Artificial intelligence
博客园 - 聂微东
J
Java Code Geeks
Blog — PlanetScale
Blog — PlanetScale
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
About on SuperTechFans
G
Google Developers Blog
Engineering at Meta
Engineering at Meta
Recent Announcements
Recent Announcements
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
F
Fortinet All Blogs
C
Check Point Blog
云风的 BLOG
云风的 BLOG
腾讯CDC
H
Help Net Security
Y
Y Combinator Blog
I
InfoQ

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(sandbox): remove registry helper generics · openclaw/...
vincentkoc · 2026-05-03 · via Recent Commits to openclaw:main

@@ -45,8 +45,8 @@ type RegistryEntry = {

4545

containerName: string;

4646

};

474748-

type RegistryFile<T extends RegistryEntry> = {

49-

entries: T[];

48+

type RegistryFile = {

49+

entries: RegistryEntry[];

5050

};

51515252

// Schemas are shared between the per-entry files (live writes) and the

@@ -101,7 +101,7 @@ async function readEntryFile<T extends RegistryEntry>(

101101

return parsed ?? null;

102102

}

103103104-

async function writeEntryFile<T extends RegistryEntry>(dir: string, entry: T): Promise<void> {

104+

async function writeEntryFile(dir: string, entry: RegistryEntry): Promise<void> {

105105

await fs.mkdir(dir, { recursive: true });

106106

await writeJsonAtomic(entryFilePath(dir, entry.containerName), entry, { trailingNewline: true });

107107

}

@@ -148,10 +148,7 @@ async function readAllEntries<T extends RegistryEntry>(dir: string): Promise<T[]

148148149149

// ── One-shot migration from monolithic file → per-entry files ──────────

150150151-

async function migrateMonolithicIfNeeded<T extends RegistryEntry>(

152-

oldPath: string,

153-

newDir: string,

154-

): Promise<void> {

151+

async function migrateMonolithicIfNeeded(oldPath: string, newDir: string): Promise<void> {

155152

let raw: string;

156153

try {

157154

raw = await fs.readFile(oldPath, "utf-8");

@@ -160,7 +157,7 @@ async function migrateMonolithicIfNeeded<T extends RegistryEntry>(

160157

// fresh install). Nothing to do.

161158

return;

162159

}

163-

const parsed = safeParseJsonWithSchema(RegistryFileSchema, raw) as RegistryFile<T> | null;

160+

const parsed = safeParseJsonWithSchema(RegistryFileSchema, raw) as RegistryFile | null;

164161

if (!parsed || parsed.entries.length === 0) {

165162

// Corrupt or empty — drop it (and its stale lock) so we don't re-attempt

166163

// migration every read.

@@ -185,10 +182,7 @@ async function migrateMonolithicIfNeeded<T extends RegistryEntry>(

185182

// ── Public API: Container Registry ─────────────────────────────────────

186183187184

export async function readRegistry(): Promise<SandboxRegistry> {

188-

await migrateMonolithicIfNeeded<SandboxRegistryEntry>(

189-

SANDBOX_REGISTRY_PATH,

190-

SANDBOX_CONTAINERS_DIR,

191-

);

185+

await migrateMonolithicIfNeeded(SANDBOX_REGISTRY_PATH, SANDBOX_CONTAINERS_DIR);

192186

const entries = await readAllEntries<SandboxRegistryEntry>(SANDBOX_CONTAINERS_DIR);

193187

return { entries: entries.map(normalizeSandboxRegistryEntry) };

194188

}

@@ -202,19 +196,13 @@ export async function readRegistry(): Promise<SandboxRegistry> {

202196

export async function readRegistryEntry(

203197

containerName: string,

204198

): Promise<SandboxRegistryEntry | null> {

205-

await migrateMonolithicIfNeeded<SandboxRegistryEntry>(

206-

SANDBOX_REGISTRY_PATH,

207-

SANDBOX_CONTAINERS_DIR,

208-

);

199+

await migrateMonolithicIfNeeded(SANDBOX_REGISTRY_PATH, SANDBOX_CONTAINERS_DIR);

209200

const entry = await readEntryFile<SandboxRegistryEntry>(SANDBOX_CONTAINERS_DIR, containerName);

210201

return entry ? normalizeSandboxRegistryEntry(entry) : null;

211202

}

212203213204

export async function updateRegistry(entry: SandboxRegistryEntry): Promise<void> {

214-

await migrateMonolithicIfNeeded<SandboxRegistryEntry>(

215-

SANDBOX_REGISTRY_PATH,

216-

SANDBOX_CONTAINERS_DIR,

217-

);

205+

await migrateMonolithicIfNeeded(SANDBOX_REGISTRY_PATH, SANDBOX_CONTAINERS_DIR);

218206

const existing = await readEntryFile<SandboxRegistryEntry>(

219207

SANDBOX_CONTAINERS_DIR,

220208

entry.containerName,

@@ -238,18 +226,12 @@ export async function removeRegistryEntry(containerName: string): Promise<void>

238226

// ── Public API: Browser Registry ───────────────────────────────────────

239227240228

export async function readBrowserRegistry(): Promise<SandboxBrowserRegistry> {

241-

await migrateMonolithicIfNeeded<SandboxBrowserRegistryEntry>(

242-

SANDBOX_BROWSER_REGISTRY_PATH,

243-

SANDBOX_BROWSERS_DIR,

244-

);

229+

await migrateMonolithicIfNeeded(SANDBOX_BROWSER_REGISTRY_PATH, SANDBOX_BROWSERS_DIR);

245230

return { entries: await readAllEntries<SandboxBrowserRegistryEntry>(SANDBOX_BROWSERS_DIR) };

246231

}

247232248233

export async function updateBrowserRegistry(entry: SandboxBrowserRegistryEntry): Promise<void> {

249-

await migrateMonolithicIfNeeded<SandboxBrowserRegistryEntry>(

250-

SANDBOX_BROWSER_REGISTRY_PATH,

251-

SANDBOX_BROWSERS_DIR,

252-

);

234+

await migrateMonolithicIfNeeded(SANDBOX_BROWSER_REGISTRY_PATH, SANDBOX_BROWSERS_DIR);

253235

const existing = await readEntryFile<SandboxBrowserRegistryEntry>(

254236

SANDBOX_BROWSERS_DIR,

255237

entry.containerName,