gclm-code 1.0.0 → 1.0.1

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 (43) hide show
  1. package/README.md +1 -1
  2. package/bin/gc.js +53 -25
  3. package/bin/install-runtime.js +253 -0
  4. package/package.json +10 -5
  5. package/vendor/manifest.json +92 -0
  6. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/package.json +9 -0
  7. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/bridgeClient.ts +1126 -0
  8. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/browserTools.ts +546 -0
  9. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/index.ts +15 -0
  10. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/mcpServer.ts +96 -0
  11. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/mcpSocketClient.ts +493 -0
  12. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/mcpSocketPool.ts +327 -0
  13. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/toolCalls.ts +301 -0
  14. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/types.ts +134 -0
  15. package/vendor/modules/node_modules/@ant/computer-use-input/package.json +9 -0
  16. package/vendor/modules/node_modules/@ant/computer-use-input/src/driver-jxa.js +341 -0
  17. package/vendor/modules/node_modules/@ant/computer-use-input/src/driver-swift.swift +417 -0
  18. package/vendor/modules/node_modules/@ant/computer-use-input/src/implementation.js +204 -0
  19. package/vendor/modules/node_modules/@ant/computer-use-input/src/index.js +5 -0
  20. package/vendor/modules/node_modules/@ant/computer-use-mcp/package.json +11 -0
  21. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/deniedApps.ts +553 -0
  22. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/imageResize.ts +108 -0
  23. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/index.ts +69 -0
  24. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/keyBlocklist.ts +153 -0
  25. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/mcpServer.ts +313 -0
  26. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/pixelCompare.ts +171 -0
  27. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/sentinelApps.ts +43 -0
  28. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/subGates.ts +19 -0
  29. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/toolCalls.ts +3872 -0
  30. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/tools.ts +706 -0
  31. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/types.ts +635 -0
  32. package/vendor/modules/node_modules/@ant/computer-use-swift/package.json +9 -0
  33. package/vendor/modules/node_modules/@ant/computer-use-swift/src/driver-jxa.js +108 -0
  34. package/vendor/modules/node_modules/@ant/computer-use-swift/src/implementation.js +706 -0
  35. package/vendor/modules/node_modules/@ant/computer-use-swift/src/index.js +7 -0
  36. package/vendor/modules/node_modules/audio-capture-napi/package.json +8 -0
  37. package/vendor/modules/node_modules/audio-capture-napi/src/index.ts +226 -0
  38. package/vendor/modules/node_modules/image-processor-napi/package.json +11 -0
  39. package/vendor/modules/node_modules/image-processor-napi/src/index.ts +396 -0
  40. package/vendor/modules/node_modules/modifiers-napi/package.json +8 -0
  41. package/vendor/modules/node_modules/modifiers-napi/src/index.ts +79 -0
  42. package/vendor/modules/node_modules/url-handler-napi/package.json +8 -0
  43. package/vendor/modules/node_modules/url-handler-napi/src/index.ts +62 -0
