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

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
MyScale Blog
MyScale Blog
U
Unit 42
M
MIT News - Artificial intelligence
小众软件
小众软件
P
Proofpoint News Feed
雷峰网
雷峰网
L
LangChain Blog
S
SegmentFault 最新的问题
腾讯CDC
F
Fortinet All Blogs
A
About on SuperTechFans
WordPress大学
WordPress大学
Vercel News
Vercel News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
Google Developers Blog
大猫的无限游戏
大猫的无限游戏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
Docker
N
Netflix TechBlog - Medium
Apple Machine Learning Research
Apple Machine Learning Research
Recent Announcements
Recent Announcements
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog

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
test: dedupe coding tool session store fixtures · opencla...
steipete · 2026-04-24 · via Recent Commits to openclaw:main

@@ -45,6 +45,44 @@ function collectActionValues(schema: unknown, values: Set<string>): void {

4545

}

4646

}

474748+

async function writeSessionStore(

49+

storeTemplate: string,

50+

agentId: string,

51+

entries: Record<string, unknown>,

52+

) {

53+

await fs.writeFile(

54+

storeTemplate.replaceAll("{agentId}", agentId),

55+

JSON.stringify(entries, null, 2),

56+

"utf-8",

57+

);

58+

}

59+60+

function createToolsForStoredSession(storeTemplate: string, sessionKey: string) {

61+

return createOpenClawCodingTools({

62+

sessionKey,

63+

config: {

64+

session: {

65+

store: storeTemplate,

66+

},

67+

agents: {

68+

defaults: {

69+

subagents: {

70+

maxSpawnDepth: 2,

71+

},

72+

},

73+

},

74+

},

75+

});

76+

}

77+78+

function expectNoSubagentControlTools(tools: ReturnType<typeof createOpenClawCodingTools>) {

79+

const names = new Set(tools.map((tool) => tool.name));

80+

expect(names.has("sessions_spawn")).toBe(false);

81+

expect(names.has("sessions_list")).toBe(false);

82+

expect(names.has("sessions_history")).toBe(false);

83+

expect(names.has("subagents")).toBe(false);

84+

}

85+4886

