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