UNPKG

scai

Version:

> **AI-powered CLI for local code analysis, commit message suggestions, and natural-language queries.** 100% local, private, GDPR-friendly, made in Denmark/EU with ❤️.

87 lines (86 loc) 3.46 kB
// File: src/modules/writeFileModule.ts import fs from "fs/promises"; import chalk from "chalk"; import { normalizePath } from "../../utils/contentUtils.js"; import { logInputOutput } from "../../utils/promptLogHelper.js"; export const writeFileModule = { name: "writeFile", description: "Writes materialized file outputs from codeTransformModule to disk. " + "Only writes files specified in the current plan step.", groups: ["finalize"], run: async (input) => { var _a; const context = input.context; const mode = input.data?.mode ?? "overwrite"; if (!context) { return { query: input.query, data: { writeMode: mode, writtenFiles: [], errors: ["Missing execution context"] }, }; } const step = context.currentStep; if (!step) { return { query: input.query, data: { writeMode: mode, writtenFiles: [], errors: ["No current step in context"] }, }; } // Determine target file(s) from the current step const targetFiles = []; if (step.targetFile) targetFiles.push(step.targetFile); if (Array.isArray(step.targetFiles)) targetFiles.push(...step.targetFiles); if (!targetFiles.length) { return { query: input.query, data: { writeMode: mode, writtenFiles: [], errors: ["No targetFile(s) specified in current step"] }, }; } // Filter codeTransformArtifacts to only the target file(s) const allFiles = context.execution?.codeTransformArtifacts?.files ?? []; const filesToWrite = allFiles.filter(f => targetFiles.includes(f.filePath)); if (!filesToWrite.length) { return { query: input.query, data: { writeMode: mode, writtenFiles: [], errors: ["No transformed files found for targetFile(s)"] }, }; } const writtenFiles = []; const errors = []; for (const f of filesToWrite) { const filePath = normalizePath(f.filePath); if (!filePath) { errors.push(`Invalid filePath: ${f.filePath}`); continue; } if (typeof f.content !== "string" || !f.content.trim()) { errors.push(`No content to write for ${filePath}`); continue; } try { await fs.writeFile(filePath, f.content, "utf-8"); console.log(chalk.green(`✅ Written: ${filePath}`)); writtenFiles.push(filePath); } catch (err) { console.error(chalk.red(`❌ Failed writing ${filePath}:`), err); errors.push(`${filePath}: ${err.message}`); } } // Mark only the files we just wrote as touched context.plan ?? (context.plan = {}); (_a = context.plan).touchedFiles ?? (_a.touchedFiles = []); for (const file of writtenFiles) { if (!context.plan.touchedFiles.includes(file)) { context.plan.touchedFiles.push(file); } } const output = { query: input.query, data: { writeMode: mode, writtenFiles, errors }, }; logInputOutput("writeFile", "output", output.data); return output; }, };