initial
This commit is contained in:
200
ts/smartagent.tools.browser.ts
Normal file
200
ts/smartagent.tools.browser.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
import * as plugins from './plugins.js';
|
||||
import * as interfaces from './smartagent.interfaces.js';
|
||||
import { BaseToolWrapper } from './smartagent.tools.base.js';
|
||||
|
||||
/**
|
||||
* Browser tool for web page interaction
|
||||
* Wraps @push.rocks/smartbrowser (Puppeteer-based)
|
||||
*/
|
||||
export class BrowserTool extends BaseToolWrapper {
|
||||
public name = 'browser';
|
||||
public description =
|
||||
'Interact with web pages - take screenshots, generate PDFs, and execute JavaScript on pages';
|
||||
|
||||
public actions: interfaces.IToolAction[] = [
|
||||
{
|
||||
name: 'screenshot',
|
||||
description: 'Take a screenshot of a webpage',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
url: { type: 'string', description: 'URL of the page to screenshot' },
|
||||
},
|
||||
required: ['url'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'pdf',
|
||||
description: 'Generate a PDF from a webpage',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
url: { type: 'string', description: 'URL of the page to convert to PDF' },
|
||||
},
|
||||
required: ['url'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'evaluate',
|
||||
description:
|
||||
'Execute JavaScript code on a webpage and return the result. The script runs in the browser context.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
url: { type: 'string', description: 'URL of the page to run the script on' },
|
||||
script: {
|
||||
type: 'string',
|
||||
description:
|
||||
'JavaScript code to execute. Must be a valid expression or statements that return a value.',
|
||||
},
|
||||
},
|
||||
required: ['url', 'script'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'getPageContent',
|
||||
description: 'Get the text content and title of a webpage',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
url: { type: 'string', description: 'URL of the page to get content from' },
|
||||
},
|
||||
required: ['url'],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
private smartbrowser!: plugins.smartbrowser.SmartBrowser;
|
||||
|
||||
public async initialize(): Promise<void> {
|
||||
this.smartbrowser = new plugins.smartbrowser.SmartBrowser();
|
||||
await this.smartbrowser.start();
|
||||
this.isInitialized = true;
|
||||
}
|
||||
|
||||
public async cleanup(): Promise<void> {
|
||||
if (this.smartbrowser) {
|
||||
await this.smartbrowser.stop();
|
||||
}
|
||||
this.isInitialized = false;
|
||||
}
|
||||
|
||||
public async execute(
|
||||
action: string,
|
||||
params: Record<string, unknown>
|
||||
): Promise<interfaces.IToolExecutionResult> {
|
||||
this.validateAction(action);
|
||||
this.ensureInitialized();
|
||||
|
||||
try {
|
||||
switch (action) {
|
||||
case 'screenshot': {
|
||||
const result = await this.smartbrowser.screenshotFromPage(params.url as string);
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
url: params.url,
|
||||
name: result.name,
|
||||
id: result.id,
|
||||
bufferBase64: Buffer.from(result.buffer).toString('base64'),
|
||||
bufferLength: result.buffer.length,
|
||||
type: 'screenshot',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
case 'pdf': {
|
||||
const result = await this.smartbrowser.pdfFromPage(params.url as string);
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
url: params.url,
|
||||
name: result.name,
|
||||
id: result.id,
|
||||
bufferBase64: Buffer.from(result.buffer).toString('base64'),
|
||||
bufferLength: result.buffer.length,
|
||||
type: 'pdf',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
case 'evaluate': {
|
||||
const script = params.script as string;
|
||||
// Create an async function from the script
|
||||
// The script should be valid JavaScript that returns a value
|
||||
const result = await this.smartbrowser.evaluateOnPage(params.url as string, async () => {
|
||||
// This runs in the browser context
|
||||
// We need to evaluate the script string dynamically
|
||||
// eslint-disable-next-line no-eval
|
||||
return eval(script);
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
url: params.url,
|
||||
script: script.substring(0, 200) + (script.length > 200 ? '...' : ''),
|
||||
evaluationResult: result,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
case 'getPageContent': {
|
||||
const result = await this.smartbrowser.evaluateOnPage(params.url as string, async () => {
|
||||
return {
|
||||
title: document.title,
|
||||
textContent: document.body?.innerText || '',
|
||||
url: window.location.href,
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
url: params.url,
|
||||
title: result.title,
|
||||
textContent:
|
||||
result.textContent.length > 10000
|
||||
? result.textContent.substring(0, 10000) + '... [truncated]'
|
||||
: result.textContent,
|
||||
actualUrl: result.url,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
default:
|
||||
return {
|
||||
success: false,
|
||||
error: `Unknown action: ${action}`,
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public getCallSummary(action: string, params: Record<string, unknown>): string {
|
||||
switch (action) {
|
||||
case 'screenshot':
|
||||
return `Take screenshot of "${params.url}"`;
|
||||
|
||||
case 'pdf':
|
||||
return `Generate PDF from "${params.url}"`;
|
||||
|
||||
case 'evaluate': {
|
||||
const script = params.script as string;
|
||||
const preview = script.length > 100 ? script.substring(0, 100) + '...' : script;
|
||||
return `Execute JavaScript on "${params.url}": "${preview}"`;
|
||||
}
|
||||
|
||||
case 'getPageContent':
|
||||
return `Get text content and title from "${params.url}"`;
|
||||
|
||||
default:
|
||||
return `Unknown action: ${action}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user