@skillful-agents/agent-computer 0.0.3 → 0.0.5

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.
Files changed (49) hide show
  1. package/bin/ac-core-darwin-arm64 +0 -0
  2. package/bin/ac-core-darwin-x64 +0 -0
  3. package/bin/ac-core-win32-arm64.exe +0 -0
  4. package/bin/ac-core-win32-x64.exe +0 -0
  5. package/dist/src/platform/resolve.d.ts.map +1 -1
  6. package/dist/src/platform/resolve.js +33 -6
  7. package/dist/src/platform/resolve.js.map +1 -1
  8. package/dist-cjs/bin/ac.js +127 -0
  9. package/dist-cjs/package.json +1 -0
  10. package/dist-cjs/src/bridge.js +693 -0
  11. package/dist-cjs/src/cdp/ax-tree.js +162 -0
  12. package/dist-cjs/src/cdp/bounds.js +66 -0
  13. package/dist-cjs/src/cdp/client.js +272 -0
  14. package/dist-cjs/src/cdp/connection.js +285 -0
  15. package/dist-cjs/src/cdp/diff.js +55 -0
  16. package/dist-cjs/src/cdp/discovery.js +91 -0
  17. package/dist-cjs/src/cdp/index.js +27 -0
  18. package/dist-cjs/src/cdp/interactions.js +301 -0
  19. package/dist-cjs/src/cdp/port-manager.js +68 -0
  20. package/dist-cjs/src/cdp/role-map.js +102 -0
  21. package/dist-cjs/src/cdp/types.js +2 -0
  22. package/dist-cjs/src/cli/commands/apps.js +63 -0
  23. package/dist-cjs/src/cli/commands/batch.js +37 -0
  24. package/dist-cjs/src/cli/commands/click.js +61 -0
  25. package/dist-cjs/src/cli/commands/clipboard.js +31 -0
  26. package/dist-cjs/src/cli/commands/dialog.js +45 -0
  27. package/dist-cjs/src/cli/commands/drag.js +26 -0
  28. package/dist-cjs/src/cli/commands/find.js +99 -0
  29. package/dist-cjs/src/cli/commands/menu.js +36 -0
  30. package/dist-cjs/src/cli/commands/screenshot.js +27 -0
  31. package/dist-cjs/src/cli/commands/scroll.js +77 -0
  32. package/dist-cjs/src/cli/commands/session.js +27 -0
  33. package/dist-cjs/src/cli/commands/snapshot.js +24 -0
  34. package/dist-cjs/src/cli/commands/type.js +69 -0
  35. package/dist-cjs/src/cli/commands/windowmgmt.js +62 -0
  36. package/dist-cjs/src/cli/commands/windows.js +10 -0
  37. package/dist-cjs/src/cli/commands.js +215 -0
  38. package/dist-cjs/src/cli/output.js +253 -0
  39. package/dist-cjs/src/cli/parser.js +128 -0
  40. package/dist-cjs/src/config.js +79 -0
  41. package/dist-cjs/src/daemon.js +183 -0
  42. package/dist-cjs/src/errors.js +118 -0
  43. package/dist-cjs/src/index.js +24 -0
  44. package/dist-cjs/src/platform/index.js +16 -0
  45. package/dist-cjs/src/platform/resolve.js +83 -0
  46. package/dist-cjs/src/refs.js +91 -0
  47. package/dist-cjs/src/sdk.js +288 -0
  48. package/dist-cjs/src/types.js +11 -0
  49. package/package.json +4 -2
@@ -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; } });