simen-keyboard-listener 1.1.9 → 1.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -11,7 +11,1344 @@ import * as fs from "fs";
11
11
  import { execFileSync } from "child_process";
12
12
  import { createRequire } from "module";
13
13
  import { fileURLToPath } from "url";
14
+
15
+ // src/osascript/executor.ts
16
+ import { execFile } from "child_process";
17
+ import { promisify } from "util";
18
+ var execFileAsync = promisify(execFile);
14
19
  var IS_MACOS = process.platform === "darwin";
20
+ var OSASCRIPT_PATH = "/usr/bin/osascript";
21
+ var DEFAULT_TIMEOUT = 3e4;
22
+ function isOsascriptAvailable() {
23
+ return IS_MACOS;
24
+ }
25
+ async function executeAppleScript(script, options) {
26
+ if (!IS_MACOS) {
27
+ return {
28
+ success: false,
29
+ error: "osascript is only available on macOS"
30
+ };
31
+ }
32
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
33
+ const startTime = Date.now();
34
+ try {
35
+ const { stdout, stderr } = await execFileAsync(
36
+ OSASCRIPT_PATH,
37
+ ["-e", script],
38
+ { timeout }
39
+ );
40
+ const executionTime = Date.now() - startTime;
41
+ if (stderr && stderr.trim()) {
42
+ return {
43
+ success: false,
44
+ error: stderr.trim(),
45
+ executionTime
46
+ };
47
+ }
48
+ return {
49
+ success: true,
50
+ data: stdout.trim(),
51
+ executionTime
52
+ };
53
+ } catch (error) {
54
+ const executionTime = Date.now() - startTime;
55
+ const errorMessage = error instanceof Error ? error.message : String(error);
56
+ return {
57
+ success: false,
58
+ error: errorMessage,
59
+ executionTime
60
+ };
61
+ }
62
+ }
63
+ async function executeAppleScriptLines(lines, options) {
64
+ if (!IS_MACOS) {
65
+ return {
66
+ success: false,
67
+ error: "osascript is only available on macOS"
68
+ };
69
+ }
70
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
71
+ const startTime = Date.now();
72
+ const args = lines.flatMap((line) => ["-e", line]);
73
+ try {
74
+ const { stdout, stderr } = await execFileAsync(
75
+ OSASCRIPT_PATH,
76
+ args,
77
+ { timeout }
78
+ );
79
+ const executionTime = Date.now() - startTime;
80
+ if (stderr && stderr.trim()) {
81
+ return {
82
+ success: false,
83
+ error: stderr.trim(),
84
+ executionTime
85
+ };
86
+ }
87
+ return {
88
+ success: true,
89
+ data: stdout.trim(),
90
+ executionTime
91
+ };
92
+ } catch (error) {
93
+ const executionTime = Date.now() - startTime;
94
+ const errorMessage = error instanceof Error ? error.message : String(error);
95
+ return {
96
+ success: false,
97
+ error: errorMessage,
98
+ executionTime
99
+ };
100
+ }
101
+ }
102
+ async function executeAndParse(script, parser, options) {
103
+ const result = await executeAppleScript(script, options);
104
+ if (!result.success) {
105
+ return {
106
+ success: false,
107
+ error: result.error,
108
+ executionTime: result.executionTime
109
+ };
110
+ }
111
+ try {
112
+ const parsed = parser(result.data ?? "");
113
+ return {
114
+ success: true,
115
+ data: parsed,
116
+ executionTime: result.executionTime
117
+ };
118
+ } catch (parseError) {
119
+ const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
120
+ return {
121
+ success: false,
122
+ error: `Failed to parse output: ${errorMessage}`,
123
+ executionTime: result.executionTime
124
+ };
125
+ }
126
+ }
127
+ async function executeMultilineAndParse(lines, parser, options) {
128
+ const result = await executeAppleScriptLines(lines, options);
129
+ if (!result.success) {
130
+ return {
131
+ success: false,
132
+ error: result.error,
133
+ executionTime: result.executionTime
134
+ };
135
+ }
136
+ try {
137
+ const parsed = parser(result.data ?? "");
138
+ return {
139
+ success: true,
140
+ data: parsed,
141
+ executionTime: result.executionTime
142
+ };
143
+ } catch (parseError) {
144
+ const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
145
+ return {
146
+ success: false,
147
+ error: `Failed to parse output: ${errorMessage}`,
148
+ executionTime: result.executionTime
149
+ };
150
+ }
151
+ }
152
+ function escapeForAppleScript(str) {
153
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
154
+ }
155
+
156
+ // src/osascript/scripts/batchContext.ts
157
+ var SEC = "\xA7\xA7\xA7";
158
+ var FLD = "|||";
159
+ var ITM = ":::";
160
+ var SCRIPT_BASIC = `
161
+ set d to "${FLD}"
162
+ set s to "${SEC}"
163
+ set i to "${ITM}"
164
+
165
+ tell application "System Events"
166
+ set fp to first application process whose frontmost is true
167
+ set appName to displayed name of fp
168
+ set sec0 to appName & d & bundle identifier of fp & d
169
+ try
170
+ set sec0 to sec0 & POSIX path of (file of fp as alias)
171
+ end try
172
+ set finderRunning to (exists process "Finder")
173
+ end tell
174
+
175
+ set sec1 to ""
176
+ set sec2 to ""
177
+ set sec3 to ""
178
+ set sec4 to do shell script "echo $HOME/Desktop/"
179
+
180
+ if not finderRunning then
181
+ -- Skip Finder operations if not running
182
+ else
183
+ -- Get Finder selection (must be in separate tell block to avoid scope issues)
184
+ try
185
+ tell application "Finder"
186
+ set sel to selection
187
+ set sc to count of sel
188
+ if sc > 0 then
189
+ set L to {}
190
+ repeat with j from 1 to sc
191
+ if j > 50 then exit repeat
192
+ set f to item j of sel
193
+ set t to "0"
194
+ if class of f as string contains "folder" then set t to "1"
195
+ set end of L to name of f & d & POSIX path of (f as alias) & d & t
196
+ end repeat
197
+ set {tid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, i}
198
+ set sec1 to L as string
199
+ set AppleScript's text item delimiters to tid
200
+ end if
201
+ end tell
202
+ end try
203
+
204
+ -- Get Finder windows (including special views like Recents)
205
+ try
206
+ tell application "Finder"
207
+ set wc to count of Finder windows
208
+ if wc > 0 then
209
+ -- Try to get current folder path (may fail for special views)
210
+ try
211
+ set sec2 to POSIX path of (target of front Finder window as alias)
212
+ on error
213
+ -- Special view (Recents, Search, etc.) - use window name as identifier
214
+ set sec2 to "special:" & (name of front Finder window)
215
+ end try
216
+ set L to {}
217
+ repeat with idx from 1 to wc
218
+ set w to Finder window idx
219
+ set wName to name of w
220
+ set wPath to ""
221
+ try
222
+ set wPath to POSIX path of (target of w as alias)
223
+ on error
224
+ -- Special view - mark with special: prefix
225
+ set wPath to "special:" & wName
226
+ end try
227
+ set end of L to wName & d & wPath & d & (idx as string)
228
+ end repeat
229
+ set {tid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, i}
230
+ set sec3 to L as string
231
+ set AppleScript's text item delimiters to tid
232
+ end if
233
+ end tell
234
+ end try
235
+ end if
236
+
237
+ set sec5 to ""
238
+ try
239
+ set c to the clipboard as text
240
+ if (length of c) > 2000 then set c to text 1 thru 2000 of c
241
+ set sec5 to c
242
+ end try
243
+
244
+ set sec6 to ""
245
+ try
246
+ set cf to the clipboard as alias list
247
+ set L to {}
248
+ repeat with f in cf
249
+ set end of L to POSIX path of f
250
+ end repeat
251
+ set {tid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, i}
252
+ set sec6 to L as string
253
+ set AppleScript's text item delimiters to tid
254
+ end try
255
+
256
+ set sec7 to "0"
257
+ try
258
+ set imgData to the clipboard as \xABclass PNGf\xBB
259
+ set sec7 to "1"
260
+ on error
261
+ try
262
+ set imgData to the clipboard as TIFF picture
263
+ set sec7 to "1"
264
+ end try
265
+ end try
266
+
267
+ return sec0 & s & sec1 & s & sec2 & s & sec3 & s & sec4 & s & sec5 & s & sec6 & s & sec7
268
+ `;
269
+ var SCRIPT_WITH_METADATA = `
270
+ set d to "${FLD}"
271
+ set s to "${SEC}"
272
+ set i to "${ITM}"
273
+
274
+ tell application "System Events"
275
+ set fp to first application process whose frontmost is true
276
+ set appName to displayed name of fp
277
+ set sec0 to appName & d & bundle identifier of fp & d
278
+ try
279
+ set sec0 to sec0 & POSIX path of (file of fp as alias)
280
+ end try
281
+ set finderRunning to (exists process "Finder")
282
+ end tell
283
+
284
+ set sec1 to ""
285
+ set sec2 to ""
286
+ set sec3 to ""
287
+ set sec4 to do shell script "echo $HOME/Desktop/"
288
+
289
+ if not finderRunning then
290
+ -- Skip Finder operations if not running
291
+ else
292
+ -- Get Finder selection with metadata (must be in separate tell block)
293
+ try
294
+ tell application "Finder"
295
+ set sel to selection
296
+ set sc to count of sel
297
+ if sc > 0 then
298
+ set L to {}
299
+ repeat with j from 1 to sc
300
+ if j > 50 then exit repeat
301
+ set f to item j of sel
302
+ set t to "0"
303
+ if class of f as string contains "folder" then set t to "1"
304
+ set fSize to "0"
305
+ set fMod to ""
306
+ try
307
+ set fSize to size of f as string
308
+ end try
309
+ try
310
+ set fMod to (modification date of f) as string
311
+ end try
312
+ set end of L to name of f & d & POSIX path of (f as alias) & d & t & d & fSize & d & fMod
313
+ end repeat
314
+ set {tid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, i}
315
+ set sec1 to L as string
316
+ set AppleScript's text item delimiters to tid
317
+ end if
318
+ end tell
319
+ end try
320
+
321
+ -- Get Finder windows (including special views like Recents)
322
+ try
323
+ tell application "Finder"
324
+ set wc to count of Finder windows
325
+ if wc > 0 then
326
+ -- Try to get current folder path (may fail for special views)
327
+ try
328
+ set sec2 to POSIX path of (target of front Finder window as alias)
329
+ on error
330
+ -- Special view (Recents, Search, etc.) - use window name as identifier
331
+ set sec2 to "special:" & (name of front Finder window)
332
+ end try
333
+ set L to {}
334
+ repeat with idx from 1 to wc
335
+ set w to Finder window idx
336
+ set wName to name of w
337
+ set wPath to ""
338
+ try
339
+ set wPath to POSIX path of (target of w as alias)
340
+ on error
341
+ -- Special view - mark with special: prefix
342
+ set wPath to "special:" & wName
343
+ end try
344
+ set end of L to wName & d & wPath & d & (idx as string)
345
+ end repeat
346
+ set {tid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, i}
347
+ set sec3 to L as string
348
+ set AppleScript's text item delimiters to tid
349
+ end if
350
+ end tell
351
+ end try
352
+ end if
353
+
354
+ set sec5 to ""
355
+ try
356
+ set c to the clipboard as text
357
+ if (length of c) > 2000 then set c to text 1 thru 2000 of c
358
+ set sec5 to c
359
+ end try
360
+
361
+ set sec6 to ""
362
+ try
363
+ set cf to the clipboard as alias list
364
+ set L to {}
365
+ repeat with f in cf
366
+ set end of L to POSIX path of f
367
+ end repeat
368
+ set {tid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, i}
369
+ set sec6 to L as string
370
+ set AppleScript's text item delimiters to tid
371
+ end try
372
+
373
+ set sec7 to "0"
374
+ try
375
+ set imgData to the clipboard as \xABclass PNGf\xBB
376
+ set sec7 to "1"
377
+ on error
378
+ try
379
+ set imgData to the clipboard as TIFF picture
380
+ set sec7 to "1"
381
+ end try
382
+ end try
383
+
384
+ return sec0 & s & sec1 & s & sec2 & s & sec3 & s & sec4 & s & sec5 & s & sec6 & s & sec7
385
+ `;
386
+ function parseBasic(out) {
387
+ const s = out.split(SEC);
388
+ const app = (s[0] ?? "").split(FLD);
389
+ const items = [];
390
+ const paths = [];
391
+ if (s[1]?.trim()) {
392
+ for (const item of s[1].split(ITM)) {
393
+ const p = item.split(FLD);
394
+ if (p.length >= 3) {
395
+ items.push({ name: p[0], path: p[1], isFolder: p[2] === "1" });
396
+ paths.push(p[1]);
397
+ }
398
+ }
399
+ }
400
+ const windows = [];
401
+ if (s[3]?.trim()) {
402
+ for (const win of s[3].split(ITM)) {
403
+ const p = win.split(FLD);
404
+ if (p.length >= 3) {
405
+ const isSpecial = p[1].startsWith("special:");
406
+ windows.push({
407
+ name: p[0],
408
+ path: isSpecial ? null : p[1],
409
+ index: parseInt(p[2], 10) || 0,
410
+ isSpecialView: isSpecial
411
+ });
412
+ }
413
+ }
414
+ }
415
+ const currentFolder = s[2]?.trim() || null;
416
+ const finderCurrentFolder = currentFolder?.startsWith("special:") ? null : currentFolder;
417
+ const clipPaths = s[6]?.trim() ? s[6].split(ITM).filter((p) => p.trim()) : [];
418
+ const hasImage = s[7]?.trim() === "1";
419
+ return {
420
+ frontmostApp: {
421
+ name: app[0] ?? "",
422
+ bundleId: app[1] ?? "",
423
+ isFinder: app[1] === "com.apple.finder",
424
+ path: app[2] ?? ""
425
+ },
426
+ finderSelection: { count: items.length, items, paths },
427
+ finderCurrentFolder,
428
+ finderWindows: windows,
429
+ desktopPath: s[4]?.trim() || "",
430
+ clipboard: {
431
+ text: s[5]?.trim() || null,
432
+ hasFiles: clipPaths.length > 0,
433
+ filePaths: clipPaths,
434
+ hasImage
435
+ },
436
+ timestamp: Date.now()
437
+ };
438
+ }
439
+ function parseWithMetadata(out) {
440
+ const s = out.split(SEC);
441
+ const app = (s[0] ?? "").split(FLD);
442
+ const items = [];
443
+ const paths = [];
444
+ if (s[1]?.trim()) {
445
+ for (const item of s[1].split(ITM)) {
446
+ const p = item.split(FLD);
447
+ if (p.length >= 3) {
448
+ const selectedItem = {
449
+ name: p[0],
450
+ path: p[1],
451
+ isFolder: p[2] === "1"
452
+ };
453
+ if (p.length >= 4 && p[3]) {
454
+ selectedItem.size = parseInt(p[3], 10) || 0;
455
+ }
456
+ if (p.length >= 5 && p[4]) {
457
+ selectedItem.modifiedAt = p[4];
458
+ }
459
+ items.push(selectedItem);
460
+ paths.push(p[1]);
461
+ }
462
+ }
463
+ }
464
+ const windows = [];
465
+ if (s[3]?.trim()) {
466
+ for (const win of s[3].split(ITM)) {
467
+ const p = win.split(FLD);
468
+ if (p.length >= 3) {
469
+ const isSpecial = p[1].startsWith("special:");
470
+ windows.push({
471
+ name: p[0],
472
+ path: isSpecial ? null : p[1],
473
+ index: parseInt(p[2], 10) || 0,
474
+ isSpecialView: isSpecial
475
+ });
476
+ }
477
+ }
478
+ }
479
+ const currentFolder = s[2]?.trim() || null;
480
+ const finderCurrentFolder = currentFolder?.startsWith("special:") ? null : currentFolder;
481
+ const clipPaths = s[6]?.trim() ? s[6].split(ITM).filter((p) => p.trim()) : [];
482
+ const hasImage = s[7]?.trim() === "1";
483
+ return {
484
+ frontmostApp: {
485
+ name: app[0] ?? "",
486
+ bundleId: app[1] ?? "",
487
+ isFinder: app[1] === "com.apple.finder",
488
+ path: app[2] ?? ""
489
+ },
490
+ finderSelection: { count: items.length, items, paths },
491
+ finderCurrentFolder,
492
+ finderWindows: windows,
493
+ desktopPath: s[4]?.trim() || "",
494
+ clipboard: {
495
+ text: s[5]?.trim() || null,
496
+ hasFiles: clipPaths.length > 0,
497
+ filePaths: clipPaths,
498
+ hasImage
499
+ },
500
+ timestamp: Date.now()
501
+ };
502
+ }
503
+ async function getAgentContext(opts) {
504
+ if (!isOsascriptAvailable()) return null;
505
+ const script = opts?.includeMetadata ? SCRIPT_WITH_METADATA : SCRIPT_BASIC;
506
+ const parser = opts?.includeMetadata ? parseWithMetadata : parseBasic;
507
+ const r = await executeAndParse(script, parser, opts);
508
+ return r.success ? r.data ?? null : null;
509
+ }
510
+
511
+ // src/osascript/scripts/finderContext.ts
512
+ var SEC2 = "\xA7\xA7\xA7";
513
+ var FLD2 = "|||";
514
+ var ITM2 = ":::";
515
+ var SCRIPT = `
516
+ set d to "${FLD2}"
517
+ set s to "${SEC2}"
518
+ set i to "${ITM2}"
519
+
520
+ -- Check if Finder is frontmost
521
+ set isFinderFront to "0"
522
+ tell application "System Events"
523
+ set finderRunning to (exists process "Finder")
524
+ if finderRunning then
525
+ try
526
+ set frontApp to bundle identifier of (first application process whose frontmost is true)
527
+ if frontApp is "com.apple.finder" then
528
+ set isFinderFront to "1"
529
+ end if
530
+ end try
531
+ end if
532
+ end tell
533
+
534
+ set sec0 to isFinderFront
535
+ set sec1 to ""
536
+ set sec2 to ""
537
+
538
+ if not finderRunning then
539
+ return sec0 & s & sec1 & s & sec2
540
+ end if
541
+
542
+ tell application "Finder"
543
+ -- Get all Finder windows
544
+ set wc to count of Finder windows
545
+ if wc > 0 then
546
+ set L to {}
547
+ repeat with idx from 1 to wc
548
+ set w to Finder window idx
549
+ set wName to name of w
550
+ set wPath to ""
551
+ try
552
+ set wPath to POSIX path of (target of w as alias)
553
+ on error
554
+ -- Special view (Recents, AirDrop, Search, Tags, etc.)
555
+ set wPath to "special:" & wName
556
+ end try
557
+ set end of L to wName & d & wPath & d & (idx as string)
558
+ end repeat
559
+ set {tid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, i}
560
+ set sec1 to L as string
561
+ set AppleScript's text item delimiters to tid
562
+ end if
563
+
564
+ -- Get selection only if Finder is frontmost
565
+ if isFinderFront is "1" then
566
+ set sel to selection
567
+ set sc to count of sel
568
+ if sc > 0 then
569
+ set L to {}
570
+ repeat with j from 1 to sc
571
+ if j > 100 then exit repeat
572
+ set f to item j of sel
573
+ try
574
+ set end of L to POSIX path of (f as alias)
575
+ end try
576
+ end repeat
577
+ set {tid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, i}
578
+ set sec2 to L as string
579
+ set AppleScript's text item delimiters to tid
580
+ end if
581
+ end if
582
+ end tell
583
+
584
+ return sec0 & s & sec1 & s & sec2
585
+ `;
586
+ function parseOutput(out) {
587
+ const sections = out.split(SEC2);
588
+ const isFinderFrontmost = sections[0]?.trim() === "1";
589
+ const windows = [];
590
+ if (sections[1]?.trim()) {
591
+ for (const win of sections[1].split(ITM2)) {
592
+ const parts = win.split(FLD2);
593
+ if (parts.length >= 3) {
594
+ const rawPath = parts[1] ?? "";
595
+ const isSpecial = rawPath.startsWith("special:");
596
+ windows.push({
597
+ name: parts[0] ?? "",
598
+ path: isSpecial ? null : rawPath,
599
+ index: parseInt(parts[2] ?? "0", 10),
600
+ isSpecialView: isSpecial
601
+ });
602
+ }
603
+ }
604
+ }
605
+ const selectedPaths = [];
606
+ if (sections[2]?.trim()) {
607
+ for (const p of sections[2].split(ITM2)) {
608
+ if (p.trim()) {
609
+ selectedPaths.push(p);
610
+ }
611
+ }
612
+ }
613
+ let frontWindow = null;
614
+ if (isFinderFrontmost && windows.length > 0) {
615
+ const first = windows[0];
616
+ frontWindow = {
617
+ name: first.name,
618
+ path: first.path,
619
+ isSpecialView: first.isSpecialView
620
+ };
621
+ }
622
+ return {
623
+ windows,
624
+ frontWindow,
625
+ selectedPaths,
626
+ isFinderFrontmost,
627
+ windowCount: windows.length
628
+ };
629
+ }
630
+ async function getFinderContext(options) {
631
+ if (!isOsascriptAvailable()) {
632
+ return null;
633
+ }
634
+ const result = await executeAndParse(SCRIPT, parseOutput, options);
635
+ return result.success ? result.data ?? null : null;
636
+ }
637
+
638
+ // src/osascript/scripts/frontmostApp.ts
639
+ var DELIMITER = "|||";
640
+ var SCRIPT2 = `
641
+ tell application "System Events"
642
+ set frontApp to first application process whose frontmost is true
643
+ set appName to displayed name of frontApp
644
+ set appId to bundle identifier of frontApp
645
+ try
646
+ set appPath to POSIX path of (file of frontApp as alias)
647
+ on error
648
+ set appPath to ""
649
+ end try
650
+ return appName & "${DELIMITER}" & appId & "${DELIMITER}" & appPath
651
+ end tell
652
+ `;
653
+ function parseOutput2(output) {
654
+ const parts = output.split(DELIMITER);
655
+ const name = parts[0] ?? "";
656
+ const bundleId = parts[1] ?? "";
657
+ const path2 = parts[2] ?? "";
658
+ return {
659
+ name,
660
+ bundleId,
661
+ isFinder: bundleId === "com.apple.finder",
662
+ path: path2
663
+ };
664
+ }
665
+ async function getFrontmostApp(options) {
666
+ if (!isOsascriptAvailable()) {
667
+ return null;
668
+ }
669
+ const result = await executeAndParse(SCRIPT2, parseOutput2, options);
670
+ if (result.success && result.data) {
671
+ return result.data;
672
+ }
673
+ return null;
674
+ }
675
+
676
+ // src/osascript/scripts/finderSelection.ts
677
+ var FIELD_DELIMITER = "|||";
678
+ var ITEM_DELIMITER = ":::";
679
+ var SCRIPT3 = `
680
+ tell application "System Events"
681
+ set finderRunning to (exists process "Finder")
682
+ end tell
683
+
684
+ if finderRunning is false then
685
+ return ""
686
+ end if
687
+
688
+ tell application "Finder"
689
+ set sel to selection
690
+ if (count of sel) = 0 then
691
+ return ""
692
+ end if
693
+ set output to ""
694
+ repeat with f in sel
695
+ set p to POSIX path of (f as alias)
696
+ set n to name of f
697
+ set k to class of f as string
698
+ if output is not "" then
699
+ set output to output & "${ITEM_DELIMITER}"
700
+ end if
701
+ set output to output & p & "${FIELD_DELIMITER}" & n & "${FIELD_DELIMITER}" & k
702
+ end repeat
703
+ return output
704
+ end tell
705
+ `;
706
+ function parseOutput3(output) {
707
+ if (!output || output.trim() === "") {
708
+ return {
709
+ paths: [],
710
+ count: 0,
711
+ items: []
712
+ };
713
+ }
714
+ const itemStrings = output.split(ITEM_DELIMITER);
715
+ const items = [];
716
+ const paths = [];
717
+ for (const itemStr of itemStrings) {
718
+ const parts = itemStr.split(FIELD_DELIMITER);
719
+ if (parts.length >= 2) {
720
+ const path2 = parts[0] ?? "";
721
+ const name = parts[1] ?? "";
722
+ const classType = parts[2] ?? "";
723
+ const isFolder = classType.toLowerCase().includes("folder");
724
+ paths.push(path2);
725
+ items.push({
726
+ name,
727
+ path: path2,
728
+ isFolder
729
+ });
730
+ }
731
+ }
732
+ return {
733
+ paths,
734
+ count: items.length,
735
+ items
736
+ };
737
+ }
738
+ async function getFinderSelection(options) {
739
+ if (!isOsascriptAvailable()) {
740
+ return null;
741
+ }
742
+ const result = await executeAndParse(SCRIPT3, parseOutput3, options);
743
+ if (result.success && result.data) {
744
+ return result.data;
745
+ }
746
+ return null;
747
+ }
748
+ var CURRENT_FOLDER_SCRIPT = `
749
+ tell application "System Events"
750
+ set finderRunning to (exists process "Finder")
751
+ end tell
752
+
753
+ if finderRunning is false then
754
+ return ""
755
+ end if
756
+
757
+ tell application "Finder"
758
+ try
759
+ set frontWindow to front Finder window
760
+ set folderPath to POSIX path of (target of frontWindow as alias)
761
+ return folderPath
762
+ on error
763
+ return ""
764
+ end try
765
+ end tell
766
+ `;
767
+ async function getFinderCurrentFolder(options) {
768
+ if (!isOsascriptAvailable()) {
769
+ return null;
770
+ }
771
+ const result = await executeAndParse(
772
+ CURRENT_FOLDER_SCRIPT,
773
+ (output) => output.trim() || null,
774
+ options
775
+ );
776
+ if (result.success) {
777
+ return result.data ?? null;
778
+ }
779
+ return null;
780
+ }
781
+
782
+ // src/osascript/scripts/finderWindows.ts
783
+ var FIELD_DELIMITER2 = "|||";
784
+ var ITEM_DELIMITER2 = ":::";
785
+ var SCRIPT4 = `
786
+ tell application "System Events"
787
+ set finderRunning to (exists process "Finder")
788
+ end tell
789
+
790
+ if finderRunning is false then
791
+ return ""
792
+ end if
793
+
794
+ tell application "Finder"
795
+ set windowList to every Finder window
796
+ if (count of windowList) = 0 then
797
+ return ""
798
+ end if
799
+ set output to ""
800
+ set idx to 1
801
+ repeat with w in windowList
802
+ set windowName to name of w
803
+ set windowPath to ""
804
+ try
805
+ set windowPath to POSIX path of (target of w as alias)
806
+ on error
807
+ -- Special view (Recents, Search, etc.) - mark with special: prefix
808
+ set windowPath to "special:" & windowName
809
+ end try
810
+ if output is not "" then
811
+ set output to output & "${ITEM_DELIMITER2}"
812
+ end if
813
+ set output to output & windowName & "${FIELD_DELIMITER2}" & windowPath & "${FIELD_DELIMITER2}" & idx
814
+ set idx to idx + 1
815
+ end repeat
816
+ return output
817
+ end tell
818
+ `;
819
+ function parseOutput4(output) {
820
+ if (!output || output.trim() === "") {
821
+ return [];
822
+ }
823
+ const itemStrings = output.split(ITEM_DELIMITER2);
824
+ const windows = [];
825
+ for (const itemStr of itemStrings) {
826
+ const parts = itemStr.split(FIELD_DELIMITER2);
827
+ if (parts.length >= 3) {
828
+ const pathValue = parts[1] ?? "";
829
+ const isSpecial = pathValue.startsWith("special:");
830
+ windows.push({
831
+ name: parts[0] ?? "",
832
+ path: isSpecial ? null : pathValue,
833
+ index: parseInt(parts[2] ?? "0", 10),
834
+ isSpecialView: isSpecial
835
+ });
836
+ }
837
+ }
838
+ return windows;
839
+ }
840
+ async function getFinderWindows(options) {
841
+ if (!isOsascriptAvailable()) {
842
+ return null;
843
+ }
844
+ const result = await executeAndParse(SCRIPT4, parseOutput4, options);
845
+ if (result.success && result.data) {
846
+ return result.data;
847
+ }
848
+ return null;
849
+ }
850
+
851
+ // src/osascript/scripts/fileMetadata.ts
852
+ var DELIMITER2 = "|||";
853
+ function buildScript(filePath) {
854
+ const escapedPath = escapeForAppleScript(filePath);
855
+ return `
856
+ tell application "System Events"
857
+ set f to disk item (POSIX file "${escapedPath}")
858
+ set n to name of f
859
+ set p to "${escapedPath}"
860
+ try
861
+ set s to size of f
862
+ on error
863
+ set s to 0
864
+ end try
865
+ set isDir to (class of f is folder) as string
866
+ try
867
+ set c to creation date of f as string
868
+ on error
869
+ set c to ""
870
+ end try
871
+ try
872
+ set m to modification date of f as string
873
+ on error
874
+ set m to ""
875
+ end try
876
+ try
877
+ set ext to name extension of f
878
+ on error
879
+ set ext to ""
880
+ end try
881
+ try
882
+ set k to kind of f
883
+ on error
884
+ set k to ""
885
+ end try
886
+ return n & "${DELIMITER2}" & p & "${DELIMITER2}" & s & "${DELIMITER2}" & isDir & "${DELIMITER2}" & c & "${DELIMITER2}" & m & "${DELIMITER2}" & ext & "${DELIMITER2}" & k
887
+ end tell
888
+ `;
889
+ }
890
+ function parseOutput5(output) {
891
+ const parts = output.split(DELIMITER2);
892
+ return {
893
+ name: parts[0] ?? "",
894
+ path: parts[1] ?? "",
895
+ size: parseInt(parts[2] ?? "0", 10) || 0,
896
+ isFolder: (parts[3] ?? "").toLowerCase() === "true",
897
+ createdAt: parts[4] ?? "",
898
+ modifiedAt: parts[5] ?? "",
899
+ extension: parts[6] ?? "",
900
+ kind: parts[7] ?? ""
901
+ };
902
+ }
903
+ async function getFileMetadata(filePath, options) {
904
+ if (!isOsascriptAvailable()) {
905
+ return null;
906
+ }
907
+ const script = buildScript(filePath);
908
+ const result = await executeAndParse(script, parseOutput5, options);
909
+ if (result.success && result.data) {
910
+ return result.data;
911
+ }
912
+ return null;
913
+ }
914
+ async function getFilesMetadata(filePaths, options) {
915
+ if (!isOsascriptAvailable()) {
916
+ return filePaths.map(() => null);
917
+ }
918
+ const results = await Promise.all(
919
+ filePaths.map((path2) => getFileMetadata(path2, options))
920
+ );
921
+ return results;
922
+ }
923
+
924
+ // src/osascript/scripts/clipboard.ts
925
+ var DELIMITER3 = "|||";
926
+ var FILE_DELIMITER = ":::";
927
+ var TEXT_SCRIPT = `
928
+ try
929
+ set clipText to the clipboard as text
930
+ return clipText
931
+ on error
932
+ return ""
933
+ end try
934
+ `;
935
+ var FILES_SCRIPT = `
936
+ try
937
+ set clipFiles to the clipboard as alias list
938
+ set output to ""
939
+ repeat with f in clipFiles
940
+ set p to POSIX path of (f as alias)
941
+ if output is not "" then
942
+ set output to output & "${FILE_DELIMITER}"
943
+ end if
944
+ set output to output & p
945
+ end repeat
946
+ if output is "" then
947
+ return "NOFILES${DELIMITER3}"
948
+ end if
949
+ return "FILES${DELIMITER3}" & output
950
+ on error
951
+ return "NOFILES${DELIMITER3}"
952
+ end try
953
+ `;
954
+ var IMAGE_SCRIPT = `
955
+ try
956
+ set imgData to the clipboard as \xABclass PNGf\xBB
957
+ return "1"
958
+ on error
959
+ try
960
+ set imgData to the clipboard as TIFF picture
961
+ return "1"
962
+ on error
963
+ return "0"
964
+ end try
965
+ end try
966
+ `;
967
+ function parseFilesOutput(output) {
968
+ if (output.startsWith("FILES" + DELIMITER3)) {
969
+ const pathsPart = output.substring(("FILES" + DELIMITER3).length);
970
+ if (pathsPart.trim()) {
971
+ const paths = pathsPart.split(FILE_DELIMITER).filter((p) => p.trim());
972
+ return { hasFiles: paths.length > 0, filePaths: paths };
973
+ }
974
+ }
975
+ return { hasFiles: false, filePaths: [] };
976
+ }
977
+ async function getClipboardContent(options) {
978
+ if (!isOsascriptAvailable()) {
979
+ return null;
980
+ }
981
+ const [textResult, filesResult, imageResult] = await Promise.all([
982
+ executeAndParse(TEXT_SCRIPT, (output) => output || null, options),
983
+ executeAndParse(FILES_SCRIPT, parseFilesOutput, options),
984
+ executeAndParse(IMAGE_SCRIPT, (output) => output.trim() === "1", options)
985
+ ]);
986
+ const text = textResult.success ? textResult.data : null;
987
+ const filesData = filesResult.success && filesResult.data ? filesResult.data : { hasFiles: false, filePaths: [] };
988
+ const hasImage = imageResult.success ? imageResult.data ?? false : false;
989
+ return {
990
+ text: text ?? null,
991
+ hasFiles: filesData.hasFiles,
992
+ filePaths: filesData.filePaths,
993
+ hasImage
994
+ };
995
+ }
996
+ async function getClipboardText(options) {
997
+ if (!isOsascriptAvailable()) {
998
+ return null;
999
+ }
1000
+ const result = await executeAndParse(TEXT_SCRIPT, (output) => output || null, options);
1001
+ if (result.success) {
1002
+ return result.data ?? null;
1003
+ }
1004
+ return null;
1005
+ }
1006
+
1007
+ // src/osascript/scripts/desktopItems.ts
1008
+ var FIELD_DELIMITER3 = "|||";
1009
+ var ITEM_DELIMITER3 = ":::";
1010
+ var SCRIPT5 = `
1011
+ tell application "System Events"
1012
+ set finderRunning to (exists process "Finder")
1013
+ end tell
1014
+
1015
+ if finderRunning is false then
1016
+ return ""
1017
+ end if
1018
+
1019
+ tell application "Finder"
1020
+ set desktopItems to every item of desktop
1021
+ if (count of desktopItems) = 0 then
1022
+ return ""
1023
+ end if
1024
+ set output to ""
1025
+ repeat with f in desktopItems
1026
+ set n to name of f
1027
+ set p to POSIX path of (f as alias)
1028
+ set k to class of f as string
1029
+ if output is not "" then
1030
+ set output to output & "${ITEM_DELIMITER3}"
1031
+ end if
1032
+ set output to output & n & "${FIELD_DELIMITER3}" & p & "${FIELD_DELIMITER3}" & k
1033
+ end repeat
1034
+ return output
1035
+ end tell
1036
+ `;
1037
+ function parseOutput6(output) {
1038
+ if (!output || output.trim() === "") {
1039
+ return [];
1040
+ }
1041
+ const itemStrings = output.split(ITEM_DELIMITER3);
1042
+ const items = [];
1043
+ for (const itemStr of itemStrings) {
1044
+ const parts = itemStr.split(FIELD_DELIMITER3);
1045
+ if (parts.length >= 2) {
1046
+ const name = parts[0] ?? "";
1047
+ const path2 = parts[1] ?? "";
1048
+ const classType = parts[2] ?? "";
1049
+ items.push({
1050
+ name,
1051
+ path: path2,
1052
+ isFolder: classType.toLowerCase().includes("folder")
1053
+ });
1054
+ }
1055
+ }
1056
+ return items;
1057
+ }
1058
+ async function getDesktopItems(options) {
1059
+ if (!isOsascriptAvailable()) {
1060
+ return null;
1061
+ }
1062
+ const result = await executeAndParse(SCRIPT5, parseOutput6, options);
1063
+ if (result.success && result.data) {
1064
+ return result.data;
1065
+ }
1066
+ return null;
1067
+ }
1068
+ async function getDesktopPath(options) {
1069
+ if (!isOsascriptAvailable()) {
1070
+ return null;
1071
+ }
1072
+ const script = `try
1073
+ return do shell script "echo $HOME/Desktop/"
1074
+ on error
1075
+ return ""
1076
+ end try`;
1077
+ const result = await executeAndParse(script, (output) => output.trim() || null, options);
1078
+ if (result.success) {
1079
+ return result.data ?? null;
1080
+ }
1081
+ return null;
1082
+ }
1083
+
1084
+ // src/osascript/scripts/recentFiles.ts
1085
+ var FIELD_DELIMITER4 = "|||";
1086
+ var ITEM_DELIMITER4 = ":::";
1087
+ function buildScript2(limit) {
1088
+ return `
1089
+ tell application "System Events"
1090
+ set finderRunning to (exists process "Finder")
1091
+ end tell
1092
+
1093
+ if finderRunning is false then
1094
+ return ""
1095
+ end if
1096
+
1097
+ tell application "Finder"
1098
+ try
1099
+ set recentFolder to folder "Recents" of home
1100
+ set recentItems to every item of recentFolder
1101
+ set itemCount to count of recentItems
1102
+ if itemCount > ${limit} then
1103
+ set itemCount to ${limit}
1104
+ end if
1105
+ if itemCount = 0 then
1106
+ return ""
1107
+ end if
1108
+ set output to ""
1109
+ repeat with i from 1 to itemCount
1110
+ set f to item i of recentItems
1111
+ try
1112
+ set n to name of f
1113
+ set p to POSIX path of (f as alias)
1114
+ set m to modification date of f as string
1115
+ if output is not "" then
1116
+ set output to output & "${ITEM_DELIMITER4}"
1117
+ end if
1118
+ set output to output & n & "${FIELD_DELIMITER4}" & p & "${FIELD_DELIMITER4}" & m
1119
+ end try
1120
+ end repeat
1121
+ return output
1122
+ on error
1123
+ return ""
1124
+ end try
1125
+ end tell
1126
+ `;
1127
+ }
1128
+ var RECENT_DOCUMENTS_SCRIPT = `
1129
+ try
1130
+ set recentApps to paragraphs of (do shell script "mdfind -onlyin ~ 'kMDItemLastUsedDate >= $time.today(-7)' | head -50")
1131
+ set output to ""
1132
+ repeat with filePath in recentApps
1133
+ if filePath is not "" then
1134
+ try
1135
+ tell application "System Events"
1136
+ set f to disk item (POSIX file filePath)
1137
+ set n to name of f
1138
+ set m to modification date of f as string
1139
+ end tell
1140
+ if output is not "" then
1141
+ set output to output & "${ITEM_DELIMITER4}"
1142
+ end if
1143
+ set output to output & n & "${FIELD_DELIMITER4}" & filePath & "${FIELD_DELIMITER4}" & m
1144
+ end try
1145
+ end if
1146
+ end repeat
1147
+ return output
1148
+ on error
1149
+ return ""
1150
+ end try
1151
+ `;
1152
+ function parseOutput7(output) {
1153
+ if (!output || output.trim() === "") {
1154
+ return [];
1155
+ }
1156
+ const itemStrings = output.split(ITEM_DELIMITER4);
1157
+ const items = [];
1158
+ for (const itemStr of itemStrings) {
1159
+ const parts = itemStr.split(FIELD_DELIMITER4);
1160
+ if (parts.length >= 2) {
1161
+ items.push({
1162
+ name: parts[0] ?? "",
1163
+ path: parts[1] ?? "",
1164
+ accessedAt: parts[2] ?? ""
1165
+ });
1166
+ }
1167
+ }
1168
+ return items;
1169
+ }
1170
+ async function getRecentFiles(limit = 20, options) {
1171
+ if (!isOsascriptAvailable()) {
1172
+ return null;
1173
+ }
1174
+ const script = buildScript2(limit);
1175
+ const result = await executeAndParse(script, parseOutput7, options);
1176
+ if (result.success && result.data) {
1177
+ return result.data;
1178
+ }
1179
+ return null;
1180
+ }
1181
+ async function getRecentDocuments(options) {
1182
+ if (!isOsascriptAvailable()) {
1183
+ return null;
1184
+ }
1185
+ const result = await executeAndParse(RECENT_DOCUMENTS_SCRIPT, parseOutput7, options);
1186
+ if (result.success && result.data) {
1187
+ return result.data;
1188
+ }
1189
+ return null;
1190
+ }
1191
+
1192
+ // src/osascript/scripts/runningApps.ts
1193
+ var FIELD_DELIMITER5 = "|||";
1194
+ var ITEM_DELIMITER5 = ":::";
1195
+ var SCRIPT6 = `
1196
+ tell application "System Events"
1197
+ set appList to every application process
1198
+ set output to ""
1199
+ repeat with proc in appList
1200
+ try
1201
+ set appName to name of proc
1202
+ set appId to bundle identifier of proc
1203
+ set isHidden to not (visible of proc)
1204
+ set isFront to frontmost of proc
1205
+ if output is not "" then
1206
+ set output to output & "${ITEM_DELIMITER5}"
1207
+ end if
1208
+ set output to output & appName & "${FIELD_DELIMITER5}" & appId & "${FIELD_DELIMITER5}" & (isHidden as string) & "${FIELD_DELIMITER5}" & (isFront as string)
1209
+ end try
1210
+ end repeat
1211
+ return output
1212
+ end tell
1213
+ `;
1214
+ function parseOutput8(output) {
1215
+ if (!output || output.trim() === "") {
1216
+ return [];
1217
+ }
1218
+ const itemStrings = output.split(ITEM_DELIMITER5);
1219
+ const apps = [];
1220
+ for (const itemStr of itemStrings) {
1221
+ const parts = itemStr.split(FIELD_DELIMITER5);
1222
+ if (parts.length >= 4) {
1223
+ apps.push({
1224
+ name: parts[0] ?? "",
1225
+ bundleId: parts[1] ?? "",
1226
+ isHidden: (parts[2] ?? "").toLowerCase() === "true",
1227
+ isFrontmost: (parts[3] ?? "").toLowerCase() === "true"
1228
+ });
1229
+ }
1230
+ }
1231
+ return apps;
1232
+ }
1233
+ async function getRunningApps(options) {
1234
+ if (!isOsascriptAvailable()) {
1235
+ return null;
1236
+ }
1237
+ const result = await executeAndParse(SCRIPT6, parseOutput8, options);
1238
+ if (result.success && result.data) {
1239
+ return result.data;
1240
+ }
1241
+ return null;
1242
+ }
1243
+ async function isAppRunning(appName, options) {
1244
+ const apps = await getRunningApps(options);
1245
+ if (!apps) {
1246
+ return false;
1247
+ }
1248
+ const lowerName = appName.toLowerCase();
1249
+ return apps.some(
1250
+ (app) => app.name.toLowerCase() === lowerName || app.bundleId.toLowerCase() === lowerName
1251
+ );
1252
+ }
1253
+ async function getFrontmostFromRunning(options) {
1254
+ const apps = await getRunningApps(options);
1255
+ if (!apps) {
1256
+ return null;
1257
+ }
1258
+ return apps.find((app) => app.isFrontmost) ?? null;
1259
+ }
1260
+
1261
+ // src/osascript/scripts/fileContent.ts
1262
+ var DELIMITER4 = "\xA7\xA7\xA7";
1263
+ async function readFileContent(filePath, opts) {
1264
+ if (!isOsascriptAvailable()) return null;
1265
+ const maxBytes = opts?.maxBytes ?? 1048576;
1266
+ const encoding = opts?.encoding ?? "utf8";
1267
+ const script = `
1268
+ set filePath to "${filePath.replace(/"/g, '\\"')}"
1269
+ set maxSize to ${maxBytes}
1270
+ set d to "${DELIMITER4}"
1271
+
1272
+ try
1273
+ set fileRef to POSIX file filePath
1274
+
1275
+ -- Get file size first
1276
+ tell application "System Events"
1277
+ set fileSize to size of (disk item filePath)
1278
+ end tell
1279
+
1280
+ -- Check size limit
1281
+ if fileSize > maxSize then
1282
+ return "ERROR" & d & "File too large: " & fileSize & " bytes (max: " & maxSize & ")"
1283
+ end if
1284
+
1285
+ -- Read file content
1286
+ set fileContent to read fileRef as \xABclass utf8\xBB
1287
+
1288
+ return "OK" & d & fileSize & d & fileContent
1289
+ on error errMsg
1290
+ return "ERROR" & d & errMsg
1291
+ end try
1292
+ `;
1293
+ const parser = (out) => {
1294
+ const parts = out.split(DELIMITER4);
1295
+ const status = parts[0]?.trim();
1296
+ if (status === "ERROR") {
1297
+ return {
1298
+ path: filePath,
1299
+ content: "",
1300
+ size: 0,
1301
+ success: false,
1302
+ error: parts[1]?.trim() || "Unknown error"
1303
+ };
1304
+ }
1305
+ return {
1306
+ path: filePath,
1307
+ content: parts.slice(2).join(DELIMITER4),
1308
+ // Content may contain delimiter
1309
+ size: parseInt(parts[1] ?? "0", 10),
1310
+ success: true
1311
+ };
1312
+ };
1313
+ const r = await executeAndParse(script, parser, opts);
1314
+ return r.success ? r.data ?? null : null;
1315
+ }
1316
+ async function readMultipleFiles(filePaths, opts) {
1317
+ if (!isOsascriptAvailable()) return [];
1318
+ const results = await Promise.all(
1319
+ filePaths.map((path2) => readFileContent(path2, opts))
1320
+ );
1321
+ return results.filter((r) => r !== null);
1322
+ }
1323
+
1324
+ // src/osascript/index.ts
1325
+ async function getSystemContext(options) {
1326
+ if (!isOsascriptAvailable()) {
1327
+ return null;
1328
+ }
1329
+ const frontmostApp = await getFrontmostApp(options);
1330
+ if (!frontmostApp) {
1331
+ return null;
1332
+ }
1333
+ let finderSelection = null;
1334
+ let finderCurrentFolder = null;
1335
+ if (frontmostApp.isFinder) {
1336
+ [finderSelection, finderCurrentFolder] = await Promise.all([
1337
+ getFinderSelection(options),
1338
+ getFinderCurrentFolder(options)
1339
+ ]);
1340
+ }
1341
+ const clipboard = await getClipboardContent(options);
1342
+ return {
1343
+ frontmostApp,
1344
+ finderSelection,
1345
+ finderCurrentFolder,
1346
+ clipboard: clipboard ?? { text: null, hasFiles: false, filePaths: [], hasImage: false }
1347
+ };
1348
+ }
1349
+
1350
+ // src/index.ts
1351
+ var IS_MACOS2 = process.platform === "darwin";
15
1352
  var IS_WINDOWS = process.platform === "win32";
