feat: write transcript for CLI provider runs [AI-assisted]
CLI backends (claude-cli, codex-cli, etc.) don't normally save session transcripts because they run as external processes. This causes issues with subagent announce flow - when a CLI-backed subagent completes, the main agent can't read the reply because no transcript exists. This change writes a JSONL transcript file after CLI provider runs complete, using the same format as embedded Pi sessions: - Session header with version, id, timestamp, cwd - Message entry with assistant role, content, timestamp, usage The transcript path is resolved from the session key/id and agent id, matching the embedded runner's behavior. Transcript writes are best-effort and won't fail the run. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
109ac1c549
commit
b61aa94c28
@ -1,5 +1,6 @@
|
|||||||
import crypto from "node:crypto";
|
import crypto from "node:crypto";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
import { resolveAgentModelFallbacksOverride } from "../../agents/agent-scope.js";
|
import { resolveAgentModelFallbacksOverride } from "../../agents/agent-scope.js";
|
||||||
import { runCliAgent } from "../../agents/cli-runner.js";
|
import { runCliAgent } from "../../agents/cli-runner.js";
|
||||||
import { getCliSessionId } from "../../agents/cli-session.js";
|
import { getCliSessionId } from "../../agents/cli-session.js";
|
||||||
@ -192,6 +193,50 @@ export async function runAgentTurnWithFallback(params: {
|
|||||||
data: { text: cliText },
|
data: { text: cliText },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Write CLI result to transcript for subagent announce flow
|
||||||
|
if (cliText && params.sessionKey && params.followupRun.run.sessionId) {
|
||||||
|
try {
|
||||||
|
const agentId = resolveAgentIdFromSessionKey(params.sessionKey);
|
||||||
|
const transcriptPath = resolveSessionTranscriptPath(
|
||||||
|
params.followupRun.run.sessionId,
|
||||||
|
agentId,
|
||||||
|
);
|
||||||
|
// Ensure directory exists
|
||||||
|
fs.mkdirSync(path.dirname(transcriptPath), { recursive: true });
|
||||||
|
// Create session header if file doesn't exist
|
||||||
|
if (!fs.existsSync(transcriptPath)) {
|
||||||
|
const header = {
|
||||||
|
type: "session",
|
||||||
|
version: 1,
|
||||||
|
id: params.followupRun.run.sessionId,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
cwd: process.cwd(),
|
||||||
|
};
|
||||||
|
fs.writeFileSync(transcriptPath, JSON.stringify(header) + "\n", "utf-8");
|
||||||
|
}
|
||||||
|
// Append assistant message
|
||||||
|
const messageEntry = {
|
||||||
|
type: "message",
|
||||||
|
id: crypto.randomUUID().slice(0, 8),
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
message: {
|
||||||
|
role: "assistant",
|
||||||
|
content: [{ type: "text", text: cliText }],
|
||||||
|
timestamp: Date.now(),
|
||||||
|
stopReason: "cli",
|
||||||
|
usage: result.meta?.agentMeta?.usage ?? {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
totalTokens: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
fs.appendFileSync(transcriptPath, JSON.stringify(messageEntry) + "\n", "utf-8");
|
||||||
|
} catch (err) {
|
||||||
|
// Best effort - don't fail the run if transcript write fails
|
||||||
|
logVerbose(`CLI transcript write failed: ${String(err)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
emitAgentEvent({
|
emitAgentEvent({
|
||||||
runId,
|
runId,
|
||||||
stream: "lifecycle",
|
stream: "lifecycle",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user