describe("createOpenClawCodingTools", () => {

4987

const testConfig: OpenClawConfig = {};

5088

@@ -196,43 +234,16 @@ describe("createOpenClawCodingTools", () => {

196234

const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-depth-policy-"));

197235

try {

198236

const storeTemplate = path.join(tmpDir, "sessions-{agentId}.json");

199-

const storePath = storeTemplate.replaceAll("{agentId}", "main");

200-

await fs.writeFile(

201-

storePath,

202-

JSON.stringify(

203-

{

204-

"agent:main:subagent:flat": {

205-

sessionId: "session-flat-depth-2",

206-

updatedAt: Date.now(),

207-

spawnDepth: 2,

208-

},

209-

},

210-

null,

211-

2,

212-

),

213-

"utf-8",

214-

);

215-216-

const tools = createOpenClawCodingTools({

217-

sessionKey: "agent:main:subagent:flat",

218-

config: {

219-

session: {

220-

store: storeTemplate,

221-

},

222-

agents: {

223-

defaults: {

224-

subagents: {

225-

maxSpawnDepth: 2,

226-

},

227-

},

228-

},

237+

await writeSessionStore(storeTemplate, "main", {

238+

"agent:main:subagent:flat": {

239+

sessionId: "session-flat-depth-2",

240+

updatedAt: Date.now(),

241+

spawnDepth: 2,

229242

},

230243

});

231-

const names = new Set(tools.map((tool) => tool.name));

232-

expect(names.has("sessions_spawn")).toBe(false);

233-

expect(names.has("sessions_list")).toBe(false);

234-

expect(names.has("sessions_history")).toBe(false);

235-

expect(names.has("subagents")).toBe(false);

244+245+

const tools = createToolsForStoredSession(storeTemplate, "agent:main:subagent:flat");

246+

expectNoSubagentControlTools(tools);

236247

} finally {

237248

await fs.rm(tmpDir, { recursive: true, force: true });

238249

}

@@ -242,112 +253,47 @@ describe("createOpenClawCodingTools", () => {

242253

const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-acp-subagent-policy-"));

243254

try {

244255

const storeTemplate = path.join(tmpDir, "sessions-{agentId}.json");

245-

const mainStorePath = storeTemplate.replaceAll("{agentId}", "main");

246-

const writerStorePath = storeTemplate.replaceAll("{agentId}", "writer");

247-

await fs.writeFile(

248-

mainStorePath,

249-

JSON.stringify(

250-

{

251-

"agent:main:acp:child": {

252-

sessionId: "session-acp-child",

253-

updatedAt: Date.now(),

254-

spawnedBy: "agent:main:subagent:parent",

255-

spawnDepth: 2,

256-

subagentRole: "leaf",

257-

subagentControlScope: "none",

258-

},

259-

"agent:main:acp:plain": {

260-

sessionId: "session-acp-plain",

261-

updatedAt: Date.now(),

262-

spawnedBy: "agent:main:main",

263-

},

264-

"agent:main:acp:parent": {

265-

sessionId: "session-acp-parent",

266-

updatedAt: Date.now(),

267-

spawnedBy: "agent:main:subagent:parent",

268-

},

269-

},

270-

null,

271-

2,

272-

),

273-

"utf-8",

274-

);

275-

await fs.writeFile(

276-

writerStorePath,

277-

JSON.stringify(

278-

{

279-

"agent:writer:acp:child": {

280-

sessionId: "session-acp-cross-agent-child",

281-

updatedAt: Date.now(),

282-

spawnedBy: "agent:main:acp:parent",

283-

},

284-

},

285-

null,

286-

2,

287-

),

288-

"utf-8",

289-

);

290-291-

const persistedEnvelopeTools = createOpenClawCodingTools({

292-

sessionKey: "agent:main:acp:child",

293-

config: {

294-

session: {

295-

store: storeTemplate,

296-

},

297-

agents: {

298-

defaults: {

299-

subagents: {

300-

maxSpawnDepth: 2,

301-

},

302-

},

303-

},

256+

await writeSessionStore(storeTemplate, "main", {

257+

"agent:main:acp:child": {

258+

sessionId: "session-acp-child",

259+

updatedAt: Date.now(),

260+

spawnedBy: "agent:main:subagent:parent",

261+

spawnDepth: 2,

262+

subagentRole: "leaf",

263+

subagentControlScope: "none",

264+

},

265+

"agent:main:acp:plain": {

266+

sessionId: "session-acp-plain",

267+

updatedAt: Date.now(),

268+

spawnedBy: "agent:main:main",

269+

},

270+

"agent:main:acp:parent": {

271+

sessionId: "session-acp-parent",

272+

updatedAt: Date.now(),

273+

spawnedBy: "agent:main:subagent:parent",

304274

},

305275

});

306-

const persistedEnvelopeNames = new Set(persistedEnvelopeTools.map((tool) => tool.name));

307-

expect(persistedEnvelopeNames.has("sessions_spawn")).toBe(false);

308-

expect(persistedEnvelopeNames.has("sessions_list")).toBe(false);

309-

expect(persistedEnvelopeNames.has("sessions_history")).toBe(false);

310-

expect(persistedEnvelopeNames.has("subagents")).toBe(false);

311-312-

const restrictedTools = createOpenClawCodingTools({

313-

sessionKey: "agent:main:acp:plain",

314-

config: {

315-

session: {

316-

store: storeTemplate,

317-

},

318-

agents: {

319-

defaults: {

320-

subagents: {

321-

maxSpawnDepth: 2,

322-

},

323-

},

324-

},

276+

await writeSessionStore(storeTemplate, "writer", {

277+

"agent:writer:acp:child": {

278+

sessionId: "session-acp-cross-agent-child",

279+

updatedAt: Date.now(),

280+

spawnedBy: "agent:main:acp:parent",

325281

},

326282

});

283+284+

const persistedEnvelopeTools = createToolsForStoredSession(

285+

storeTemplate,

286+

"agent:main:acp:child",

287+

);

288+

expectNoSubagentControlTools(persistedEnvelopeTools);

289+290+

const restrictedTools = createToolsForStoredSession(storeTemplate, "agent:main:acp:plain");

327291

const restrictedNames = new Set(restrictedTools.map((tool) => tool.name));

328292

expect(restrictedNames.has("sessions_spawn")).toBe(true);

329293

expect(restrictedNames.has("subagents")).toBe(true);

330294331-

const ancestryTools = createOpenClawCodingTools({

332-

sessionKey: "agent:writer:acp:child",

333-

config: {

334-

session: {

335-

store: storeTemplate,

336-

},

337-

agents: {

338-

defaults: {

339-

subagents: {

340-

maxSpawnDepth: 2,

341-

},

342-

},

343-

},

344-

},

345-

});

346-

const ancestryNames = new Set(ancestryTools.map((tool) => tool.name));

347-

expect(ancestryNames.has("sessions_spawn")).toBe(false);

348-

expect(ancestryNames.has("sessions_list")).toBe(false);

349-

expect(ancestryNames.has("sessions_history")).toBe(false);

350-

expect(ancestryNames.has("subagents")).toBe(false);

295+

const ancestryTools = createToolsForStoredSession(storeTemplate, "agent:writer:acp:child");

296+

expectNoSubagentControlTools(ancestryTools);

351297

} finally {

352298

await fs.rm(tmpDir, { recursive: true, force: true });

353299

}

@@ -357,59 +303,23 @@ describe("createOpenClawCodingTools", () => {

357303

const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-cross-agent-subagent-"));

358304

try {

359305

const storeTemplate = path.join(tmpDir, "sessions-{agentId}.json");

360-

const mainStorePath = storeTemplate.replaceAll("{agentId}", "main");

361-

const writerStorePath = storeTemplate.replaceAll("{agentId}", "writer");

362-

await fs.writeFile(

363-

mainStorePath,

364-

JSON.stringify(

365-

{

366-

"agent:main:subagent:parent": {

367-

sessionId: "session-main-parent",

368-

updatedAt: Date.now(),

369-

spawnedBy: "agent:main:main",

370-

},

371-

},

372-

null,

373-

2,

374-

),

375-

"utf-8",

376-

);

377-

await fs.writeFile(

378-

writerStorePath,

379-

JSON.stringify(

380-

{

381-

"agent:writer:subagent:child": {

382-

sessionId: "session-writer-child",

383-

updatedAt: Date.now(),

384-

spawnedBy: "agent:main:subagent:parent",

385-

},

386-

},

387-

null,

388-

2,

389-

),

390-

"utf-8",

391-

);

392-393-

const tools = createOpenClawCodingTools({

394-

sessionKey: "agent:writer:subagent:child",

395-

config: {

396-

session: {

397-

store: storeTemplate,

398-

},

399-

agents: {

400-

defaults: {

401-

subagents: {

402-

maxSpawnDepth: 2,

403-

},

404-

},

405-

},

306+

await writeSessionStore(storeTemplate, "main", {

307+

"agent:main:subagent:parent": {

308+

sessionId: "session-main-parent",

309+

updatedAt: Date.now(),

310+

spawnedBy: "agent:main:main",

406311

},

407312

});

408-

const names = new Set(tools.map((tool) => tool.name));

409-

expect(names.has("sessions_spawn")).toBe(false);

410-

expect(names.has("sessions_list")).toBe(false);

411-

expect(names.has("sessions_history")).toBe(false);

412-

expect(names.has("subagents")).toBe(false);

313+

await writeSessionStore(storeTemplate, "writer", {

314+

"agent:writer:subagent:child": {

315+

sessionId: "session-writer-child",

316+

updatedAt: Date.now(),

317+

spawnedBy: "agent:main:subagent:parent",

318+

},

319+

});

320+321+

const tools = createToolsForStoredSession(storeTemplate, "agent:writer:subagent:child");

322+

expectNoSubagentControlTools(tools);

413323

} finally {

414324

await fs.rm(tmpDir, { recursive: true, force: true });

415325

}