n8n-nodes-smart-browser-automation 1.2.0 → 1.3.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.
|
@@ -4,8 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.SmartBrowserAutomation = void 0;
|
|
7
|
-
const n8n_workflow_1 = require("n8n-workflow");
|
|
8
7
|
const BrowserSessionManager_1 = __importDefault(require("./BrowserSessionManager"));
|
|
8
|
+
const DynamicBrowserTools_1 = require("./tools/DynamicBrowserTools");
|
|
9
9
|
class SmartBrowserAutomation {
|
|
10
10
|
description = {
|
|
11
11
|
displayName: 'Smart Browser Automation',
|
|
@@ -61,20 +61,10 @@ class SmartBrowserAutomation {
|
|
|
61
61
|
type: 'string',
|
|
62
62
|
default: '',
|
|
63
63
|
placeholder: 'wss://gridnew.doingerp.com/devtools/...',
|
|
64
|
-
description: '
|
|
64
|
+
description: 'Browser CDP endpoint to connect to. If not provided, MCP server will launch a new browser.',
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
|
-
displayName: '
|
|
68
|
-
name: 'enabledTools',
|
|
69
|
-
type: 'multiOptions',
|
|
70
|
-
typeOptions: {
|
|
71
|
-
loadOptionsMethod: 'getAvailableTools',
|
|
72
|
-
},
|
|
73
|
-
default: [],
|
|
74
|
-
description: 'Select which tools to expose to the AI Agent or Manual list. Leave empty for all. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
displayName: 'Verbose',
|
|
67
|
+
displayName: 'Verbose Logging',
|
|
78
68
|
name: 'verbose',
|
|
79
69
|
type: 'boolean',
|
|
80
70
|
default: false,
|
|
@@ -118,110 +108,14 @@ class SmartBrowserAutomation {
|
|
|
118
108
|
};
|
|
119
109
|
// Expose tools to AI Agent nodes
|
|
120
110
|
async getTools() {
|
|
121
|
-
|
|
122
|
-
//
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
displayName: 'Browser Action',
|
|
126
|
-
description: `Execute browser automation actions. ALWAYS use this tool for browser interactions.
|
|
127
|
-
|
|
128
|
-
WHEN TO USE:
|
|
129
|
-
✓ User wants to visit/open/go to a website → action='navigate'
|
|
130
|
-
✓ User wants to click something → action='click'
|
|
131
|
-
✓ User wants to type/enter text → action='type'
|
|
132
|
-
✓ User wants to read/get text from page → action='snapshot' or action='get_text'
|
|
133
|
-
✓ User wants a screenshot → action='take_screenshot'
|
|
134
|
-
|
|
135
|
-
REQUIRED PARAMETERS:
|
|
136
|
-
• action: The action name (navigate, click, type, snapshot, take_screenshot, etc.)
|
|
137
|
-
• params: JSON object with action-specific parameters
|
|
138
|
-
|
|
139
|
-
EXAMPLES:
|
|
140
|
-
1. Navigate: { "action": "navigate", "params": { "url": "https://example.com" } }
|
|
141
|
-
2. Click: { "action": "click", "params": { "element": "button text", "ref": "..." } }
|
|
142
|
-
3. Type: { "action": "type", "params": { "element": "input field", "ref": "...", "text": "hello" } }
|
|
143
|
-
4. Snapshot: { "action": "snapshot", "params": {} }
|
|
144
|
-
5. Screenshot: { "action": "take_screenshot", "params": {} }
|
|
145
|
-
|
|
146
|
-
IMPORTANT: For navigate action, params must include "url" key.`,
|
|
147
|
-
properties: [
|
|
148
|
-
{
|
|
149
|
-
displayName: 'Action Name',
|
|
150
|
-
name: 'action',
|
|
151
|
-
type: 'string',
|
|
152
|
-
required: true,
|
|
153
|
-
default: '',
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
displayName: 'Parameters',
|
|
157
|
-
name: 'params',
|
|
158
|
-
type: 'json',
|
|
159
|
-
default: '{}',
|
|
160
|
-
description: 'JSON parameters for the action (e.g., { "URL": "..." })',
|
|
161
|
-
},
|
|
162
|
-
],
|
|
163
|
-
async execute(input) {
|
|
164
|
-
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
165
|
-
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
166
|
-
// Ensure session is initialized
|
|
167
|
-
if (!sessionManager.isReady()) {
|
|
168
|
-
// Check for connection tool usage specifically
|
|
169
|
-
if (input.action === 'connect_cdp' || input.action === 'browser_connect_cdp') {
|
|
170
|
-
const endpoint = input.params?.endpoint;
|
|
171
|
-
if (endpoint) {
|
|
172
|
-
console.log(`[Router] Connecting to CDP: ${endpoint}`);
|
|
173
|
-
await sessionManager.initialize(credentials.mcpEndpoint, true, endpoint);
|
|
174
|
-
return {
|
|
175
|
-
content: [{ type: 'text', text: `Connected to browser at ${endpoint}.` }],
|
|
176
|
-
isError: false,
|
|
177
|
-
toolName: 'browser_connect_cdp',
|
|
178
|
-
requestedAction: input.action
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
// Session not ready and no explicit connection requested
|
|
183
|
-
// This shouldn't happen - session should be initialized first
|
|
184
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Browser session not initialized. Please connect to browser first using Initialize Session or connect_cdp action.');
|
|
185
|
-
} // Normalize action name
|
|
186
|
-
let toolName = input.action;
|
|
187
|
-
if (!toolName.startsWith('browser_') && toolName !== 'connect_cdp') {
|
|
188
|
-
toolName = `browser_${toolName}`;
|
|
189
|
-
}
|
|
190
|
-
// Handle params
|
|
191
|
-
let toolArgs = input.params || {};
|
|
192
|
-
if (typeof toolArgs === 'string') {
|
|
193
|
-
try {
|
|
194
|
-
toolArgs = JSON.parse(toolArgs);
|
|
195
|
-
}
|
|
196
|
-
catch (e) {
|
|
197
|
-
// ignore
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
console.log(`[Router] Routing '${input.action}' to '${toolName}' with args:`, toolArgs);
|
|
201
|
-
try {
|
|
202
|
-
const result = await sessionManager.callTool(toolName, toolArgs);
|
|
203
|
-
// Add tool name to result for visibility
|
|
204
|
-
if (result && typeof result === 'object') {
|
|
205
|
-
result.toolName = toolName;
|
|
206
|
-
result.requestedAction = input.action;
|
|
207
|
-
}
|
|
208
|
-
return result;
|
|
209
|
-
}
|
|
210
|
-
catch (error) {
|
|
211
|
-
return {
|
|
212
|
-
content: [{ type: 'text', text: `Error executing ${toolName}: ${error.message}` }],
|
|
213
|
-
isError: true,
|
|
214
|
-
toolName: toolName,
|
|
215
|
-
requestedAction: input.action
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
// Add a custom tool for specific CDP connection (legacy support)
|
|
111
|
+
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
112
|
+
// Get all individual MCP tools
|
|
113
|
+
const mcpTools = await (0, DynamicBrowserTools_1.createDynamicBrowserTools)(credentials);
|
|
114
|
+
// Add custom CDP connection tool
|
|
221
115
|
const connectTool = {
|
|
222
116
|
name: 'browser_connect_cdp',
|
|
223
117
|
displayName: 'Connect to Browser (CDP)',
|
|
224
|
-
description: 'Connect to a specific browser instance using a CDP
|
|
118
|
+
description: 'Connect to a specific browser instance using a CDP endpoint URL',
|
|
225
119
|
properties: [
|
|
226
120
|
{
|
|
227
121
|
displayName: 'Endpoint URL',
|
|
@@ -229,7 +123,7 @@ IMPORTANT: For navigate action, params must include "url" key.`,
|
|
|
229
123
|
type: 'string',
|
|
230
124
|
default: '',
|
|
231
125
|
required: true,
|
|
232
|
-
description: 'The wss:// or http:// endpoint',
|
|
126
|
+
description: 'The wss:// or http:// CDP endpoint',
|
|
233
127
|
},
|
|
234
128
|
],
|
|
235
129
|
async execute(input) {
|
|
@@ -243,7 +137,7 @@ IMPORTANT: For navigate action, params must include "url" key.`,
|
|
|
243
137
|
};
|
|
244
138
|
}
|
|
245
139
|
};
|
|
246
|
-
return [
|
|
140
|
+
return [...mcpTools, connectTool];
|
|
247
141
|
}
|
|
248
142
|
async execute() {
|
|
249
143
|
const items = this.getInputData();
|
|
@@ -51,6 +51,7 @@ async function createDynamicBrowserTools(credentials) {
|
|
|
51
51
|
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
52
52
|
// Initialize and get MCP tools
|
|
53
53
|
const mcpTools = await sessionManager.initialize(credentials.mcpEndpoint, credentials.browserMode === 'cdp', credentials.cdpEndpoint);
|
|
54
|
+
console.log(`[DynamicTools] Fetched ${mcpTools.length} tools from MCP server`);
|
|
54
55
|
// Create n8n tool for each MCP tool
|
|
55
56
|
const n8nTools = mcpTools.map((mcpTool) => {
|
|
56
57
|
const toolName = mcpTool.name;
|
|
@@ -58,18 +59,26 @@ async function createDynamicBrowserTools(credentials) {
|
|
|
58
59
|
.split('_')
|
|
59
60
|
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
|
60
61
|
.join(' ');
|
|
62
|
+
// Use MCP's description or create a better one
|
|
63
|
+
let description = mcpTool.description;
|
|
64
|
+
if (!description || description.trim() === '') {
|
|
65
|
+
description = `Execute ${displayName} action in the browser.`;
|
|
66
|
+
}
|
|
67
|
+
console.log(`[DynamicTools] Tool: ${toolName}, Description: ${description.substring(0, 100)}...`);
|
|
61
68
|
return {
|
|
62
69
|
name: toolName,
|
|
63
70
|
displayName: displayName,
|
|
64
|
-
description:
|
|
71
|
+
description: description,
|
|
65
72
|
properties: mcpSchemaToN8nProperties(mcpTool.inputSchema),
|
|
66
73
|
async execute(toolInput) {
|
|
67
74
|
try {
|
|
68
|
-
console.log(`[AI Agent] Executing tool: ${toolName}
|
|
75
|
+
console.log(`[AI Agent] Executing tool: ${toolName} with input:`, JSON.stringify(toolInput));
|
|
69
76
|
const result = await sessionManager.callTool(toolName, toolInput);
|
|
77
|
+
console.log(`[AI Agent] Tool ${toolName} result:`, JSON.stringify(result).substring(0, 200));
|
|
70
78
|
return result;
|
|
71
79
|
}
|
|
72
80
|
catch (error) {
|
|
81
|
+
console.error(`[AI Agent] Tool ${toolName} error:`, error.message);
|
|
73
82
|
throw new Error(error.message || 'Unknown error occurred');
|
|
74
83
|
}
|
|
75
84
|
}
|