From c2e270fc4896cb48da948efb74857d7b95fd9f25 Mon Sep 17 00:00:00 2001 From: tsingliu <410869548@qq.com> Date: Sat, 7 Feb 2026 20:34:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=88=AA=E5=B1=8F=E5=B7=A5?= =?UTF-8?q?=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tools/core.ts | 3 +- src/tools/email.ts | 14 +++++++-- src/tools/index.ts | 4 ++- src/tools/screenshot.ts | 69 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 src/tools/screenshot.ts diff --git a/src/tools/core.ts b/src/tools/core.ts index c0453d7..1d48e0b 100644 --- a/src/tools/core.ts +++ b/src/tools/core.ts @@ -117,7 +117,8 @@ export const DateTimeTool: ToolModule = { description: "Get the current system date and time. Use this when the user refers to relative dates (like 'today', 'next week', 'this March') to ensure accuracy.", parameters: { type: "object", - properties: {} + properties: {}, + required: [] } } }, diff --git a/src/tools/email.ts b/src/tools/email.ts index 3bf9417..f968dd4 100644 --- a/src/tools/email.ts +++ b/src/tools/email.ts @@ -8,13 +8,18 @@ export const EmailTool: ToolModule = { type: "function", function: { name: "send_email", - description: "Send an email using configured SMTP settings.", + description: "Send an email using configured SMTP settings. Can include optional file attachments.", parameters: { type: "object", properties: { to: { type: "string", description: "Recipient email address." }, subject: { type: "string", description: "Email subject." }, - body: { type: "string", description: "Email body content (text)." } + body: { type: "string", description: "Email body content (text)." }, + attachments: { + type: "array", + items: { type: "string" }, + description: "Optional list of local file paths to attach to the email." + } }, required: ["to", "subject", "body"] } @@ -37,11 +42,16 @@ export const EmailTool: ToolModule = { }, }); + const emailAttachments = args.attachments?.map((filePath: string) => ({ + path: filePath + })) || []; + const info = await transporter.sendMail({ from: config.smtpFrom || config.smtpUser, // sender address to: args.to, // list of receivers subject: args.subject, // Subject line text: args.body, // plain text body + attachments: emailAttachments }); return `Email sent successfully. Message ID: ${info.messageId}`; diff --git a/src/tools/index.ts b/src/tools/index.ts index 1d09cb7..2b991cc 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -4,6 +4,7 @@ import { EmailTool } from './email.js'; import { SearchTool } from './search.js'; import { NotifyTool } from './notify.js'; import { BrowserTool } from './browser.js'; +import { ScreenshotTool } from './screenshot.js'; // Central Registry of all available tools export const toolRegistry: ToolModule[] = [ @@ -14,7 +15,8 @@ export const toolRegistry: ToolModule[] = [ EmailTool, SearchTool, NotifyTool, - BrowserTool + BrowserTool, + ScreenshotTool ]; export function getToolDefinitions() { diff --git a/src/tools/screenshot.ts b/src/tools/screenshot.ts new file mode 100644 index 0000000..7dd6fc0 --- /dev/null +++ b/src/tools/screenshot.ts @@ -0,0 +1,69 @@ +import { chromium } from 'playwright'; +import { ToolModule } from './interface.js'; + +export const ScreenshotTool: ToolModule = { + name: "Screenshot Tool", + configKeys: [], + definition: { + type: "function", + function: { + name: "take_screenshot", + description: "Captures a screenshot of a specified website and saves it as an image file.", + parameters: { + type: "object", + properties: { + url: { + type: "string", + description: "The full URL of the website to capture (e.g., https://google.com)." + }, + outputPath: { + type: "string", + description: "The file path where the screenshot should be saved (e.g., 'homepage.png')." + }, + fullPage: { + type: "boolean", + description: "If true, takes a screenshot of the full scrollable page instead of just the viewport." + } + }, + required: ["url", "outputPath"] + } + } + }, + handler: async (args: any, config: any) => { + let browser; + try { + browser = await chromium.launch({ headless: true }); + } catch (error: any) { + if (error.message.includes("Executable doesn't exist")) { + return "Error: Playwright browsers are not installed. Please run `npx playwright install chromium` to enable this feature."; + } + return `Error launching browser: ${error.message}`; + } + + const context = await browser.newContext({ + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + viewport: { width: 1280, height: 720 } + }); + const page = await context.newPage(); + + try { + console.log(`Navigating to ${args.url} for screenshot...`); + await page.goto(args.url, { waitUntil: 'networkidle', timeout: 30000 }); + + // Wait a bit for animations etc. + await page.waitForTimeout(1000); + + await page.screenshot({ + path: args.outputPath, + fullPage: args.fullPage || false + }); + + return `Successfully captured screenshot of ${args.url} and saved to ${args.outputPath}`; + + } catch (error: any) { + return `Error taking screenshot: ${error.message}`; + } finally { + await browser.close(); + } + } +};