( args, toolCallId, extras, )
| 4 | import { ClientToolImpl } from "./callClientTool"; |
| 5 | |
| 6 | export const editToolImpl: ClientToolImpl = async ( |
| 7 | args, |
| 8 | toolCallId, |
| 9 | extras, |
| 10 | ) => { |
| 11 | if (!args.filepath || !args.changes) { |
| 12 | throw new Error( |
| 13 | "`filepath` and `changes` arguments are required to edit an existing file.", |
| 14 | ); |
| 15 | } |
| 16 | let filepath = args.filepath; |
| 17 | if (filepath.startsWith("./")) { |
| 18 | filepath = filepath.slice(2); |
| 19 | } |
| 20 | |
| 21 | let firstUriMatch = await resolveRelativePathInDir( |
| 22 | filepath, |
| 23 | extras.ideMessenger.ide, |
| 24 | ); |
| 25 | |
| 26 | if (!firstUriMatch) { |
| 27 | const openFiles = await extras.ideMessenger.ide.getOpenFiles(); |
| 28 | for (const uri of openFiles) { |
| 29 | if (uri.endsWith(filepath)) { |
| 30 | firstUriMatch = uri; |
| 31 | break; |
| 32 | } |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | if (!firstUriMatch) { |
| 37 | throw new Error(`${filepath} does not exist`); |
| 38 | } |
| 39 | const streamId = uuid(); |
| 40 | void extras.dispatch( |
| 41 | applyForEditTool({ |
| 42 | streamId, |
| 43 | text: args.changes, |
| 44 | toolCallId, |
| 45 | filepath: firstUriMatch, |
| 46 | }), |
| 47 | ); |
| 48 | |
| 49 | return { |
| 50 | respondImmediately: false, |
| 51 | output: undefined, // no immediate output - output for edit tools should be added based on apply state coming in |
| 52 | }; |
| 53 | }; |
no test coverage detected