diff --git a/src/auto-reply/reply/agent-runner-execution.ts b/src/auto-reply/reply/agent-runner-execution.ts index 1aaf22fc6..f86ecb8a9 100644 --- a/src/auto-reply/reply/agent-runner-execution.ts +++ b/src/auto-reply/reply/agent-runner-execution.ts @@ -1,6 +1,5 @@ import crypto from "node:crypto"; import fs from "node:fs"; -import path from "node:path"; import { resolveAgentModelFallbacksOverride } from "../../agents/agent-scope.js"; import { runCliAgent } from "../../agents/cli-runner.js"; import { getCliSessionId } from "../../agents/cli-session.js"; @@ -193,50 +192,6 @@ export async function runAgentTurnWithFallback(params: { 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({ runId, stream: "lifecycle", diff --git a/src/commands/agent.ts b/src/commands/agent.ts index 0e745557c..31c137d77 100644 --- a/src/commands/agent.ts +++ b/src/commands/agent.ts @@ -1,3 +1,6 @@ +import fs from "node:fs"; +import path from "node:path"; +import crypto from "node:crypto"; import { listAgentIds, resolveAgentDir, @@ -40,6 +43,7 @@ import { type SessionEntry, updateSessionStore, } from "../config/sessions.js"; +import { resolveSessionTranscriptPath } from "../config/sessions/paths.js"; import { clearAgentRunContext, emitAgentEvent, @@ -460,6 +464,43 @@ export async function agentCommand( result = fallbackResult.result; fallbackProvider = fallbackResult.provider; fallbackModel = fallbackResult.model; + + // Write CLI transcript for subagent announce flow + // CLI backends don't normally write transcripts, but subagent-announce + // needs them to read the findings when the run completes. + if (isCliProvider(fallbackProvider, cfg) && result.payloads?.[0]?.text) { + try { + const agentId = resolveAgentIdFromSessionKey(sessionKey); + const transcriptPath = resolveSessionTranscriptPath(sessionId, agentId); + fs.mkdirSync(path.dirname(transcriptPath), { recursive: true }); + if (!fs.existsSync(transcriptPath)) { + const header = { + type: "session", + version: 1, + id: sessionId, + timestamp: new Date().toISOString(), + cwd: process.cwd(), + }; + fs.writeFileSync(transcriptPath, JSON.stringify(header) + "\n", "utf-8"); + } + const messageEntry = { + type: "message", + id: crypto.randomUUID().slice(0, 8), + timestamp: new Date().toISOString(), + message: { + role: "assistant", + content: [{ type: "text", text: result.payloads[0].text }], + timestamp: Date.now(), + stopReason: "cli", + usage: result.meta?.usage ?? { input: 0, output: 0, totalTokens: 0 }, + }, + }; + fs.appendFileSync(transcriptPath, JSON.stringify(messageEntry) + "\n", "utf-8"); + } catch { + // Transcript write failure is non-fatal - log silently + } + } + if (!lifecycleEnded) { emitAgentEvent({ runId,