diff --git a/apps/server/agent/file-io.ts b/apps/server/agent/file-io.ts index 6f07b13..211befc 100644 --- a/apps/server/agent/file-io.ts +++ b/apps/server/agent/file-io.ts @@ -8,8 +8,8 @@ * Output: .cw/output/ — written by agent during execution */ -import { readdirSync, existsSync, readFileSync } from 'node:fs'; -import { mkdir, writeFile } from 'node:fs/promises'; +import { existsSync } from 'node:fs'; +import { mkdir, writeFile, readFile, readdir } from 'node:fs/promises'; import { join } from 'node:path'; import matter from 'gray-matter'; import { nanoid } from 'nanoid'; @@ -303,9 +303,9 @@ export async function writeInputFiles(options: WriteInputFilesOptions): Promise< // OUTPUT FILE READING // ============================================================================= -export function readFrontmatterFile(filePath: string): { data: Record; body: string } | null { +export async function readFrontmatterFile(filePath: string): Promise<{ data: Record; body: string } | null> { try { - const raw = readFileSync(filePath, 'utf-8'); + const raw = await readFile(filePath, 'utf-8'); const parsed = matter(raw); return { data: parsed.data as Record, body: parsed.content.trim() }; } catch { @@ -313,19 +313,19 @@ export function readFrontmatterFile(filePath: string): { data: Record( +async function readFrontmatterDir( dirPath: string, mapper: (data: Record, body: string, filename: string) => T | null, -): T[] { +): Promise { if (!existsSync(dirPath)) return []; const results: T[] = []; try { - const entries = readdirSync(dirPath); + const entries = await readdir(dirPath); for (const entry of entries) { if (!entry.endsWith('.md')) continue; const filePath = join(dirPath, entry); - const parsed = readFrontmatterFile(filePath); + const parsed = await readFrontmatterFile(filePath); if (!parsed) continue; const mapped = mapper(parsed.data, parsed.body, entry); if (mapped) results.push(mapped); @@ -336,9 +336,9 @@ function readFrontmatterDir( return results; } -export function readSummary(agentWorkdir: string): ParsedSummary | null { +export async function readSummary(agentWorkdir: string): Promise { const filePath = join(agentWorkdir, '.cw', 'output', 'SUMMARY.md'); - const parsed = readFrontmatterFile(filePath); + const parsed = await readFrontmatterFile(filePath); if (!parsed) return null; const filesModified = parsed.data.files_modified; @@ -348,7 +348,7 @@ export function readSummary(agentWorkdir: string): ParsedSummary | null { }; } -export function readPhaseFiles(agentWorkdir: string): ParsedPhaseFile[] { +export async function readPhaseFiles(agentWorkdir: string): Promise { const dirPath = join(agentWorkdir, '.cw', 'output', 'phases'); return readFrontmatterDir(dirPath, (data, body, filename) => { const id = filename.replace(/\.md$/, ''); @@ -364,7 +364,7 @@ export function readPhaseFiles(agentWorkdir: string): ParsedPhaseFile[] { }); } -export function readTaskFiles(agentWorkdir: string): ParsedTaskFile[] { +export async function readTaskFiles(agentWorkdir: string): Promise { const dirPath = join(agentWorkdir, '.cw', 'output', 'tasks'); return readFrontmatterDir(dirPath, (data, body, filename) => { const id = filename.replace(/\.md$/, ''); @@ -384,7 +384,7 @@ export function readTaskFiles(agentWorkdir: string): ParsedTaskFile[] { }); } -export function readDecisionFiles(agentWorkdir: string): ParsedDecisionFile[] { +export async function readDecisionFiles(agentWorkdir: string): Promise { const dirPath = join(agentWorkdir, '.cw', 'output', 'decisions'); return readFrontmatterDir(dirPath, (data, body, filename) => { const id = filename.replace(/\.md$/, ''); @@ -398,7 +398,7 @@ export function readDecisionFiles(agentWorkdir: string): ParsedDecisionFile[] { }); } -export function readPageFiles(agentWorkdir: string): ParsedPageFile[] { +export async function readPageFiles(agentWorkdir: string): Promise { const dirPath = join(agentWorkdir, '.cw', 'output', 'pages'); return readFrontmatterDir(dirPath, (data, body, filename) => { const pageId = filename.replace(/\.md$/, ''); diff --git a/apps/server/agent/output-handler.ts b/apps/server/agent/output-handler.ts index 2413c17..9c85b2c 100644 --- a/apps/server/agent/output-handler.ts +++ b/apps/server/agent/output-handler.ts @@ -415,14 +415,14 @@ export class OutputHandler { getAgentWorkdir: (alias: string) => string, ): Promise { const agentWorkdir = getAgentWorkdir(agent.worktreeId); - const summary = readSummary(agentWorkdir); + const summary = await readSummary(agentWorkdir); const initiativeId = agent.initiativeId; const canWriteChangeSets = this.changeSetRepository && initiativeId; let resultMessage = summary?.body ?? 'Task completed'; switch (mode) { case 'plan': { - const phases = readPhaseFiles(agentWorkdir); + const phases = await readPhaseFiles(agentWorkdir); if (canWriteChangeSets && this.phaseRepository && phases.length > 0) { const entries: CreateChangeSetEntryData[] = []; @@ -499,9 +499,9 @@ export class OutputHandler { break; } case 'detail': { - const tasks = readTaskFiles(agentWorkdir); + const tasks = await readTaskFiles(agentWorkdir); if (canWriteChangeSets && this.taskRepository && tasks.length > 0) { - const phaseInput = readFrontmatterFile(join(agentWorkdir, '.cw', 'input', 'phase.md')); + const phaseInput = await readFrontmatterFile(join(agentWorkdir, '.cw', 'input', 'phase.md')); const phaseId = (phaseInput?.data?.id as string) ?? null; const entries: CreateChangeSetEntryData[] = []; const fileIdToDbId = new Map(); @@ -595,12 +595,12 @@ export class OutputHandler { break; } case 'discuss': { - const decisions = readDecisionFiles(agentWorkdir); + const decisions = await readDecisionFiles(agentWorkdir); resultMessage = JSON.stringify({ summary: summary?.body, decisions }); break; } case 'refine': { - const pages = readPageFiles(agentWorkdir); + const pages = await readPageFiles(agentWorkdir); if (canWriteChangeSets && this.pageRepository && pages.length > 0) { const entries: CreateChangeSetEntryData[] = []; @@ -662,9 +662,9 @@ export class OutputHandler { break; } case 'chat': { - const chatPhases = readPhaseFiles(agentWorkdir); - const chatTasks = readTaskFiles(agentWorkdir); - const chatPages = readPageFiles(agentWorkdir); + const chatPhases = await readPhaseFiles(agentWorkdir); + const chatTasks = await readTaskFiles(agentWorkdir); + const chatPages = await readPageFiles(agentWorkdir); if (canWriteChangeSets) { const entries: CreateChangeSetEntryData[] = []; let sortOrd = 0;