@yuaone/tools 0.1.0
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/LICENSE +663 -0
- package/README.md +15 -0
- package/dist/__tests__/file-edit.test.d.ts +8 -0
- package/dist/__tests__/file-edit.test.d.ts.map +1 -0
- package/dist/__tests__/file-edit.test.js +125 -0
- package/dist/__tests__/file-edit.test.js.map +1 -0
- package/dist/__tests__/registry.test.d.ts +7 -0
- package/dist/__tests__/registry.test.d.ts.map +1 -0
- package/dist/__tests__/registry.test.js +83 -0
- package/dist/__tests__/registry.test.js.map +1 -0
- package/dist/__tests__/validators.test.d.ts +8 -0
- package/dist/__tests__/validators.test.d.ts.map +1 -0
- package/dist/__tests__/validators.test.js +189 -0
- package/dist/__tests__/validators.test.js.map +1 -0
- package/dist/base-tool.d.ts +45 -0
- package/dist/base-tool.d.ts.map +1 -0
- package/dist/base-tool.js +87 -0
- package/dist/base-tool.js.map +1 -0
- package/dist/browser-tool.d.ts +39 -0
- package/dist/browser-tool.d.ts.map +1 -0
- package/dist/browser-tool.js +518 -0
- package/dist/browser-tool.js.map +1 -0
- package/dist/code-search.d.ts +42 -0
- package/dist/code-search.d.ts.map +1 -0
- package/dist/code-search.js +298 -0
- package/dist/code-search.js.map +1 -0
- package/dist/design-tools.d.ts +70 -0
- package/dist/design-tools.d.ts.map +1 -0
- package/dist/design-tools.js +471 -0
- package/dist/design-tools.js.map +1 -0
- package/dist/dev-server-manager.d.ts +32 -0
- package/dist/dev-server-manager.d.ts.map +1 -0
- package/dist/dev-server-manager.js +183 -0
- package/dist/dev-server-manager.js.map +1 -0
- package/dist/file-edit.d.ts +19 -0
- package/dist/file-edit.d.ts.map +1 -0
- package/dist/file-edit.js +217 -0
- package/dist/file-edit.js.map +1 -0
- package/dist/file-read.d.ts +19 -0
- package/dist/file-read.d.ts.map +1 -0
- package/dist/file-read.js +142 -0
- package/dist/file-read.js.map +1 -0
- package/dist/file-write.d.ts +18 -0
- package/dist/file-write.d.ts.map +1 -0
- package/dist/file-write.js +139 -0
- package/dist/file-write.js.map +1 -0
- package/dist/git-ops.d.ts +25 -0
- package/dist/git-ops.d.ts.map +1 -0
- package/dist/git-ops.js +219 -0
- package/dist/git-ops.js.map +1 -0
- package/dist/glob.d.ts +18 -0
- package/dist/glob.d.ts.map +1 -0
- package/dist/glob.js +91 -0
- package/dist/glob.js.map +1 -0
- package/dist/grep.d.ts +19 -0
- package/dist/grep.d.ts.map +1 -0
- package/dist/grep.js +177 -0
- package/dist/grep.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/security-scan.d.ts +62 -0
- package/dist/security-scan.d.ts.map +1 -0
- package/dist/security-scan.js +445 -0
- package/dist/security-scan.js.map +1 -0
- package/dist/shell-exec.d.ts +20 -0
- package/dist/shell-exec.d.ts.map +1 -0
- package/dist/shell-exec.js +206 -0
- package/dist/shell-exec.js.map +1 -0
- package/dist/test-run.d.ts +51 -0
- package/dist/test-run.d.ts.map +1 -0
- package/dist/test-run.js +359 -0
- package/dist/test-run.js.map +1 -0
- package/dist/tool-registry.d.ts +70 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +181 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/types.d.ts +137 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/validators.d.ts +57 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +218 -0
- package/dist/validators.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @yuaone/tools — Browser Visual Debugging Tool
|
|
3
|
+
*
|
|
4
|
+
* Provides browser automation for visual debugging:
|
|
5
|
+
* - browser open: Launch browser and navigate to URL
|
|
6
|
+
* - browser screenshot: Capture page screenshot (returns base64)
|
|
7
|
+
* - browser click: Click an element by selector
|
|
8
|
+
* - browser type: Type text into an element
|
|
9
|
+
* - browser evaluate: Execute JavaScript in page context
|
|
10
|
+
* - browser dom: Extract DOM structure for analysis
|
|
11
|
+
* - browser close: Close browser
|
|
12
|
+
*
|
|
13
|
+
* Uses Playwright for cross-browser automation.
|
|
14
|
+
* Screenshots are returned as base64 for LLM vision analysis.
|
|
15
|
+
*
|
|
16
|
+
* Security constraints:
|
|
17
|
+
* - Only localhost / 127.0.0.1 / file:// URLs allowed
|
|
18
|
+
* - Script evaluation timeout: 5s
|
|
19
|
+
* - Script length limit: 10KB
|
|
20
|
+
* - DOM extraction depth: 5 levels, max 500 nodes
|
|
21
|
+
* - Max 5 concurrent sessions, 5-minute timeout
|
|
22
|
+
*/
|
|
23
|
+
import type { ParameterDef, RiskLevel, ToolResult } from './types.js';
|
|
24
|
+
import { BaseTool } from './base-tool.js';
|
|
25
|
+
export declare class BrowserTool extends BaseTool {
|
|
26
|
+
readonly name = "browser";
|
|
27
|
+
readonly description: string;
|
|
28
|
+
readonly riskLevel: RiskLevel;
|
|
29
|
+
readonly parameters: Record<string, ParameterDef>;
|
|
30
|
+
execute(args: Record<string, unknown>, workDir: string, _abortSignal?: AbortSignal): Promise<ToolResult>;
|
|
31
|
+
private browserOpen;
|
|
32
|
+
private browserScreenshot;
|
|
33
|
+
private browserClick;
|
|
34
|
+
private browserType;
|
|
35
|
+
private browserEvaluate;
|
|
36
|
+
private browserDom;
|
|
37
|
+
private browserClose;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=browser-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-tool.d.ts","sourceRoot":"","sources":["../src/browser-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAsK1C,qBAAa,WAAY,SAAQ,QAAQ;IACvC,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,WAAW,SAI8C;IAClE,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAU;IAEvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAgD/C;IAEI,OAAO,CACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,GACzB,OAAO,CAAC,UAAU,CAAC;YAkCR,WAAW;YAkEX,iBAAiB;YA8CjB,YAAY;YA+DZ,WAAW;YAiDX,eAAe;YA2Ef,UAAU;YAsCV,YAAY;CAwC3B"}
|
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @yuaone/tools — Browser Visual Debugging Tool
|
|
3
|
+
*
|
|
4
|
+
* Provides browser automation for visual debugging:
|
|
5
|
+
* - browser open: Launch browser and navigate to URL
|
|
6
|
+
* - browser screenshot: Capture page screenshot (returns base64)
|
|
7
|
+
* - browser click: Click an element by selector
|
|
8
|
+
* - browser type: Type text into an element
|
|
9
|
+
* - browser evaluate: Execute JavaScript in page context
|
|
10
|
+
* - browser dom: Extract DOM structure for analysis
|
|
11
|
+
* - browser close: Close browser
|
|
12
|
+
*
|
|
13
|
+
* Uses Playwright for cross-browser automation.
|
|
14
|
+
* Screenshots are returned as base64 for LLM vision analysis.
|
|
15
|
+
*
|
|
16
|
+
* Security constraints:
|
|
17
|
+
* - Only localhost / 127.0.0.1 / file:// URLs allowed
|
|
18
|
+
* - Script evaluation timeout: 5s
|
|
19
|
+
* - Script length limit: 10KB
|
|
20
|
+
* - DOM extraction depth: 5 levels, max 500 nodes
|
|
21
|
+
* - Max 5 concurrent sessions, 5-minute timeout
|
|
22
|
+
*/
|
|
23
|
+
import { BaseTool } from './base-tool.js';
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Lazy-load Playwright so the tool doesn't crash if not installed
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
let playwrightModule = null;
|
|
28
|
+
async function getPlaywright() {
|
|
29
|
+
if (!playwrightModule) {
|
|
30
|
+
try {
|
|
31
|
+
// Dynamic import with variable to prevent TypeScript from resolving the module
|
|
32
|
+
const moduleName = 'playwright';
|
|
33
|
+
playwrightModule = await Function('m', 'return import(m)')(moduleName);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
throw new Error('Playwright is not installed. Run: pnpm --filter @yuaone/tools add playwright && npx playwright install chromium');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return playwrightModule;
|
|
40
|
+
}
|
|
41
|
+
const sessions = new Map();
|
|
42
|
+
const MAX_SESSIONS = 5;
|
|
43
|
+
const SESSION_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
44
|
+
/** Generate a short random session ID. */
|
|
45
|
+
function generateSessionId() {
|
|
46
|
+
return `bs_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
47
|
+
}
|
|
48
|
+
/** Evict expired sessions. */
|
|
49
|
+
async function evictExpiredSessions() {
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
for (const [id, session] of sessions) {
|
|
52
|
+
if (now - session.createdAt > SESSION_TIMEOUT_MS) {
|
|
53
|
+
try {
|
|
54
|
+
await session.browser?.close();
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// ignore
|
|
58
|
+
}
|
|
59
|
+
sessions.delete(id);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** Get a session or return an error ToolResult. */
|
|
64
|
+
function getSession(sessionId) {
|
|
65
|
+
if (!sessionId)
|
|
66
|
+
return null;
|
|
67
|
+
const session = sessions.get(sessionId);
|
|
68
|
+
if (!session)
|
|
69
|
+
return null;
|
|
70
|
+
// Check if expired
|
|
71
|
+
if (Date.now() - session.createdAt > SESSION_TIMEOUT_MS) {
|
|
72
|
+
session.browser?.close().catch(() => { });
|
|
73
|
+
sessions.delete(sessionId);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return session;
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// URL validation — only allow safe local URLs
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
const ALLOWED_URL_PATTERNS = [
|
|
82
|
+
/^https?:\/\/localhost(:\d+)?(\/|$)/,
|
|
83
|
+
/^https?:\/\/127\.0\.0\.1(:\d+)?(\/|$)/,
|
|
84
|
+
/^https?:\/\/0\.0\.0\.0(:\d+)?(\/|$)/,
|
|
85
|
+
/^https?:\/\/\[::1\](:\d+)?(\/|$)/,
|
|
86
|
+
/^file:\/\//,
|
|
87
|
+
];
|
|
88
|
+
function isAllowedUrl(url) {
|
|
89
|
+
return ALLOWED_URL_PATTERNS.some((p) => p.test(url));
|
|
90
|
+
}
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// DOM extraction helpers
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
const MAX_DOM_DEPTH = 5;
|
|
95
|
+
const MAX_DOM_NODES = 500;
|
|
96
|
+
/**
|
|
97
|
+
* Script injected into the page to extract a simplified DOM tree.
|
|
98
|
+
* Returns a serializable object with tag, id, class, text, and children.
|
|
99
|
+
*/
|
|
100
|
+
function buildDomExtractionScript(maxDepth, maxNodes) {
|
|
101
|
+
return `
|
|
102
|
+
(() => {
|
|
103
|
+
let nodeCount = 0;
|
|
104
|
+
const MAX_DEPTH = ${maxDepth};
|
|
105
|
+
const MAX_NODES = ${maxNodes};
|
|
106
|
+
const SKIP_TAGS = new Set(['SCRIPT', 'STYLE', 'NOSCRIPT', 'SVG', 'PATH']);
|
|
107
|
+
|
|
108
|
+
function extract(el, depth) {
|
|
109
|
+
if (depth > MAX_DEPTH || nodeCount >= MAX_NODES) return null;
|
|
110
|
+
if (!el || !el.tagName) return null;
|
|
111
|
+
if (SKIP_TAGS.has(el.tagName)) return null;
|
|
112
|
+
|
|
113
|
+
nodeCount++;
|
|
114
|
+
|
|
115
|
+
const node = {
|
|
116
|
+
tag: el.tagName.toLowerCase(),
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
if (el.id) node.id = el.id;
|
|
120
|
+
if (el.className && typeof el.className === 'string' && el.className.trim()) {
|
|
121
|
+
node.cls = el.className.trim().split(/\\s+/).slice(0, 5).join(' ');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Direct text content (not from children)
|
|
125
|
+
const textContent = Array.from(el.childNodes)
|
|
126
|
+
.filter(n => n.nodeType === 3)
|
|
127
|
+
.map(n => n.textContent?.trim())
|
|
128
|
+
.filter(Boolean)
|
|
129
|
+
.join(' ')
|
|
130
|
+
.slice(0, 100);
|
|
131
|
+
|
|
132
|
+
if (textContent) node.text = textContent;
|
|
133
|
+
|
|
134
|
+
// Useful attributes
|
|
135
|
+
if (el.href) node.href = el.href;
|
|
136
|
+
if (el.src) node.src = el.src;
|
|
137
|
+
if (el.type) node.type = el.type;
|
|
138
|
+
if (el.name) node.name = el.name;
|
|
139
|
+
if (el.value && el.value.length < 100) node.value = el.value;
|
|
140
|
+
if (el.placeholder) node.placeholder = el.placeholder;
|
|
141
|
+
|
|
142
|
+
// Children
|
|
143
|
+
if (depth < MAX_DEPTH && el.children && el.children.length > 0) {
|
|
144
|
+
const children = [];
|
|
145
|
+
for (const child of el.children) {
|
|
146
|
+
if (nodeCount >= MAX_NODES) break;
|
|
147
|
+
const childNode = extract(child, depth + 1);
|
|
148
|
+
if (childNode) children.push(childNode);
|
|
149
|
+
}
|
|
150
|
+
if (children.length > 0) node.children = children;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return node;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return extract(document.body, 0);
|
|
157
|
+
})()
|
|
158
|
+
`;
|
|
159
|
+
}
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
// BrowserTool
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
export class BrowserTool extends BaseTool {
|
|
164
|
+
name = 'browser';
|
|
165
|
+
description = 'Browser automation for visual debugging. ' +
|
|
166
|
+
'Actions: open, screenshot, click, type, evaluate, dom, close. ' +
|
|
167
|
+
'Screenshots are returned as base64 for visual analysis. ' +
|
|
168
|
+
'Only localhost/127.0.0.1/file:// URLs are allowed (security).';
|
|
169
|
+
riskLevel = 'high';
|
|
170
|
+
parameters = {
|
|
171
|
+
action: {
|
|
172
|
+
type: 'string',
|
|
173
|
+
description: 'Browser action to perform',
|
|
174
|
+
required: true,
|
|
175
|
+
enum: ['open', 'screenshot', 'click', 'type', 'evaluate', 'dom', 'close'],
|
|
176
|
+
},
|
|
177
|
+
url: {
|
|
178
|
+
type: 'string',
|
|
179
|
+
description: 'URL to navigate to (for open action). Only localhost/127.0.0.1/file:// allowed.',
|
|
180
|
+
required: false,
|
|
181
|
+
},
|
|
182
|
+
selector: {
|
|
183
|
+
type: 'string',
|
|
184
|
+
description: 'CSS selector for target element (for click, type actions)',
|
|
185
|
+
required: false,
|
|
186
|
+
},
|
|
187
|
+
text: {
|
|
188
|
+
type: 'string',
|
|
189
|
+
description: 'Text to type (for type action)',
|
|
190
|
+
required: false,
|
|
191
|
+
},
|
|
192
|
+
script: {
|
|
193
|
+
type: 'string',
|
|
194
|
+
description: 'JavaScript to evaluate in page context (for evaluate action, max 10KB)',
|
|
195
|
+
required: false,
|
|
196
|
+
},
|
|
197
|
+
sessionId: {
|
|
198
|
+
type: 'string',
|
|
199
|
+
description: 'Browser session ID. Auto-generated on open; reuse for subsequent actions.',
|
|
200
|
+
required: false,
|
|
201
|
+
},
|
|
202
|
+
fullPage: {
|
|
203
|
+
type: 'boolean',
|
|
204
|
+
description: 'Capture full page screenshot (default: false)',
|
|
205
|
+
required: false,
|
|
206
|
+
default: false,
|
|
207
|
+
},
|
|
208
|
+
viewport: {
|
|
209
|
+
type: 'object',
|
|
210
|
+
description: 'Viewport size { width, height } for open action (default: 1280x720)',
|
|
211
|
+
required: false,
|
|
212
|
+
},
|
|
213
|
+
waitFor: {
|
|
214
|
+
type: 'string',
|
|
215
|
+
description: 'CSS selector to wait for before performing action',
|
|
216
|
+
required: false,
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
async execute(args, workDir, _abortSignal) {
|
|
220
|
+
const toolCallId = args._toolCallId ?? '';
|
|
221
|
+
const action = args.action;
|
|
222
|
+
// Evict expired sessions before every action
|
|
223
|
+
await evictExpiredSessions();
|
|
224
|
+
try {
|
|
225
|
+
switch (action) {
|
|
226
|
+
case 'open':
|
|
227
|
+
return await this.browserOpen(toolCallId, args);
|
|
228
|
+
case 'screenshot':
|
|
229
|
+
return await this.browserScreenshot(toolCallId, args);
|
|
230
|
+
case 'click':
|
|
231
|
+
return await this.browserClick(toolCallId, args);
|
|
232
|
+
case 'type':
|
|
233
|
+
return await this.browserType(toolCallId, args);
|
|
234
|
+
case 'evaluate':
|
|
235
|
+
return await this.browserEvaluate(toolCallId, args);
|
|
236
|
+
case 'dom':
|
|
237
|
+
return await this.browserDom(toolCallId, args);
|
|
238
|
+
case 'close':
|
|
239
|
+
return await this.browserClose(toolCallId, args);
|
|
240
|
+
default:
|
|
241
|
+
return this.fail(toolCallId, `Unknown browser action: ${action}. Valid actions: open, screenshot, click, type, evaluate, dom, close`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
246
|
+
return this.fail(toolCallId, `Browser action "${action}" failed: ${message}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// ─── open ──────────────────────────────────────────────────────────
|
|
250
|
+
async browserOpen(toolCallId, args) {
|
|
251
|
+
const url = args.url;
|
|
252
|
+
if (!url) {
|
|
253
|
+
return this.fail(toolCallId, 'Missing required parameter: url');
|
|
254
|
+
}
|
|
255
|
+
// Security: only allow local URLs
|
|
256
|
+
if (!isAllowedUrl(url)) {
|
|
257
|
+
return this.fail(toolCallId, `URL not allowed: "${url}". Only localhost, 127.0.0.1, 0.0.0.0, [::1], and file:// URLs are permitted.`);
|
|
258
|
+
}
|
|
259
|
+
// Enforce session limit
|
|
260
|
+
if (sessions.size >= MAX_SESSIONS) {
|
|
261
|
+
return this.fail(toolCallId, `Maximum concurrent browser sessions reached (${MAX_SESSIONS}). Close an existing session first.`);
|
|
262
|
+
}
|
|
263
|
+
const pw = await getPlaywright();
|
|
264
|
+
const viewport = args.viewport;
|
|
265
|
+
const vw = viewport?.width ?? 1280;
|
|
266
|
+
const vh = viewport?.height ?? 720;
|
|
267
|
+
const browser = await pw.chromium.launch({ headless: true });
|
|
268
|
+
const context = await browser.newContext({
|
|
269
|
+
viewport: { width: vw, height: vh },
|
|
270
|
+
ignoreHTTPSErrors: true,
|
|
271
|
+
});
|
|
272
|
+
const page = await context.newPage();
|
|
273
|
+
// Navigate
|
|
274
|
+
await page.goto(url, {
|
|
275
|
+
waitUntil: 'networkidle',
|
|
276
|
+
timeout: 30_000,
|
|
277
|
+
});
|
|
278
|
+
const sessionId = generateSessionId();
|
|
279
|
+
sessions.set(sessionId, {
|
|
280
|
+
browser,
|
|
281
|
+
context,
|
|
282
|
+
page,
|
|
283
|
+
createdAt: Date.now(),
|
|
284
|
+
});
|
|
285
|
+
const title = await page.title();
|
|
286
|
+
return this.ok(toolCallId, JSON.stringify({
|
|
287
|
+
sessionId,
|
|
288
|
+
title,
|
|
289
|
+
url: page.url(),
|
|
290
|
+
viewport: { width: vw, height: vh },
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
293
|
+
// ─── screenshot ────────────────────────────────────────────────────
|
|
294
|
+
async browserScreenshot(toolCallId, args) {
|
|
295
|
+
const sessionId = args.sessionId;
|
|
296
|
+
const session = getSession(sessionId);
|
|
297
|
+
if (!session) {
|
|
298
|
+
return this.fail(toolCallId, sessionId
|
|
299
|
+
? `Session not found or expired: ${sessionId}`
|
|
300
|
+
: 'Missing required parameter: sessionId');
|
|
301
|
+
}
|
|
302
|
+
const fullPage = args.fullPage ?? false;
|
|
303
|
+
const waitFor = args.waitFor;
|
|
304
|
+
if (waitFor) {
|
|
305
|
+
await session.page.waitForSelector(waitFor, { timeout: 10_000 });
|
|
306
|
+
}
|
|
307
|
+
const screenshotBuffer = await session.page.screenshot({
|
|
308
|
+
fullPage,
|
|
309
|
+
type: 'png',
|
|
310
|
+
});
|
|
311
|
+
const base64 = screenshotBuffer.toString('base64');
|
|
312
|
+
const title = await session.page.title();
|
|
313
|
+
return this.ok(toolCallId, JSON.stringify({
|
|
314
|
+
sessionId,
|
|
315
|
+
title,
|
|
316
|
+
url: session.page.url(),
|
|
317
|
+
fullPage,
|
|
318
|
+
imageBase64: base64,
|
|
319
|
+
imageMimeType: 'image/png',
|
|
320
|
+
imageSizeBytes: screenshotBuffer.byteLength,
|
|
321
|
+
}));
|
|
322
|
+
}
|
|
323
|
+
// ─── click ─────────────────────────────────────────────────────────
|
|
324
|
+
async browserClick(toolCallId, args) {
|
|
325
|
+
const sessionId = args.sessionId;
|
|
326
|
+
const session = getSession(sessionId);
|
|
327
|
+
if (!session) {
|
|
328
|
+
return this.fail(toolCallId, sessionId
|
|
329
|
+
? `Session not found or expired: ${sessionId}`
|
|
330
|
+
: 'Missing required parameter: sessionId');
|
|
331
|
+
}
|
|
332
|
+
const selector = args.selector;
|
|
333
|
+
if (!selector) {
|
|
334
|
+
return this.fail(toolCallId, 'Missing required parameter: selector');
|
|
335
|
+
}
|
|
336
|
+
const waitFor = args.waitFor;
|
|
337
|
+
if (waitFor) {
|
|
338
|
+
await session.page.waitForSelector(waitFor, { timeout: 10_000 });
|
|
339
|
+
}
|
|
340
|
+
// Wait for the target element
|
|
341
|
+
await session.page.waitForSelector(selector, { timeout: 10_000 });
|
|
342
|
+
// Get element info before clicking (evaluate as string to avoid TS DOM type issues)
|
|
343
|
+
const elementInfoScript = `
|
|
344
|
+
(() => {
|
|
345
|
+
const el = document.querySelector(${JSON.stringify(selector)});
|
|
346
|
+
if (!el) return null;
|
|
347
|
+
return {
|
|
348
|
+
tag: el.tagName.toLowerCase(),
|
|
349
|
+
text: (el.textContent || '').trim().slice(0, 100),
|
|
350
|
+
id: el.id || undefined,
|
|
351
|
+
className: el.className && typeof el.className === 'string'
|
|
352
|
+
? el.className.trim().slice(0, 100)
|
|
353
|
+
: undefined,
|
|
354
|
+
};
|
|
355
|
+
})()
|
|
356
|
+
`;
|
|
357
|
+
const elementInfo = await session.page.evaluate(elementInfoScript);
|
|
358
|
+
// Click and wait for any navigation or network activity to settle
|
|
359
|
+
await session.page.click(selector);
|
|
360
|
+
await session.page.waitForLoadState('networkidle', { timeout: 5_000 }).catch(() => { });
|
|
361
|
+
return this.ok(toolCallId, JSON.stringify({
|
|
362
|
+
sessionId,
|
|
363
|
+
action: 'click',
|
|
364
|
+
selector,
|
|
365
|
+
element: elementInfo,
|
|
366
|
+
url: session.page.url(),
|
|
367
|
+
}));
|
|
368
|
+
}
|
|
369
|
+
// ─── type ──────────────────────────────────────────────────────────
|
|
370
|
+
async browserType(toolCallId, args) {
|
|
371
|
+
const sessionId = args.sessionId;
|
|
372
|
+
const session = getSession(sessionId);
|
|
373
|
+
if (!session) {
|
|
374
|
+
return this.fail(toolCallId, sessionId
|
|
375
|
+
? `Session not found or expired: ${sessionId}`
|
|
376
|
+
: 'Missing required parameter: sessionId');
|
|
377
|
+
}
|
|
378
|
+
const selector = args.selector;
|
|
379
|
+
if (!selector) {
|
|
380
|
+
return this.fail(toolCallId, 'Missing required parameter: selector');
|
|
381
|
+
}
|
|
382
|
+
const text = args.text;
|
|
383
|
+
if (text === undefined || text === null) {
|
|
384
|
+
return this.fail(toolCallId, 'Missing required parameter: text');
|
|
385
|
+
}
|
|
386
|
+
const waitFor = args.waitFor;
|
|
387
|
+
if (waitFor) {
|
|
388
|
+
await session.page.waitForSelector(waitFor, { timeout: 10_000 });
|
|
389
|
+
}
|
|
390
|
+
// Wait for the target element
|
|
391
|
+
await session.page.waitForSelector(selector, { timeout: 10_000 });
|
|
392
|
+
// Use fill() to clear and set value (works for input/textarea)
|
|
393
|
+
await session.page.fill(selector, text);
|
|
394
|
+
return this.ok(toolCallId, JSON.stringify({
|
|
395
|
+
sessionId,
|
|
396
|
+
action: 'type',
|
|
397
|
+
selector,
|
|
398
|
+
textLength: text.length,
|
|
399
|
+
}));
|
|
400
|
+
}
|
|
401
|
+
// ─── evaluate ──────────────────────────────────────────────────────
|
|
402
|
+
async browserEvaluate(toolCallId, args) {
|
|
403
|
+
const sessionId = args.sessionId;
|
|
404
|
+
const session = getSession(sessionId);
|
|
405
|
+
if (!session) {
|
|
406
|
+
return this.fail(toolCallId, sessionId
|
|
407
|
+
? `Session not found or expired: ${sessionId}`
|
|
408
|
+
: 'Missing required parameter: sessionId');
|
|
409
|
+
}
|
|
410
|
+
const script = args.script;
|
|
411
|
+
if (!script) {
|
|
412
|
+
return this.fail(toolCallId, 'Missing required parameter: script');
|
|
413
|
+
}
|
|
414
|
+
// Security: limit script length
|
|
415
|
+
const MAX_SCRIPT_LENGTH = 10 * 1024; // 10KB
|
|
416
|
+
if (script.length > MAX_SCRIPT_LENGTH) {
|
|
417
|
+
return this.fail(toolCallId, `Script too long: ${script.length} bytes (max ${MAX_SCRIPT_LENGTH} bytes)`);
|
|
418
|
+
}
|
|
419
|
+
const waitFor = args.waitFor;
|
|
420
|
+
if (waitFor) {
|
|
421
|
+
await session.page.waitForSelector(waitFor, { timeout: 10_000 });
|
|
422
|
+
}
|
|
423
|
+
// Evaluate with timeout
|
|
424
|
+
const EVAL_TIMEOUT = 5_000;
|
|
425
|
+
let result;
|
|
426
|
+
try {
|
|
427
|
+
result = await Promise.race([
|
|
428
|
+
session.page.evaluate(script),
|
|
429
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('Script evaluation timed out (5s)')), EVAL_TIMEOUT)),
|
|
430
|
+
]);
|
|
431
|
+
}
|
|
432
|
+
catch (err) {
|
|
433
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
434
|
+
return this.fail(toolCallId, `Script evaluation error: ${msg}`);
|
|
435
|
+
}
|
|
436
|
+
// Serialize result
|
|
437
|
+
let serialized;
|
|
438
|
+
try {
|
|
439
|
+
serialized = JSON.stringify(result, null, 2);
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
serialized = String(result);
|
|
443
|
+
}
|
|
444
|
+
// Limit output size
|
|
445
|
+
const MAX_OUTPUT = 50 * 1024; // 50KB
|
|
446
|
+
if (serialized.length > MAX_OUTPUT) {
|
|
447
|
+
serialized = serialized.slice(0, MAX_OUTPUT) + '\n...(truncated)';
|
|
448
|
+
}
|
|
449
|
+
return this.ok(toolCallId, JSON.stringify({
|
|
450
|
+
sessionId,
|
|
451
|
+
action: 'evaluate',
|
|
452
|
+
result: serialized,
|
|
453
|
+
}));
|
|
454
|
+
}
|
|
455
|
+
// ─── dom ───────────────────────────────────────────────────────────
|
|
456
|
+
async browserDom(toolCallId, args) {
|
|
457
|
+
const sessionId = args.sessionId;
|
|
458
|
+
const session = getSession(sessionId);
|
|
459
|
+
if (!session) {
|
|
460
|
+
return this.fail(toolCallId, sessionId
|
|
461
|
+
? `Session not found or expired: ${sessionId}`
|
|
462
|
+
: 'Missing required parameter: sessionId');
|
|
463
|
+
}
|
|
464
|
+
const waitFor = args.waitFor;
|
|
465
|
+
if (waitFor) {
|
|
466
|
+
await session.page.waitForSelector(waitFor, { timeout: 10_000 });
|
|
467
|
+
}
|
|
468
|
+
const domScript = buildDomExtractionScript(MAX_DOM_DEPTH, MAX_DOM_NODES);
|
|
469
|
+
const domTree = await session.page.evaluate(domScript);
|
|
470
|
+
const title = await session.page.title();
|
|
471
|
+
return this.ok(toolCallId, JSON.stringify({
|
|
472
|
+
sessionId,
|
|
473
|
+
title,
|
|
474
|
+
url: session.page.url(),
|
|
475
|
+
dom: domTree,
|
|
476
|
+
}));
|
|
477
|
+
}
|
|
478
|
+
// ─── close ─────────────────────────────────────────────────────────
|
|
479
|
+
async browserClose(toolCallId, args) {
|
|
480
|
+
const sessionId = args.sessionId;
|
|
481
|
+
// If no sessionId, close all sessions
|
|
482
|
+
if (!sessionId) {
|
|
483
|
+
const count = sessions.size;
|
|
484
|
+
for (const [id, session] of sessions) {
|
|
485
|
+
try {
|
|
486
|
+
await session.browser?.close();
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
// ignore
|
|
490
|
+
}
|
|
491
|
+
sessions.delete(id);
|
|
492
|
+
}
|
|
493
|
+
return this.ok(toolCallId, JSON.stringify({ action: 'close', closedSessions: count }));
|
|
494
|
+
}
|
|
495
|
+
const session = sessions.get(sessionId);
|
|
496
|
+
if (!session) {
|
|
497
|
+
return this.fail(toolCallId, `Session not found: ${sessionId}`);
|
|
498
|
+
}
|
|
499
|
+
try {
|
|
500
|
+
await session.browser?.close();
|
|
501
|
+
}
|
|
502
|
+
catch {
|
|
503
|
+
// ignore
|
|
504
|
+
}
|
|
505
|
+
sessions.delete(sessionId);
|
|
506
|
+
return this.ok(toolCallId, JSON.stringify({ action: 'close', sessionId }));
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
// ---------------------------------------------------------------------------
|
|
510
|
+
// Cleanup all sessions on process exit
|
|
511
|
+
// ---------------------------------------------------------------------------
|
|
512
|
+
process.on('exit', () => {
|
|
513
|
+
for (const [, session] of sessions) {
|
|
514
|
+
session.browser?.close?.().catch(() => { });
|
|
515
|
+
}
|
|
516
|
+
sessions.clear();
|
|
517
|
+
});
|
|
518
|
+
//# sourceMappingURL=browser-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-tool.js","sourceRoot":"","sources":["../src/browser-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @yuaone/tools — code_search tool
|
|
3
|
+
*
|
|
4
|
+
* Phase 1: Symbol-based code search using regex patterns.
|
|
5
|
+
* (Embedding-based semantic search planned for Phase 2)
|
|
6
|
+
*
|
|
7
|
+
* Search modes:
|
|
8
|
+
* 1. symbol: Find function/class/variable/type/interface definitions by name
|
|
9
|
+
* 2. reference: Find usages of a specific symbol
|
|
10
|
+
* 3. definition: Find where a symbol is defined
|
|
11
|
+
*
|
|
12
|
+
* Supports: TypeScript, JavaScript, Python
|
|
13
|
+
* Excludes: node_modules, dist, .git, build, coverage, __pycache__
|
|
14
|
+
*
|
|
15
|
+
* riskLevel: 'low' (read-only)
|
|
16
|
+
*/
|
|
17
|
+
import type { ParameterDef, RiskLevel, ToolResult } from './types.js';
|
|
18
|
+
import { BaseTool } from './base-tool.js';
|
|
19
|
+
export declare class CodeSearchTool extends BaseTool {
|
|
20
|
+
readonly name = "code_search";
|
|
21
|
+
readonly description: string;
|
|
22
|
+
readonly riskLevel: RiskLevel;
|
|
23
|
+
readonly parameters: Record<string, ParameterDef>;
|
|
24
|
+
execute(args: Record<string, unknown>, workDir: string): Promise<ToolResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Search a single file for matching symbols.
|
|
27
|
+
*/
|
|
28
|
+
private searchFile;
|
|
29
|
+
/**
|
|
30
|
+
* Infer the kind of symbol from the line content.
|
|
31
|
+
*/
|
|
32
|
+
private inferKind;
|
|
33
|
+
/**
|
|
34
|
+
* Get a snippet with context lines around a match.
|
|
35
|
+
*/
|
|
36
|
+
private getSnippet;
|
|
37
|
+
/**
|
|
38
|
+
* Format results for output.
|
|
39
|
+
*/
|
|
40
|
+
private formatResults;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=code-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-search.d.ts","sourceRoot":"","sources":["../src/code-search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA2D1C,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,SAGyB;IAC7C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAS;IAEtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CA8B/C;IAEI,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAyElF;;OAEG;IACH,OAAO,CAAC,UAAU;IAqElB;;OAEG;IACH,OAAO,CAAC,SAAS;IAiBjB;;OAEG;IACH,OAAO,CAAC,UAAU;IAalB;;OAEG;IACH,OAAO,CAAC,aAAa;CAiBtB"}
|