agent-browser 0.3.1 → 0.3.3
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/bin/agent-browser +13 -2
- package/bin/agent-browser-darwin-arm64 +0 -0
- package/bin/agent-browser-darwin-x64 +0 -0
- package/bin/agent-browser-linux-arm64 +0 -0
- package/bin/agent-browser-linux-x64 +0 -0
- package/package.json +6 -1
- package/.prettierrc +0 -7
- package/AGENTS.md +0 -26
- package/benchmark/benchmark.ts +0 -521
- package/benchmark/run.ts +0 -322
- package/cli/Cargo.lock +0 -114
- package/cli/Cargo.toml +0 -17
- package/cli/src/main.rs +0 -332
- package/docker/Dockerfile.build +0 -31
- package/docker/docker-compose.yml +0 -68
- package/src/actions.ts +0 -1670
- package/src/browser.test.ts +0 -157
- package/src/browser.ts +0 -686
- package/src/cli-light.ts +0 -457
- package/src/client.ts +0 -150
- package/src/daemon.ts +0 -187
- package/src/index.ts +0 -1185
- package/src/protocol.test.ts +0 -216
- package/src/protocol.ts +0 -852
- package/src/snapshot.ts +0 -380
- package/src/types.ts +0 -913
- package/tsconfig.json +0 -28
- package/vitest.config.ts +0 -9
package/src/daemon.ts
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
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
|
-
|
|
9
|
-
// Session support - each session gets its own socket/pid
|
|
10
|
-
let currentSession = process.env.AGENT_BROWSER_SESSION || 'default';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Set the current session
|
|
14
|
-
*/
|
|
15
|
-
export function setSession(session: string): void {
|
|
16
|
-
currentSession = session;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Get the current session
|
|
21
|
-
*/
|
|
22
|
-
export function getSession(): string {
|
|
23
|
-
return currentSession;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get the socket path for the current session
|
|
28
|
-
*/
|
|
29
|
-
export function getSocketPath(session?: string): string {
|
|
30
|
-
const sess = session ?? currentSession;
|
|
31
|
-
return path.join(os.tmpdir(), `agent-browser-${sess}.sock`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get the PID file path for the current session
|
|
36
|
-
*/
|
|
37
|
-
export function getPidFile(session?: string): string {
|
|
38
|
-
const sess = session ?? currentSession;
|
|
39
|
-
return path.join(os.tmpdir(), `agent-browser-${sess}.pid`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Check if daemon is running for the current session
|
|
44
|
-
*/
|
|
45
|
-
export function isDaemonRunning(session?: string): boolean {
|
|
46
|
-
const pidFile = getPidFile(session);
|
|
47
|
-
if (!fs.existsSync(pidFile)) return false;
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
|
|
51
|
-
// Check if process exists
|
|
52
|
-
process.kill(pid, 0);
|
|
53
|
-
return true;
|
|
54
|
-
} catch {
|
|
55
|
-
// Process doesn't exist, clean up stale files
|
|
56
|
-
cleanupSocket(session);
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Clean up socket and PID file for the current session
|
|
63
|
-
*/
|
|
64
|
-
export function cleanupSocket(session?: string): void {
|
|
65
|
-
const socketPath = getSocketPath(session);
|
|
66
|
-
const pidFile = getPidFile(session);
|
|
67
|
-
try {
|
|
68
|
-
if (fs.existsSync(socketPath)) fs.unlinkSync(socketPath);
|
|
69
|
-
if (fs.existsSync(pidFile)) fs.unlinkSync(pidFile);
|
|
70
|
-
} catch {
|
|
71
|
-
// Ignore cleanup errors
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Start the daemon server
|
|
77
|
-
*/
|
|
78
|
-
export async function startDaemon(): Promise<void> {
|
|
79
|
-
// Clean up any stale socket
|
|
80
|
-
cleanupSocket();
|
|
81
|
-
|
|
82
|
-
const browser = new BrowserManager();
|
|
83
|
-
let shuttingDown = false;
|
|
84
|
-
|
|
85
|
-
const server = net.createServer((socket) => {
|
|
86
|
-
let buffer = '';
|
|
87
|
-
|
|
88
|
-
socket.on('data', async (data) => {
|
|
89
|
-
buffer += data.toString();
|
|
90
|
-
|
|
91
|
-
// Process complete lines
|
|
92
|
-
while (buffer.includes('\n')) {
|
|
93
|
-
const newlineIdx = buffer.indexOf('\n');
|
|
94
|
-
const line = buffer.substring(0, newlineIdx);
|
|
95
|
-
buffer = buffer.substring(newlineIdx + 1);
|
|
96
|
-
|
|
97
|
-
if (!line.trim()) continue;
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
const parseResult = parseCommand(line);
|
|
101
|
-
|
|
102
|
-
if (!parseResult.success) {
|
|
103
|
-
const resp = errorResponse(parseResult.id ?? 'unknown', parseResult.error);
|
|
104
|
-
socket.write(serializeResponse(resp) + '\n');
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Auto-launch browser if not already launched and this isn't a launch command
|
|
109
|
-
if (
|
|
110
|
-
!browser.isLaunched() &&
|
|
111
|
-
parseResult.command.action !== 'launch' &&
|
|
112
|
-
parseResult.command.action !== 'close'
|
|
113
|
-
) {
|
|
114
|
-
await browser.launch({ id: 'auto', action: 'launch', headless: true });
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Handle close command specially
|
|
118
|
-
if (parseResult.command.action === 'close') {
|
|
119
|
-
const response = await executeCommand(parseResult.command, browser);
|
|
120
|
-
socket.write(serializeResponse(response) + '\n');
|
|
121
|
-
|
|
122
|
-
if (!shuttingDown) {
|
|
123
|
-
shuttingDown = true;
|
|
124
|
-
setTimeout(() => {
|
|
125
|
-
server.close();
|
|
126
|
-
cleanupSocket();
|
|
127
|
-
process.exit(0);
|
|
128
|
-
}, 100);
|
|
129
|
-
}
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const response = await executeCommand(parseResult.command, browser);
|
|
134
|
-
socket.write(serializeResponse(response) + '\n');
|
|
135
|
-
} catch (err) {
|
|
136
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
137
|
-
socket.write(serializeResponse(errorResponse('error', message)) + '\n');
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
socket.on('error', () => {
|
|
143
|
-
// Client disconnected, ignore
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
const socketPath = getSocketPath();
|
|
148
|
-
const pidFile = getPidFile();
|
|
149
|
-
|
|
150
|
-
// Write PID file before listening
|
|
151
|
-
fs.writeFileSync(pidFile, process.pid.toString());
|
|
152
|
-
|
|
153
|
-
server.listen(socketPath, () => {
|
|
154
|
-
// Daemon is ready
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
server.on('error', (err) => {
|
|
158
|
-
console.error('Server error:', err);
|
|
159
|
-
cleanupSocket();
|
|
160
|
-
process.exit(1);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
// Handle shutdown signals
|
|
164
|
-
const shutdown = async () => {
|
|
165
|
-
if (shuttingDown) return;
|
|
166
|
-
shuttingDown = true;
|
|
167
|
-
await browser.close();
|
|
168
|
-
server.close();
|
|
169
|
-
cleanupSocket();
|
|
170
|
-
process.exit(0);
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
process.on('SIGINT', shutdown);
|
|
174
|
-
process.on('SIGTERM', shutdown);
|
|
175
|
-
|
|
176
|
-
// Keep process alive
|
|
177
|
-
process.stdin.resume();
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Run daemon if this is the entry point
|
|
181
|
-
if (process.argv[1]?.endsWith('daemon.js') || process.env.AGENT_BROWSER_DAEMON === '1') {
|
|
182
|
-
startDaemon().catch((err) => {
|
|
183
|
-
console.error('Daemon error:', err);
|
|
184
|
-
cleanupSocket();
|
|
185
|
-
process.exit(1);
|
|
186
|
-
});
|
|
187
|
-
}
|