/ tools / FileEditTool / types.ts
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 }