From 3bca6ed7857fc22950b02ce3633efb4c906fe28d Mon Sep 17 00:00:00 2001 From: Ziyang Guo <121015044+RerankerGuo@users.noreply.github.com> Date: Thu, 11 Jun 2026 00:18:03 +0800 Subject: [PATCH] fix(runner): seed clean workspace task brief Signed-off-by: Ziyang Guo <121015044+RerankerGuo@users.noreply.github.com> --- src/utils/clean-context-runner.test.ts | 59 ++++++++++++++++++++++++++ src/utils/clean-context-runner.ts | 30 +++++++++++-- 2 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 src/utils/clean-context-runner.test.ts diff --git a/src/utils/clean-context-runner.test.ts b/src/utils/clean-context-runner.test.ts new file mode 100644 index 0000000..044a064 --- /dev/null +++ b/src/utils/clean-context-runner.test.ts @@ -0,0 +1,59 @@ +import fs from "node:fs/promises"; +import path from "node:path"; +import { describe, expect, it } from "vitest"; +import { CleanContextRunner } from "./clean-context-runner.js"; + +describe("CleanContextRunner", () => { + it("seeds default clean workspace with task brief files and passes explicit prompts", async () => { + const calls: Array> = []; + const runner = new CleanContextRunner({ + config: { + agents: { + defaults: { + systemPromptOverride: "existing host prompt", + }, + }, + }, + agentRuntime: { + runEmbeddedPiAgent: (async (args: Record) => { + calls.push(args); + return { + payloads: [ + { + text: "[]", + }, + ], + }; + }) as never, + }, + }); + + const result = await runner.run({ + taskId: "l1-extraction", + systemPrompt: "extract memories as JSON", + prompt: "conversation payload", + timeoutMs: 1000, + }); + + expect(result).toBe("[]"); + expect(calls).toHaveLength(1); + const call = calls[0]; + expect(call.prompt).toBe("conversation payload"); + expect(call.extraSystemPrompt).toBe("extract memories as JSON"); + expect(call.disableTools).toBe(true); + expect((call.config as { + agents: { defaults: { systemPromptOverride: string } }; + }).agents.defaults.systemPromptOverride).toBe("extract memories as JSON"); + + const workspaceDir = call.workspaceDir; + expect(typeof workspaceDir).toBe("string"); + const agents = await fs.readFile(path.join(workspaceDir as string, "AGENTS.md"), "utf8"); + const soul = await fs.readFile(path.join(workspaceDir as string, "SOUL.md"), "utf8"); + + expect(agents.length).toBeGreaterThan(76); + expect(agents).toContain("TencentDB Agent Memory"); + expect(agents).toContain("Follow the explicit system prompt and user prompt"); + expect(soul.length).toBeGreaterThan(76); + expect(soul).toContain("system and user prompts"); + }); +}); diff --git a/src/utils/clean-context-runner.ts b/src/utils/clean-context-runner.ts index d8ae883..9cd5101 100644 --- a/src/utils/clean-context-runner.ts +++ b/src/utils/clean-context-runner.ts @@ -285,14 +285,38 @@ export interface CleanContextRunnerOptions { logger?: RunnerLogger; } -// Stable empty directory used as default workspaceDir so that: -// 1. Bootstrap/skills scans find nothing → clean LLM context +const CLEAN_WORKSPACE_AGENTS = `# TencentDB Agent Memory Background Task + +This is an isolated workspace for TencentDB Agent Memory background LLM tasks. +Do not infer task requirements from repository files in this directory. +Follow the explicit system prompt and user prompt passed with the current run. +Return only the output format requested by that prompt. +`; + +const CLEAN_WORKSPACE_SOUL = `You are running an isolated TencentDB Agent Memory background task. +The real task instructions are supplied directly in the current system and user prompts. +Ignore the absence of project files here and answer according to those prompts only. +`; + +async function ensureCleanWorkspaceBrief(dir: string): Promise { + await Promise.all([ + fs.writeFile(path.join(dir, "AGENTS.md"), CLEAN_WORKSPACE_AGENTS, "utf8"), + fs.writeFile(path.join(dir, "SOUL.md"), CLEAN_WORKSPACE_SOUL, "utf8"), + ]); +} + +// Stable low-context directory used as default workspaceDir so that: +// 1. Bootstrap/skills scans see only a tiny task brief → clean LLM context // 2. The path is constant → plugin cacheKey stays stable (no re-registration) let _cleanWorkspaceDir: string | undefined; async function getCleanWorkspaceDir(): Promise { - if (_cleanWorkspaceDir) return _cleanWorkspaceDir; + if (_cleanWorkspaceDir) { + await ensureCleanWorkspaceBrief(_cleanWorkspaceDir); + return _cleanWorkspaceDir; + } const dir = path.join(resolveOpenClawTmpDir(), "memory-tdai-clean-workspace"); await fs.mkdir(dir, { recursive: true }); + await ensureCleanWorkspaceBrief(dir); _cleanWorkspaceDir = dir; return dir; }