/**
* 屏幕截图工具
*/
import { exec } from 'child_process';
import { promisify } from 'util';
import fs from 'fs/promises';
import path from 'path';
const execAsync = promisify(exec);
export class ScreenTools {
getToolDefinitions() {
return [
{
name: 'take_screenshot',
description: '截取屏幕截图',
inputSchema: {
type: 'object',
properties: {
path: { type: 'string', description: '保存路径(可选,默认桌面)' },
format: { type: 'string', enum: ['png', 'jpg'], description: '图片格式(可选,默认 png)' },
},
},
},
{
name: 'take_screenshot_region',
description: '截取屏幕区域',
inputSchema: {
type: 'object',
properties: {
x: { type: 'number', description: 'X 坐标' },
y: { type: 'number', description: 'Y 坐标' },
width: { type: 'number', description: '宽度' },
height: { type: 'number', description: '高度' },
path: { type: 'string', description: '保存路径(可选)' },
},
required: ['x', 'y', 'width', 'height'],
},
},
];
}
canHandle(toolName) {
const tools = ['take_screenshot', 'take_screenshot_region'];
return tools.includes(toolName);
}
async executeTool(name, args) {
switch (name) {
case 'take_screenshot':
return await this.takeScreenshot(args.path, args.format);
case 'take_screenshot_region':
return await this.takeScreenshotRegion(args.x, args.y, args.width, args.height, args.path);
default:
throw new Error(`未知工具: ${name}`);
}
}
async takeScreenshot(savePath, format = 'png') {
try {
// 生成文件名
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const fileName = `screenshot-${timestamp}.${format}`;
const defaultPath = path.join(process.env.USERPROFILE, 'Desktop', fileName);
const finalPath = savePath || defaultPath;
// 使用 PowerShell 截图
const script = `
Add-Type -AssemblyName System.Windows.Forms,System.Drawing
$bounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
$bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
$graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)
$bitmap.Save("${finalPath}", [System.Drawing.Imaging.ImageFormat]::${format === 'jpg' ? 'Jpeg' : 'Png'})
$bitmap.Dispose()
$graphics.Dispose()
`;
await execAsync(`powershell -Command "${script.replace(/"/g, '\\"')}"`, {
shell: 'powershell.exe'
});
// 验证文件是否创建
await fs.access(finalPath);
return {
success: true,
path: finalPath,
format,
message: '截图已保存'
};
} catch (error) {
return { success: false, error: error.message };
}
}
async takeScreenshotRegion(x, y, width, height, savePath) {
try {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const fileName = `screenshot-region-${timestamp}.png`;
const defaultPath = path.join(process.env.USERPROFILE, 'Desktop', fileName);
const finalPath = savePath || defaultPath;
const script = `
Add-Type -AssemblyName System.Windows.Forms,System.Drawing
$bitmap = New-Object System.Drawing.Bitmap ${width}, ${height}
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
$graphics.CopyFromScreen(${x}, ${y}, 0, 0, [System.Drawing.Size]::new(${width}, ${height}))
$bitmap.Save("${finalPath}", [System.Drawing.Imaging.ImageFormat]::Png)
$bitmap.Dispose()
$graphics.Dispose()
`;
await execAsync(`powershell -Command "${script.replace(/"/g, '\\"')}"`, {
shell: 'powershell.exe'
});
await fs.access(finalPath);
return {
success: true,
path: finalPath,
region: { x, y, width, height },
message: '区域截图已保存'
};
} catch (error) {
return { success: false, error: error.message };
}
}
}