@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.
Files changed (50) 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 +5 -3
  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 +71 -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
  50. package/scripts/fix-cjs-resolve.js +27 -0
@@ -0,0 +1,215 @@
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.registerCommand = registerCommand;
37
+ exports.getCommand = getCommand;
38
+ exports.getCommandAsync = getCommandAsync;
39
+ exports.getAllCommands = getAllCommands;
40
+ const daemon_js_1 = require("../daemon.js");
41
+ const config_js_1 = require("../config.js");
42
+ const commands = {};
43
+ let commandModulesLoaded = false;
44
+ function registerCommand(name, handler) {
45
+ commands[name] = handler;
46
+ }
47
+ async function ensureCommandModulesLoaded() {
48
+ if (commandModulesLoaded)
49
+ return;
50
+ commandModulesLoaded = true;
51
+ await Promise.resolve().then(() => __importStar(require('./commands/apps.js')));
52
+ await Promise.resolve().then(() => __importStar(require('./commands/windows.js')));
53
+ await Promise.resolve().then(() => __importStar(require('./commands/session.js')));
54
+ await Promise.resolve().then(() => __importStar(require('./commands/snapshot.js')));
55
+ await Promise.resolve().then(() => __importStar(require('./commands/click.js')));
56
+ await Promise.resolve().then(() => __importStar(require('./commands/type.js')));
57
+ await Promise.resolve().then(() => __importStar(require('./commands/clipboard.js')));
58
+ await Promise.resolve().then(() => __importStar(require('./commands/windowmgmt.js')));
59
+ await Promise.resolve().then(() => __importStar(require('./commands/screenshot.js')));
60
+ await Promise.resolve().then(() => __importStar(require('./commands/scroll.js')));
61
+ await Promise.resolve().then(() => __importStar(require('./commands/find.js')));
62
+ await Promise.resolve().then(() => __importStar(require('./commands/menu.js')));
63
+ await Promise.resolve().then(() => __importStar(require('./commands/dialog.js')));
64
+ await Promise.resolve().then(() => __importStar(require('./commands/drag.js')));
65
+ await Promise.resolve().then(() => __importStar(require('./commands/batch.js')));
66
+ }
67
+ function getCommand(name) {
68
+ return commands[name];
69
+ }
70
+ async function getCommandAsync(name) {
71
+ await ensureCommandModulesLoaded();
72
+ return commands[name];
73
+ }
74
+ function getAllCommands() {
75
+ return Object.keys(commands).sort();
76
+ }
77
+ // Register built-in commands
78
+ registerCommand('version', async () => {
79
+ return { data: { version: '0.1.0' }, exitCode: 0 };
80
+ });
81
+ registerCommand('help', async () => {
82
+ const help = `agent-computer — Agent Computer CLI for macOS
83
+
84
+ Usage: agent-computer <command> [options]
85
+
86
+ Commands:
87
+ snapshot Snapshot the accessibility tree
88
+ screenshot [path] Take a screenshot
89
+ click <sel> Click an element
90
+ type <text> Type text
91
+ fill <sel> <text> Focus, clear, and type into an element
92
+ key <combo> Press a key combination
93
+ find <text> Find elements by text
94
+ read <sel> Read element value
95
+ scroll <dir> [amount] Scroll in a direction
96
+ menu <path> Click a menu item by path
97
+
98
+ apps List applications
99
+ launch <name> Launch an application
100
+ quit <name> Quit an application
101
+ windows List windows
102
+ grab <sel> Set active window context
103
+ ungrab Clear active window context
104
+ status Show session state
105
+
106
+ wait <sel|ms> Wait for condition
107
+ clipboard [set <text>] Clipboard operations
108
+ alert Handle alerts
109
+ dialog Handle dialogs
110
+
111
+ daemon <start|stop|status|restart> Manage daemon
112
+ config [set <key> <val> | reset] Configuration
113
+ permissions [grant] Permission status
114
+ doctor Run diagnostics
115
+ version Print version
116
+
117
+ Global options:
118
+ --json JSON output (default: human-readable text)
119
+ --timeout <ms> Override timeout (default: 10000)
120
+ --verbose Debug logging to stderr
121
+ --content-boundary Wrap output in delimiters
122
+ --max-output <n> Truncate output to N characters
123
+
124
+ See: https://github.com/datawizz/agent-computer`;
125
+ return { data: help, exitCode: 0 };
126
+ });
127
+ registerCommand('daemon', async (args) => {
128
+ const manager = new daemon_js_1.DaemonManager();
129
+ const sub = args.subcommand;
130
+ switch (sub) {
131
+ case 'start': {
132
+ const status = await manager.start();
133
+ return { data: status, exitCode: 0 };
134
+ }
135
+ case 'stop': {
136
+ await manager.stop();
137
+ return { data: { ok: true }, exitCode: 0 };
138
+ }
139
+ case 'status': {
140
+ const status = await manager.status();
141
+ return { data: status, exitCode: 0 };
142
+ }
143
+ case 'restart': {
144
+ const status = await manager.restart();
145
+ return { data: status, exitCode: 0 };
146
+ }
147
+ default:
148
+ return { data: { error: `Unknown daemon subcommand: ${sub}. Use: start, stop, status, restart` }, exitCode: 1 };
149
+ }
150
+ });
151
+ registerCommand('config', async (args) => {
152
+ const sub = args.subcommand;
153
+ switch (sub) {
154
+ case 'set': {
155
+ const key = args.positional[0];
156
+ const value = args.positional[1];
157
+ if (!key || value === undefined) {
158
+ return { data: { error: 'Usage: agent-computer config set <key> <value>' }, exitCode: 1 };
159
+ }
160
+ const defaults = (0, config_js_1.getDefaults)();
161
+ if (!(key in defaults)) {
162
+ return { data: { error: `Unknown config key: ${key}` }, exitCode: 1 };
163
+ }
164
+ // Coerce value to correct type
165
+ const defaultVal = defaults[key];
166
+ let coerced = value;
167
+ if (typeof defaultVal === 'number')
168
+ coerced = parseInt(value, 10);
169
+ if (typeof defaultVal === 'boolean')
170
+ coerced = value === 'true' || value === '1';
171
+ (0, config_js_1.setConfigValue)(key, coerced);
172
+ return { data: { ok: true, key, value: coerced }, exitCode: 0 };
173
+ }
174
+ case 'reset': {
175
+ (0, config_js_1.resetConfig)();
176
+ return { data: { ok: true }, exitCode: 0 };
177
+ }
178
+ default: {
179
+ // Show current config
180
+ const config = (0, config_js_1.resolveConfig)();
181
+ return { data: config, exitCode: 0 };
182
+ }
183
+ }
184
+ });
185
+ registerCommand('ping', async (_args, bridge) => {
186
+ const result = await bridge.send('ping');
187
+ return { data: result, exitCode: 0 };
188
+ });
189
+ registerCommand('status', async (_args, bridge) => {
190
+ const result = await bridge.send('status');
191
+ return { data: result, exitCode: 0 };
192
+ });
193
+ registerCommand('permissions', async (args, bridge) => {
194
+ if (args.subcommand === 'grant') {
195
+ const result = await bridge.send('permissions_grant');
196
+ return { data: result, exitCode: 0 };
197
+ }
198
+ const result = await bridge.send('permissions');
199
+ return { data: result, exitCode: 0 };
200
+ });
201
+ registerCommand('doctor', async (_args, bridge) => {
202
+ const [permissions, version, daemonStatus] = await Promise.all([
203
+ bridge.send('permissions'),
204
+ bridge.send('version'),
205
+ new daemon_js_1.DaemonManager().status(),
206
+ ]);
207
+ const result = {
208
+ version: version.version,
209
+ permissions,
210
+ daemon: daemonStatus,
211
+ platform: process.platform,
212
+ arch: process.arch,
213
+ };
214
+ return { data: result, exitCode: 0 };
215
+ });
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatOutput = formatOutput;
4
+ exports.wrapBoundary = wrapBoundary;
5
+ exports.truncateOutput = truncateOutput;
6
+ const crypto_1 = require("crypto");
7
+ // Format output — text mode is default, --json for JSON
8
+ function formatOutput(data, textMode) {
9
+ if (textMode) {
10
+ return formatText(data);
11
+ }
12
+ return JSON.stringify(data, null, 2);
13
+ }
14
+ // Human-readable text formatting
15
+ function formatText(data) {
16
+ if (data === null || data === undefined) {
17
+ return '';
18
+ }
19
+ if (typeof data === 'string') {
20
+ return data;
21
+ }
22
+ if (typeof data === 'boolean' || typeof data === 'number') {
23
+ return String(data);
24
+ }
25
+ if (Array.isArray(data)) {
26
+ return data.map(item => formatText(item)).join('\n');
27
+ }
28
+ if (typeof data === 'object') {
29
+ const obj = data;
30
+ // Snapshot result — format as tree
31
+ if ('snapshot_id' in obj && 'elements' in obj) {
32
+ return formatSnapshotText(obj);
33
+ }
34
+ // Windows list
35
+ if ('windows' in obj && Array.isArray(obj.windows)) {
36
+ return formatWindowsList(obj.windows);
37
+ }
38
+ // Apps list
39
+ if ('apps' in obj && Array.isArray(obj.apps)) {
40
+ return formatAppsList(obj.apps);
41
+ }
42
+ // Find results
43
+ if ('elements' in obj && Array.isArray(obj.elements) && !('snapshot_id' in obj)) {
44
+ return formatFindResults(obj.elements);
45
+ }
46
+ // Dialog detection
47
+ if ('found' in obj && 'dialog' in obj) {
48
+ return formatDialogResult(obj);
49
+ }
50
+ // Batch results
51
+ if ('results' in obj && Array.isArray(obj.results) && 'total' in obj) {
52
+ return formatBatchResults(obj);
53
+ }
54
+ // Diff/changed
55
+ if ('changed' in obj && typeof obj.changed === 'boolean') {
56
+ return formatDiffResult(obj);
57
+ }
58
+ // Menu list
59
+ if ('items' in obj && Array.isArray(obj.items)) {
60
+ return formatMenuItems(obj.items, obj.menu);
61
+ }
62
+ // Screenshot
63
+ if ('path' in obj && typeof obj.path === 'string' && ('width' in obj || 'ok' in obj)) {
64
+ return formatScreenshot(obj);
65
+ }
66
+ // Displays
67
+ if ('displays' in obj && Array.isArray(obj.displays)) {
68
+ return formatDisplays(obj.displays);
69
+ }
70
+ // Permissions
71
+ if ('accessibility' in obj && 'screen_recording' in obj) {
72
+ return formatPermissions(obj);
73
+ }
74
+ // Simple ok result
75
+ if ('ok' in obj && Object.keys(obj).length <= 3) {
76
+ const extra = Object.entries(obj)
77
+ .filter(([k]) => k !== 'ok')
78
+ .map(([k, v]) => {
79
+ if (typeof v !== 'object' || v === null)
80
+ return `${k}: ${v}`;
81
+ // Format nested objects as key=value pairs
82
+ const inner = Object.entries(v)
83
+ .map(([ik, iv]) => `${ik}=${Array.isArray(iv) ? iv.join(',') : iv}`)
84
+ .join(', ');
85
+ return `${k}: ${inner}`;
86
+ })
87
+ .join(', ');
88
+ return extra ? `OK (${extra})` : 'OK';
89
+ }
90
+ // Clipboard
91
+ if ('text' in obj && typeof obj.text === 'string' && Object.keys(obj).length <= 2) {
92
+ return obj.text;
93
+ }
94
+ // Generic key-value
95
+ return Object.entries(obj)
96
+ .map(([key, val]) => `${key}: ${typeof val === 'object' ? JSON.stringify(val) : val}`)
97
+ .join('\n');
98
+ }
99
+ return JSON.stringify(data);
100
+ }
101
+ // Format snapshot as hierarchical tree
102
+ function formatSnapshotText(snap) {
103
+ const elements = snap.elements;
104
+ const lines = [];
105
+ for (const el of elements) {
106
+ formatElementTree(el, 0, lines);
107
+ }
108
+ return lines.join('\n');
109
+ }
110
+ function formatElementTree(el, indent, lines) {
111
+ const prefix = ' '.repeat(indent);
112
+ const focusMarker = el.focused ? '*' : '';
113
+ const parts = [];
114
+ parts.push(`${focusMarker}[${el.ref}] ${capitalize(el.role)}`);
115
+ if (el.label)
116
+ parts.push(`"${el.label}"`);
117
+ if (el.value !== null && el.value !== undefined)
118
+ parts.push(`value="${truncate(String(el.value), 50)}"`);
119
+ const attrs = [];
120
+ if (el.enabled)
121
+ attrs.push('enabled');
122
+ if (!el.enabled)
123
+ attrs.push('disabled');
124
+ if (el.focused)
125
+ attrs.push('focused');
126
+ if (el.bounds) {
127
+ const [x, y, w, h] = el.bounds;
128
+ attrs.push(`${x},${y} ${w}x${h}`);
129
+ }
130
+ lines.push(`${prefix}${parts.join(' ')} (${attrs.join(', ')})`);
131
+ if (el.children) {
132
+ for (const child of el.children) {
133
+ formatElementTree(child, indent + 1, lines);
134
+ }
135
+ }
136
+ }
137
+ function formatWindowsList(windows) {
138
+ if (windows.length === 0)
139
+ return 'No windows';
140
+ return windows.map(w => `${w.ref || '-'} ${w.app}: "${w.title}"${w.minimized ? ' (minimized)' : ''}${w.hidden ? ' (hidden)' : ''}`).join('\n');
141
+ }
142
+ function formatAppsList(apps) {
143
+ if (apps.length === 0)
144
+ return 'No running apps';
145
+ return apps.map(a => `${a.name}${a.is_active ? ' *' : ''}${a.is_hidden ? ' (hidden)' : ''}${a.bundle_id ? ` [${a.bundle_id}]` : ''}`).join('\n');
146
+ }
147
+ function formatFindResults(elements) {
148
+ if (elements.length === 0)
149
+ return 'No elements found';
150
+ return elements.map(e => {
151
+ const parts = [`[${e.ref}] ${e.role}`];
152
+ if (e.label)
153
+ parts.push(`"${e.label}"`);
154
+ if (e.value)
155
+ parts.push(`value="${truncate(String(e.value), 40)}"`);
156
+ return parts.join(' ');
157
+ }).join('\n');
158
+ }
159
+ function formatDialogResult(obj) {
160
+ if (!obj.found)
161
+ return 'No dialog found';
162
+ const dialog = obj.dialog;
163
+ const lines = [`Dialog: ${dialog.type}`];
164
+ if (dialog.title)
165
+ lines.push(` Title: ${dialog.title}`);
166
+ if (dialog.message)
167
+ lines.push(` Message: ${dialog.message}`);
168
+ if (dialog.buttons && Array.isArray(dialog.buttons)) {
169
+ const btns = dialog.buttons.map(b => b.title).join(', ');
170
+ lines.push(` Buttons: ${btns}`);
171
+ }
172
+ return lines.join('\n');
173
+ }
174
+ function formatBatchResults(obj) {
175
+ const results = obj.results;
176
+ const lines = [`Batch: ${obj.count}/${obj.total} completed${obj.ok ? '' : ' (stopped on error)'}`];
177
+ for (const r of results) {
178
+ if (r.error) {
179
+ lines.push(` [${r.index}] ${r.method}: ERROR - ${r.error}`);
180
+ }
181
+ else {
182
+ lines.push(` [${r.index}] ${r.method}: OK`);
183
+ }
184
+ }
185
+ return lines.join('\n');
186
+ }
187
+ function formatDiffResult(obj) {
188
+ if (!obj.changed)
189
+ return 'No changes detected';
190
+ const lines = ['Changes detected'];
191
+ if (obj.added_count)
192
+ lines.push(` Added: ${obj.added_count}`);
193
+ if (obj.removed_count)
194
+ lines.push(` Removed: ${obj.removed_count}`);
195
+ if (Array.isArray(obj.added) && obj.added.length > 0) {
196
+ lines.push(` Added elements: ${obj.added.length}`);
197
+ }
198
+ if (Array.isArray(obj.removed) && obj.removed.length > 0) {
199
+ lines.push(` Removed elements: ${obj.removed.length}`);
200
+ }
201
+ return lines.join('\n');
202
+ }
203
+ function formatMenuItems(items, menuName) {
204
+ if (items.length === 0)
205
+ return menuName ? `No items in menu "${menuName}"` : 'No menus';
206
+ const header = menuName ? `Menu: ${menuName}` : 'Menus';
207
+ const lines = [header];
208
+ for (const item of items) {
209
+ const enabled = item.enabled !== false ? '' : ' (disabled)';
210
+ lines.push(` ${item.title}${enabled}`);
211
+ if (Array.isArray(item.children)) {
212
+ for (const child of item.children) {
213
+ const cEnabled = child.enabled !== false ? '' : ' (disabled)';
214
+ lines.push(` ${child.title}${cEnabled}`);
215
+ }
216
+ }
217
+ }
218
+ return lines.join('\n');
219
+ }
220
+ function formatScreenshot(obj) {
221
+ const parts = [`Screenshot: ${obj.path}`];
222
+ if (obj.width && obj.height)
223
+ parts.push(`(${obj.width}x${obj.height})`);
224
+ return parts.join(' ');
225
+ }
226
+ function formatDisplays(displays) {
227
+ return displays.map(d => `Display ${d.id}${d.is_main ? ' (main)' : ''}: ${d.width}x${d.height} @ ${d.x},${d.y} scale=${d.scale_factor}`).join('\n');
228
+ }
229
+ function formatPermissions(obj) {
230
+ const lines = ['Permissions:'];
231
+ lines.push(` Accessibility: ${obj.accessibility ? 'granted' : 'NOT GRANTED'}`);
232
+ lines.push(` Screen Recording: ${obj.screen_recording ? 'granted' : 'NOT GRANTED'}`);
233
+ return lines.join('\n');
234
+ }
235
+ function capitalize(s) {
236
+ return s.charAt(0).toUpperCase() + s.slice(1);
237
+ }
238
+ function truncate(s, maxLen) {
239
+ if (s.length <= maxLen)
240
+ return s;
241
+ return s.slice(0, maxLen - 3) + '...';
242
+ }
243
+ // Content boundary wrapping
244
+ function wrapBoundary(content) {
245
+ const boundary = `AC_BOUNDARY_${(0, crypto_1.randomBytes)(4).toString('hex')}`;
246
+ return `<<<${boundary}\n${content}\n${boundary}>>>`;
247
+ }
248
+ // Max-output truncation
249
+ function truncateOutput(content, maxChars) {
250
+ if (content.length <= maxChars)
251
+ return content;
252
+ return content.slice(0, maxChars) + `\n... (truncated at ${maxChars} chars)`;
253
+ }
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ // CLI argument parser — verb-first pattern
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.parseArgs = parseArgs;
5
+ exports.parseSelector = parseSelector;
6
+ // Commands that have subcommands
7
+ const SUBCOMMAND_COMMANDS = new Set([
8
+ 'daemon', 'menu', 'menubar', 'clipboard', 'mouse',
9
+ 'record', 'config', 'permissions', 'dock', 'diff',
10
+ 'dialog', 'alert', 'is',
11
+ ]);
12
+ // Commands where the first positional arg looks like a subcommand
13
+ const DIRECTION_COMMANDS = new Set(['scroll']);
14
+ // Flag aliases
15
+ const FLAG_ALIASES = {
16
+ '-i': '--interactive',
17
+ '-c': '--compact',
18
+ '-d': '--depth',
19
+ '-o': '--output',
20
+ '-t': '--threshold',
21
+ };
22
+ // Flags that take a value (next arg)
23
+ const VALUE_FLAGS = new Set([
24
+ '--timeout', '--depth', '--app', '--pid', '--window', '--subtree',
25
+ '--on', '--modifiers', '--count', '--delay', '--repeat',
26
+ '--format', '--quality', '--output', '--threshold',
27
+ '--preset', '--text-match', '--role', '--attr',
28
+ '--max-output', '--duration', '--steps', '--to-coords',
29
+ '--from-coords', '--to-app', '--pixels', '--open',
30
+ ]);
31
+ function parseArgs(argv) {
32
+ // Strip node and script path if present
33
+ const args = argv[0]?.includes('node') || argv[0]?.includes('tsx')
34
+ ? argv.slice(2)
35
+ : argv;
36
+ const result = {
37
+ command: '',
38
+ subcommand: null,
39
+ positional: [],
40
+ flags: {},
41
+ };
42
+ if (args.length === 0) {
43
+ result.command = 'help';
44
+ return result;
45
+ }
46
+ let i = 0;
47
+ // Check for global flags before command
48
+ while (i < args.length && args[i].startsWith('-')) {
49
+ const flag = args[i];
50
+ if (flag === '--version') {
51
+ result.command = 'version';
52
+ return result;
53
+ }
54
+ if (flag === '--help' || flag === '-h') {
55
+ result.command = 'help';
56
+ return result;
57
+ }
58
+ // Global flags
59
+ const resolved = FLAG_ALIASES[flag] || flag;
60
+ const flagName = resolved.replace(/^--/, '');
61
+ if (VALUE_FLAGS.has(resolved) && i + 1 < args.length) {
62
+ result.flags[flagName] = args[i + 1];
63
+ i += 2;
64
+ }
65
+ else {
66
+ result.flags[flagName] = true;
67
+ i += 1;
68
+ }
69
+ }
70
+ // Command
71
+ if (i >= args.length) {
72
+ result.command = 'help';
73
+ return result;
74
+ }
75
+ result.command = args[i];
76
+ i++;
77
+ // Subcommand (for commands that have them)
78
+ if (SUBCOMMAND_COMMANDS.has(result.command) && i < args.length && !args[i].startsWith('-') && !args[i].startsWith('@')) {
79
+ result.subcommand = args[i];
80
+ i++;
81
+ }
82
+ // Direction for scroll
83
+ if (DIRECTION_COMMANDS.has(result.command) && i < args.length && !args[i].startsWith('-') && !args[i].startsWith('@')) {
84
+ result.subcommand = args[i];
85
+ i++;
86
+ }
87
+ // Remaining args
88
+ while (i < args.length) {
89
+ const arg = args[i];
90
+ if (arg.startsWith('-')) {
91
+ const resolved = FLAG_ALIASES[arg] || arg;
92
+ const flagName = resolved.replace(/^--/, '');
93
+ if (VALUE_FLAGS.has(resolved) && i + 1 < args.length) {
94
+ result.flags[flagName] = args[i + 1];
95
+ i += 2;
96
+ }
97
+ else if (resolved === '--interactive' || resolved === '-i') {
98
+ result.flags['interactive'] = true;
99
+ i++;
100
+ }
101
+ else if (resolved === '--compact' || resolved === '-c') {
102
+ result.flags['compact'] = true;
103
+ i++;
104
+ }
105
+ else {
106
+ // Boolean flag
107
+ result.flags[flagName] = true;
108
+ i++;
109
+ }
110
+ }
111
+ else {
112
+ result.positional.push(arg);
113
+ i++;
114
+ }
115
+ }
116
+ return result;
117
+ }
118
+ // Parse a selector: could be a ref (@b1), coordinates (100,200), or a label string
119
+ function parseSelector(sel) {
120
+ if (sel.startsWith('@')) {
121
+ return { type: 'ref', ref: sel };
122
+ }
123
+ const coordMatch = /^(\d+),(\d+)$/.exec(sel);
124
+ if (coordMatch) {
125
+ return { type: 'coords', x: parseInt(coordMatch[1], 10), y: parseInt(coordMatch[2], 10) };
126
+ }
127
+ return { type: 'label', label: sel };
128
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveConfig = resolveConfig;
4
+ exports.getConfigValue = getConfigValue;
5
+ exports.setConfigValue = setConfigValue;
6
+ exports.resetConfig = resetConfig;
7
+ exports.getDefaults = getDefaults;
8
+ const fs_1 = require("fs");
9
+ const path_1 = require("path");
10
+ const os_1 = require("os");
11
+ const DEFAULTS = {
12
+ 'default-timeout': 10000,
13
+ 'screenshot-dir': '/tmp/agent-computer',
14
+ 'screenshot-format': 'png',
15
+ retina: false,
16
+ 'content-boundary': false,
17
+ 'daemon-idle-timeout': 300000,
18
+ };
19
+ const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), '.config', 'agent-computer');
20
+ const CONFIG_FILE = (0, path_1.join)(CONFIG_DIR, 'config.json');
21
+ // Environment variable overrides
22
+ const ENV_MAP = {
23
+ AC_TIMEOUT: 'default-timeout',
24
+ AC_SCREENSHOT_DIR: 'screenshot-dir',
25
+ };
26
+ function loadConfigFile() {
27
+ try {
28
+ const raw = (0, fs_1.readFileSync)(CONFIG_FILE, 'utf-8');
29
+ return JSON.parse(raw);
30
+ }
31
+ catch {
32
+ return {};
33
+ }
34
+ }
35
+ function loadEnvOverrides() {
36
+ const overrides = {};
37
+ for (const [envVar, configKey] of Object.entries(ENV_MAP)) {
38
+ const val = process.env[envVar];
39
+ if (val !== undefined) {
40
+ if (configKey) {
41
+ if (configKey === 'default-timeout' || configKey === 'daemon-idle-timeout') {
42
+ overrides[configKey] = parseInt(val, 10);
43
+ }
44
+ else {
45
+ overrides[configKey] = val;
46
+ }
47
+ }
48
+ }
49
+ }
50
+ // Boolean env vars
51
+ if (process.env.AC_JSON === '1') {
52
+ // This is handled at the CLI level, not config
53
+ }
54
+ if (process.env.AC_VERBOSE === '1') {
55
+ // This is handled at the CLI level, not config
56
+ }
57
+ return overrides;
58
+ }
59
+ function resolveConfig() {
60
+ const fileConfig = loadConfigFile();
61
+ const envConfig = loadEnvOverrides();
62
+ return { ...DEFAULTS, ...fileConfig, ...envConfig };
63
+ }
64
+ function getConfigValue(key) {
65
+ return resolveConfig()[key];
66
+ }
67
+ function setConfigValue(key, value) {
68
+ const existing = loadConfigFile();
69
+ existing[key] = value;
70
+ (0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
71
+ (0, fs_1.writeFileSync)(CONFIG_FILE, JSON.stringify(existing, null, 2) + '\n');
72
+ }
73
+ function resetConfig() {
74
+ (0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
75
+ (0, fs_1.writeFileSync)(CONFIG_FILE, JSON.stringify({}, null, 2) + '\n');
76
+ }
77
+ function getDefaults() {
78
+ return { ...DEFAULTS };
79
+ }