@push.rocks/smartagent 1.8.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/index.d.ts +8 -14
- package/dist_ts/index.js +8 -24
- package/dist_ts/plugins.d.ts +8 -9
- package/dist_ts/plugins.js +10 -12
- package/dist_ts/smartagent.classes.agent.d.ts +2 -0
- package/dist_ts/smartagent.classes.agent.js +173 -0
- package/dist_ts/smartagent.classes.toolregistry.d.ts +7 -70
- package/dist_ts/smartagent.classes.toolregistry.js +11 -155
- package/dist_ts/smartagent.interfaces.d.ts +47 -283
- package/dist_ts/smartagent.interfaces.js +6 -7
- package/dist_ts/smartagent.utils.truncation.d.ts +10 -0
- package/dist_ts/smartagent.utils.truncation.js +26 -0
- package/dist_ts_compaction/index.d.ts +1 -0
- package/dist_ts_compaction/index.js +2 -0
- package/dist_ts_compaction/plugins.d.ts +4 -0
- package/dist_ts_compaction/plugins.js +3 -0
- package/dist_ts_compaction/smartagent.compaction.d.ts +10 -0
- package/dist_ts_compaction/smartagent.compaction.js +46 -0
- package/dist_ts_tools/index.d.ts +8 -0
- package/dist_ts_tools/index.js +6 -0
- package/dist_ts_tools/plugins.d.ts +15 -0
- package/dist_ts_tools/plugins.js +19 -0
- package/dist_ts_tools/tool.filesystem.d.ts +6 -0
- package/dist_ts_tools/tool.filesystem.js +102 -0
- package/dist_ts_tools/tool.http.d.ts +2 -0
- package/dist_ts_tools/tool.http.js +65 -0
- package/dist_ts_tools/tool.json.d.ts +2 -0
- package/dist_ts_tools/tool.json.js +47 -0
- package/dist_ts_tools/tool.shell.d.ts +8 -0
- package/dist_ts_tools/tool.shell.js +40 -0
- package/npmextra.json +1 -1
- package/package.json +30 -18
- package/readme.hints.md +38 -84
- package/readme.md +254 -682
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/index.ts +10 -37
- package/ts/plugins.ts +22 -21
- package/ts/smartagent.classes.agent.ts +198 -0
- package/ts/smartagent.classes.toolregistry.ts +11 -179
- package/ts/smartagent.interfaces.ts +51 -363
- package/ts/smartagent.utils.truncation.ts +39 -0
- package/ts_compaction/index.ts +1 -0
- package/ts_compaction/plugins.ts +6 -0
- package/ts_compaction/smartagent.compaction.ts +51 -0
- package/ts_tools/index.ts +8 -0
- package/ts_tools/plugins.ts +30 -0
- package/ts_tools/tool.filesystem.ts +131 -0
- package/ts_tools/tool.http.ts +78 -0
- package/ts_tools/tool.json.ts +53 -0
- package/ts_tools/tool.shell.ts +62 -0
- package/dist_ts/smartagent.classes.driveragent.d.ts +0 -134
- package/dist_ts/smartagent.classes.driveragent.js +0 -671
- package/dist_ts/smartagent.classes.dualagent.d.ts +0 -93
- package/dist_ts/smartagent.classes.dualagent.js +0 -614
- package/dist_ts/smartagent.classes.guardianagent.d.ts +0 -46
- package/dist_ts/smartagent.classes.guardianagent.js +0 -201
- package/dist_ts/smartagent.tools.base.d.ts +0 -52
- package/dist_ts/smartagent.tools.base.js +0 -42
- package/dist_ts/smartagent.tools.browser.d.ts +0 -17
- package/dist_ts/smartagent.tools.browser.js +0 -229
- package/dist_ts/smartagent.tools.deno.d.ts +0 -21
- package/dist_ts/smartagent.tools.deno.js +0 -191
- package/dist_ts/smartagent.tools.expert.d.ts +0 -27
- package/dist_ts/smartagent.tools.expert.js +0 -126
- package/dist_ts/smartagent.tools.filesystem.d.ts +0 -40
- package/dist_ts/smartagent.tools.filesystem.js +0 -801
- package/dist_ts/smartagent.tools.http.d.ts +0 -16
- package/dist_ts/smartagent.tools.http.js +0 -264
- package/dist_ts/smartagent.tools.json.d.ts +0 -24
- package/dist_ts/smartagent.tools.json.js +0 -202
- package/dist_ts/smartagent.tools.search.d.ts +0 -29
- package/dist_ts/smartagent.tools.search.js +0 -215
- package/dist_ts/smartagent.tools.shell.d.ts +0 -17
- package/dist_ts/smartagent.tools.shell.js +0 -202
- package/ts/smartagent.classes.driveragent.ts +0 -775
- package/ts/smartagent.classes.dualagent.ts +0 -692
- package/ts/smartagent.classes.guardianagent.ts +0 -241
- package/ts/smartagent.tools.base.ts +0 -83
- package/ts/smartagent.tools.browser.ts +0 -253
- package/ts/smartagent.tools.deno.ts +0 -230
- package/ts/smartagent.tools.expert.ts +0 -144
- package/ts/smartagent.tools.filesystem.ts +0 -885
- package/ts/smartagent.tools.http.ts +0 -283
- package/ts/smartagent.tools.json.ts +0 -224
- package/ts/smartagent.tools.search.ts +0 -237
- package/ts/smartagent.tools.shell.ts +0 -230
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import * as plugins from './plugins.js';
|
|
2
|
-
import * as interfaces from './smartagent.interfaces.js';
|
|
3
|
-
import type { BaseToolWrapper } from './smartagent.tools.base.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* GuardianAgent - Evaluates tool call proposals against a policy
|
|
7
|
-
* Uses AI reasoning to approve or reject tool calls
|
|
8
|
-
*/
|
|
9
|
-
export class GuardianAgent {
|
|
10
|
-
private provider: plugins.smartai.MultiModalModel;
|
|
11
|
-
private policyPrompt: string;
|
|
12
|
-
private tools: Map<string, BaseToolWrapper> = new Map();
|
|
13
|
-
|
|
14
|
-
constructor(
|
|
15
|
-
provider: plugins.smartai.MultiModalModel,
|
|
16
|
-
policyPrompt: string
|
|
17
|
-
) {
|
|
18
|
-
this.provider = provider;
|
|
19
|
-
this.policyPrompt = policyPrompt;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Register a tool for reference during evaluation
|
|
24
|
-
*/
|
|
25
|
-
public registerTool(tool: BaseToolWrapper): void {
|
|
26
|
-
this.tools.set(tool.name, tool);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Evaluate a tool call proposal against the policy
|
|
31
|
-
*/
|
|
32
|
-
public async evaluate(
|
|
33
|
-
proposal: interfaces.IToolCallProposal,
|
|
34
|
-
taskContext: string
|
|
35
|
-
): Promise<interfaces.IGuardianDecision> {
|
|
36
|
-
// Get the tool to generate a human-readable summary
|
|
37
|
-
const tool = this.tools.get(proposal.toolName);
|
|
38
|
-
let callSummary = `${proposal.toolName}.${proposal.action}(${JSON.stringify(proposal.params)})`;
|
|
39
|
-
|
|
40
|
-
if (tool) {
|
|
41
|
-
try {
|
|
42
|
-
callSummary = tool.getCallSummary(proposal.action, proposal.params);
|
|
43
|
-
} catch {
|
|
44
|
-
// Fallback to basic summary
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Build the evaluation prompt
|
|
49
|
-
const evaluationPrompt = this.buildEvaluationPrompt(
|
|
50
|
-
proposal,
|
|
51
|
-
callSummary,
|
|
52
|
-
taskContext
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
// Get response from provider
|
|
56
|
-
const response = await this.provider.chat({
|
|
57
|
-
systemMessage: this.buildGuardianSystemMessage(),
|
|
58
|
-
userMessage: evaluationPrompt,
|
|
59
|
-
messageHistory: [],
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// Parse the decision from the response
|
|
63
|
-
return this.parseDecision(response.message, proposal);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Build the system message for the Guardian
|
|
68
|
-
*/
|
|
69
|
-
private buildGuardianSystemMessage(): string {
|
|
70
|
-
return `You are a Guardian AI responsible for evaluating tool call proposals.
|
|
71
|
-
|
|
72
|
-
## Your Role
|
|
73
|
-
You evaluate whether proposed tool calls are safe and aligned with the policy.
|
|
74
|
-
|
|
75
|
-
## Policy to Enforce
|
|
76
|
-
${this.policyPrompt}
|
|
77
|
-
|
|
78
|
-
## Response Format
|
|
79
|
-
For EVERY evaluation, respond with a decision in this exact format:
|
|
80
|
-
|
|
81
|
-
<guardian_decision>
|
|
82
|
-
<decision>approve OR reject</decision>
|
|
83
|
-
<reason>Your detailed explanation</reason>
|
|
84
|
-
<concerns>List any concerns, even if approving</concerns>
|
|
85
|
-
<suggestions>Alternative approaches if rejecting</suggestions>
|
|
86
|
-
</guardian_decision>
|
|
87
|
-
|
|
88
|
-
## Guidelines
|
|
89
|
-
1. Carefully analyze what the tool call will do
|
|
90
|
-
2. Consider security implications
|
|
91
|
-
3. Check against the policy requirements
|
|
92
|
-
4. If uncertain, err on the side of caution (reject)
|
|
93
|
-
5. Provide actionable feedback when rejecting`;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Build the evaluation prompt for a specific proposal
|
|
98
|
-
*/
|
|
99
|
-
private buildEvaluationPrompt(
|
|
100
|
-
proposal: interfaces.IToolCallProposal,
|
|
101
|
-
callSummary: string,
|
|
102
|
-
taskContext: string
|
|
103
|
-
): string {
|
|
104
|
-
const toolInfo = this.tools.get(proposal.toolName);
|
|
105
|
-
const toolDescription = toolInfo ? toolInfo.getFullDescription() : 'Unknown tool';
|
|
106
|
-
|
|
107
|
-
return `## Task Context
|
|
108
|
-
${taskContext}
|
|
109
|
-
|
|
110
|
-
## Tool Being Used
|
|
111
|
-
${toolDescription}
|
|
112
|
-
|
|
113
|
-
## Proposed Tool Call
|
|
114
|
-
- **Tool**: ${proposal.toolName}
|
|
115
|
-
- **Action**: ${proposal.action}
|
|
116
|
-
- **Parameters**: ${JSON.stringify(proposal.params, null, 2)}
|
|
117
|
-
|
|
118
|
-
## Human-Readable Summary
|
|
119
|
-
${callSummary}
|
|
120
|
-
|
|
121
|
-
## Driver's Reasoning
|
|
122
|
-
${proposal.reasoning || 'No reasoning provided'}
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
Evaluate this tool call against the policy. Should it be approved or rejected?`;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Parse the guardian decision from the response
|
|
131
|
-
*/
|
|
132
|
-
private parseDecision(
|
|
133
|
-
response: string,
|
|
134
|
-
proposal: interfaces.IToolCallProposal
|
|
135
|
-
): interfaces.IGuardianDecision {
|
|
136
|
-
// Try to extract from XML tags
|
|
137
|
-
const decisionMatch = response.match(/<decision>(.*?)<\/decision>/s);
|
|
138
|
-
const reasonMatch = response.match(/<reason>([\s\S]*?)<\/reason>/);
|
|
139
|
-
const concernsMatch = response.match(/<concerns>([\s\S]*?)<\/concerns>/);
|
|
140
|
-
const suggestionsMatch = response.match(/<suggestions>([\s\S]*?)<\/suggestions>/);
|
|
141
|
-
|
|
142
|
-
// Determine decision
|
|
143
|
-
let decision: 'approve' | 'reject' = 'reject';
|
|
144
|
-
if (decisionMatch) {
|
|
145
|
-
const decisionText = decisionMatch[1].trim().toLowerCase();
|
|
146
|
-
decision = decisionText.includes('approve') ? 'approve' : 'reject';
|
|
147
|
-
} else {
|
|
148
|
-
// Fallback: look for approval keywords in the response
|
|
149
|
-
const lowerResponse = response.toLowerCase();
|
|
150
|
-
if (
|
|
151
|
-
lowerResponse.includes('approved') ||
|
|
152
|
-
lowerResponse.includes('i approve') ||
|
|
153
|
-
lowerResponse.includes('looks safe')
|
|
154
|
-
) {
|
|
155
|
-
decision = 'approve';
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Extract reason
|
|
160
|
-
let reason = reasonMatch ? reasonMatch[1].trim() : '';
|
|
161
|
-
if (!reason) {
|
|
162
|
-
// Use the full response as reason if no tag found
|
|
163
|
-
reason = response.substring(0, 500);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Extract concerns
|
|
167
|
-
const concerns: string[] = [];
|
|
168
|
-
if (concernsMatch) {
|
|
169
|
-
const concernsText = concernsMatch[1].trim();
|
|
170
|
-
if (concernsText && concernsText.toLowerCase() !== 'none') {
|
|
171
|
-
// Split by newlines or bullet points
|
|
172
|
-
const concernLines = concernsText.split(/[\n\r]+/).map(l => l.trim()).filter(l => l);
|
|
173
|
-
concerns.push(...concernLines);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Extract suggestions
|
|
178
|
-
const suggestions = suggestionsMatch ? suggestionsMatch[1].trim() : undefined;
|
|
179
|
-
|
|
180
|
-
return {
|
|
181
|
-
decision,
|
|
182
|
-
reason,
|
|
183
|
-
concerns: concerns.length > 0 ? concerns : undefined,
|
|
184
|
-
suggestions: suggestions && suggestions.toLowerCase() !== 'none' ? suggestions : undefined,
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Quick validation without AI (for obviously safe/unsafe operations)
|
|
190
|
-
* Returns null if AI evaluation is needed
|
|
191
|
-
*/
|
|
192
|
-
public quickValidate(proposal: interfaces.IToolCallProposal): interfaces.IGuardianDecision | null {
|
|
193
|
-
// Check if tool exists
|
|
194
|
-
if (!this.tools.has(proposal.toolName)) {
|
|
195
|
-
return {
|
|
196
|
-
decision: 'reject',
|
|
197
|
-
reason: `Unknown tool: ${proposal.toolName}`,
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Check if action exists
|
|
202
|
-
const tool = this.tools.get(proposal.toolName)!;
|
|
203
|
-
const validAction = tool.actions.find(a => a.name === proposal.action);
|
|
204
|
-
if (!validAction) {
|
|
205
|
-
return {
|
|
206
|
-
decision: 'reject',
|
|
207
|
-
reason: `Unknown action "${proposal.action}" for tool "${proposal.toolName}". Available actions: ${tool.actions.map(a => a.name).join(', ')}`,
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Check required parameters
|
|
212
|
-
const schema = validAction.parameters;
|
|
213
|
-
if (schema && schema.required && Array.isArray(schema.required)) {
|
|
214
|
-
for (const requiredParam of schema.required as string[]) {
|
|
215
|
-
if (!(requiredParam in proposal.params)) {
|
|
216
|
-
return {
|
|
217
|
-
decision: 'reject',
|
|
218
|
-
reason: `Missing required parameter: ${requiredParam}`,
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Needs full AI evaluation
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Update the policy prompt
|
|
230
|
-
*/
|
|
231
|
-
public setPolicy(policyPrompt: string): void {
|
|
232
|
-
this.policyPrompt = policyPrompt;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Get current policy
|
|
237
|
-
*/
|
|
238
|
-
public getPolicy(): string {
|
|
239
|
-
return this.policyPrompt;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import * as interfaces from './smartagent.interfaces.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Abstract base class for tool wrappers
|
|
5
|
-
* All tool implementations should extend this class
|
|
6
|
-
*/
|
|
7
|
-
export abstract class BaseToolWrapper implements interfaces.IAgentToolWrapper {
|
|
8
|
-
abstract name: string;
|
|
9
|
-
abstract description: string;
|
|
10
|
-
abstract actions: interfaces.IToolAction[];
|
|
11
|
-
|
|
12
|
-
protected isInitialized = false;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Initialize the tool and any required resources
|
|
16
|
-
*/
|
|
17
|
-
abstract initialize(): Promise<void>;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Cleanup any resources used by the tool
|
|
21
|
-
*/
|
|
22
|
-
abstract cleanup(): Promise<void>;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Execute an action with the given parameters
|
|
26
|
-
*/
|
|
27
|
-
abstract execute(
|
|
28
|
-
action: string,
|
|
29
|
-
params: Record<string, unknown>
|
|
30
|
-
): Promise<interfaces.IToolExecutionResult>;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Generate a human-readable summary of what the action will do
|
|
34
|
-
* This is used by the Guardian to understand the proposed action
|
|
35
|
-
*/
|
|
36
|
-
abstract getCallSummary(action: string, params: Record<string, unknown>): string;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Get a comprehensive explanation of this tool for LLM consumption.
|
|
40
|
-
* Tools should implement this to provide detailed usage instructions with examples.
|
|
41
|
-
* This includes parameter schemas and concrete <tool_call> XML examples.
|
|
42
|
-
*/
|
|
43
|
-
abstract getToolExplanation(): string;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Validate that an action exists for this tool
|
|
47
|
-
* @throws Error if the action is not valid
|
|
48
|
-
*/
|
|
49
|
-
protected validateAction(action: string): void {
|
|
50
|
-
const validAction = this.actions.find((a) => a.name === action);
|
|
51
|
-
if (!validAction) {
|
|
52
|
-
const availableActions = this.actions.map((a) => a.name).join(', ');
|
|
53
|
-
throw new Error(
|
|
54
|
-
`Unknown action "${action}" for tool "${this.name}". Available actions: ${availableActions}`
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Check if the tool is initialized
|
|
61
|
-
*/
|
|
62
|
-
protected ensureInitialized(): void {
|
|
63
|
-
if (!this.isInitialized) {
|
|
64
|
-
throw new Error(`Tool "${this.name}" is not initialized. Call initialize() first.`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Get the full tool description including all actions
|
|
70
|
-
* Used for Driver's tool awareness - now delegates to getToolExplanation()
|
|
71
|
-
*/
|
|
72
|
-
public getFullDescription(): string {
|
|
73
|
-
return this.getToolExplanation();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Get the JSON schema for a specific action
|
|
78
|
-
*/
|
|
79
|
-
public getActionSchema(action: string): Record<string, unknown> | undefined {
|
|
80
|
-
const actionDef = this.actions.find((a) => a.name === action);
|
|
81
|
-
return actionDef?.parameters;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
import * as plugins from './plugins.js';
|
|
2
|
-
import * as interfaces from './smartagent.interfaces.js';
|
|
3
|
-
import { BaseToolWrapper } from './smartagent.tools.base.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Browser tool for web page interaction
|
|
7
|
-
* Wraps @push.rocks/smartbrowser (Puppeteer-based)
|
|
8
|
-
*/
|
|
9
|
-
export class BrowserTool extends BaseToolWrapper {
|
|
10
|
-
public name = 'browser';
|
|
11
|
-
public description =
|
|
12
|
-
'Interact with web pages - take screenshots, generate PDFs, and execute JavaScript on pages';
|
|
13
|
-
|
|
14
|
-
public actions: interfaces.IToolAction[] = [
|
|
15
|
-
{
|
|
16
|
-
name: 'screenshot',
|
|
17
|
-
description: 'Take a screenshot of a webpage',
|
|
18
|
-
parameters: {
|
|
19
|
-
type: 'object',
|
|
20
|
-
properties: {
|
|
21
|
-
url: { type: 'string', description: 'URL of the page to screenshot' },
|
|
22
|
-
},
|
|
23
|
-
required: ['url'],
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: 'pdf',
|
|
28
|
-
description: 'Generate a PDF from a webpage',
|
|
29
|
-
parameters: {
|
|
30
|
-
type: 'object',
|
|
31
|
-
properties: {
|
|
32
|
-
url: { type: 'string', description: 'URL of the page to convert to PDF' },
|
|
33
|
-
},
|
|
34
|
-
required: ['url'],
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
name: 'evaluate',
|
|
39
|
-
description:
|
|
40
|
-
'Execute JavaScript code on a webpage and return the result. The script runs in the browser context.',
|
|
41
|
-
parameters: {
|
|
42
|
-
type: 'object',
|
|
43
|
-
properties: {
|
|
44
|
-
url: { type: 'string', description: 'URL of the page to run the script on' },
|
|
45
|
-
script: {
|
|
46
|
-
type: 'string',
|
|
47
|
-
description:
|
|
48
|
-
'JavaScript code to execute. Must be a valid expression or statements that return a value.',
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
required: ['url', 'script'],
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
name: 'getPageContent',
|
|
56
|
-
description: 'Get the text content and title of a webpage',
|
|
57
|
-
parameters: {
|
|
58
|
-
type: 'object',
|
|
59
|
-
properties: {
|
|
60
|
-
url: { type: 'string', description: 'URL of the page to get content from' },
|
|
61
|
-
},
|
|
62
|
-
required: ['url'],
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
];
|
|
66
|
-
|
|
67
|
-
private smartbrowser!: plugins.smartbrowser.SmartBrowser;
|
|
68
|
-
|
|
69
|
-
public async initialize(): Promise<void> {
|
|
70
|
-
this.smartbrowser = new plugins.smartbrowser.SmartBrowser();
|
|
71
|
-
await this.smartbrowser.start();
|
|
72
|
-
this.isInitialized = true;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
public async cleanup(): Promise<void> {
|
|
76
|
-
if (this.smartbrowser) {
|
|
77
|
-
await this.smartbrowser.stop();
|
|
78
|
-
}
|
|
79
|
-
this.isInitialized = false;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
public async execute(
|
|
83
|
-
action: string,
|
|
84
|
-
params: Record<string, unknown>
|
|
85
|
-
): Promise<interfaces.IToolExecutionResult> {
|
|
86
|
-
this.validateAction(action);
|
|
87
|
-
this.ensureInitialized();
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
switch (action) {
|
|
91
|
-
case 'screenshot': {
|
|
92
|
-
const result = await this.smartbrowser.screenshotFromPage(params.url as string);
|
|
93
|
-
return {
|
|
94
|
-
success: true,
|
|
95
|
-
result: {
|
|
96
|
-
url: params.url,
|
|
97
|
-
name: result.name,
|
|
98
|
-
id: result.id,
|
|
99
|
-
bufferBase64: Buffer.from(result.buffer).toString('base64'),
|
|
100
|
-
bufferLength: result.buffer.length,
|
|
101
|
-
type: 'screenshot',
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
case 'pdf': {
|
|
107
|
-
const result = await this.smartbrowser.pdfFromPage(params.url as string);
|
|
108
|
-
return {
|
|
109
|
-
success: true,
|
|
110
|
-
result: {
|
|
111
|
-
url: params.url,
|
|
112
|
-
name: result.name,
|
|
113
|
-
id: result.id,
|
|
114
|
-
bufferBase64: Buffer.from(result.buffer).toString('base64'),
|
|
115
|
-
bufferLength: result.buffer.length,
|
|
116
|
-
type: 'pdf',
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
case 'evaluate': {
|
|
122
|
-
const script = params.script as string;
|
|
123
|
-
// Create an async function from the script
|
|
124
|
-
// The script should be valid JavaScript that returns a value
|
|
125
|
-
const result = await this.smartbrowser.evaluateOnPage(params.url as string, async () => {
|
|
126
|
-
// This runs in the browser context
|
|
127
|
-
// We need to evaluate the script string dynamically
|
|
128
|
-
// eslint-disable-next-line no-eval
|
|
129
|
-
return eval(script);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
success: true,
|
|
134
|
-
result: {
|
|
135
|
-
url: params.url,
|
|
136
|
-
script: script.substring(0, 200) + (script.length > 200 ? '...' : ''),
|
|
137
|
-
evaluationResult: result,
|
|
138
|
-
},
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
case 'getPageContent': {
|
|
143
|
-
const result = await this.smartbrowser.evaluateOnPage(params.url as string, async () => {
|
|
144
|
-
return {
|
|
145
|
-
title: document.title,
|
|
146
|
-
textContent: document.body?.innerText || '',
|
|
147
|
-
url: window.location.href,
|
|
148
|
-
};
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
return {
|
|
152
|
-
success: true,
|
|
153
|
-
result: {
|
|
154
|
-
url: params.url,
|
|
155
|
-
title: result.title,
|
|
156
|
-
textContent:
|
|
157
|
-
result.textContent.length > 10000
|
|
158
|
-
? result.textContent.substring(0, 10000) + '... [truncated]'
|
|
159
|
-
: result.textContent,
|
|
160
|
-
actualUrl: result.url,
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
default:
|
|
166
|
-
return {
|
|
167
|
-
success: false,
|
|
168
|
-
error: `Unknown action: ${action}`,
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
} catch (error) {
|
|
172
|
-
return {
|
|
173
|
-
success: false,
|
|
174
|
-
error: error instanceof Error ? error.message : String(error),
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
public getToolExplanation(): string {
|
|
180
|
-
return `## Tool: browser
|
|
181
|
-
Interact with web pages - take screenshots, generate PDFs, and execute JavaScript on pages.
|
|
182
|
-
|
|
183
|
-
### Actions:
|
|
184
|
-
|
|
185
|
-
**screenshot** - Take a screenshot of a webpage
|
|
186
|
-
Parameters:
|
|
187
|
-
- url (required): URL of the page to screenshot
|
|
188
|
-
|
|
189
|
-
Example:
|
|
190
|
-
<tool_call>
|
|
191
|
-
<tool>browser</tool>
|
|
192
|
-
<action>screenshot</action>
|
|
193
|
-
<params>{"url": "https://example.com"}</params>
|
|
194
|
-
</tool_call>
|
|
195
|
-
|
|
196
|
-
**pdf** - Generate a PDF from a webpage
|
|
197
|
-
Parameters:
|
|
198
|
-
- url (required): URL of the page to convert to PDF
|
|
199
|
-
|
|
200
|
-
Example:
|
|
201
|
-
<tool_call>
|
|
202
|
-
<tool>browser</tool>
|
|
203
|
-
<action>pdf</action>
|
|
204
|
-
<params>{"url": "https://example.com/report"}</params>
|
|
205
|
-
</tool_call>
|
|
206
|
-
|
|
207
|
-
**evaluate** - Execute JavaScript code on a webpage and return the result
|
|
208
|
-
Parameters:
|
|
209
|
-
- url (required): URL of the page to run the script on
|
|
210
|
-
- script (required): JavaScript code to execute (must return a value)
|
|
211
|
-
|
|
212
|
-
Example:
|
|
213
|
-
<tool_call>
|
|
214
|
-
<tool>browser</tool>
|
|
215
|
-
<action>evaluate</action>
|
|
216
|
-
<params>{"url": "https://example.com", "script": "document.querySelectorAll('a').length"}</params>
|
|
217
|
-
</tool_call>
|
|
218
|
-
|
|
219
|
-
**getPageContent** - Get the text content and title of a webpage
|
|
220
|
-
Parameters:
|
|
221
|
-
- url (required): URL of the page to get content from
|
|
222
|
-
|
|
223
|
-
Example:
|
|
224
|
-
<tool_call>
|
|
225
|
-
<tool>browser</tool>
|
|
226
|
-
<action>getPageContent</action>
|
|
227
|
-
<params>{"url": "https://example.com"}</params>
|
|
228
|
-
</tool_call>
|
|
229
|
-
`;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
public getCallSummary(action: string, params: Record<string, unknown>): string {
|
|
233
|
-
switch (action) {
|
|
234
|
-
case 'screenshot':
|
|
235
|
-
return `Take screenshot of "${params.url}"`;
|
|
236
|
-
|
|
237
|
-
case 'pdf':
|
|
238
|
-
return `Generate PDF from "${params.url}"`;
|
|
239
|
-
|
|
240
|
-
case 'evaluate': {
|
|
241
|
-
const script = params.script as string;
|
|
242
|
-
const preview = script.length > 100 ? script.substring(0, 100) + '...' : script;
|
|
243
|
-
return `Execute JavaScript on "${params.url}": "${preview}"`;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
case 'getPageContent':
|
|
247
|
-
return `Get text content and title from "${params.url}"`;
|
|
248
|
-
|
|
249
|
-
default:
|
|
250
|
-
return `Unknown action: ${action}`;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|