@@ -0,0 +1,706 @@
1
+ import { spawnSync } from 'node:child_process'
2
+ import { existsSync, mkdtempSync, readFileSync, readdirSync, rmSync } from 'node:fs'
3
+ import { createRequire } from 'node:module'
4
+ import { homedir, tmpdir } from 'node:os'
5
+ import { dirname, join } from 'node:path'
6
+ import { fileURLToPath } from 'node:url'
7
+
8
+ const require = createRequire(import.meta.url)
9
+ const __dirname = dirname(fileURLToPath(import.meta.url))
10
+ const DRIVER_PATH = join(__dirname, 'driver-jxa.js')
11
+ const FINDER_BUNDLE_ID = 'com.apple.finder'
12
+ const APP_SCAN_ROOTS = [
13
+ '/Applications',
14
+ '/System/Applications',
15
+ join(homedir(), 'Applications'),
16
+ ]
17
+ const APP_SCAN_MAX_DEPTH = 3
18
+ const PNG_SIGNATURE = Buffer.from([
19
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
20
+ ])
21
+
22
+ let cachedSharp = null
23
+
24
+ function sharpFactory() {
25
+ if (cachedSharp) {
26
+ return cachedSharp
27
+ }
28
+ const imported = require('sharp')
29
+ cachedSharp = typeof imported === 'function' ? imported : imported.default
30
+ return cachedSharp
31
+ }
32
+
33
+ function run(command, args, options = {}) {
34
+ const result = spawnSync(command, args, {
35
+ encoding: options.encoding ?? 'utf8',
36
+ stdio: 'pipe',
37
+ ...options,
38
+ })
39
+
40
+ if (result.error) {
41
+ throw result.error
42
+ }
43
+ if (result.status !== 0) {
44
+ throw new Error((result.stderr || result.stdout || `${command} failed`).trim())
45
+ }
46
+ return result
47
+ }
48
+
49
+ function runDriver(payload) {
50
+ const result = run('/usr/bin/osascript', [
51
+ '-l',
52
+ 'JavaScript',
53
+ DRIVER_PATH,
54
+ JSON.stringify(payload),
55
+ ])
56
+ const output = (result.stdout ?? '').trim()
57
+ if (!output) {
58
+ return null
59
+ }
60
+ return JSON.parse(output)
61
+ }
62
+
63
+ function readPngDimensions(buffer) {
64
+ if (buffer.length < 24) return null
65
+ if (!buffer.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE)) return null
66
+ if (buffer.toString('ascii', 12, 16) !== 'IHDR') return null
67
+ return {
68
+ width: buffer.readUInt32BE(16),
69
+ height: buffer.readUInt32BE(20),
70
+ }
71
+ }
72
+
73
+ function displayList() {
74
+ return runDriver({ op: 'listDisplays' }) ?? []
75
+ }
76
+
77
+ function displayFor(displayId) {
78
+ const displays = displayList()
79
+ if (displays.length === 0) {
80
+ throw new Error('No displays were reported by the host.')
81
+ }
82
+
83
+ const display =
84
+ displayId == null
85
+ ? displays[0]
86
+ : displays.find(item => item.displayId === displayId) ?? displays[0]
87
+
88
+ return {
89
+ ...display,
90
+ scaleFactor: display.scaleFactor ?? 1,
91
+ }
92
+ }
93
+
94
+ function windowIntersectsDisplay(window, display) {
95
+ const insideX =
96
+ window.x < display.originX + display.width &&
97
+ window.x + window.width > display.originX
98
+ const insideY =
99
+ window.y < display.originY + display.height &&
100
+ window.y + window.height > display.originY
101
+ return insideX && insideY
102
+ }
103
+
104
+ function captureScreenToBuffer(displayId) {
105
+ const tempDir = mkdtempSync(join(tmpdir(), 'claude-code-screen-'))
106
+ const outputPath = join(tempDir, 'capture.png')
107
+ try {
108
+ const args = ['-x']
109
+ if (displayId != null) {
110
+ args.push('-D', String(displayId))
111
+ }
112
+ args.push(outputPath)
113
+ run('/usr/sbin/screencapture', args)
114
+ return readFileSync(outputPath)
115
+ } finally {
116
+ rmSync(tempDir, { recursive: true, force: true })
117
+ }
118
+ }
119
+
120
+ async function toSizedJpegBase64(buffer, targetWidth, targetHeight, quality) {
121
+ const sharp = sharpFactory()
122
+ const pipeline = sharp(buffer)
123
+ .resize(targetWidth, targetHeight, {
124
+ fit: 'inside',
125
+ withoutEnlargement: true,
126
+ })
127
+ .jpeg({ quality: Math.max(1, Math.min(100, Math.round(quality * 100))) })
128
+ const out = await pipeline.toBuffer()
129
+ const meta = await sharp(out).metadata()
130
+ return {
131
+ base64: out.toString('base64'),
132
+ width: meta.width ?? targetWidth,
133
+ height: meta.height ?? targetHeight,
134
+ }
135
+ }
136
+
137
+ async function captureRegionBase64(
138
+ displayId,
139
+ region,
140
+ outWidth,
141
+ outHeight,
142
+ quality,
143
+ ) {
144
+ const source = captureScreenToBuffer(displayId)
145
+ const sharp = sharpFactory()
146
+ const display = displayFor(displayId)
147
+ const scaleFactor = display.scaleFactor ?? 1
148
+ const left = Math.max(
149
+ 0,
150
+ Math.round((region.x - display.originX) * scaleFactor),
151
+ )
152
+ const top = Math.max(
153
+ 0,
154
+ Math.round((region.y - display.originY) * scaleFactor),
155
+ )
156
+ const maxWidth = Math.max(1, Math.round(display.width * scaleFactor) - left)
157
+ const maxHeight = Math.max(1, Math.round(display.height * scaleFactor) - top)
158
+ const width = Math.max(
159
+ 1,
160
+ Math.min(Math.round(region.w * scaleFactor), maxWidth),
161
+ )
162
+ const height = Math.max(
163
+ 1,
164
+ Math.min(Math.round(region.h * scaleFactor), maxHeight),
165
+ )
166
+
167
+ const cropped = await sharp(source)
168
+ .extract({
169
+ left,
170
+ top,
171
+ width,
172
+ height,
173
+ })
174
+ .png()
175
+ .toBuffer()
176
+
177
+ return toSizedJpegBase64(cropped, outWidth, outHeight, quality)
178
+ }
179
+
180
+ function listWindows() {
181
+ return runDriver({ op: 'listWindows' }) ?? []
182
+ }
183
+
184
+ function listRunningApps() {
185
+ return runDriver({ op: 'listRunningApps' }) ?? []
186
+ }
187
+
188
+ function escapeAppleScriptString(value) {
189
+ return String(value).replaceAll('\\', '\\\\').replaceAll('"', '\\"')
190
+ }
191
+
192
+ function plistValue(plistPath, key) {
193
+ const result = spawnSync(
194
+ '/usr/bin/plutil',
195
+ ['-extract', key, 'raw', '-o', '-', plistPath],
196
+ { encoding: 'utf8', stdio: 'pipe' },
197
+ )
198
+ if (result.status !== 0) {
199
+ return null
200
+ }
201
+ const value = String(result.stdout ?? '').trim()
202
+ return value || null
203
+ }
204
+
205
+ function appBaseName(appPath) {
206
+ return appPath.split('/').pop()?.replace(/\.app$/i, '') ?? null
207
+ }
208
+
209
+ function readAppMetadata(appPath) {
210
+ const infoPlistPath = join(appPath, 'Contents', 'Info.plist')
211
+ if (!existsSync(infoPlistPath)) {
212
+ return null
213
+ }
214
+
215
+ const bundleId = plistValue(infoPlistPath, 'CFBundleIdentifier')
216
+ const displayName =
217
+ plistValue(infoPlistPath, 'CFBundleDisplayName') ??
218
+ plistValue(infoPlistPath, 'CFBundleName') ??
219
+ appBaseName(appPath)
220
+
221
+ if (!bundleId || !displayName) {
222
+ return null
223
+ }
224
+
225
+ return {
226
+ bundleId,
227
+ displayName,
228
+ path: appPath,
229
+ }
230
+ }
231
+
232
+ function findAppIconPath(appPath) {
233
+ const infoPlistPath = join(appPath, 'Contents', 'Info.plist')
234
+ const resourcesPath = join(appPath, 'Contents', 'Resources')
235
+ if (!existsSync(infoPlistPath) || !existsSync(resourcesPath)) {
236
+ return null
237
+ }
238
+
239
+ const candidateNames = [
240
+ plistValue(infoPlistPath, 'CFBundleIconFile'),
241
+ plistValue(infoPlistPath, 'CFBundleIconName'),
242
+ appBaseName(appPath),
243
+ ].filter(Boolean)
244
+
245
+ for (const candidateName of candidateNames) {
246
+ for (const fileName of [
247
+ candidateName,
248
+ `${candidateName}.icns`,
249
+ `${candidateName}.png`,
250
+ ]) {
251
+ const iconPath = join(resourcesPath, fileName)
252
+ if (existsSync(iconPath)) {
253
+ return iconPath
254
+ }
255
+ }
256
+ }
257
+
258
+ const fallback = readdirSync(resourcesPath).find(name =>
259
+ name.toLowerCase().endsWith('.icns'),
260
+ )
261
+ return fallback ? join(resourcesPath, fallback) : null
262
+ }
263
+
264
+ function listSpotlightApplicationPaths() {
265
+ const result = spawnSync(
266
+ '/usr/bin/mdfind',
267
+ ['kMDItemContentTypeTree == "com.apple.application-bundle"'],
268
+ { encoding: 'utf8', stdio: 'pipe' },
269
+ )
270
+ if (result.status !== 0) {
271
+ return []
272
+ }
273
+
274
+ return String(result.stdout ?? '')
275
+ .split('\n')
276
+ .map(line => line.trim())
277
+ .filter(Boolean)
278
+ }
279
+
280
+ function scanApplicationRoots() {
281
+ const appPaths = []
282
+ const queue = APP_SCAN_ROOTS.filter(root => existsSync(root)).map(root => ({
283
+ dir: root,
284
+ depth: APP_SCAN_MAX_DEPTH,
285
+ }))
286
+
287
+ while (queue.length > 0) {
288
+ const current = queue.pop()
289
+ if (!current) continue
290
+
291
+ let entries
292
+ try {
293
+ entries = readdirSync(current.dir, { withFileTypes: true })
294
+ } catch {
295
+ continue
296
+ }
297
+
298
+ for (const entry of entries) {
299
+ if (!entry.isDirectory()) continue
300
+ const fullPath = join(current.dir, entry.name)
301
+ if (entry.name.toLowerCase().endsWith('.app')) {
302
+ appPaths.push(fullPath)
303
+ continue
304
+ }
305
+ if (current.depth > 0) {
306
+ queue.push({ dir: fullPath, depth: current.depth - 1 })
307
+ }
308
+ }
309
+ }
310
+
311
+ return appPaths
312
+ }
313
+
314
+ function runningAppsByBundleId() {
315
+ return new Map(listRunningApps().map(app => [app.bundleId, app]))
316
+ }
317
+
318
+ function appsOnDisplay(displayId) {
319
+ const display = displayFor(displayId)
320
+ const runningByBundle = runningAppsByBundleId()
321
+ const seen = new Set()
322
+ const apps = []
323
+
324
+ for (const window of listWindows()) {
325
+ if (!window.bundleId || seen.has(window.bundleId)) continue
326
+ if (!windowIntersectsDisplay(window, display)) continue
327
+
328
+ const running = runningByBundle.get(window.bundleId)
329
+ apps.push({
330
+ bundleId: window.bundleId,
331
+ displayName: running?.displayName ?? window.displayName ?? window.bundleId,
332
+ })
333
+ seen.add(window.bundleId)
334
+ }
335
+
336
+ return apps
337
+ }
338
+
339
+ function appsToHide(exemptBundleIds, displayId) {
340
+ const exempt = new Set(
341
+ (exemptBundleIds ?? []).filter(
342
+ bundleId => typeof bundleId === 'string' && bundleId.length > 0,
343
+ ),
344
+ )
345
+
346
+ return appsOnDisplay(displayId).filter(
347
+ app => app.bundleId !== FINDER_BUNDLE_ID && !exempt.has(app.bundleId),
348
+ )
349
+ }
350
+
351
+ function hideApp(bundleId) {
352
+ run('/usr/bin/osascript', [
353
+ '-e',
354
+ `tell application id "${escapeAppleScriptString(bundleId)}" to hide`,
355
+ ])
356
+ }
357
+
358
+ function openApp(bundleId) {
359
+ run('/usr/bin/open', ['-b', bundleId])
360
+ return true
361
+ }
362
+
363
+ function unhideAppInBackground(bundleId) {
364
+ run('/usr/bin/open', ['-g', '-b', bundleId])
365
+ }
366
+
367
+ function bundleIdsToDisplayIds(bundleIds) {
368
+ const windows = listWindows()
369
+ const displays = displayList()
370
+
371
+ return bundleIds.map(bundleId => {
372
+ const ids = new Set()
373
+ for (const window of windows) {
374
+ if (window.bundleId !== bundleId) continue
375
+ for (const display of displays) {
376
+ if (windowIntersectsDisplay(window, display)) {
377
+ ids.add(display.displayId)
378
+ }
379
+ }
380
+ }
381
+ return {
382
+ bundleId,
383
+ displayIds: [...ids].sort((a, b) => a - b),
384
+ }
385
+ })
386
+ }
387
+
388
+ function appUnderPoint(x, y) {
389
+ const windows = listWindows()
390
+ for (const window of windows) {
391
+ const inside =
392
+ x >= window.x &&
393
+ x <= window.x + window.width &&
394
+ y >= window.y &&
395
+ y <= window.y + window.height
396
+ if (inside && window.bundleId) {
397
+ return {
398
+ bundleId: window.bundleId,
399
+ displayName: window.displayName ?? window.bundleId,
400
+ }
401
+ }
402
+ }
403
+ return null
404
+ }
405
+
406
+ function terminalIconDataUrl(path) {
407
+ if (!path || !existsSync(path)) {
408
+ return null
409
+ }
410
+
411
+ const iconPath = findAppIconPath(path)
412
+ if (!iconPath) {
413
+ return null
414
+ }
415
+
416
+ const tempDir = mkdtempSync(join(tmpdir(), 'claude-code-icon-'))
417
+ const outputPath = join(tempDir, 'icon.png')
418
+ try {
419
+ const result = spawnSync(
420
+ '/usr/bin/sips',
421
+ ['-s', 'format', 'png', iconPath, '--out', outputPath],
422
+ { encoding: 'utf8', stdio: 'pipe' },
423
+ )
424
+ if (result.status !== 0) {
425
+ return null
426
+ }
427
+ if (!existsSync(outputPath)) {
428
+ return null
429
+ }
430
+ const preview = readFileSync(outputPath)
431
+ return `data:image/png;base64,${preview.toString('base64')}`
432
+ } finally {
433
+ rmSync(tempDir, { recursive: true, force: true })
434
+ }
435
+ }
436
+
437
+ function listInstalledApps() {
438
+ const paths = [
439
+ ...listSpotlightApplicationPaths(),
440
+ ...scanApplicationRoots(),
441
+ ]
442
+
443
+ const apps = []
444
+ const seenBundleIds = new Set()
445
+ const seenPaths = new Set()
446
+ for (const appPath of paths) {
447
+ if (seenPaths.has(appPath)) continue
448
+ seenPaths.add(appPath)
449
+
450
+ const metadata = readAppMetadata(appPath)
451
+ if (!metadata || seenBundleIds.has(metadata.bundleId)) continue
452
+
453
+ seenBundleIds.add(metadata.bundleId)
454
+ apps.push(metadata)
455
+ }
456
+ return apps.sort((a, b) => a.displayName.localeCompare(b.displayName))
457
+ }
458
+
459
+ function unhideApps(bundleIds) {
460
+ for (const bundleId of Array.isArray(bundleIds) ? bundleIds : [bundleIds]) {
461
+ if (!bundleId) continue
462
+ try {
463
+ unhideAppInBackground(bundleId)
464
+ } catch {
465
+ // Best-effort restore.
466
+ }
467
+ }
468
+ return true
469
+ }
470
+
471
+ function prepareDisplay(allowedBundleIds, hostBundleId, displayId) {
472
+ const hidden = []
473
+ const candidates = appsToHide(
474
+ [...(allowedBundleIds ?? []), hostBundleId],
475
+ displayId,
476
+ )
477
+
478
+ for (const app of candidates) {
479
+ try {
480
+ hideApp(app.bundleId)
481
+ hidden.push(app.bundleId)
482
+ } catch {
483
+ // Best-effort hide.
484
+ }
485
+ }
486
+
487
+ const allowed = new Set(allowedBundleIds ?? [])
488
+ const running = runningAppsByBundleId()
489
+ const displayLocalCandidate = appsOnDisplay(displayId).find(app =>
490
+ allowed.has(app.bundleId),
491
+ )
492
+ const activated =
493
+ displayLocalCandidate?.bundleId ??
494
+ [...allowed].find(bundleId => running.has(bundleId))
495
+
496
+ if (!activated) {
497
+ return { hidden }
498
+ }
499
+
500
+ try {
501
+ openApp(activated)
502
+ return { hidden, activated }
503
+ } catch {
504
+ return { hidden }
505
+ }
506
+ }
507
+
508
+ function checkAccessibility() {
509
+ const result = spawnSync('/usr/bin/osascript', [
510
+ '-e',
511
+ 'tell application "System Events" to return UI elements enabled',
512
+ ], {
513
+ encoding: 'utf8',
514
+ stdio: 'pipe',
515
+ })
516
+ return result.status === 0 && String(result.stdout).trim() === 'true'
517
+ }
518
+
519
+ function requestAccessibility() {
520
+ run('/usr/bin/open', [
521
+ 'x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility',
522
+ ])
523
+ return true
524
+ }
525
+
526
+ function checkScreenRecording() {
527
+ const tempDir = mkdtempSync(join(tmpdir(), 'claude-screen-recording-'))
528
+ const outputPath = join(tempDir, 'screen.png')
529
+ try {
530
+ const result = spawnSync('/usr/sbin/screencapture', ['-x', outputPath], {
531
+ encoding: 'utf8',
532
+ stdio: 'pipe',
533
+ })
534
+ return result.status === 0
535
+ } finally {
536
+ rmSync(tempDir, { recursive: true, force: true })
537
+ }
538
+ }
539
+
540
+ function requestScreenRecording() {
541
+ run('/usr/bin/open', [
542
+ 'x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture',
543
+ ])
544
+ return true
545
+ }
546
+
547
+ function getDisplaySize(displayId) {
548
+ return displayFor(displayId)
549
+ }
550
+
551
+ function resolveTargetDisplayId(allowedBundleIds, preferredDisplayId, autoResolve) {
552
+ const fallbackDisplayId = displayFor(preferredDisplayId).displayId
553
+ if (!autoResolve || !allowedBundleIds || allowedBundleIds.length === 0) {
554
+ return fallbackDisplayId
555
+ }
556
+
557
+ const counts = new Map()
558
+ for (const match of bundleIdsToDisplayIds(allowedBundleIds)) {
559
+ for (const displayId of match.displayIds) {
560
+ counts.set(displayId, (counts.get(displayId) ?? 0) + 1)
561
+ }
562
+ }
563
+
564
+ if (preferredDisplayId != null && counts.has(preferredDisplayId)) {
565
+ return preferredDisplayId
566
+ }
567
+
568
+ const bestDisplayId = [...counts.entries()].sort((a, b) => {
569
+ if (b[1] !== a[1]) return b[1] - a[1]
570
+ return a[0] - b[0]
571
+ })[0]?.[0]
572
+
573
+ return bestDisplayId ?? fallbackDisplayId
574
+ }
575
+
576
+ async function captureDisplay(displayId, outWidth, outHeight, quality) {
577
+ const display = displayFor(displayId)
578
+ const source = captureScreenToBuffer(display.displayId)
579
+ const sized = await toSizedJpegBase64(source, outWidth, outHeight, quality)
580
+ return {
581
+ ...sized,
582
+ displayWidth: display.width,
583
+ displayHeight: display.height,
584
+ displayId: display.displayId,
585
+ originX: display.originX,
586
+ originY: display.originY,
587
+ }
588
+ }
589
+
590
+ async function resolvePrepareCapture(
591
+ allowedBundleIds,
592
+ hostBundleId,
593
+ quality,
594
+ outWidth,
595
+ outHeight,
596
+ preferredDisplayId,
597
+ autoResolve,
598
+ doHide,
599
+ ) {
600
+ const displayId = resolveTargetDisplayId(
601
+ allowedBundleIds ?? [],
602
+ preferredDisplayId,
603
+ autoResolve,
604
+ )
605
+ const display = displayFor(displayId)
606
+ const hidden = doHide
607
+ ? prepareDisplay(allowedBundleIds ?? [], hostBundleId, display.displayId).hidden
608
+ : []
609
+
610
+ try {
611
+ return {
612
+ ...(await captureDisplay(display.displayId, outWidth, outHeight, quality)),
613
+ hidden,
614
+ }
615
+ } catch (error) {
616
+ return {
617
+ base64: '',
618
+ width: 0,
619
+ height: 0,
620
+ displayWidth: display.width,
621
+ displayHeight: display.height,
622
+ displayId: display.displayId,
623
+ originX: display.originX,
624
+ originY: display.originY,
625
+ hidden,
626
+ captureError: error instanceof Error ? error.message : String(error),
627
+ }
628
+ }
629
+ }
630
+
631
+ async function captureExcluding(
632
+ _allowedBundleIds,
633
+ quality,
634
+ outWidth,
635
+ outHeight,
636
+ displayId,
637
+ ) {
638
+ return captureDisplay(displayId, outWidth, outHeight, quality)
639
+ }
640
+
641
+ async function captureRegion(
642
+ _allowedBundleIds,
643
+ x,
644
+ y,
645
+ w,
646
+ h,
647
+ outWidth,
648
+ outHeight,
649
+ quality,
650
+ displayId,
651
+ ) {
652
+ return captureRegionBase64(
653
+ displayId,
654
+ { x, y, w, h },
655
+ outWidth,
656
+ outHeight,
657
+ quality,
658
+ )
659
+ }
660
+
661
+ function drainMainRunLoop() {
662
+ return true
663
+ }
664
+
665
+ function registerEscape() {
666
+ return true
667
+ }
668
+
669
+ function noop() {
670
+ return true
671
+ }
672
+
673
+ export default {
674
+ _drainMainRunLoop: drainMainRunLoop,
675
+ resolvePrepareCapture,
676
+ tcc: {
677
+ checkAccessibility,
678
+ requestAccessibility,
679
+ checkScreenRecording,
680
+ requestScreenRecording,
681
+ },
682
+ hotkey: {
683
+ registerEscape,
684
+ unregister: noop,
685
+ notifyExpectedEscape: noop,
686
+ },
687
+ display: {
688
+ getSize: getDisplaySize,
689
+ listAll: displayList,
690
+ },
691
+ apps: {
692
+ prepareDisplay,
693
+ previewHideSet: appsToHide,
694
+ findWindowDisplays: bundleIdsToDisplayIds,
695
+ appUnderPoint,
696
+ listInstalled: listInstalledApps,
697
+ iconDataUrl: terminalIconDataUrl,
698
+ listRunning: listRunningApps,
699
+ open: openApp,
700
+ unhide: unhideApps,
701
+ },
702
+ screenshot: {
703
+ captureExcluding,
704
+ captureRegion,
705
+ },
706
+ }
@@ -0,0 +1,7 @@
1
+ import implementation from './implementation.js'
2
+
3
+ if (process.platform !== 'darwin') {
4
+ throw new Error('computer-use is only available on macOS')
5
+ }
6
+
7
+ export default implementation
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "audio-capture-napi",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "types": "./src/index.ts"
8
+ }