| 104 | argsSchema = ScreenshotArgs; |
| 105 | |
| 106 | async execute(args: z.infer<typeof ScreenshotArgs>, _ctx: ToolContext): Promise<ToolResult> { |
| 107 | if (!isMacos()) return macosOnly(this.name); |
| 108 | try { |
| 109 | const dir = path.join(os.tmpdir(), 'qodex-screenshots'); |
| 110 | await fs.mkdir(dir, { recursive: true }); |
| 111 | const dest = args.path ?? path.join(dir, `desktop-${Date.now()}.png`); |
| 112 | |
| 113 | if (args.window) { |
| 114 | // First, ask System Events for the window id of the app's frontmost window. |
| 115 | // Then use screencapture -l <id>. |
| 116 | const script = `tell application "System Events" to tell process "${args.window.replace(/"/g, '\\"')}" to set winId to id of window 1`; |
| 117 | let windowId: string; |
| 118 | try { |
| 119 | const { stdout } = await runCmd('osascript', ['-e', script], { timeoutMs: 5000 }); |
| 120 | windowId = stdout.trim(); |
| 121 | } catch (e: any) { |
| 122 | return { |
| 123 | content: `[COMPUTER_USE_ERROR] Couldn't find a window for app "${args.window}". Make sure the app is running and has at least one window. (osascript: ${e?.message ?? e}). If you got an Accessibility-permission prompt, grant it in System Settings > Privacy & Security > Accessibility, then retry.`, |
| 124 | isError: true, |
| 125 | }; |
| 126 | } |
| 127 | await runCmd('screencapture', ['-l', windowId, '-x', dest], { timeoutMs: 10_000 }); |
| 128 | } else { |
| 129 | // Whole screen, no sound (-x) |
| 130 | await runCmd('screencapture', ['-x', dest], { timeoutMs: 10_000 }); |
| 131 | } |
| 132 | const stat = await fs.stat(dest); |
| 133 | return { |
| 134 | content: `Screenshot saved: ${dest}\n Size: ${(stat.size / 1024).toFixed(1)} KB${args.window ? `\n Window: ${args.window}` : '\n Capture: full screen'}\n\nNext step: vision_analyze({image_path: "${dest}", prompt: "..."}) to understand what's in it.`, |
| 135 | metadata: { path: dest, sizeBytes: stat.size, window: args.window }, |
| 136 | }; |
| 137 | } catch (e: any) { |
| 138 | return { content: `[COMPUTER_USE_ERROR] screenshot failed: ${e?.message ?? e}`, isError: true }; |
| 139 | } |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | // ───────────────────────────────────────────────────────────────────────────── |