@skillful-agents/agent-computer 0.0.4 → 0.0.6
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/ac-core-darwin-arm64 +0 -0
- package/bin/ac-core-darwin-x64 +0 -0
- package/bin/ac-core-win32-arm64.exe +0 -0
- package/bin/ac-core-win32-x64.exe +0 -0
- package/dist/src/platform/resolve.d.ts.map +1 -1
- package/dist/src/platform/resolve.js +5 -3
- package/dist/src/platform/resolve.js.map +1 -1
- package/dist-cjs/bin/ac.js +127 -0
- package/dist-cjs/package.json +1 -0
- package/dist-cjs/src/bridge.js +693 -0
- package/dist-cjs/src/cdp/ax-tree.js +162 -0
- package/dist-cjs/src/cdp/bounds.js +66 -0
- package/dist-cjs/src/cdp/client.js +272 -0
- package/dist-cjs/src/cdp/connection.js +285 -0
- package/dist-cjs/src/cdp/diff.js +55 -0
- package/dist-cjs/src/cdp/discovery.js +91 -0
- package/dist-cjs/src/cdp/index.js +27 -0
- package/dist-cjs/src/cdp/interactions.js +301 -0
- package/dist-cjs/src/cdp/port-manager.js +68 -0
- package/dist-cjs/src/cdp/role-map.js +102 -0
- package/dist-cjs/src/cdp/types.js +2 -0
- package/dist-cjs/src/cli/commands/apps.js +63 -0
- package/dist-cjs/src/cli/commands/batch.js +37 -0
- package/dist-cjs/src/cli/commands/click.js +61 -0
- package/dist-cjs/src/cli/commands/clipboard.js +31 -0
- package/dist-cjs/src/cli/commands/dialog.js +45 -0
- package/dist-cjs/src/cli/commands/drag.js +26 -0
- package/dist-cjs/src/cli/commands/find.js +99 -0
- package/dist-cjs/src/cli/commands/menu.js +36 -0
- package/dist-cjs/src/cli/commands/screenshot.js +27 -0
- package/dist-cjs/src/cli/commands/scroll.js +77 -0
- package/dist-cjs/src/cli/commands/session.js +27 -0
- package/dist-cjs/src/cli/commands/snapshot.js +24 -0
- package/dist-cjs/src/cli/commands/type.js +69 -0
- package/dist-cjs/src/cli/commands/windowmgmt.js +62 -0
- package/dist-cjs/src/cli/commands/windows.js +10 -0
- package/dist-cjs/src/cli/commands.js +215 -0
- package/dist-cjs/src/cli/output.js +253 -0
- package/dist-cjs/src/cli/parser.js +128 -0
- package/dist-cjs/src/config.js +79 -0
- package/dist-cjs/src/daemon.js +183 -0
- package/dist-cjs/src/errors.js +118 -0
- package/dist-cjs/src/index.js +24 -0
- package/dist-cjs/src/platform/index.js +16 -0
- package/dist-cjs/src/platform/resolve.js +71 -0
- package/dist-cjs/src/refs.js +91 -0
- package/dist-cjs/src/sdk.js +288 -0
- package/dist-cjs/src/types.js +11 -0
- package/package.json +4 -2
- package/scripts/fix-cjs-resolve.js +27 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CDPConnection = void 0;
|
|
37
|
+
const http = __importStar(require("http"));
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
class CDPConnection {
|
|
40
|
+
socket = null;
|
|
41
|
+
nextId = 1;
|
|
42
|
+
pending = new Map();
|
|
43
|
+
eventHandlers = new Map();
|
|
44
|
+
buffer = Buffer.alloc(0);
|
|
45
|
+
_url = '';
|
|
46
|
+
commandTimeout;
|
|
47
|
+
constructor(options = {}) {
|
|
48
|
+
this.commandTimeout = options.timeout ?? 10000;
|
|
49
|
+
}
|
|
50
|
+
get url() { return this._url; }
|
|
51
|
+
get connected() { return this.socket !== null && !this.socket.destroyed; }
|
|
52
|
+
async connect(wsUrl) {
|
|
53
|
+
this._url = wsUrl;
|
|
54
|
+
const url = new URL(wsUrl);
|
|
55
|
+
const key = crypto.randomBytes(16).toString('base64');
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
const req = http.get({
|
|
58
|
+
hostname: url.hostname,
|
|
59
|
+
port: url.port || 80,
|
|
60
|
+
path: url.pathname + url.search,
|
|
61
|
+
headers: {
|
|
62
|
+
'Connection': 'Upgrade',
|
|
63
|
+
'Upgrade': 'websocket',
|
|
64
|
+
'Sec-WebSocket-Key': key,
|
|
65
|
+
'Sec-WebSocket-Version': '13',
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
const timeout = setTimeout(() => {
|
|
69
|
+
req.destroy();
|
|
70
|
+
reject(new Error('WebSocket connection timed out'));
|
|
71
|
+
}, 5000);
|
|
72
|
+
req.on('upgrade', (_res, socket, head) => {
|
|
73
|
+
clearTimeout(timeout);
|
|
74
|
+
this.socket = socket;
|
|
75
|
+
this.buffer = Buffer.alloc(0);
|
|
76
|
+
if (head.length > 0) {
|
|
77
|
+
this.buffer = Buffer.concat([this.buffer, head]);
|
|
78
|
+
}
|
|
79
|
+
this.setupSocketHandlers();
|
|
80
|
+
resolve();
|
|
81
|
+
});
|
|
82
|
+
req.on('error', (err) => {
|
|
83
|
+
clearTimeout(timeout);
|
|
84
|
+
reject(new Error(`WebSocket connection failed: ${err.message}`));
|
|
85
|
+
});
|
|
86
|
+
req.on('response', (res) => {
|
|
87
|
+
clearTimeout(timeout);
|
|
88
|
+
reject(new Error(`WebSocket upgrade failed with status ${res.statusCode}`));
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
async send(method, params) {
|
|
93
|
+
if (!this.socket || this.socket.destroyed) {
|
|
94
|
+
throw new Error('CDP connection not open');
|
|
95
|
+
}
|
|
96
|
+
const id = this.nextId++;
|
|
97
|
+
const message = JSON.stringify({ id, method, params: params ?? {} });
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
const timer = setTimeout(() => {
|
|
100
|
+
this.pending.delete(id);
|
|
101
|
+
reject(new Error(`CDP command "${method}" timed out after ${this.commandTimeout}ms`));
|
|
102
|
+
}, this.commandTimeout);
|
|
103
|
+
this.pending.set(id, { resolve, reject, timer });
|
|
104
|
+
this.writeFrame(message);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
on(event, handler) {
|
|
108
|
+
if (!this.eventHandlers.has(event)) {
|
|
109
|
+
this.eventHandlers.set(event, new Set());
|
|
110
|
+
}
|
|
111
|
+
this.eventHandlers.get(event).add(handler);
|
|
112
|
+
}
|
|
113
|
+
off(event, handler) {
|
|
114
|
+
this.eventHandlers.get(event)?.delete(handler);
|
|
115
|
+
}
|
|
116
|
+
async close() {
|
|
117
|
+
if (!this.socket || this.socket.destroyed)
|
|
118
|
+
return;
|
|
119
|
+
// Send close frame
|
|
120
|
+
const frame = Buffer.alloc(6);
|
|
121
|
+
frame[0] = 0x88; // FIN + close opcode
|
|
122
|
+
frame[1] = 0x80; // Mask bit set, 0 payload length
|
|
123
|
+
crypto.randomBytes(4).copy(frame, 2); // Masking key
|
|
124
|
+
this.socket.write(frame);
|
|
125
|
+
// Reject pending
|
|
126
|
+
for (const [id, p] of this.pending) {
|
|
127
|
+
clearTimeout(p.timer);
|
|
128
|
+
p.reject(new Error('Connection closed'));
|
|
129
|
+
this.pending.delete(id);
|
|
130
|
+
}
|
|
131
|
+
return new Promise((resolve) => {
|
|
132
|
+
const timer = setTimeout(() => {
|
|
133
|
+
this.socket?.destroy();
|
|
134
|
+
this.socket = null;
|
|
135
|
+
resolve();
|
|
136
|
+
}, 1000);
|
|
137
|
+
this.socket.once('close', () => {
|
|
138
|
+
clearTimeout(timer);
|
|
139
|
+
this.socket = null;
|
|
140
|
+
resolve();
|
|
141
|
+
});
|
|
142
|
+
this.socket.end();
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
setupSocketHandlers() {
|
|
146
|
+
if (!this.socket)
|
|
147
|
+
return;
|
|
148
|
+
this.socket.on('data', (chunk) => {
|
|
149
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
150
|
+
this.processFrames();
|
|
151
|
+
});
|
|
152
|
+
this.socket.on('close', () => {
|
|
153
|
+
for (const [id, p] of this.pending) {
|
|
154
|
+
clearTimeout(p.timer);
|
|
155
|
+
p.reject(new Error('Connection closed'));
|
|
156
|
+
}
|
|
157
|
+
this.pending.clear();
|
|
158
|
+
this.socket = null;
|
|
159
|
+
});
|
|
160
|
+
this.socket.on('error', () => {
|
|
161
|
+
// Handled by close event
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
processFrames() {
|
|
165
|
+
while (this.buffer.length >= 2) {
|
|
166
|
+
const firstByte = this.buffer[0];
|
|
167
|
+
const secondByte = this.buffer[1];
|
|
168
|
+
const opcode = firstByte & 0x0f;
|
|
169
|
+
const masked = (secondByte & 0x80) !== 0;
|
|
170
|
+
let payloadLength = secondByte & 0x7f;
|
|
171
|
+
let offset = 2;
|
|
172
|
+
if (payloadLength === 126) {
|
|
173
|
+
if (this.buffer.length < 4)
|
|
174
|
+
return; // Need more data
|
|
175
|
+
payloadLength = this.buffer.readUInt16BE(2);
|
|
176
|
+
offset = 4;
|
|
177
|
+
}
|
|
178
|
+
else if (payloadLength === 127) {
|
|
179
|
+
if (this.buffer.length < 10)
|
|
180
|
+
return;
|
|
181
|
+
// For simplicity, read as 32-bit (CDP messages won't exceed 4GB)
|
|
182
|
+
payloadLength = this.buffer.readUInt32BE(6);
|
|
183
|
+
offset = 10;
|
|
184
|
+
}
|
|
185
|
+
if (masked)
|
|
186
|
+
offset += 4; // Skip masking key (server shouldn't mask, but handle it)
|
|
187
|
+
if (this.buffer.length < offset + payloadLength)
|
|
188
|
+
return; // Need more data
|
|
189
|
+
let payload = this.buffer.subarray(offset, offset + payloadLength);
|
|
190
|
+
if (masked) {
|
|
191
|
+
const maskKey = this.buffer.subarray(offset - 4, offset);
|
|
192
|
+
payload = Buffer.from(payload); // Copy so we can mutate
|
|
193
|
+
for (let i = 0; i < payload.length; i++) {
|
|
194
|
+
payload[i] ^= maskKey[i % 4];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
this.buffer = this.buffer.subarray(offset + payloadLength);
|
|
198
|
+
if (opcode === 0x1) {
|
|
199
|
+
// Text frame
|
|
200
|
+
this.handleMessage(payload.toString('utf-8'));
|
|
201
|
+
}
|
|
202
|
+
else if (opcode === 0x8) {
|
|
203
|
+
// Close frame
|
|
204
|
+
this.socket?.end();
|
|
205
|
+
}
|
|
206
|
+
else if (opcode === 0x9) {
|
|
207
|
+
// Ping — respond with pong
|
|
208
|
+
this.writePong(payload);
|
|
209
|
+
}
|
|
210
|
+
// Ignore other opcodes (pong, binary, continuation)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
handleMessage(text) {
|
|
214
|
+
try {
|
|
215
|
+
const msg = JSON.parse(text);
|
|
216
|
+
if (msg.id !== undefined && this.pending.has(msg.id)) {
|
|
217
|
+
const p = this.pending.get(msg.id);
|
|
218
|
+
this.pending.delete(msg.id);
|
|
219
|
+
clearTimeout(p.timer);
|
|
220
|
+
if (msg.error) {
|
|
221
|
+
p.reject(new Error(`CDP error: ${msg.error.message}`));
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
p.resolve(msg.result);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else if (msg.method) {
|
|
228
|
+
// Event
|
|
229
|
+
const handlers = this.eventHandlers.get(msg.method);
|
|
230
|
+
if (handlers) {
|
|
231
|
+
for (const handler of handlers) {
|
|
232
|
+
handler(msg.params);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// Ignore malformed messages
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
writeFrame(text) {
|
|
242
|
+
if (!this.socket || this.socket.destroyed)
|
|
243
|
+
return;
|
|
244
|
+
const payload = Buffer.from(text, 'utf-8');
|
|
245
|
+
const maskKey = crypto.randomBytes(4);
|
|
246
|
+
let header;
|
|
247
|
+
if (payload.length < 126) {
|
|
248
|
+
header = Buffer.alloc(2);
|
|
249
|
+
header[0] = 0x81; // FIN + text opcode
|
|
250
|
+
header[1] = 0x80 | payload.length; // Masked
|
|
251
|
+
}
|
|
252
|
+
else if (payload.length < 65536) {
|
|
253
|
+
header = Buffer.alloc(4);
|
|
254
|
+
header[0] = 0x81;
|
|
255
|
+
header[1] = 0x80 | 126;
|
|
256
|
+
header.writeUInt16BE(payload.length, 2);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
header = Buffer.alloc(10);
|
|
260
|
+
header[0] = 0x81;
|
|
261
|
+
header[1] = 0x80 | 127;
|
|
262
|
+
header.writeBigUInt64BE(BigInt(payload.length), 2);
|
|
263
|
+
}
|
|
264
|
+
// Mask the payload
|
|
265
|
+
const masked = Buffer.alloc(payload.length);
|
|
266
|
+
for (let i = 0; i < payload.length; i++) {
|
|
267
|
+
masked[i] = payload[i] ^ maskKey[i % 4];
|
|
268
|
+
}
|
|
269
|
+
this.socket.write(Buffer.concat([header, maskKey, masked]));
|
|
270
|
+
}
|
|
271
|
+
writePong(payload) {
|
|
272
|
+
if (!this.socket || this.socket.destroyed)
|
|
273
|
+
return;
|
|
274
|
+
const maskKey = crypto.randomBytes(4);
|
|
275
|
+
const header = Buffer.alloc(2);
|
|
276
|
+
header[0] = 0x8a; // FIN + pong opcode
|
|
277
|
+
header[1] = 0x80 | payload.length;
|
|
278
|
+
const masked = Buffer.alloc(payload.length);
|
|
279
|
+
for (let i = 0; i < payload.length; i++) {
|
|
280
|
+
masked[i] = payload[i] ^ maskKey[i % 4];
|
|
281
|
+
}
|
|
282
|
+
this.socket.write(Buffer.concat([header, maskKey, masked]));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
exports.CDPConnection = CDPConnection;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.computeChanged = computeChanged;
|
|
4
|
+
exports.computeDiff = computeDiff;
|
|
5
|
+
/** Quick check if anything changed between two element arrays */
|
|
6
|
+
function computeChanged(prev, curr) {
|
|
7
|
+
if (prev.length !== curr.length)
|
|
8
|
+
return true;
|
|
9
|
+
for (let i = 0; i < prev.length; i++) {
|
|
10
|
+
const p = prev[i];
|
|
11
|
+
const c = curr[i];
|
|
12
|
+
if (p.ref !== c.ref || p.role !== c.role || p.label !== c.label ||
|
|
13
|
+
p.value !== c.value || p.enabled !== c.enabled || p.focused !== c.focused) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
/** Detailed diff between two element arrays */
|
|
20
|
+
function computeDiff(prev, curr) {
|
|
21
|
+
const prevMap = new Map(prev.map(e => [e.ref, e]));
|
|
22
|
+
const currMap = new Map(curr.map(e => [e.ref, e]));
|
|
23
|
+
const added = [];
|
|
24
|
+
const removed = [];
|
|
25
|
+
const modified = [];
|
|
26
|
+
// Find added and modified
|
|
27
|
+
for (const [ref, el] of currMap) {
|
|
28
|
+
const prevEl = prevMap.get(ref);
|
|
29
|
+
if (!prevEl) {
|
|
30
|
+
added.push(el);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const changes = {};
|
|
34
|
+
if (prevEl.label !== el.label)
|
|
35
|
+
changes.label = { from: prevEl.label, to: el.label };
|
|
36
|
+
if (prevEl.value !== el.value)
|
|
37
|
+
changes.value = { from: prevEl.value, to: el.value };
|
|
38
|
+
if (prevEl.enabled !== el.enabled)
|
|
39
|
+
changes.enabled = { from: prevEl.enabled, to: el.enabled };
|
|
40
|
+
if (prevEl.focused !== el.focused)
|
|
41
|
+
changes.focused = { from: prevEl.focused, to: el.focused };
|
|
42
|
+
if (Object.keys(changes).length > 0) {
|
|
43
|
+
modified.push({ ref, changes });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Find removed
|
|
48
|
+
for (const [ref, el] of prevMap) {
|
|
49
|
+
if (!currMap.has(ref)) {
|
|
50
|
+
removed.push(el);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const changed = added.length > 0 || removed.length > 0 || modified.length > 0;
|
|
54
|
+
return { changed, added, removed, modified };
|
|
55
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.discoverTargets = discoverTargets;
|
|
37
|
+
exports.findPageTarget = findPageTarget;
|
|
38
|
+
exports.waitForCDP = waitForCDP;
|
|
39
|
+
const http = __importStar(require("http"));
|
|
40
|
+
/** GET http://localhost:{port}/json/list — returns all CDP targets */
|
|
41
|
+
async function discoverTargets(port) {
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
const req = http.get(`http://127.0.0.1:${port}/json/list`, (res) => {
|
|
44
|
+
let data = '';
|
|
45
|
+
res.on('data', (chunk) => { data += chunk.toString(); });
|
|
46
|
+
res.on('end', () => {
|
|
47
|
+
try {
|
|
48
|
+
const targets = JSON.parse(data);
|
|
49
|
+
resolve(targets);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
reject(new Error(`Failed to parse CDP targets: ${err}`));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
req.on('error', (err) => {
|
|
57
|
+
reject(new Error(`Failed to discover CDP targets on port ${port}: ${err.message}`));
|
|
58
|
+
});
|
|
59
|
+
req.setTimeout(5000, () => {
|
|
60
|
+
req.destroy();
|
|
61
|
+
reject(new Error(`CDP discovery timed out on port ${port}`));
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/** Filter targets for type === 'page' and return first match */
|
|
66
|
+
async function findPageTarget(port) {
|
|
67
|
+
const targets = await discoverTargets(port);
|
|
68
|
+
const page = targets.find(t => t.type === 'page');
|
|
69
|
+
if (!page) {
|
|
70
|
+
throw new Error(`No page target found on port ${port}. Found: ${targets.map(t => t.type).join(', ')}`);
|
|
71
|
+
}
|
|
72
|
+
return page;
|
|
73
|
+
}
|
|
74
|
+
/** Poll until a page target appears, with timeout */
|
|
75
|
+
async function waitForCDP(port, timeout = 10000) {
|
|
76
|
+
const start = Date.now();
|
|
77
|
+
let lastError;
|
|
78
|
+
while (Date.now() - start < timeout) {
|
|
79
|
+
try {
|
|
80
|
+
return await findPageTarget(port);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
lastError = err;
|
|
84
|
+
await sleep(200);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
throw new Error(`CDP not available on port ${port} after ${timeout}ms: ${lastError?.message}`);
|
|
88
|
+
}
|
|
89
|
+
function sleep(ms) {
|
|
90
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
91
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findFreePort = exports.computeDiff = exports.computeChanged = exports.resolveAllBounds = exports.toScreenCoords = exports.getBounds = exports.INTERACTIVE_ROLES = exports.mapCDPRole = exports.CDPClient = exports.CDPInteractions = exports.CDPAXTree = exports.waitForCDP = exports.findPageTarget = exports.discoverTargets = exports.CDPConnection = void 0;
|
|
4
|
+
var connection_js_1 = require("./connection.js");
|
|
5
|
+
Object.defineProperty(exports, "CDPConnection", { enumerable: true, get: function () { return connection_js_1.CDPConnection; } });
|
|
6
|
+
var discovery_js_1 = require("./discovery.js");
|
|
7
|
+
Object.defineProperty(exports, "discoverTargets", { enumerable: true, get: function () { return discovery_js_1.discoverTargets; } });
|
|
8
|
+
Object.defineProperty(exports, "findPageTarget", { enumerable: true, get: function () { return discovery_js_1.findPageTarget; } });
|
|
9
|
+
Object.defineProperty(exports, "waitForCDP", { enumerable: true, get: function () { return discovery_js_1.waitForCDP; } });
|
|
10
|
+
var ax_tree_js_1 = require("./ax-tree.js");
|
|
11
|
+
Object.defineProperty(exports, "CDPAXTree", { enumerable: true, get: function () { return ax_tree_js_1.CDPAXTree; } });
|
|
12
|
+
var interactions_js_1 = require("./interactions.js");
|
|
13
|
+
Object.defineProperty(exports, "CDPInteractions", { enumerable: true, get: function () { return interactions_js_1.CDPInteractions; } });
|
|
14
|
+
var client_js_1 = require("./client.js");
|
|
15
|
+
Object.defineProperty(exports, "CDPClient", { enumerable: true, get: function () { return client_js_1.CDPClient; } });
|
|
16
|
+
var role_map_js_1 = require("./role-map.js");
|
|
17
|
+
Object.defineProperty(exports, "mapCDPRole", { enumerable: true, get: function () { return role_map_js_1.mapCDPRole; } });
|
|
18
|
+
Object.defineProperty(exports, "INTERACTIVE_ROLES", { enumerable: true, get: function () { return role_map_js_1.INTERACTIVE_ROLES; } });
|
|
19
|
+
var bounds_js_1 = require("./bounds.js");
|
|
20
|
+
Object.defineProperty(exports, "getBounds", { enumerable: true, get: function () { return bounds_js_1.getBounds; } });
|
|
21
|
+
Object.defineProperty(exports, "toScreenCoords", { enumerable: true, get: function () { return bounds_js_1.toScreenCoords; } });
|
|
22
|
+
Object.defineProperty(exports, "resolveAllBounds", { enumerable: true, get: function () { return bounds_js_1.resolveAllBounds; } });
|
|
23
|
+
var diff_js_1 = require("./diff.js");
|
|
24
|
+
Object.defineProperty(exports, "computeChanged", { enumerable: true, get: function () { return diff_js_1.computeChanged; } });
|
|
25
|
+
Object.defineProperty(exports, "computeDiff", { enumerable: true, get: function () { return diff_js_1.computeDiff; } });
|
|
26
|
+
var port_manager_js_1 = require("./port-manager.js");
|
|
27
|
+
Object.defineProperty(exports, "findFreePort", { enumerable: true, get: function () { return port_manager_js_1.findFreePort; } });
|