agent-browser 0.0.0 → 0.1.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/.prettierrc +7 -0
- package/LICENSE +201 -0
- package/README.md +274 -1
- package/bin/agent-browser +2 -0
- package/dist/actions.d.ts +7 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +1138 -0
- package/dist/actions.js.map +1 -0
- package/dist/browser.d.ts +232 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +477 -0
- package/dist/browser.js.map +1 -0
- package/dist/browser.test.d.ts +2 -0
- package/dist/browser.test.d.ts.map +1 -0
- package/dist/browser.test.js +136 -0
- package/dist/browser.test.js.map +1 -0
- package/dist/client.d.ts +17 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +133 -0
- package/dist/client.js.map +1 -0
- package/dist/daemon.d.ts +29 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +165 -0
- package/dist/daemon.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1158 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +26 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +717 -0
- package/dist/protocol.js.map +1 -0
- package/dist/protocol.test.d.ts +2 -0
- package/dist/protocol.test.d.ts.map +1 -0
- package/dist/protocol.test.js +176 -0
- package/dist/protocol.test.js.map +1 -0
- package/dist/types.d.ts +604 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +39 -8
- package/scripts/postinstall.js +17 -0
- package/src/actions.ts +1658 -0
- package/src/browser.test.ts +157 -0
- package/src/browser.ts +586 -0
- package/src/client.ts +150 -0
- package/src/daemon.ts +187 -0
- package/src/index.ts +1180 -0
- package/src/protocol.test.ts +216 -0
- package/src/protocol.ts +848 -0
- package/src/types.ts +913 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +9 -0
- package/index.js +0 -2
package/dist/client.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import * as net from 'net';
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import { getSocketPath, isDaemonRunning, setSession, getSession } from './daemon.js';
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
let DEBUG = false;
|
|
9
|
+
export function setDebug(enabled) {
|
|
10
|
+
DEBUG = enabled;
|
|
11
|
+
}
|
|
12
|
+
export { setSession, getSession };
|
|
13
|
+
function debug(...args) {
|
|
14
|
+
if (DEBUG) {
|
|
15
|
+
console.error('[debug]', ...args);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Wait for socket to exist
|
|
20
|
+
*/
|
|
21
|
+
async function waitForSocket(maxAttempts = 30) {
|
|
22
|
+
const socketPath = getSocketPath();
|
|
23
|
+
debug('Waiting for socket at', socketPath);
|
|
24
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
25
|
+
if (fs.existsSync(socketPath)) {
|
|
26
|
+
debug('Socket found after', i * 100, 'ms');
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
30
|
+
}
|
|
31
|
+
debug('Socket not found after', maxAttempts * 100, 'ms');
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Ensure daemon is running, start if not
|
|
36
|
+
*/
|
|
37
|
+
export async function ensureDaemon() {
|
|
38
|
+
const session = getSession();
|
|
39
|
+
debug(`Checking if daemon is running for session "${session}"...`);
|
|
40
|
+
if (isDaemonRunning()) {
|
|
41
|
+
debug('Daemon already running');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
debug('Starting daemon...');
|
|
45
|
+
const daemonPath = path.join(__dirname, 'daemon.js');
|
|
46
|
+
const child = spawn(process.execPath, [daemonPath], {
|
|
47
|
+
detached: true,
|
|
48
|
+
stdio: 'ignore',
|
|
49
|
+
env: { ...process.env, AGENT_BROWSER_DAEMON: '1', AGENT_BROWSER_SESSION: session },
|
|
50
|
+
});
|
|
51
|
+
child.unref();
|
|
52
|
+
// Wait for socket to be created
|
|
53
|
+
const ready = await waitForSocket();
|
|
54
|
+
if (!ready) {
|
|
55
|
+
throw new Error('Failed to start daemon');
|
|
56
|
+
}
|
|
57
|
+
debug(`Daemon started for session "${session}"`);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Send a command to the daemon
|
|
61
|
+
*/
|
|
62
|
+
export async function sendCommand(command) {
|
|
63
|
+
const socketPath = getSocketPath();
|
|
64
|
+
debug('Sending command:', JSON.stringify(command));
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
let resolved = false;
|
|
67
|
+
let buffer = '';
|
|
68
|
+
const startTime = Date.now();
|
|
69
|
+
const socket = net.createConnection(socketPath);
|
|
70
|
+
socket.on('connect', () => {
|
|
71
|
+
debug('Connected to daemon, sending command...');
|
|
72
|
+
socket.write(JSON.stringify(command) + '\n');
|
|
73
|
+
});
|
|
74
|
+
socket.on('data', (data) => {
|
|
75
|
+
buffer += data.toString();
|
|
76
|
+
debug('Received data:', buffer.length, 'bytes');
|
|
77
|
+
// Try to parse complete JSON from buffer
|
|
78
|
+
const newlineIdx = buffer.indexOf('\n');
|
|
79
|
+
if (newlineIdx !== -1) {
|
|
80
|
+
const jsonStr = buffer.substring(0, newlineIdx);
|
|
81
|
+
try {
|
|
82
|
+
const response = JSON.parse(jsonStr);
|
|
83
|
+
debug('Response received in', Date.now() - startTime, 'ms');
|
|
84
|
+
resolved = true;
|
|
85
|
+
socket.end();
|
|
86
|
+
resolve(response);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
debug('JSON parse error:', e);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
socket.on('error', (err) => {
|
|
94
|
+
debug('Socket error:', err.message);
|
|
95
|
+
if (!resolved) {
|
|
96
|
+
reject(new Error(`Connection error: ${err.message}`));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
socket.on('close', () => {
|
|
100
|
+
debug('Socket closed, resolved:', resolved, 'buffer:', buffer.length);
|
|
101
|
+
if (!resolved && buffer.trim()) {
|
|
102
|
+
try {
|
|
103
|
+
const response = JSON.parse(buffer.trim());
|
|
104
|
+
resolve(response);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
reject(new Error('Invalid response from daemon'));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else if (!resolved) {
|
|
111
|
+
reject(new Error('Connection closed without response'));
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
// Timeout after 15 seconds (allows for 10s Playwright timeout + overhead)
|
|
115
|
+
setTimeout(() => {
|
|
116
|
+
if (!resolved) {
|
|
117
|
+
debug('Command timeout after 15s');
|
|
118
|
+
socket.destroy();
|
|
119
|
+
reject(new Error('Command timeout'));
|
|
120
|
+
}
|
|
121
|
+
}, 15000);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Send a command, ensuring daemon is running first
|
|
126
|
+
*/
|
|
127
|
+
export async function send(command) {
|
|
128
|
+
const startTime = Date.now();
|
|
129
|
+
await ensureDaemon();
|
|
130
|
+
debug('ensureDaemon took', Date.now() - startTime, 'ms');
|
|
131
|
+
return sendCommand(command);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/daemon.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set the current session
|
|
3
|
+
*/
|
|
4
|
+
export declare function setSession(session: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Get the current session
|
|
7
|
+
*/
|
|
8
|
+
export declare function getSession(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Get the socket path for the current session
|
|
11
|
+
*/
|
|
12
|
+
export declare function getSocketPath(session?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Get the PID file path for the current session
|
|
15
|
+
*/
|
|
16
|
+
export declare function getPidFile(session?: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Check if daemon is running for the current session
|
|
19
|
+
*/
|
|
20
|
+
export declare function isDaemonRunning(session?: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Clean up socket and PID file for the current session
|
|
23
|
+
*/
|
|
24
|
+
export declare function cleanupSocket(session?: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Start the daemon server
|
|
27
|
+
*/
|
|
28
|
+
export declare function startDaemon(): Promise<void>;
|
|
29
|
+
//# sourceMappingURL=daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAGtD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAczD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CASpD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoGjD"}
|
package/dist/daemon.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import * as net from 'net';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import * as os from 'os';
|
|
5
|
+
import { BrowserManager } from './browser.js';
|
|
6
|
+
import { parseCommand, serializeResponse, errorResponse } from './protocol.js';
|
|
7
|
+
import { executeCommand } from './actions.js';
|
|
8
|
+
// Session support - each session gets its own socket/pid
|
|
9
|
+
let currentSession = process.env.AGENT_BROWSER_SESSION || 'default';
|
|
10
|
+
/**
|
|
11
|
+
* Set the current session
|
|
12
|
+
*/
|
|
13
|
+
export function setSession(session) {
|
|
14
|
+
currentSession = session;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get the current session
|
|
18
|
+
*/
|
|
19
|
+
export function getSession() {
|
|
20
|
+
return currentSession;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get the socket path for the current session
|
|
24
|
+
*/
|
|
25
|
+
export function getSocketPath(session) {
|
|
26
|
+
const sess = session ?? currentSession;
|
|
27
|
+
return path.join(os.tmpdir(), `agent-browser-${sess}.sock`);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get the PID file path for the current session
|
|
31
|
+
*/
|
|
32
|
+
export function getPidFile(session) {
|
|
33
|
+
const sess = session ?? currentSession;
|
|
34
|
+
return path.join(os.tmpdir(), `agent-browser-${sess}.pid`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check if daemon is running for the current session
|
|
38
|
+
*/
|
|
39
|
+
export function isDaemonRunning(session) {
|
|
40
|
+
const pidFile = getPidFile(session);
|
|
41
|
+
if (!fs.existsSync(pidFile))
|
|
42
|
+
return false;
|
|
43
|
+
try {
|
|
44
|
+
const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
|
|
45
|
+
// Check if process exists
|
|
46
|
+
process.kill(pid, 0);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Process doesn't exist, clean up stale files
|
|
51
|
+
cleanupSocket(session);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Clean up socket and PID file for the current session
|
|
57
|
+
*/
|
|
58
|
+
export function cleanupSocket(session) {
|
|
59
|
+
const socketPath = getSocketPath(session);
|
|
60
|
+
const pidFile = getPidFile(session);
|
|
61
|
+
try {
|
|
62
|
+
if (fs.existsSync(socketPath))
|
|
63
|
+
fs.unlinkSync(socketPath);
|
|
64
|
+
if (fs.existsSync(pidFile))
|
|
65
|
+
fs.unlinkSync(pidFile);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Ignore cleanup errors
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Start the daemon server
|
|
73
|
+
*/
|
|
74
|
+
export async function startDaemon() {
|
|
75
|
+
// Clean up any stale socket
|
|
76
|
+
cleanupSocket();
|
|
77
|
+
const browser = new BrowserManager();
|
|
78
|
+
let shuttingDown = false;
|
|
79
|
+
const server = net.createServer((socket) => {
|
|
80
|
+
let buffer = '';
|
|
81
|
+
socket.on('data', async (data) => {
|
|
82
|
+
buffer += data.toString();
|
|
83
|
+
// Process complete lines
|
|
84
|
+
while (buffer.includes('\n')) {
|
|
85
|
+
const newlineIdx = buffer.indexOf('\n');
|
|
86
|
+
const line = buffer.substring(0, newlineIdx);
|
|
87
|
+
buffer = buffer.substring(newlineIdx + 1);
|
|
88
|
+
if (!line.trim())
|
|
89
|
+
continue;
|
|
90
|
+
try {
|
|
91
|
+
const parseResult = parseCommand(line);
|
|
92
|
+
if (!parseResult.success) {
|
|
93
|
+
const resp = errorResponse(parseResult.id ?? 'unknown', parseResult.error);
|
|
94
|
+
socket.write(serializeResponse(resp) + '\n');
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
// Auto-launch browser if not already launched and this isn't a launch command
|
|
98
|
+
if (!browser.isLaunched() &&
|
|
99
|
+
parseResult.command.action !== 'launch' &&
|
|
100
|
+
parseResult.command.action !== 'close') {
|
|
101
|
+
await browser.launch({ id: 'auto', action: 'launch', headless: true });
|
|
102
|
+
}
|
|
103
|
+
// Handle close command specially
|
|
104
|
+
if (parseResult.command.action === 'close') {
|
|
105
|
+
const response = await executeCommand(parseResult.command, browser);
|
|
106
|
+
socket.write(serializeResponse(response) + '\n');
|
|
107
|
+
if (!shuttingDown) {
|
|
108
|
+
shuttingDown = true;
|
|
109
|
+
setTimeout(() => {
|
|
110
|
+
server.close();
|
|
111
|
+
cleanupSocket();
|
|
112
|
+
process.exit(0);
|
|
113
|
+
}, 100);
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const response = await executeCommand(parseResult.command, browser);
|
|
118
|
+
socket.write(serializeResponse(response) + '\n');
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
122
|
+
socket.write(serializeResponse(errorResponse('error', message)) + '\n');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
socket.on('error', () => {
|
|
127
|
+
// Client disconnected, ignore
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
const socketPath = getSocketPath();
|
|
131
|
+
const pidFile = getPidFile();
|
|
132
|
+
// Write PID file before listening
|
|
133
|
+
fs.writeFileSync(pidFile, process.pid.toString());
|
|
134
|
+
server.listen(socketPath, () => {
|
|
135
|
+
// Daemon is ready
|
|
136
|
+
});
|
|
137
|
+
server.on('error', (err) => {
|
|
138
|
+
console.error('Server error:', err);
|
|
139
|
+
cleanupSocket();
|
|
140
|
+
process.exit(1);
|
|
141
|
+
});
|
|
142
|
+
// Handle shutdown signals
|
|
143
|
+
const shutdown = async () => {
|
|
144
|
+
if (shuttingDown)
|
|
145
|
+
return;
|
|
146
|
+
shuttingDown = true;
|
|
147
|
+
await browser.close();
|
|
148
|
+
server.close();
|
|
149
|
+
cleanupSocket();
|
|
150
|
+
process.exit(0);
|
|
151
|
+
};
|
|
152
|
+
process.on('SIGINT', shutdown);
|
|
153
|
+
process.on('SIGTERM', shutdown);
|
|
154
|
+
// Keep process alive
|
|
155
|
+
process.stdin.resume();
|
|
156
|
+
}
|
|
157
|
+
// Run daemon if this is the entry point
|
|
158
|
+
if (process.argv[1]?.endsWith('daemon.js') || process.env.AGENT_BROWSER_DAEMON === '1') {
|
|
159
|
+
startDaemon().catch((err) => {
|
|
160
|
+
console.error('Daemon error:', err);
|
|
161
|
+
cleanupSocket();
|
|
162
|
+
process.exit(1);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|