16
1353
  var PLATFORM_PACKAGES = {
17
1354
  "darwin-arm64": "@simen-keyboard-listener/darwin-arm64",
@@ -48,7 +1385,7 @@ function getNativeAddon() {
48
1385
  try {
49
1386
  const candidate = localRequire(packageName);
50
1387
  const hasCoreFunctions = candidate && typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.isRunning === "function" && typeof candidate.checkPermission === "function";
51
- const hasMacOSFunctions = IS_MACOS ? typeof candidate.getFocusedInputValue === "function" && typeof candidate.getFocusedInputSelectedText === "function" : true;
1388
+ const hasMacOSFunctions = IS_MACOS2 ? typeof candidate.getFocusedInputValue === "function" && typeof candidate.getFocusedInputSelectedText === "function" : true;
52
1389
  if (hasCoreFunctions && hasMacOSFunctions) {
53
1390
  nativeAddon = candidate;
54
1391
  return nativeAddon;
@@ -165,7 +1502,7 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
165
1502
  }
166
1503
  };
167
1504
  function getGlobalKeyboardListener() {
168
- if (!IS_MACOS && !IS_WINDOWS) {
1505
+ if (!IS_MACOS2 && !IS_WINDOWS) {
169
1506
  throw new Error(`Unsupported platform for global keyboard listener: ${process.platform}`);
170
1507
  }
171
1508
  return NativeKeyboardListener.getInstance();
@@ -174,7 +1511,7 @@ function createGlobalKeyboardListener() {
174
1511
  return getGlobalKeyboardListener();
175
1512
  }
176
1513
  function checkKeyboardPermission() {
177
- if (!IS_MACOS && !IS_WINDOWS) {
1514
+ if (!IS_MACOS2 && !IS_WINDOWS) {
178
1515
  return false;
179
1516
  }
180
1517
  try {
@@ -186,7 +1523,7 @@ function checkKeyboardPermission() {
186
1523
  }
187
1524
  var lastMacAccessibilitySettingsOpenTs = 0;
188
1525
  function openMacAccessibilitySettings() {
189
- if (!IS_MACOS) {
1526
+ if (!IS_MACOS2) {
190
1527
  return;
191
1528
  }
192
1529
  const now = Date.now();
@@ -212,7 +1549,7 @@ function ensureAccessibilityPermission(addon) {
212
1549
  return false;
213
1550
  }
214
1551
  function getFocusedInputValue() {
215
- if (!IS_MACOS) {
1552
+ if (!IS_MACOS2) {
216
1553
  return null;
217
1554
  }
218
1555
  const addon = getNativeAddon();
@@ -226,7 +1563,7 @@ function getFocusedInputValue() {
226
1563
  }
227
1564
  }
228
1565
  function getFocusedInputSelectedText() {
229
- if (!IS_MACOS) {
1566
+ if (!IS_MACOS2) {
230
1567
  return null;
231
1568
  }
232
1569
  const addon = getNativeAddon();
@@ -240,7 +1577,7 @@ function getFocusedInputSelectedText() {
240
1577
  }
241
1578
  }
242
1579
  function getContextJSON() {
243
- if (!IS_MACOS) return null;
1580
+ if (!IS_MACOS2) return null;
244
1581
  const addon = getNativeAddon();
245
1582
  if (!ensureAccessibilityPermission(addon)) return null;
246
1583
  try {
@@ -250,7 +1587,7 @@ function getContextJSON() {
250
1587
  }
251
1588
  }
252
1589
  function getSelectedTextSmart() {
253
- if (!IS_MACOS) return null;
1590
+ if (!IS_MACOS2) return null;
254
1591
  const addon = getNativeAddon();
255
1592
  if (!ensureAccessibilityPermission(addon)) return null;
256
1593
  try {
@@ -272,10 +1609,36 @@ function setBlockSystemHotkeys(block) {
272
1609
  export {
273
1610
  checkKeyboardPermission,
274
1611
  createGlobalKeyboardListener,
1612
+ escapeForAppleScript,
1613
+ executeAndParse,
1614
+ executeAppleScript,
1615
+ executeAppleScriptLines,
1616
+ executeMultilineAndParse,
1617
+ getAgentContext,
1618
+ getClipboardContent,
1619
+ getClipboardText,
275
1620
  getContextJSON,
1621
+ getDesktopItems,
1622
+ getDesktopPath,
1623
+ getFileMetadata,
1624
+ getFilesMetadata,
1625
+ getFinderContext,
1626
+ getFinderCurrentFolder,
1627
+ getFinderSelection,
1628
+ getFinderWindows,
276
1629
  getFocusedInputSelectedText,
277
1630
  getFocusedInputValue,
1631
+ getFrontmostApp,
1632
+ getFrontmostFromRunning,
278
1633
  getGlobalKeyboardListener,
1634
+ getRecentDocuments,
1635
+ getRecentFiles,
1636
+ getRunningApps,
279
1637
  getSelectedTextSmart,
1638
+ getSystemContext,
1639
+ isAppRunning,
1640
+ isOsascriptAvailable,
1641
+ readFileContent,
1642
+ readMultipleFiles,
280
1643
  setBlockSystemHotkeys
281
1644
  };