Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 24802f51db |
@@ -22,7 +22,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@uncaged/json-cas": "^0.4.0",
|
||||
"@uncaged/workflow-agent-kit": "workspace:^"
|
||||
"@uncaged/workflow-agent-kit": "workspace:^",
|
||||
"@uncaged/workflow-util": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.8.3"
|
||||
|
||||
@@ -9,12 +9,15 @@ import {
|
||||
getCachedSessionId,
|
||||
setCachedSessionId,
|
||||
} from "@uncaged/workflow-agent-kit";
|
||||
import { createLogger } from "@uncaged/workflow-util";
|
||||
|
||||
import { parseClaudeCodeJsonOutput, storeClaudeCodeDetail } from "./session-detail.js";
|
||||
|
||||
const CLAUDE_COMMAND = "claude";
|
||||
const CLAUDE_MAX_TURNS = 90;
|
||||
|
||||
const log = createLogger({ sink: { kind: "stderr" } });
|
||||
|
||||
function buildHistorySummary(steps: AgentContext["steps"]): string {
|
||||
if (steps.length === 0) {
|
||||
return "";
|
||||
@@ -135,17 +138,22 @@ async function runClaudeCode(ctx: AgentContext): Promise<AgentRunResult> {
|
||||
try {
|
||||
const { stdout } = await spawnClaudeResume(cachedSessionId, fullPrompt);
|
||||
const result = await processClaudeOutput(stdout, ctx.store);
|
||||
await setCachedSessionId(ctx.threadId, ctx.role, result.sessionId);
|
||||
if (result.sessionId !== "") {
|
||||
await setCachedSessionId(ctx.threadId, ctx.role, result.sessionId);
|
||||
}
|
||||
return result;
|
||||
} catch {
|
||||
// Resume failed — fall through to fresh run.
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
log("5VKR8N3Q", `session resume failed, falling back to new session: ${message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { stdout } = await spawnClaudeRun(fullPrompt);
|
||||
const result = await processClaudeOutput(stdout, ctx.store);
|
||||
await setCachedSessionId(ctx.threadId, ctx.role, result.sessionId);
|
||||
if (result.sessionId !== "") {
|
||||
await setCachedSessionId(ctx.threadId, ctx.role, result.sessionId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
||||
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
||||
import { dirname, join } from "node:path";
|
||||
|
||||
import type { ThreadId } from "@uncaged/workflow-protocol";
|
||||
@@ -43,10 +43,20 @@ async function readCache(): Promise<SessionCache> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomic write: write to a temp file, then rename.
|
||||
* Prevents partial reads if another process reads mid-write.
|
||||
* Note: read-modify-write is still not concurrency-safe across processes;
|
||||
* the current workflow engine runs agent steps sequentially (execFileSync),
|
||||
* so this is sufficient. If parallel execution is added later, a proper
|
||||
* lockfile (e.g. proper-lockfile) will be needed.
|
||||
*/
|
||||
async function writeCache(cache: SessionCache): Promise<void> {
|
||||
const path = getCachePath();
|
||||
const tmpPath = `${path}.${process.pid}.tmp`;
|
||||
await mkdir(dirname(path), { recursive: true });
|
||||
await writeFile(path, `${JSON.stringify(cache, null, 2)}\n`, "utf8");
|
||||
await writeFile(tmpPath, `${JSON.stringify(cache, null, 2)}\n`, "utf8");
|
||||
await rename(tmpPath, path);
|
||||
}
|
||||
|
||||
/** Read the cached session ID for a thread+role pair. */
|
||||
|
||||
Reference in New Issue
Block a user