@kritchoff/agent-browser 0.9.2
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 +201 -0
- package/README.md +903 -0
- package/README.sdk.md +77 -0
- package/bin/agent-browser-linux-x64 +0 -0
- package/bin/agent-browser.js +109 -0
- package/dist/actions.d.ts +17 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +1427 -0
- package/dist/actions.js.map +1 -0
- package/dist/browser.d.ts +474 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +1566 -0
- package/dist/browser.js.map +1 -0
- package/dist/cdp-client.d.ts +103 -0
- package/dist/cdp-client.d.ts.map +1 -0
- package/dist/cdp-client.js +223 -0
- package/dist/cdp-client.js.map +1 -0
- package/dist/daemon.d.ts +60 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +401 -0
- package/dist/daemon.js.map +1 -0
- package/dist/dualmode-config.d.ts +37 -0
- package/dist/dualmode-config.d.ts.map +1 -0
- package/dist/dualmode-config.js +44 -0
- package/dist/dualmode-config.js.map +1 -0
- package/dist/dualmode-fetcher.d.ts +60 -0
- package/dist/dualmode-fetcher.d.ts.map +1 -0
- package/dist/dualmode-fetcher.js +449 -0
- package/dist/dualmode-fetcher.js.map +1 -0
- package/dist/dualmode-types.d.ts +183 -0
- package/dist/dualmode-types.d.ts.map +1 -0
- package/dist/dualmode-types.js +8 -0
- package/dist/dualmode-types.js.map +1 -0
- package/dist/ios-actions.d.ts +11 -0
- package/dist/ios-actions.d.ts.map +1 -0
- package/dist/ios-actions.js +228 -0
- package/dist/ios-actions.js.map +1 -0
- package/dist/ios-manager.d.ts +266 -0
- package/dist/ios-manager.d.ts.map +1 -0
- package/dist/ios-manager.js +1073 -0
- package/dist/ios-manager.js.map +1 -0
- package/dist/protocol.d.ts +26 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +832 -0
- package/dist/protocol.js.map +1 -0
- package/dist/snapshot.d.ts +83 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +653 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/stream-server.d.ts +117 -0
- package/dist/stream-server.d.ts.map +1 -0
- package/dist/stream-server.js +305 -0
- package/dist/stream-server.js.map +1 -0
- package/dist/types.d.ts +742 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/docker-compose.sdk.yml +45 -0
- package/package.json +85 -0
- package/scripts/benchmark.sh +80 -0
- package/scripts/build-all-platforms.sh +68 -0
- package/scripts/check-version-sync.js +39 -0
- package/scripts/copy-native.js +36 -0
- package/scripts/fast_reset.sh +108 -0
- package/scripts/postinstall.js +235 -0
- package/scripts/publish_images.sh +55 -0
- package/scripts/snapshot_manager.sh +293 -0
- package/scripts/start-android-agent.sh +49 -0
- package/scripts/sync-version.js +69 -0
- package/scripts/vaccine-run +26 -0
- package/sdk.sh +153 -0
- package/skills/agent-browser/SKILL.md +217 -0
- package/skills/agent-browser/references/authentication.md +202 -0
- package/skills/agent-browser/references/commands.md +259 -0
- package/skills/agent-browser/references/proxy-support.md +188 -0
- package/skills/agent-browser/references/session-management.md +193 -0
- package/skills/agent-browser/references/snapshot-refs.md +194 -0
- package/skills/agent-browser/references/video-recording.md +173 -0
- package/skills/agent-browser/templates/authenticated-session.sh +97 -0
- package/skills/agent-browser/templates/capture-workflow.sh +69 -0
- package/skills/agent-browser/templates/form-automation.sh +62 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +356 -0
- package/skills/skill-creator/references/output-patterns.md +82 -0
- package/skills/skill-creator/references/workflows.md +28 -0
- package/skills/skill-creator/scripts/init_skill.py +303 -0
- package/skills/skill-creator/scripts/package_skill.py +113 -0
- package/skills/skill-creator/scripts/quick_validate.py +95 -0
package/dist/daemon.js
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import * as net from 'net';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as os from 'os';
|
|
6
|
+
import { BrowserManager } from './browser.js';
|
|
7
|
+
import { IOSManager } from './ios-manager.js';
|
|
8
|
+
import { parseCommand, serializeResponse, errorResponse } from './protocol.js';
|
|
9
|
+
import { executeCommand } from './actions.js';
|
|
10
|
+
import { executeIOSCommand } from './ios-actions.js';
|
|
11
|
+
import { StreamServer } from './stream-server.js';
|
|
12
|
+
// Platform detection
|
|
13
|
+
const isWindows = process.platform === 'win32';
|
|
14
|
+
// Session support - each session gets its own socket/pid
|
|
15
|
+
let currentSession = process.env.AGENT_BROWSER_SESSION || 'default';
|
|
16
|
+
// Stream server for browser preview
|
|
17
|
+
let streamServer = null;
|
|
18
|
+
// Default stream port (can be overridden with AGENT_BROWSER_STREAM_PORT)
|
|
19
|
+
const DEFAULT_STREAM_PORT = 9223;
|
|
20
|
+
/**
|
|
21
|
+
* Set the current session
|
|
22
|
+
*/
|
|
23
|
+
export function setSession(session) {
|
|
24
|
+
currentSession = session;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the current session
|
|
28
|
+
*/
|
|
29
|
+
export function getSession() {
|
|
30
|
+
return currentSession;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get port number for TCP mode (Windows)
|
|
34
|
+
* Uses a hash of the session name to get a consistent port
|
|
35
|
+
*/
|
|
36
|
+
function getPortForSession(session) {
|
|
37
|
+
let hash = 0;
|
|
38
|
+
for (let i = 0; i < session.length; i++) {
|
|
39
|
+
hash = (hash << 5) - hash + session.charCodeAt(i);
|
|
40
|
+
hash |= 0;
|
|
41
|
+
}
|
|
42
|
+
// Port range 49152-65535 (dynamic/private ports)
|
|
43
|
+
return 49152 + (Math.abs(hash) % 16383);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the base directory for socket/pid files.
|
|
47
|
+
* Priority: AGENT_BROWSER_SOCKET_DIR > XDG_RUNTIME_DIR > ~/.agent-browser > tmpdir
|
|
48
|
+
*/
|
|
49
|
+
export function getAppDir() {
|
|
50
|
+
// 1. XDG_RUNTIME_DIR (Linux standard)
|
|
51
|
+
if (process.env.XDG_RUNTIME_DIR) {
|
|
52
|
+
return path.join(process.env.XDG_RUNTIME_DIR, 'agent-browser');
|
|
53
|
+
}
|
|
54
|
+
// 2. Home directory fallback (like Docker Desktop's ~/.docker/run/)
|
|
55
|
+
const homeDir = os.homedir();
|
|
56
|
+
if (homeDir) {
|
|
57
|
+
return path.join(homeDir, '.agent-browser');
|
|
58
|
+
}
|
|
59
|
+
// 3. Last resort: temp dir
|
|
60
|
+
return path.join(os.tmpdir(), 'agent-browser');
|
|
61
|
+
}
|
|
62
|
+
export function getSocketDir() {
|
|
63
|
+
// Allow explicit override for socket directory
|
|
64
|
+
if (process.env.AGENT_BROWSER_SOCKET_DIR) {
|
|
65
|
+
return process.env.AGENT_BROWSER_SOCKET_DIR;
|
|
66
|
+
}
|
|
67
|
+
return getAppDir();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get the socket path for the current session (Unix) or port (Windows)
|
|
71
|
+
*/
|
|
72
|
+
export function getSocketPath(session) {
|
|
73
|
+
const sess = session ?? currentSession;
|
|
74
|
+
if (isWindows) {
|
|
75
|
+
return String(getPortForSession(sess));
|
|
76
|
+
}
|
|
77
|
+
return path.join(getSocketDir(), `${sess}.sock`);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get the port file path for Windows (stores the port number)
|
|
81
|
+
*/
|
|
82
|
+
export function getPortFile(session) {
|
|
83
|
+
const sess = session ?? currentSession;
|
|
84
|
+
return path.join(getSocketDir(), `${sess}.port`);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the PID file path for the current session
|
|
88
|
+
*/
|
|
89
|
+
export function getPidFile(session) {
|
|
90
|
+
const sess = session ?? currentSession;
|
|
91
|
+
return path.join(getSocketDir(), `${sess}.pid`);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Check if daemon is running for the current session
|
|
95
|
+
*/
|
|
96
|
+
export function isDaemonRunning(session) {
|
|
97
|
+
const pidFile = getPidFile(session);
|
|
98
|
+
if (!fs.existsSync(pidFile))
|
|
99
|
+
return false;
|
|
100
|
+
try {
|
|
101
|
+
const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
|
|
102
|
+
// Check if process exists (works on both Unix and Windows)
|
|
103
|
+
process.kill(pid, 0);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Process doesn't exist, clean up stale files
|
|
108
|
+
cleanupSocket(session);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get connection info for the current session
|
|
114
|
+
* Returns { type: 'unix', path: string } or { type: 'tcp', port: number }
|
|
115
|
+
*/
|
|
116
|
+
export function getConnectionInfo(session) {
|
|
117
|
+
const sess = session ?? currentSession;
|
|
118
|
+
if (isWindows) {
|
|
119
|
+
return { type: 'tcp', port: getPortForSession(sess) };
|
|
120
|
+
}
|
|
121
|
+
return { type: 'unix', path: path.join(getSocketDir(), `${sess}.sock`) };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Clean up socket and PID file for the current session
|
|
125
|
+
*/
|
|
126
|
+
export function cleanupSocket(session) {
|
|
127
|
+
const pidFile = getPidFile(session);
|
|
128
|
+
const streamPortFile = getStreamPortFile(session);
|
|
129
|
+
try {
|
|
130
|
+
if (fs.existsSync(pidFile))
|
|
131
|
+
fs.unlinkSync(pidFile);
|
|
132
|
+
if (fs.existsSync(streamPortFile))
|
|
133
|
+
fs.unlinkSync(streamPortFile);
|
|
134
|
+
if (isWindows) {
|
|
135
|
+
const portFile = getPortFile(session);
|
|
136
|
+
if (fs.existsSync(portFile))
|
|
137
|
+
fs.unlinkSync(portFile);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const socketPath = getSocketPath(session);
|
|
141
|
+
if (fs.existsSync(socketPath))
|
|
142
|
+
fs.unlinkSync(socketPath);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Ignore cleanup errors
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get the stream port file path
|
|
151
|
+
*/
|
|
152
|
+
export function getStreamPortFile(session) {
|
|
153
|
+
const sess = session ?? currentSession;
|
|
154
|
+
return path.join(getSocketDir(), `${sess}.stream`);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Start the daemon server
|
|
158
|
+
* @param options.streamPort Port for WebSocket stream server (0 to disable)
|
|
159
|
+
* @param options.provider Provider type ('ios' for iOS Simulator, undefined for desktop)
|
|
160
|
+
*/
|
|
161
|
+
export async function startDaemon(options) {
|
|
162
|
+
// Ensure socket directory exists
|
|
163
|
+
const socketDir = getSocketDir();
|
|
164
|
+
if (!fs.existsSync(socketDir)) {
|
|
165
|
+
fs.mkdirSync(socketDir, { recursive: true });
|
|
166
|
+
}
|
|
167
|
+
// Clean up any stale socket
|
|
168
|
+
cleanupSocket();
|
|
169
|
+
// Determine provider from options or environment
|
|
170
|
+
const provider = options?.provider ?? process.env.AGENT_BROWSER_PROVIDER;
|
|
171
|
+
const isIOS = provider === 'ios';
|
|
172
|
+
// Create appropriate manager
|
|
173
|
+
const manager = isIOS ? new IOSManager() : new BrowserManager();
|
|
174
|
+
let shuttingDown = false;
|
|
175
|
+
// Start stream server if port is specified (or use default if env var is set)
|
|
176
|
+
// Note: Stream server only works with BrowserManager (desktop), not iOS
|
|
177
|
+
const streamPort = options?.streamPort ??
|
|
178
|
+
(process.env.AGENT_BROWSER_STREAM_PORT
|
|
179
|
+
? parseInt(process.env.AGENT_BROWSER_STREAM_PORT, 10)
|
|
180
|
+
: 0);
|
|
181
|
+
if (streamPort > 0 && !isIOS && manager instanceof BrowserManager) {
|
|
182
|
+
streamServer = new StreamServer(manager, streamPort);
|
|
183
|
+
await streamServer.start();
|
|
184
|
+
// Write stream port to file for clients to discover
|
|
185
|
+
const streamPortFile = getStreamPortFile();
|
|
186
|
+
fs.writeFileSync(streamPortFile, streamPort.toString());
|
|
187
|
+
}
|
|
188
|
+
const server = net.createServer((socket) => {
|
|
189
|
+
let buffer = '';
|
|
190
|
+
let httpChecked = false;
|
|
191
|
+
socket.on('data', async (data) => {
|
|
192
|
+
buffer += data.toString();
|
|
193
|
+
// Security: Detect and reject HTTP requests to prevent cross-origin attacks.
|
|
194
|
+
// Browsers using fetch() must send HTTP headers (e.g., "POST / HTTP/1.1"),
|
|
195
|
+
// while legitimate clients send raw JSON starting with "{".
|
|
196
|
+
if (!httpChecked) {
|
|
197
|
+
httpChecked = true;
|
|
198
|
+
const trimmed = buffer.trimStart();
|
|
199
|
+
if (/^(GET|POST|PUT|DELETE|HEAD|OPTIONS|PATCH|CONNECT|TRACE)\s/i.test(trimmed)) {
|
|
200
|
+
socket.destroy();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Process complete lines
|
|
205
|
+
while (buffer.includes('\n')) {
|
|
206
|
+
const newlineIdx = buffer.indexOf('\n');
|
|
207
|
+
const line = buffer.substring(0, newlineIdx);
|
|
208
|
+
buffer = buffer.substring(newlineIdx + 1);
|
|
209
|
+
if (!line.trim())
|
|
210
|
+
continue;
|
|
211
|
+
try {
|
|
212
|
+
const parseResult = parseCommand(line);
|
|
213
|
+
if (!parseResult.success) {
|
|
214
|
+
const resp = errorResponse(parseResult.id ?? 'unknown', parseResult.error);
|
|
215
|
+
socket.write(serializeResponse(resp) + '\n');
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
// Handle device_list specially - it works without a session and always uses IOSManager
|
|
219
|
+
if (parseResult.command.action === 'device_list') {
|
|
220
|
+
const iosManager = new IOSManager();
|
|
221
|
+
try {
|
|
222
|
+
const devices = await iosManager.listAllDevices();
|
|
223
|
+
const response = {
|
|
224
|
+
id: parseResult.command.id,
|
|
225
|
+
success: true,
|
|
226
|
+
data: { devices },
|
|
227
|
+
};
|
|
228
|
+
socket.write(serializeResponse(response) + '\n');
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
232
|
+
socket.write(serializeResponse(errorResponse(parseResult.command.id, message)) + '\n');
|
|
233
|
+
}
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
// Auto-launch if not already launched and this isn't a launch/close command
|
|
237
|
+
if (!manager.isLaunched() &&
|
|
238
|
+
parseResult.command.action !== 'launch' &&
|
|
239
|
+
parseResult.command.action !== 'close') {
|
|
240
|
+
if (isIOS && manager instanceof IOSManager) {
|
|
241
|
+
// Auto-launch iOS Safari
|
|
242
|
+
// Check for device in command first (for reused daemons), then fall back to env vars
|
|
243
|
+
const cmd = parseResult.command;
|
|
244
|
+
const iosDevice = cmd.iosDevice || process.env.AGENT_BROWSER_IOS_DEVICE;
|
|
245
|
+
await manager.launch({
|
|
246
|
+
device: iosDevice,
|
|
247
|
+
udid: process.env.AGENT_BROWSER_IOS_UDID,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
else if (manager instanceof BrowserManager) {
|
|
251
|
+
// Auto-launch desktop browser
|
|
252
|
+
const extensions = process.env.AGENT_BROWSER_EXTENSIONS
|
|
253
|
+
? process.env.AGENT_BROWSER_EXTENSIONS.split(',')
|
|
254
|
+
.map((p) => p.trim())
|
|
255
|
+
.filter(Boolean)
|
|
256
|
+
: undefined;
|
|
257
|
+
// Parse args from env (comma or newline separated)
|
|
258
|
+
const argsEnv = process.env.AGENT_BROWSER_ARGS;
|
|
259
|
+
const args = argsEnv
|
|
260
|
+
? argsEnv
|
|
261
|
+
.split(/[,\n]/)
|
|
262
|
+
.map((a) => a.trim())
|
|
263
|
+
.filter((a) => a.length > 0)
|
|
264
|
+
: undefined;
|
|
265
|
+
// Parse proxy from env
|
|
266
|
+
const proxyServer = process.env.AGENT_BROWSER_PROXY;
|
|
267
|
+
const proxyBypass = process.env.AGENT_BROWSER_PROXY_BYPASS;
|
|
268
|
+
const proxy = proxyServer
|
|
269
|
+
? {
|
|
270
|
+
server: proxyServer,
|
|
271
|
+
...(proxyBypass && { bypass: proxyBypass }),
|
|
272
|
+
}
|
|
273
|
+
: undefined;
|
|
274
|
+
const ignoreHTTPSErrors = process.env.AGENT_BROWSER_IGNORE_HTTPS_ERRORS === '1';
|
|
275
|
+
const allowFileAccess = process.env.AGENT_BROWSER_ALLOW_FILE_ACCESS === '1';
|
|
276
|
+
await manager.launch({
|
|
277
|
+
id: 'auto',
|
|
278
|
+
action: 'launch',
|
|
279
|
+
headless: process.env.AGENT_BROWSER_HEADED !== '1',
|
|
280
|
+
executablePath: process.env.AGENT_BROWSER_EXECUTABLE_PATH,
|
|
281
|
+
extensions: extensions,
|
|
282
|
+
profile: process.env.AGENT_BROWSER_PROFILE,
|
|
283
|
+
storageState: process.env.AGENT_BROWSER_STATE,
|
|
284
|
+
args,
|
|
285
|
+
userAgent: process.env.AGENT_BROWSER_USER_AGENT,
|
|
286
|
+
proxy,
|
|
287
|
+
ignoreHTTPSErrors: ignoreHTTPSErrors,
|
|
288
|
+
allowFileAccess: allowFileAccess,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// Handle close command specially - shuts down daemon
|
|
293
|
+
if (parseResult.command.action === 'close') {
|
|
294
|
+
const response = isIOS && manager instanceof IOSManager
|
|
295
|
+
? await executeIOSCommand(parseResult.command, manager)
|
|
296
|
+
: await executeCommand(parseResult.command, manager);
|
|
297
|
+
socket.write(serializeResponse(response) + '\n');
|
|
298
|
+
if (!shuttingDown) {
|
|
299
|
+
shuttingDown = true;
|
|
300
|
+
setTimeout(() => {
|
|
301
|
+
server.close();
|
|
302
|
+
cleanupSocket();
|
|
303
|
+
process.exit(0);
|
|
304
|
+
}, 100);
|
|
305
|
+
}
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
// Execute command with appropriate handler
|
|
309
|
+
const response = isIOS && manager instanceof IOSManager
|
|
310
|
+
? await executeIOSCommand(parseResult.command, manager)
|
|
311
|
+
: await executeCommand(parseResult.command, manager);
|
|
312
|
+
socket.write(serializeResponse(response) + '\n');
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
316
|
+
socket.write(serializeResponse(errorResponse('error', message)) + '\n');
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
socket.on('error', () => {
|
|
321
|
+
// Client disconnected, ignore
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
const pidFile = getPidFile();
|
|
325
|
+
// Write PID file before listening
|
|
326
|
+
fs.writeFileSync(pidFile, process.pid.toString());
|
|
327
|
+
if (isWindows) {
|
|
328
|
+
// Windows: use TCP socket on localhost
|
|
329
|
+
const port = getPortForSession(currentSession);
|
|
330
|
+
const portFile = getPortFile();
|
|
331
|
+
fs.writeFileSync(portFile, port.toString());
|
|
332
|
+
server.listen(port, '127.0.0.1', () => {
|
|
333
|
+
// Daemon is ready on TCP port
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
// Unix: use Unix domain socket
|
|
338
|
+
const socketPath = getSocketPath();
|
|
339
|
+
server.listen(socketPath, () => {
|
|
340
|
+
// Daemon is ready
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
server.on('error', (err) => {
|
|
344
|
+
console.error('Server error:', err);
|
|
345
|
+
cleanupSocket();
|
|
346
|
+
process.exit(1);
|
|
347
|
+
});
|
|
348
|
+
// Handle shutdown signals
|
|
349
|
+
const shutdown = async () => {
|
|
350
|
+
if (shuttingDown)
|
|
351
|
+
return;
|
|
352
|
+
shuttingDown = true;
|
|
353
|
+
// Stop stream server if running
|
|
354
|
+
if (streamServer) {
|
|
355
|
+
await streamServer.stop();
|
|
356
|
+
streamServer = null;
|
|
357
|
+
// Clean up stream port file
|
|
358
|
+
const streamPortFile = getStreamPortFile();
|
|
359
|
+
try {
|
|
360
|
+
if (fs.existsSync(streamPortFile))
|
|
361
|
+
fs.unlinkSync(streamPortFile);
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
// Ignore cleanup errors
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
await manager.close();
|
|
368
|
+
server.close();
|
|
369
|
+
cleanupSocket();
|
|
370
|
+
process.exit(0);
|
|
371
|
+
};
|
|
372
|
+
process.on('SIGINT', shutdown);
|
|
373
|
+
process.on('SIGTERM', shutdown);
|
|
374
|
+
process.on('SIGHUP', shutdown);
|
|
375
|
+
// Handle unexpected errors - always cleanup
|
|
376
|
+
process.on('uncaughtException', (err) => {
|
|
377
|
+
console.error('Uncaught exception:', err);
|
|
378
|
+
cleanupSocket();
|
|
379
|
+
process.exit(1);
|
|
380
|
+
});
|
|
381
|
+
process.on('unhandledRejection', (reason) => {
|
|
382
|
+
console.error('Unhandled rejection:', reason);
|
|
383
|
+
cleanupSocket();
|
|
384
|
+
process.exit(1);
|
|
385
|
+
});
|
|
386
|
+
// Cleanup on normal exit
|
|
387
|
+
process.on('exit', () => {
|
|
388
|
+
cleanupSocket();
|
|
389
|
+
});
|
|
390
|
+
// Keep process alive
|
|
391
|
+
process.stdin.resume();
|
|
392
|
+
}
|
|
393
|
+
// Run daemon if this is the entry point
|
|
394
|
+
if (process.argv[1]?.endsWith('daemon.js') || process.env.AGENT_BROWSER_DAEMON === '1') {
|
|
395
|
+
startDaemon().catch((err) => {
|
|
396
|
+
console.error('Daemon error:', err);
|
|
397
|
+
cleanupSocket();
|
|
398
|
+
process.exit(1);
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for DualMode / WootzApp engine
|
|
3
|
+
*
|
|
4
|
+
* Reads environment variables and provides configuration for switching
|
|
5
|
+
* between Playwright and WootzApp engines.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* DualMode engine configuration
|
|
9
|
+
*/
|
|
10
|
+
export interface DualModeConfig {
|
|
11
|
+
/** Engine to use: 'playwright' or 'wootzapp' */
|
|
12
|
+
engine: 'playwright' | 'wootzapp';
|
|
13
|
+
/** CDP host (for WootzApp) */
|
|
14
|
+
cdpHost: string;
|
|
15
|
+
/** CDP port (for WootzApp) */
|
|
16
|
+
cdpPort: number;
|
|
17
|
+
/** CDP connection timeout in milliseconds */
|
|
18
|
+
cdpTimeout: number;
|
|
19
|
+
/** Whether DualMode engine is enabled */
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get DualMode configuration from environment variables
|
|
24
|
+
*/
|
|
25
|
+
export declare function getDualModeConfig(): DualModeConfig;
|
|
26
|
+
/**
|
|
27
|
+
* Check if WootzApp engine is enabled
|
|
28
|
+
*/
|
|
29
|
+
export declare function isWootzAppEnabled(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get CDP endpoint URL
|
|
32
|
+
*/
|
|
33
|
+
export declare function getCDPEndpoint(): {
|
|
34
|
+
host: string;
|
|
35
|
+
port: number;
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=dualmode-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dualmode-config.d.ts","sourceRoot":"","sources":["../src/dualmode-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,MAAM,EAAE,YAAY,GAAG,UAAU,CAAC;IAElC,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAEhB,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAEhB,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IAEnB,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAoBlD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAM/D"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for DualMode / WootzApp engine
|
|
3
|
+
*
|
|
4
|
+
* Reads environment variables and provides configuration for switching
|
|
5
|
+
* between Playwright and WootzApp engines.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Get DualMode configuration from environment variables
|
|
9
|
+
*/
|
|
10
|
+
export function getDualModeConfig() {
|
|
11
|
+
const rawEngine = process.env.AGENT_BROWSER_ENGINE;
|
|
12
|
+
const engine = (rawEngine?.toLowerCase() || 'playwright');
|
|
13
|
+
const config = {
|
|
14
|
+
engine,
|
|
15
|
+
cdpHost: process.env.AGENT_BROWSER_CDP_HOST || 'localhost',
|
|
16
|
+
cdpPort: parseInt(process.env.AGENT_BROWSER_CDP_PORT || '9224', 10),
|
|
17
|
+
cdpTimeout: parseInt(process.env.AGENT_BROWSER_CDP_TIMEOUT || '30000', 10),
|
|
18
|
+
enabled: engine === 'wootzapp',
|
|
19
|
+
};
|
|
20
|
+
console.log('[DualMode Config] Retrieved configuration:', {
|
|
21
|
+
rawEnv: rawEngine,
|
|
22
|
+
processedEngine: engine,
|
|
23
|
+
enabled: config.enabled,
|
|
24
|
+
cdpEndpoint: `${config.cdpHost}:${config.cdpPort}`
|
|
25
|
+
});
|
|
26
|
+
return config;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if WootzApp engine is enabled
|
|
30
|
+
*/
|
|
31
|
+
export function isWootzAppEnabled() {
|
|
32
|
+
return getDualModeConfig().enabled;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get CDP endpoint URL
|
|
36
|
+
*/
|
|
37
|
+
export function getCDPEndpoint() {
|
|
38
|
+
const config = getDualModeConfig();
|
|
39
|
+
return {
|
|
40
|
+
host: config.cdpHost,
|
|
41
|
+
port: config.cdpPort,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=dualmode-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dualmode-config.js","sourceRoot":"","sources":["../src/dualmode-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACnD,MAAM,MAAM,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,YAAY,CAA8B,CAAC;IAEvF,MAAM,MAAM,GAAG;QACb,MAAM;QACN,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,WAAW;QAC1D,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,MAAM,EAAE,EAAE,CAAC;QACnE,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,OAAO,EAAE,EAAE,CAAC;QAC1E,OAAO,EAAE,MAAM,KAAK,UAAU;KAC/B,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE;QACxD,MAAM,EAAE,SAAS;QACjB,eAAe,EAAE,MAAM;QACvB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE;KACnD,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,iBAAiB,EAAE,CAAC,OAAO,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;IACnC,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,OAAO;QACpB,IAAI,EAAE,MAAM,CAAC,OAAO;KACrB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DualMode Accessibility Tree Fetcher
|
|
3
|
+
*
|
|
4
|
+
* Fetches enhanced accessibility tree from WootzApp Android browser via CDP.
|
|
5
|
+
* Transforms flat node list into hierarchical tree structure with refs.
|
|
6
|
+
*/
|
|
7
|
+
import type { DualModeTree, GetDualModeAXTreeResponse, DualModeSnapshotOptions, DualModeEnhancedSnapshot } from './dualmode-types.js';
|
|
8
|
+
/**
|
|
9
|
+
* DualMode AXTree fetcher
|
|
10
|
+
*/
|
|
11
|
+
export declare class DualModeAXTreeFetcher {
|
|
12
|
+
private host;
|
|
13
|
+
private port;
|
|
14
|
+
constructor(host?: string, port?: number);
|
|
15
|
+
/**
|
|
16
|
+
* Clear Chrome app data using pm clear command
|
|
17
|
+
*/
|
|
18
|
+
private clearBrowserData;
|
|
19
|
+
/**
|
|
20
|
+
* Fetch DualMode AXTree for a URL
|
|
21
|
+
*/
|
|
22
|
+
fetchTree(url: string): Promise<GetDualModeAXTreeResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* Convert standard CDP accessibility tree to DualMode format
|
|
25
|
+
*/
|
|
26
|
+
private convertStandardTreeToDualMode;
|
|
27
|
+
/**
|
|
28
|
+
* Parse node ID (handle string or number)
|
|
29
|
+
*/
|
|
30
|
+
private parseNodeId;
|
|
31
|
+
/**
|
|
32
|
+
* Fetch tree for current page (no navigation)
|
|
33
|
+
*/
|
|
34
|
+
fetchCurrentPageTree(): Promise<GetDualModeAXTreeResponse>;
|
|
35
|
+
/**
|
|
36
|
+
* Build hierarchical tree from flat node list
|
|
37
|
+
*/
|
|
38
|
+
buildTree(response: GetDualModeAXTreeResponse): DualModeTree;
|
|
39
|
+
/**
|
|
40
|
+
* Check if role is interactive
|
|
41
|
+
*/
|
|
42
|
+
private isInteractiveRole;
|
|
43
|
+
/**
|
|
44
|
+
* Generate selector for node (best effort)
|
|
45
|
+
*/
|
|
46
|
+
private generateSelector;
|
|
47
|
+
/**
|
|
48
|
+
* Generate text tree representation
|
|
49
|
+
*/
|
|
50
|
+
generateTextTree(tree: DualModeTree, options?: DualModeSnapshotOptions): string;
|
|
51
|
+
/**
|
|
52
|
+
* Get enhanced snapshot with refs
|
|
53
|
+
*/
|
|
54
|
+
getEnhancedSnapshot(url: string, options?: DualModeSnapshotOptions): Promise<DualModeEnhancedSnapshot>;
|
|
55
|
+
/**
|
|
56
|
+
* Get current page snapshot (no navigation)
|
|
57
|
+
*/
|
|
58
|
+
getCurrentPageSnapshot(options?: DualModeSnapshotOptions): Promise<DualModeEnhancedSnapshot>;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=dualmode-fetcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dualmode-fetcher.d.ts","sourceRoot":"","sources":["../src/dualmode-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAEV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,IAAI,CAAS;gBAET,IAAI,GAAE,MAAoB,EAAE,IAAI,GAAE,MAAa;IAK3D;;OAEG;YACW,gBAAgB;IAmB9B;;OAEG;IACG,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAuEhE;;OAEG;IACH,OAAO,CAAC,6BAA6B;IA6ErC;;OAEG;IACH,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,yBAAyB,CAAC;IA6BhE;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,yBAAyB,GAAG,YAAY;IA6D5D;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAYzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkCxB;;OAEG;IACH,gBAAgB,CACd,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE,uBAA4B,GACpC,MAAM;IA0FT;;OAEG;IACG,mBAAmB,CACvB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,wBAAwB,CAAC;IA8BpC;;OAEG;IACG,sBAAsB,CAC1B,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,wBAAwB,CAAC;CA6CrC"}
|