-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Expand file tree
/
Copy pathwrite_file.ts
More file actions
84 lines (71 loc) · 2.68 KB
/
Copy pathwrite_file.ts
File metadata and controls
84 lines (71 loc) · 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import fs from "node:fs";
import path from "node:path";
import { z } from "zod";
import log from "electron-log";
import { ToolDefinition, AgentContext, escapeXmlAttr } from "./types";
import { safeJoin } from "@/ipc/utils/path_utils";
import { deploySupabaseFunction } from "../../../../../../supabase_admin/supabase_management_client";
import {
isServerFunction,
isSharedServerModule,
} from "../../../../../../supabase_admin/supabase_utils";
import { resolveFileUploadContent } from "./file_upload_utils";
const logger = log.scope("write_file");
const writeFileSchema = z.object({
path: z.string().describe("The file path relative to the app root"),
content: z.string().describe("The content to write to the file"),
description: z
.string()
.optional()
.describe("Brief description of the change"),
});
export const writeFileTool: ToolDefinition<z.infer<typeof writeFileSchema>> = {
name: "write_file",
description: "Create or completely overwrite a file in the codebase",
inputSchema: writeFileSchema,
defaultConsent: "always",
modifiesState: true,
getConsentPreview: (args) => `Write to ${args.path}`,
buildXml: (args, isComplete) => {
if (!args.path) return undefined;
let xml = `<dyad-write path="${escapeXmlAttr(args.path)}" description="${escapeXmlAttr(args.description ?? "")}">\n${args.content ?? ""}`;
if (isComplete) {
xml += "\n</dyad-write>";
}
return xml;
},
execute: async (args, ctx: AgentContext) => {
const fullFilePath = safeJoin(ctx.appPath, args.path);
// Track if this is a shared module
if (isSharedServerModule(args.path)) {
ctx.isSharedModulesChanged = true;
}
// Resolve file upload IDs to actual content
const resolved = await resolveFileUploadContent(args.content, ctx.chatId);
const contentToWrite = resolved.content;
// Ensure directory exists
const dirPath = path.dirname(fullFilePath);
fs.mkdirSync(dirPath, { recursive: true });
// Write file content
fs.writeFileSync(fullFilePath, contentToWrite);
logger.log(`Successfully wrote file: ${fullFilePath}`);
// Deploy Supabase function if applicable
if (
ctx.supabaseProjectId &&
isServerFunction(args.path) &&
!ctx.isSharedModulesChanged
) {
try {
await deploySupabaseFunction({
supabaseProjectId: ctx.supabaseProjectId,
functionName: path.basename(path.dirname(args.path)),
appPath: ctx.appPath,
organizationSlug: ctx.supabaseOrganizationSlug ?? null,
});
} catch (error) {
return `File written, but failed to deploy Supabase function: ${error}`;
}
}
return `Successfully wrote ${args.path}`;
},
};