@hasna/computer 0.1.1 → 0.1.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.
@@ -1,5 +1,11 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
+ var __require = import.meta.require;
4
+
5
+ // src/server/index.ts
6
+ import { join as join6, dirname as dirname2 } from "path";
7
+ import { fileURLToPath as fileURLToPath2 } from "url";
8
+ import { existsSync as existsSync4 } from "fs";
3
9
 
4
10
  // src/agent/loop.ts
5
11
  import { randomUUID } from "crypto";
@@ -9,10 +15,15 @@ import { mkdir } from "fs/promises";
9
15
  import { tmpdir } from "os";
10
16
  import { join } from "path";
11
17
  import { readFile, unlink } from "fs/promises";
12
- async function captureScreenshot() {
18
+ async function captureScreenshot(displayNumber) {
13
19
  const timestamp = Date.now();
14
20
  const tmpPath = join(tmpdir(), `computer-screenshot-${timestamp}.png`);
15
- const proc = Bun.spawn(["screencapture", "-x", "-C", "-t", "png", tmpPath], {
21
+ const args = ["screencapture", "-x", "-C", "-t", "png"];
22
+ if (displayNumber) {
23
+ args.push(`-D${displayNumber}`);
24
+ }
25
+ args.push(tmpPath);
26
+ const proc = Bun.spawn(args, {
16
27
  stdout: "pipe",
17
28
  stderr: "pipe"
18
29
  });
@@ -235,19 +246,23 @@ function getScrollHelperPath() {
235
246
 
236
247
  // src/drivers/mac/index.ts
237
248
  class MacDriver {
249
+ displayNumber;
250
+ constructor(opts) {
251
+ this.displayNumber = opts?.displayNumber;
252
+ }
238
253
  async getScreenSize() {
239
254
  return getScreenSize();
240
255
  }
241
256
  async screenshot() {
242
- return captureScreenshot();
257
+ return captureScreenshot(this.displayNumber);
243
258
  }
244
259
  async execute(action) {
245
260
  return executeAction(action);
246
261
  }
247
262
  async dispose() {}
248
263
  }
249
- function createMacDriver() {
250
- return new MacDriver;
264
+ function createMacDriver(opts) {
265
+ return new MacDriver(opts);
251
266
  }
252
267
 
253
268
  // node_modules/@anthropic-ai/sdk/version.mjs
@@ -9537,7 +9552,7 @@ var __export = (target, all) => {
9537
9552
  set: __exportSetter.bind(all, name)
9538
9553
  });
9539
9554
  };
9540
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
9555
+ var __require2 = /* @__PURE__ */ createRequire(import.meta.url);
9541
9556
  var require_postgres_array = __commonJS((exports) => {
9542
9557
  exports.parse = function(source, transform) {
9543
9558
  return new ArrayParser(source, transform).parse();
@@ -10477,7 +10492,7 @@ var require_defaults = __commonJS((exports, module) => {
10477
10492
  });
10478
10493
  var require_utils = __commonJS((exports, module) => {
10479
10494
  var defaults2 = require_defaults();
10480
- var util = __require("util");
10495
+ var util = __require2("util");
10481
10496
  var { isDate } = util.types || util;
10482
10497
  function escapeElement(elementRepresentation) {
10483
10498
  const escaped = elementRepresentation.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
@@ -10633,7 +10648,7 @@ var require_utils = __commonJS((exports, module) => {
10633
10648
  };
10634
10649
  });
10635
10650
  var require_utils_legacy = __commonJS((exports, module) => {
10636
- var nodeCrypto = __require("crypto");
10651
+ var nodeCrypto = __require2("crypto");
10637
10652
  function md5(string) {
10638
10653
  return nodeCrypto.createHash("md5").update(string, "utf-8").digest("hex");
10639
10654
  }
@@ -10666,7 +10681,7 @@ var require_utils_legacy = __commonJS((exports, module) => {
10666
10681
  };
10667
10682
  });
10668
10683
  var require_utils_webcrypto = __commonJS((exports, module) => {
10669
- var nodeCrypto = __require("crypto");
10684
+ var nodeCrypto = __require2("crypto");
10670
10685
  module.exports = {
10671
10686
  postgresMd5PasswordHash,
10672
10687
  randomBytes,
@@ -11076,7 +11091,7 @@ var require_pg_connection_string = __commonJS((exports, module) => {
11076
11091
  if (config.sslcert || config.sslkey || config.sslrootcert || config.sslmode) {
11077
11092
  config.ssl = {};
11078
11093
  }
11079
- const fs = config.sslcert || config.sslkey || config.sslrootcert ? __require("fs") : null;
11094
+ const fs = config.sslcert || config.sslkey || config.sslrootcert ? __require2("fs") : null;
11080
11095
  if (config.sslcert) {
11081
11096
  config.ssl.cert = fs.readFileSync(config.sslcert).toString();
11082
11097
  }
@@ -11199,7 +11214,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
11199
11214
  parse.parseIntoClientConfig = parseIntoClientConfig;
11200
11215
  });
11201
11216
  var require_connection_parameters = __commonJS((exports, module) => {
11202
- var dns = __require("dns");
11217
+ var dns = __require2("dns");
11203
11218
  var defaults2 = require_defaults();
11204
11219
  var parse = require_pg_connection_string().parse;
11205
11220
  var val = function(key, config, envVar) {
@@ -11422,7 +11437,7 @@ var require_result = __commonJS((exports, module) => {
11422
11437
  module.exports = Result;
11423
11438
  });
11424
11439
  var require_query = __commonJS((exports, module) => {
11425
- var { EventEmitter } = __require("events");
11440
+ var { EventEmitter } = __require2("events");
11426
11441
  var Result = require_result();
11427
11442
  var utils = require_utils();
11428
11443
 
@@ -12405,11 +12420,11 @@ var require_stream = __commonJS((exports, module) => {
12405
12420
  };
12406
12421
  function getNodejsStreamFuncs() {
12407
12422
  function getStream2(ssl) {
12408
- const net = __require("net");
12423
+ const net = __require2("net");
12409
12424
  return new net.Socket;
12410
12425
  }
12411
12426
  function getSecureStream2(options) {
12412
- const tls = __require("tls");
12427
+ const tls = __require2("tls");
12413
12428
  return tls.connect(options);
12414
12429
  }
12415
12430
  return {
@@ -12451,7 +12466,7 @@ var require_stream = __commonJS((exports, module) => {
12451
12466
  }
12452
12467
  });
12453
12468
  var require_connection = __commonJS((exports, module) => {
12454
- var EventEmitter = __require("events").EventEmitter;
12469
+ var EventEmitter = __require2("events").EventEmitter;
12455
12470
  var { parse, serialize } = require_dist();
12456
12471
  var { getStream, getSecureStream } = require_stream();
12457
12472
  var flushBuffer = serialize.flush();
@@ -12524,7 +12539,7 @@ var require_connection = __commonJS((exports, module) => {
12524
12539
  options.key = self.ssl.key;
12525
12540
  }
12526
12541
  }
12527
- const net = __require("net");
12542
+ const net = __require2("net");
12528
12543
  if (net.isIP && net.isIP(host) === 0) {
12529
12544
  options.servername = host;
12530
12545
  }
@@ -12627,8 +12642,8 @@ var require_connection = __commonJS((exports, module) => {
12627
12642
  module.exports = Connection;
12628
12643
  });
12629
12644
  var require_split2 = __commonJS((exports, module) => {
12630
- var { Transform } = __require("stream");
12631
- var { StringDecoder } = __require("string_decoder");
12645
+ var { Transform } = __require2("stream");
12646
+ var { StringDecoder } = __require2("string_decoder");
12632
12647
  var kLast = Symbol("last");
12633
12648
  var kDecoder = Symbol("decoder");
12634
12649
  function transform(chunk, enc, cb) {
@@ -12724,10 +12739,10 @@ var require_split2 = __commonJS((exports, module) => {
12724
12739
  module.exports = split;
12725
12740
  });
12726
12741
  var require_helper = __commonJS((exports, module) => {
12727
- var path = __require("path");
12728
- var Stream3 = __require("stream").Stream;
12742
+ var path = __require2("path");
12743
+ var Stream3 = __require2("stream").Stream;
12729
12744
  var split = require_split2();
12730
- var util = __require("util");
12745
+ var util = __require2("util");
12731
12746
  var defaultPort = 5432;
12732
12747
  var isWin = process.platform === "win32";
12733
12748
  var warnStream = process.stderr;
@@ -12886,8 +12901,8 @@ var require_helper = __commonJS((exports, module) => {
12886
12901
  };
12887
12902
  });
12888
12903
  var require_lib = __commonJS((exports, module) => {
12889
- var path = __require("path");
12890
- var fs = __require("fs");
12904
+ var path = __require2("path");
12905
+ var fs = __require2("fs");
12891
12906
  var helper = require_helper();
12892
12907
  module.exports = function(connInfo, cb) {
12893
12908
  var file = helper.getFileName();
@@ -12902,9 +12917,9 @@ var require_lib = __commonJS((exports, module) => {
12902
12917
  module.exports.warnTo = helper.warnTo;
12903
12918
  });
12904
12919
  var require_client = __commonJS((exports, module) => {
12905
- var EventEmitter = __require("events").EventEmitter;
12920
+ var EventEmitter = __require2("events").EventEmitter;
12906
12921
  var utils = require_utils();
12907
- var nodeUtils = __require("util");
12922
+ var nodeUtils = __require2("util");
12908
12923
  var sasl = require_sasl();
12909
12924
  var TypeOverrides = require_type_overrides();
12910
12925
  var ConnectionParameters = require_connection_parameters();
@@ -13481,7 +13496,7 @@ var require_client = __commonJS((exports, module) => {
13481
13496
  module.exports = Client;
13482
13497
  });
13483
13498
  var require_pg_pool = __commonJS((exports, module) => {
13484
- var EventEmitter = __require("events").EventEmitter;
13499
+ var EventEmitter = __require2("events").EventEmitter;
13485
13500
  var NOOP = function() {};
13486
13501
  var removeWhere = (list, predicate) => {
13487
13502
  const i = list.findIndex(predicate);
@@ -13891,8 +13906,8 @@ var require_pg_pool = __commonJS((exports, module) => {
13891
13906
  module.exports = Pool;
13892
13907
  });
13893
13908
  var require_query2 = __commonJS((exports, module) => {
13894
- var EventEmitter = __require("events").EventEmitter;
13895
- var util = __require("util");
13909
+ var EventEmitter = __require2("events").EventEmitter;
13910
+ var util = __require2("util");
13896
13911
  var utils = require_utils();
13897
13912
  var NativeQuery = module.exports = function(config, values, callback) {
13898
13913
  EventEmitter.call(this);
@@ -14025,7 +14040,7 @@ var require_query2 = __commonJS((exports, module) => {
14025
14040
  };
14026
14041
  });
14027
14042
  var require_client2 = __commonJS((exports, module) => {
14028
- var nodeUtils = __require("util");
14043
+ var nodeUtils = __require2("util");
14029
14044
  var Native;
14030
14045
  try {
14031
14046
  Native = (() => {
@@ -14035,8 +14050,8 @@ var require_client2 = __commonJS((exports, module) => {
14035
14050
  throw e;
14036
14051
  }
14037
14052
  var TypeOverrides = require_type_overrides();
14038
- var EventEmitter = __require("events").EventEmitter;
14039
- var util = __require("util");
14053
+ var EventEmitter = __require2("events").EventEmitter;
14054
+ var util = __require2("util");
14040
14055
  var ConnectionParameters = require_connection_parameters();
14041
14056
  var NativeQuery = require_query2();
14042
14057
  var queryQueueLengthDeprecationNotice = nodeUtils.deprecate(() => {}, "Calling client.query() when the client is already executing a query is deprecated and will be removed in pg@9.0. Use async/await or an external async flow control mechanism instead.");
@@ -18530,6 +18545,7 @@ function getDb() {
18530
18545
  total_tokens_in INTEGER NOT NULL DEFAULT 0,
18531
18546
  total_tokens_out INTEGER NOT NULL DEFAULT 0,
18532
18547
  total_duration_ms INTEGER NOT NULL DEFAULT 0,
18548
+ tags TEXT,
18533
18549
  error TEXT,
18534
18550
  created_at TEXT NOT NULL,
18535
18551
  completed_at TEXT
@@ -18585,9 +18601,9 @@ function getDb() {
18585
18601
  async function createSession(session) {
18586
18602
  const d = getDb();
18587
18603
  d.prepare(`
18588
- INSERT INTO sessions (id, task, provider, model, status, steps, total_tokens_in, total_tokens_out, total_duration_ms, error, created_at, completed_at)
18589
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
18590
- `).run(session.id, session.task, session.provider, session.model, session.status, session.steps, session.total_tokens_in, session.total_tokens_out, session.total_duration_ms, session.error ?? null, session.created_at, session.completed_at ?? null);
18604
+ INSERT INTO sessions (id, task, provider, model, status, steps, total_tokens_in, total_tokens_out, total_duration_ms, tags, error, created_at, completed_at)
18605
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
18606
+ `).run(session.id, session.task, session.provider, session.model, session.status, session.steps, session.total_tokens_in, session.total_tokens_out, session.total_duration_ms, session.tags?.length ? JSON.stringify(session.tags) : null, session.error ?? null, session.created_at, session.completed_at ?? null);
18591
18607
  }
18592
18608
  async function updateSession(session) {
18593
18609
  const d = getDb();
@@ -18615,10 +18631,18 @@ function listSessions(opts) {
18615
18631
  const d = getDb();
18616
18632
  let sql = "SELECT * FROM sessions";
18617
18633
  const params = [];
18634
+ const conditions = [];
18618
18635
  if (opts?.status) {
18619
- sql += " WHERE status = ?";
18636
+ conditions.push("status = ?");
18620
18637
  params.push(opts.status);
18621
18638
  }
18639
+ if (opts?.tag) {
18640
+ conditions.push("tags LIKE ?");
18641
+ params.push(`%"${opts.tag}"%`);
18642
+ }
18643
+ if (conditions.length > 0) {
18644
+ sql += " WHERE " + conditions.join(" AND ");
18645
+ }
18622
18646
  sql += " ORDER BY created_at DESC";
18623
18647
  if (opts?.limit) {
18624
18648
  sql += " LIMIT ?";
@@ -18684,12 +18708,104 @@ function rowToSession(row) {
18684
18708
  total_tokens_in: row.total_tokens_in,
18685
18709
  total_tokens_out: row.total_tokens_out,
18686
18710
  total_duration_ms: row.total_duration_ms,
18711
+ tags: row.tags ? JSON.parse(row.tags) : undefined,
18687
18712
  error: row.error,
18688
18713
  created_at: row.created_at,
18689
18714
  completed_at: row.completed_at
18690
18715
  };
18691
18716
  }
18692
18717
 
18718
+ // src/lib/integrations.ts
18719
+ async function saveToRecordings(session, logs) {
18720
+ try {
18721
+ const { saveRecording } = await import("@hasna/recordings");
18722
+ await saveRecording({
18723
+ title: `Computer Use: ${session.task.slice(0, 100)}`,
18724
+ type: "computer-use",
18725
+ source: "computer",
18726
+ duration_ms: session.total_duration_ms,
18727
+ metadata: {
18728
+ session_id: session.id,
18729
+ provider: session.provider,
18730
+ model: session.model,
18731
+ steps: session.steps,
18732
+ tokens_in: session.total_tokens_in,
18733
+ tokens_out: session.total_tokens_out,
18734
+ status: session.status,
18735
+ tags: session.tags
18736
+ },
18737
+ transcript: logs.map((l) => ({
18738
+ step: l.step,
18739
+ action: l.action.type,
18740
+ reasoning: l.reasoning?.slice(0, 200),
18741
+ success: l.success,
18742
+ timestamp: l.created_at
18743
+ }))
18744
+ });
18745
+ return true;
18746
+ } catch {
18747
+ return false;
18748
+ }
18749
+ }
18750
+ async function registerWithSessions(session) {
18751
+ try {
18752
+ const mod = await import("@hasna/sessions");
18753
+ const registerSession = mod.registerSession ?? mod.createSession ?? mod.saveSession;
18754
+ if (typeof registerSession !== "function")
18755
+ return false;
18756
+ await registerSession({
18757
+ id: session.id,
18758
+ type: "computer-use",
18759
+ source: "computer",
18760
+ status: session.status,
18761
+ metadata: {
18762
+ task: session.task,
18763
+ provider: session.provider,
18764
+ model: session.model,
18765
+ steps: session.steps
18766
+ },
18767
+ started_at: session.created_at,
18768
+ ended_at: session.completed_at
18769
+ });
18770
+ return true;
18771
+ } catch {
18772
+ return false;
18773
+ }
18774
+ }
18775
+ async function pushToLogs(session, logs) {
18776
+ try {
18777
+ const mod = await import("@hasna/logs");
18778
+ const pushBatch = mod.logPushBatch ?? mod.pushBatch;
18779
+ if (typeof pushBatch !== "function")
18780
+ return false;
18781
+ await pushBatch(logs.map((l) => ({
18782
+ level: l.success ? "info" : "error",
18783
+ source: "computer",
18784
+ message: `[${l.action.type}] ${l.reasoning?.slice(0, 100) ?? ""}`,
18785
+ metadata: {
18786
+ session_id: session.id,
18787
+ step: l.step,
18788
+ action_type: l.action.type,
18789
+ success: l.success,
18790
+ error: l.error,
18791
+ duration_ms: l.duration_ms
18792
+ },
18793
+ timestamp: l.created_at
18794
+ })));
18795
+ return true;
18796
+ } catch {
18797
+ return false;
18798
+ }
18799
+ }
18800
+ async function runPostSessionIntegrations(session, logs) {
18801
+ const [recordings, sessions, logsPushed] = await Promise.all([
18802
+ saveToRecordings(session, logs),
18803
+ registerWithSessions(session),
18804
+ pushToLogs(session, logs)
18805
+ ]);
18806
+ return { recordings, sessions, logs: logsPushed };
18807
+ }
18808
+
18693
18809
  // src/agent/loop.ts
18694
18810
  var DEFAULT_MAX_STEPS = 50;
18695
18811
  async function runTask(options) {
@@ -18703,10 +18819,12 @@ async function runTask(options) {
18703
18819
  systemPrompt,
18704
18820
  screenshotMaxWidth,
18705
18821
  dryRun = false,
18822
+ tags,
18823
+ displayNumber,
18706
18824
  onStep,
18707
18825
  onDone
18708
18826
  } = options;
18709
- const driver = createMacDriver();
18827
+ const driver = createMacDriver({ displayNumber });
18710
18828
  const provider = createProvider(providerName, { model });
18711
18829
  const config = loadConfig();
18712
18830
  const safetyConfig = config.safety;
@@ -18717,6 +18835,7 @@ async function runTask(options) {
18717
18835
  provider: providerName,
18718
18836
  model: model ?? (providerName === "anthropic" ? "claude-sonnet-4-5-20250514" : "computer-use-preview"),
18719
18837
  status: "running",
18838
+ tags,
18720
18839
  steps: 0,
18721
18840
  total_tokens_in: 0,
18722
18841
  total_tokens_out: 0,
@@ -18769,6 +18888,8 @@ async function runTask(options) {
18769
18888
  });
18770
18889
  await updateSession(session);
18771
18890
  onStep?.(step, response, { success: true, duration_ms: 0 });
18891
+ const logs = getActionLogs(sessionId);
18892
+ await runPostSessionIntegrations(session, logs).catch(() => {});
18772
18893
  onDone?.(session);
18773
18894
  await driver.dispose();
18774
18895
  return session;
@@ -18834,6 +18955,8 @@ async function runTask(options) {
18834
18955
  session.completed_at = new Date().toISOString();
18835
18956
  session.error = `Reached max steps (${maxSteps})`;
18836
18957
  await updateSession(session);
18958
+ const endLogs = getActionLogs(sessionId);
18959
+ await runPostSessionIntegrations(session, endLogs).catch(() => {});
18837
18960
  onDone?.(session);
18838
18961
  await driver.dispose();
18839
18962
  return session;
@@ -18843,6 +18966,8 @@ async function runTask(options) {
18843
18966
  session.total_duration_ms = Date.now() - startTime;
18844
18967
  session.completed_at = new Date().toISOString();
18845
18968
  await updateSession(session);
18969
+ const errLogs = getActionLogs(sessionId);
18970
+ await runPostSessionIntegrations(session, errLogs).catch(() => {});
18846
18971
  onDone?.(session);
18847
18972
  await driver.dispose();
18848
18973
  return session;
@@ -18872,6 +18997,12 @@ function remapCoordinates(action, from, to) {
18872
18997
 
18873
18998
  // src/server/index.ts
18874
18999
  var PORT = parseInt(process.env.COMPUTER_PORT ?? "19450");
19000
+ var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
19001
+ var DASHBOARD_DIRS = [
19002
+ join6(__dirname2, "..", "..", "dashboard", "dist"),
19003
+ join6(__dirname2, "..", "dashboard", "dist")
19004
+ ];
19005
+ var DASHBOARD_DIR = DASHBOARD_DIRS.find((d) => existsSync4(d));
18875
19006
  var server = Bun.serve({
18876
19007
  port: PORT,
18877
19008
  async fetch(req) {
@@ -18939,6 +19070,21 @@ var server = Bun.serve({
18939
19070
  if (method === "GET" && (path === "/health" || path === "/")) {
18940
19071
  return Response.json({ status: "ok", name: "computer", version: "0.1.0", port: PORT }, { headers: corsHeaders });
18941
19072
  }
19073
+ if (DASHBOARD_DIR && method === "GET" && (path.startsWith("/dashboard") || path === "/")) {
19074
+ if (path === "/" || path === "/dashboard" || path === "/dashboard/") {
19075
+ return new Response(Bun.file(join6(DASHBOARD_DIR, "index.html")), {
19076
+ headers: { "Content-Type": "text/html", "Access-Control-Allow-Origin": "*" }
19077
+ });
19078
+ }
19079
+ const filePath = path.replace("/dashboard", "");
19080
+ const fullPath = join6(DASHBOARD_DIR, filePath);
19081
+ if (existsSync4(fullPath)) {
19082
+ return new Response(Bun.file(fullPath), { headers: { "Access-Control-Allow-Origin": "*" } });
19083
+ }
19084
+ return new Response(Bun.file(join6(DASHBOARD_DIR, "index.html")), {
19085
+ headers: { "Content-Type": "text/html", "Access-Control-Allow-Origin": "*" }
19086
+ });
19087
+ }
18942
19088
  return Response.json({ error: "Not found" }, { status: 404, headers: corsHeaders });
18943
19089
  } catch (err) {
18944
19090
  const message = err instanceof Error ? err.message : String(err);
@@ -128,6 +128,7 @@ export interface Session {
128
128
  total_tokens_in: number;
129
129
  total_tokens_out: number;
130
130
  total_duration_ms: number;
131
+ tags?: string[];
131
132
  error?: string;
132
133
  created_at: string;
133
134
  completed_at?: string;
@@ -152,6 +153,10 @@ export interface RunOptions {
152
153
  screenshotMaxWidth?: number;
153
154
  /** Dry-run mode — model plans actions but they are not executed */
154
155
  dryRun?: boolean;
156
+ /** Tags for this session */
157
+ tags?: string[];
158
+ /** Display number to capture (1=main, 2=secondary, etc.) */
159
+ displayNumber?: number;
155
160
  /** Callback for each step */
156
161
  onStep?: (step: number, response: ModelResponse, result: ActionResult) => void;
157
162
  /** Callback when done */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
Binary file
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env swift
2
+ // accessibility.swift — Query macOS Accessibility tree (AXUIElement)
3
+ // Usage: accessibility [--app <name>] [--focused] [--depth <n>]
4
+ // Output: JSON array of UI elements with role, title, position, size
5
+ //
6
+ // Requires: Accessibility permissions in System Settings
7
+
8
+ import AppKit
9
+ import Foundation
10
+
11
+ struct UIElement: Codable {
12
+ let role: String?
13
+ let title: String?
14
+ let value: String?
15
+ let label: String?
16
+ let x: Int
17
+ let y: Int
18
+ let width: Int
19
+ let height: Int
20
+ let enabled: Bool
21
+ let focused: Bool
22
+ let children: Int
23
+ }
24
+
25
+ func getAXValue<T>(_ element: AXUIElement, _ attribute: String) -> T? {
26
+ var value: AnyObject?
27
+ let result = AXUIElementCopyAttributeValue(element, attribute as CFString, &value)
28
+ guard result == .success else { return nil }
29
+ return value as? T
30
+ }
31
+
32
+ func getPosition(_ element: AXUIElement) -> CGPoint? {
33
+ var value: AnyObject?
34
+ let result = AXUIElementCopyAttributeValue(element, kAXPositionAttribute as String as CFString, &value)
35
+ guard result == .success, let val = value else { return nil }
36
+ var point = CGPoint.zero
37
+ AXValueGetValue(val as! AXValue, .cgPoint, &point)
38
+ return point
39
+ }
40
+
41
+ func getSize(_ element: AXUIElement) -> CGSize? {
42
+ var value: AnyObject?
43
+ let result = AXUIElementCopyAttributeValue(element, kAXSizeAttribute as String as CFString, &value)
44
+ guard result == .success, let val = value else { return nil }
45
+ var size = CGSize.zero
46
+ AXValueGetValue(val as! AXValue, .cgSize, &size)
47
+ return size
48
+ }
49
+
50
+ func getChildren(_ element: AXUIElement) -> [AXUIElement] {
51
+ var value: AnyObject?
52
+ let result = AXUIElementCopyAttributeValue(element, kAXChildrenAttribute as String as CFString, &value)
53
+ guard result == .success, let children = value as? [AXUIElement] else { return [] }
54
+ return children
55
+ }
56
+
57
+ func elementToStruct(_ element: AXUIElement) -> UIElement {
58
+ let role: String? = getAXValue(element, kAXRoleAttribute as String)
59
+ let title: String? = getAXValue(element, kAXTitleAttribute as String)
60
+ let value: String? = getAXValue(element, kAXValueAttribute as String)
61
+ let label: String? = getAXValue(element, kAXDescriptionAttribute as String)
62
+ let enabled: Bool = getAXValue(element, kAXEnabledAttribute as String) ?? true
63
+ let focused: Bool = getAXValue(element, kAXFocusedAttribute as String) ?? false
64
+
65
+ let pos = getPosition(element) ?? CGPoint.zero
66
+ let sz = getSize(element) ?? CGSize.zero
67
+ let children = getChildren(element)
68
+
69
+ return UIElement(
70
+ role: role,
71
+ title: title,
72
+ value: (value?.count ?? 0) > 200 ? String(value!.prefix(200)) + "..." : value,
73
+ label: label,
74
+ x: Int(pos.x),
75
+ y: Int(pos.y),
76
+ width: Int(sz.width),
77
+ height: Int(sz.height),
78
+ enabled: enabled,
79
+ focused: focused,
80
+ children: children.count
81
+ )
82
+ }
83
+
84
+ func walkTree(_ element: AXUIElement, depth: Int, maxDepth: Int) -> [UIElement] {
85
+ var results: [UIElement] = []
86
+ let el = elementToStruct(element)
87
+
88
+ // Skip tiny/invisible elements
89
+ if el.width > 5 && el.height > 5 {
90
+ results.append(el)
91
+ }
92
+
93
+ if depth < maxDepth {
94
+ for child in getChildren(element) {
95
+ results.append(contentsOf: walkTree(child, depth: depth + 1, maxDepth: maxDepth))
96
+ }
97
+ }
98
+
99
+ return results
100
+ }
101
+
102
+ // Parse arguments
103
+ var appName: String? = nil
104
+ var focusedOnly = false
105
+ var maxDepth = 3
106
+
107
+ var args = Array(CommandLine.arguments.dropFirst())
108
+ while !args.isEmpty {
109
+ let arg = args.removeFirst()
110
+ switch arg {
111
+ case "--app":
112
+ if !args.isEmpty { appName = args.removeFirst() }
113
+ case "--focused":
114
+ focusedOnly = true
115
+ case "--depth":
116
+ if !args.isEmpty { maxDepth = Int(args.removeFirst()) ?? 3 }
117
+ default:
118
+ break
119
+ }
120
+ }
121
+
122
+ // Get target application
123
+ var targetApp: NSRunningApplication?
124
+ if let name = appName {
125
+ targetApp = NSWorkspace.shared.runningApplications.first {
126
+ $0.localizedName?.lowercased() == name.lowercased()
127
+ }
128
+ if targetApp == nil {
129
+ fputs("Error: Application '\(name)' not found\n", stderr)
130
+ exit(1)
131
+ }
132
+ } else {
133
+ targetApp = NSWorkspace.shared.frontmostApplication
134
+ }
135
+
136
+ guard let app = targetApp, let pid = Optional(app.processIdentifier) else {
137
+ fputs("Error: No application found\n", stderr)
138
+ exit(1)
139
+ }
140
+
141
+ let appElement = AXUIElementCreateApplication(pid)
142
+
143
+ var elements: [UIElement]
144
+ if focusedOnly {
145
+ var focusedElement: AnyObject?
146
+ AXUIElementCopyAttributeValue(appElement, kAXFocusedUIElementAttribute as CFString, &focusedElement)
147
+ if let focused = focusedElement {
148
+ elements = walkTree(focused as! AXUIElement, depth: 0, maxDepth: maxDepth)
149
+ } else {
150
+ elements = []
151
+ }
152
+ } else {
153
+ elements = walkTree(appElement, depth: 0, maxDepth: maxDepth)
154
+ }
155
+
156
+ // Output as JSON
157
+ let encoder = JSONEncoder()
158
+ encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
159
+ if let data = try? encoder.encode(elements) {
160
+ print(String(data: data, encoding: .utf8)!)
161
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/computer",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Open-source computer use for AI agents — control your Mac with Anthropic or OpenAI. CLI + MCP server + REST API + Dashboard.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,6 +20,8 @@
20
20
  "dist",
21
21
  "helpers/scroll",
22
22
  "helpers/scroll.swift",
23
+ "helpers/accessibility",
24
+ "helpers/accessibility.swift",
23
25
  "src/db/migrations",
24
26
  "dashboard/dist",
25
27
  "LICENSE",