* Done if: * * 1. Tab is closed in IDE * 2. Tab is saved in IDE (we then close the tab) * 3. User selected an option in IDE * 4. User selected an option in terminal (or hit esc) * * Resolves with the new file content. * * TODO: Time out after 5 mins of inactivity? * TODO: Update auto-appro
( file_path: string, edits: FileEdit[], toolUseContext: ToolUseContext, tabName: string, )
| 214 | * TODO: Close the IDE tab when the approval prompt is unmounted |
| 215 | */ |
| 216 | async function showDiffInIDE( |
| 217 | file_path: string, |
| 218 | edits: FileEdit[], |
| 219 | toolUseContext: ToolUseContext, |
| 220 | tabName: string, |
| 221 | ): Promise<{ oldContent: string; newContent: string }> { |
| 222 | let isCleanedUp = false |
| 223 | |
| 224 | const oldFilePath = expandPath(file_path) |
| 225 | let oldContent = '' |
| 226 | try { |
| 227 | oldContent = readFileSync(oldFilePath) |
| 228 | } catch (e: unknown) { |
| 229 | if (!isENOENT(e)) { |
| 230 | throw e |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | async function cleanup() { |
| 235 | // Careful to avoid race conditions, since this |
| 236 | // function can be called from multiple places. |
| 237 | if (isCleanedUp) { |
| 238 | return |
| 239 | } |
| 240 | isCleanedUp = true |
| 241 | |
| 242 | // Don't fail if this fails |
| 243 | try { |
| 244 | await closeTabInIDE(tabName, ideClient) |
| 245 | } catch (e) { |
| 246 | logError(e as Error) |
| 247 | } |
| 248 | |
| 249 | process.off('beforeExit', cleanup) |
| 250 | toolUseContext.abortController.signal.removeEventListener('abort', cleanup) |
| 251 | } |
| 252 | |
| 253 | // Cleanup if the user hits esc to cancel the tool call - or on exit |
| 254 | toolUseContext.abortController.signal.addEventListener('abort', cleanup) |
| 255 | process.on('beforeExit', cleanup) |
| 256 | |
| 257 | // Open the diff in the IDE |
| 258 | const ideClient = getConnectedIdeClient(toolUseContext.options.mcpClients) |
| 259 | try { |
| 260 | const { updatedFile } = getPatchForEdits({ |
| 261 | filePath: oldFilePath, |
| 262 | fileContents: oldContent, |
| 263 | edits, |
| 264 | }) |
| 265 | |
| 266 | if (!ideClient || ideClient.type !== 'connected') { |
| 267 | throw new Error('IDE client not available') |
| 268 | } |
| 269 | let ideOldPath = oldFilePath |
| 270 | |
| 271 | // Only convert paths if we're in WSL and IDE is on Windows |
| 272 | const ideRunningInWindows = |
| 273 | (ideClient.config as McpSSEIDEServerConfig | McpWebSocketIDEServerConfig) |
no test coverage detected