types.ts
1 import { z } from 'zod/v4' 2 import { lazySchema } from '../../utils/lazySchema.js' 3 import { semanticBoolean } from '../../utils/semanticBoolean.js' 4 5 // The input schema with optional replace_all 6 const inputSchema = lazySchema(() => 7 z.strictObject({ 8 file_path: z.string().describe('The absolute path to the file to modify'), 9 old_string: z.string().describe('The text to replace'), 10 new_string: z 11 .string() 12 .describe( 13 'The text to replace it with (must be different from old_string)', 14 ), 15 replace_all: semanticBoolean( 16 z.boolean().default(false).optional(), 17 ).describe('Replace all occurrences of old_string (default false)'), 18 }), 19 ) 20 type InputSchema = ReturnType<typeof inputSchema> 21 22 // Parsed output — what call() receives. z.output not z.input: with 23 // semanticBoolean the input side is unknown (preprocess accepts anything). 24 export type FileEditInput = z.output<InputSchema> 25 26 // Individual edit without file_path 27 export type EditInput = Omit<FileEditInput, 'file_path'> 28 29 // Runtime version where replace_all is always defined 30 export type FileEdit = { 31 old_string: string 32 new_string: string 33 replace_all: boolean 34 } 35 36 export const hunkSchema = lazySchema(() => 37 z.object({ 38 oldStart: z.number(), 39 oldLines: z.number(), 40 newStart: z.number(), 41 newLines: z.number(), 42 lines: z.array(z.string()), 43 }), 44 ) 45 46 export const gitDiffSchema = lazySchema(() => 47 z.object({ 48 filename: z.string(), 49 status: z.enum(['modified', 'added']), 50 additions: z.number(), 51 deletions: z.number(), 52 changes: z.number(), 53 patch: z.string(), 54 repository: z 55 .string() 56 .nullable() 57 .optional() 58 .describe('GitHub owner/repo when available'), 59 }), 60 ) 61 62 // Output schema for FileEditTool 63 const outputSchema = lazySchema(() => 64 z.object({ 65 filePath: z.string().describe('The file path that was edited'), 66 oldString: z.string().describe('The original string that was replaced'), 67 newString: z.string().describe('The new string that replaced it'), 68 originalFile: z 69 .string() 70 .describe('The original file contents before editing'), 71 structuredPatch: z 72 .array(hunkSchema()) 73 .describe('Diff patch showing the changes'), 74 userModified: z 75 .boolean() 76 .describe('Whether the user modified the proposed changes'), 77 replaceAll: z.boolean().describe('Whether all occurrences were replaced'), 78 gitDiff: gitDiffSchema().optional(), 79 }), 80 ) 81 type OutputSchema = ReturnType<typeof outputSchema> 82 83 export type FileEditOutput = z.infer<OutputSchema> 84 85 export { inputSchema, outputSchema }