simen-keyboard-listener 1.1.11 → 1.1.12

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
@@ -1,9 +1,14 @@
1
+ var __defProp = Object.defineProperty;
1
2
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
3
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
4
  }) : x)(function(x) {
4
5
  if (typeof require !== "undefined") return require.apply(this, arguments);
5
6
  throw Error('Dynamic require of "' + x + '" is not supported');
6
7
  });
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
7
12
 
8
13
  // src/index.ts
9
14
  import * as path from "path";
@@ -1347,9 +1352,887 @@ async function getSystemContext(options) {
1347
1352
  };
1348
1353
  }
1349
1354
 
1355
+ // src/powershell/index.ts
1356
+ var powershell_exports = {};
1357
+ __export(powershell_exports, {
1358
+ escapeForPowerShell: () => escapeForPowerShell,
1359
+ executeAndParse: () => executeAndParse2,
1360
+ executeMultilineAndParse: () => executeMultilineAndParse2,
1361
+ executePowerShell: () => executePowerShell,
1362
+ executePowerShellLines: () => executePowerShellLines,
1363
+ getAgentContext: () => getAgentContext2,
1364
+ getClipboardContent: () => getClipboardContent2,
1365
+ getClipboardText: () => getClipboardText2,
1366
+ getExplorerCurrentFolder: () => getExplorerCurrentFolder,
1367
+ getExplorerSelection: () => getExplorerSelection,
1368
+ getExplorerWindows: () => getExplorerWindows,
1369
+ getFrontmostApp: () => getFrontmostApp2,
1370
+ getSystemContext: () => getSystemContext2,
1371
+ isPowerShellAvailable: () => isPowerShellAvailable
1372
+ });
1373
+
1374
+ // src/powershell/executor.ts
1375
+ import { execFile as execFile2 } from "child_process";
1376
+ import { promisify as promisify2 } from "util";
1377
+ var execFileAsync2 = promisify2(execFile2);
1378
+ var IS_WINDOWS = process.platform === "win32";
1379
+ var POWERSHELL_PATHS = [
1380
+ "pwsh.exe",
1381
+ // PowerShell Core (faster, recommended)
1382
+ "powershell.exe"
1383
+ // Windows PowerShell (legacy)
1384
+ ];
1385
+ var DEFAULT_TIMEOUT2 = 3e4;
1386
+ var cachedPowerShellPath = null;
1387
+ async function findPowerShell() {
1388
+ if (cachedPowerShellPath) {
1389
+ return cachedPowerShellPath;
1390
+ }
1391
+ for (const psPath of POWERSHELL_PATHS) {
1392
+ try {
1393
+ await execFileAsync2(psPath, ["-NoProfile", "-Command", "exit 0"], { timeout: 5e3 });
1394
+ cachedPowerShellPath = psPath;
1395
+ return psPath;
1396
+ } catch {
1397
+ }
1398
+ }
1399
+ return null;
1400
+ }
1401
+ function isPowerShellAvailable() {
1402
+ return IS_WINDOWS;
1403
+ }
1404
+ async function executePowerShell(script, options) {
1405
+ if (!IS_WINDOWS) {
1406
+ return {
1407
+ success: false,
1408
+ error: "PowerShell is only available on Windows"
1409
+ };
1410
+ }
1411
+ const psPath = await findPowerShell();
1412
+ if (!psPath) {
1413
+ return {
1414
+ success: false,
1415
+ error: "PowerShell not found. Please install PowerShell Core or Windows PowerShell."
1416
+ };
1417
+ }
1418
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT2;
1419
+ const startTime = Date.now();
1420
+ try {
1421
+ const { stdout, stderr } = await execFileAsync2(
1422
+ psPath,
1423
+ [
1424
+ "-NoProfile",
1425
+ // Don't load user profile (faster)
1426
+ "-NonInteractive",
1427
+ // Non-interactive mode
1428
+ "-ExecutionPolicy",
1429
+ "Bypass",
1430
+ // Bypass execution policy
1431
+ "-Command",
1432
+ script
1433
+ ],
1434
+ {
1435
+ timeout,
1436
+ // Set output encoding to UTF-8 to handle Chinese characters
1437
+ encoding: "utf8"
1438
+ }
1439
+ );
1440
+ const executionTime = Date.now() - startTime;
1441
+ if (stderr && stderr.trim() && !stdout) {
1442
+ return {
1443
+ success: false,
1444
+ error: stderr.trim(),
1445
+ executionTime
1446
+ };
1447
+ }
1448
+ return {
1449
+ success: true,
1450
+ data: stdout.trim(),
1451
+ executionTime
1452
+ };
1453
+ } catch (error) {
1454
+ const executionTime = Date.now() - startTime;
1455
+ const errorMessage = error instanceof Error ? error.message : String(error);
1456
+ return {
1457
+ success: false,
1458
+ error: errorMessage,
1459
+ executionTime
1460
+ };
1461
+ }
1462
+ }
1463
+ async function executePowerShellLines(lines, options) {
1464
+ const script = lines.join("; ");
1465
+ return executePowerShell(script, options);
1466
+ }
1467
+ async function executeAndParse2(script, parser, options) {
1468
+ const result = await executePowerShell(script, options);
1469
+ if (!result.success) {
1470
+ return {
1471
+ success: false,
1472
+ error: result.error,
1473
+ executionTime: result.executionTime
1474
+ };
1475
+ }
1476
+ try {
1477
+ const parsed = parser(result.data ?? "");
1478
+ return {
1479
+ success: true,
1480
+ data: parsed,
1481
+ executionTime: result.executionTime
1482
+ };
1483
+ } catch (parseError) {
1484
+ const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
1485
+ return {
1486
+ success: false,
1487
+ error: `Failed to parse output: ${errorMessage}`,
1488
+ executionTime: result.executionTime
1489
+ };
1490
+ }
1491
+ }
1492
+ async function executeMultilineAndParse2(lines, parser, options) {
1493
+ const result = await executePowerShellLines(lines, options);
1494
+ if (!result.success) {
1495
+ return {
1496
+ success: false,
1497
+ error: result.error,
1498
+ executionTime: result.executionTime
1499
+ };
1500
+ }
1501
+ try {
1502
+ const parsed = parser(result.data ?? "");
1503
+ return {
1504
+ success: true,
1505
+ data: parsed,
1506
+ executionTime: result.executionTime
1507
+ };
1508
+ } catch (parseError) {
1509
+ const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
1510
+ return {
1511
+ success: false,
1512
+ error: `Failed to parse output: ${errorMessage}`,
1513
+ executionTime: result.executionTime
1514
+ };
1515
+ }
1516
+ }
1517
+ function escapeForPowerShell(str) {
1518
+ return str.replace(/`/g, "``").replace(/"/g, '`"').replace(/\$/g, "`$").replace(/\n/g, "`n").replace(/\r/g, "`r").replace(/\t/g, "`t");
1519
+ }
1520
+
1521
+ // src/powershell/scripts/batchContext.ts
1522
+ async function getAgentContext2(options) {
1523
+ const includeClipboard = options?.includeClipboard ?? true;
1524
+ const includeExplorerWindows = options?.includeExplorerWindows ?? true;
1525
+ const maxSelectedItems = options?.maxSelectedItems ?? 50;
1526
+ const script = `
1527
+ # Add required types
1528
+ try {
1529
+ Add-Type -AssemblyName System.Windows.Forms
1530
+ } catch {
1531
+ # Assembly may already be loaded, ignore error
1532
+ }
1533
+
1534
+ try {
1535
+ Add-Type @"
1536
+ using System;
1537
+ using System.Runtime.InteropServices;
1538
+ using System.Text;
1539
+
1540
+ public class Win32 {
1541
+ [DllImport("user32.dll")]
1542
+ public static extern IntPtr GetForegroundWindow();
1543
+
1544
+ [DllImport("user32.dll")]
1545
+ public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
1546
+
1547
+ [DllImport("user32.dll")]
1548
+ public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId);
1549
+ }
1550
+ "@
1551
+ } catch {
1552
+ # Type may already be loaded, ignore error
1553
+ }
1554
+
1555
+ # Initialize result object
1556
+ $result = @{
1557
+ frontmostApp = $null
1558
+ explorerSelection = $null
1559
+ explorerCurrentFolder = $null
1560
+ explorerWindows = @()
1561
+ desktopPath = ""
1562
+ clipboard = @{
1563
+ text = $null
1564
+ hasFiles = $false
1565
+ filePaths = @()
1566
+ hasImage = $false
1567
+ }
1568
+ timestamp = (Get-Date -Format "o")
1569
+ }
1570
+
1571
+ # ============================================================================
1572
+ # 1. Get Frontmost Application
1573
+ # ============================================================================
1574
+ try {
1575
+ $hwnd = [Win32]::GetForegroundWindow()
1576
+ if ($hwnd -ne [IntPtr]::Zero) {
1577
+ $processId = 0
1578
+ [Win32]::GetWindowThreadProcessId($hwnd, [ref]$processId) | Out-Null
1579
+
1580
+ $process = Get-Process -Id $processId -ErrorAction SilentlyContinue
1581
+ if ($process) {
1582
+ $windowTitle = New-Object System.Text.StringBuilder 256
1583
+ [Win32]::GetWindowText($hwnd, $windowTitle, 256) | Out-Null
1584
+
1585
+ $processName = $process.ProcessName
1586
+ $path = ""
1587
+ try {
1588
+ $path = $process.Path
1589
+ if (-not $path) {
1590
+ $path = $process.MainModule.FileName
1591
+ }
1592
+ } catch {
1593
+ $path = ""
1594
+ }
1595
+
1596
+ $name = $process.MainWindowTitle
1597
+ if (-not $name -or $name -eq "") {
1598
+ $name = $processName
1599
+ }
1600
+
1601
+ $isExplorer = $processName -eq "explorer"
1602
+
1603
+ $result.frontmostApp = @{
1604
+ name = $name
1605
+ processName = $processName
1606
+ path = $path
1607
+ processId = $processId
1608
+ windowTitle = $windowTitle.ToString()
1609
+ isExplorer = $isExplorer
1610
+ }
1611
+ }
1612
+ }
1613
+ } catch {
1614
+ # Frontmost app detection failed
1615
+ }
1616
+
1617
+ # ============================================================================
1618
+ # 2. Get Explorer Context (if frontmost app is Explorer)
1619
+ # ============================================================================
1620
+ if ($result.frontmostApp -and $result.frontmostApp.isExplorer) {
1621
+ try {
1622
+ $shell = New-Object -ComObject Shell.Application
1623
+ $windows = $shell.Windows()
1624
+
1625
+ $activeHwnd = [Win32]::GetForegroundWindow()
1626
+ $selectedItems = @()
1627
+ $currentFolder = $null
1628
+ $explorerWindows = @()
1629
+ $foundActiveWindow = $false
1630
+
1631
+ foreach ($window in $windows) {
1632
+ if ($window.Name -eq "File Explorer" -or $window.FullName -like "*explorer.exe") {
1633
+ try {
1634
+ $path = $window.Document.Folder.Self.Path
1635
+ if ($path) {
1636
+ # Check if this is the active window
1637
+ $isActive = $false
1638
+ try {
1639
+ $hwnd = $window.HWND
1640
+ if ($hwnd -eq $activeHwnd.ToInt64()) {
1641
+ $isActive = $true
1642
+
1643
+ # Get current folder for active window
1644
+ $currentFolder = $path
1645
+
1646
+ # Get selected items for active window
1647
+ $items = $window.Document.SelectedItems()
1648
+ if ($items -and $items.Count -gt 0) {
1649
+ foreach ($item in $items) {
1650
+ if ($selectedItems.Count -ge ${maxSelectedItems}) {
1651
+ break
1652
+ }
1653
+
1654
+ $isFolder = $false
1655
+ try {
1656
+ $isFolder = $item.IsFolder
1657
+ } catch {
1658
+ try {
1659
+ if (Test-Path $item.Path -PathType Container) {
1660
+ $isFolder = $true
1661
+ }
1662
+ } catch {
1663
+ $isFolder = $false
1664
+ }
1665
+ }
1666
+
1667
+ $selectedItems += @{
1668
+ path = if ($item.Path) { $item.Path } else { "" }
1669
+ name = if ($item.Name) { $item.Name } else { "" }
1670
+ isFolder = $isFolder
1671
+ }
1672
+ }
1673
+ }
1674
+ }
1675
+ } catch {
1676
+ # HWND may not be accessible
1677
+ }
1678
+
1679
+ # Add to explorer windows list (if enabled)
1680
+ if (${includeExplorerWindows}) {
1681
+ $title = $window.LocationName
1682
+ if (-not $title) {
1683
+ $title = Split-Path $path -Leaf
1684
+ }
1685
+
1686
+ $explorerWindows += @{
1687
+ title = if ($title) { $title } else { "" }
1688
+ path = if ($path) { $path } else { "" }
1689
+ isActive = $isActive
1690
+ }
1691
+ }
1692
+ }
1693
+ } catch {
1694
+ # Window may not have a valid path
1695
+ }
1696
+ }
1697
+ }
1698
+
1699
+ # Set explorer selection
1700
+ if ($selectedItems.Count -gt 0) {
1701
+ $result.explorerSelection = @{
1702
+ items = $selectedItems
1703
+ count = $selectedItems.Count
1704
+ }
1705
+ }
1706
+
1707
+ # Set current folder
1708
+ $result.explorerCurrentFolder = $currentFolder
1709
+
1710
+ # Set explorer windows
1711
+ $result.explorerWindows = $explorerWindows
1712
+
1713
+ } catch {
1714
+ # Explorer context detection failed
1715
+ }
1716
+ }
1717
+
1718
+ # ============================================================================
1719
+ # 3. Get Desktop Path
1720
+ # ============================================================================
1721
+ try {
1722
+ $result.desktopPath = [Environment]::GetFolderPath("Desktop")
1723
+ } catch {
1724
+ $result.desktopPath = ""
1725
+ }
1726
+
1727
+ # ============================================================================
1728
+ # 4. Get Clipboard Content (if enabled)
1729
+ # ============================================================================
1730
+ if (${includeClipboard}) {
1731
+ try {
1732
+ $clipboardData = [System.Windows.Forms.Clipboard]::GetDataObject()
1733
+ if ($clipboardData) {
1734
+ # Check for text
1735
+ if ($clipboardData.GetDataPresent([System.Windows.Forms.DataFormats]::Text)) {
1736
+ $result.clipboard.text = $clipboardData.GetData([System.Windows.Forms.DataFormats]::Text)
1737
+ }
1738
+
1739
+ # Check for files
1740
+ if ($clipboardData.GetDataPresent([System.Windows.Forms.DataFormats]::FileDrop)) {
1741
+ $result.clipboard.hasFiles = $true
1742
+ $files = $clipboardData.GetData([System.Windows.Forms.DataFormats]::FileDrop)
1743
+ if ($files) {
1744
+ $result.clipboard.filePaths = @($files)
1745
+ }
1746
+ }
1747
+
1748
+ # Check for image
1749
+ if ($clipboardData.GetDataPresent([System.Windows.Forms.DataFormats]::Bitmap)) {
1750
+ $result.clipboard.hasImage = $true
1751
+ }
1752
+ }
1753
+ } catch {
1754
+ # Clipboard access failed
1755
+ }
1756
+ }
1757
+
1758
+ # ============================================================================
1759
+ # Output JSON
1760
+ # ============================================================================
1761
+ $result | ConvertTo-Json -Compress -Depth 4
1762
+ `;
1763
+ const result = await executeAndParse2(
1764
+ script,
1765
+ (output) => {
1766
+ if (!output) {
1767
+ throw new Error("No output from PowerShell script");
1768
+ }
1769
+ const parsed = JSON.parse(output);
1770
+ return {
1771
+ frontmostApp: parsed.frontmostApp || {
1772
+ name: "",
1773
+ processName: "",
1774
+ path: "",
1775
+ processId: 0,
1776
+ windowTitle: "",
1777
+ isExplorer: false
1778
+ },
1779
+ explorerSelection: parsed.explorerSelection || null,
1780
+ explorerCurrentFolder: parsed.explorerCurrentFolder || null,
1781
+ explorerWindows: parsed.explorerWindows || [],
1782
+ desktopPath: parsed.desktopPath || "",
1783
+ clipboard: {
1784
+ text: parsed.clipboard?.text || null,
1785
+ hasFiles: parsed.clipboard?.hasFiles || false,
1786
+ filePaths: parsed.clipboard?.filePaths || [],
1787
+ hasImage: parsed.clipboard?.hasImage || false
1788
+ },
1789
+ timestamp: parsed.timestamp || (/* @__PURE__ */ new Date()).toISOString()
1790
+ };
1791
+ },
1792
+ options
1793
+ );
1794
+ if (!result.success) {
1795
+ return null;
1796
+ }
1797
+ return result.data ?? null;
1798
+ }
1799
+
1800
+ // src/powershell/scripts/frontmostApp.ts
1801
+ async function getFrontmostApp2(options) {
1802
+ const script = `
1803
+ try {
1804
+ Add-Type @"
1805
+ using System;
1806
+ using System.Runtime.InteropServices;
1807
+ using System.Text;
1808
+
1809
+ public class Win32 {
1810
+ [DllImport("user32.dll")]
1811
+ public static extern IntPtr GetForegroundWindow();
1812
+
1813
+ [DllImport("user32.dll")]
1814
+ public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
1815
+
1816
+ [DllImport("user32.dll")]
1817
+ public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId);
1818
+ }
1819
+ "@
1820
+ } catch {
1821
+ # Type may already be loaded, ignore error
1822
+ }
1823
+
1824
+ $hwnd = [Win32]::GetForegroundWindow()
1825
+ if ($hwnd -eq [IntPtr]::Zero) {
1826
+ Write-Output "{}"
1827
+ exit
1828
+ }
1829
+
1830
+ $processId = 0
1831
+ [Win32]::GetWindowThreadProcessId($hwnd, [ref]$processId) | Out-Null
1832
+
1833
+ $process = Get-Process -Id $processId -ErrorAction SilentlyContinue
1834
+ if (-not $process) {
1835
+ Write-Output "{}"
1836
+ exit
1837
+ }
1838
+
1839
+ $windowTitle = New-Object System.Text.StringBuilder 256
1840
+ [Win32]::GetWindowText($hwnd, $windowTitle, 256) | Out-Null
1841
+
1842
+ $processName = $process.ProcessName
1843
+ $path = ""
1844
+ try {
1845
+ $path = $process.Path
1846
+ if (-not $path) {
1847
+ $path = $process.MainModule.FileName
1848
+ }
1849
+ } catch {
1850
+ $path = ""
1851
+ }
1852
+
1853
+ $name = $process.MainWindowTitle
1854
+ if (-not $name -or $name -eq "") {
1855
+ $name = $processName
1856
+ }
1857
+
1858
+ $isExplorer = ($processName -eq "explorer")
1859
+
1860
+ $result = @{
1861
+ name = if ($name) { $name } else { "" }
1862
+ processName = if ($processName) { $processName } else { "" }
1863
+ path = if ($path) { $path } else { "" }
1864
+ processId = $processId
1865
+ windowTitle = $windowTitle.ToString()
1866
+ isExplorer = $isExplorer
1867
+ }
1868
+
1869
+ $result | ConvertTo-Json -Compress
1870
+ `;
1871
+ const result = await executeAndParse2(
1872
+ script,
1873
+ (output) => {
1874
+ if (!output || output === "{}") {
1875
+ throw new Error("No frontmost window found");
1876
+ }
1877
+ return JSON.parse(output);
1878
+ },
1879
+ options
1880
+ );
1881
+ if (!result.success) {
1882
+ return null;
1883
+ }
1884
+ return result.data ?? null;
1885
+ }
1886
+
1887
+ // src/powershell/scripts/explorerSelection.ts
1888
+ async function getExplorerSelection(options) {
1889
+ const maxItems = 50;
1890
+ const script = `
1891
+ try {
1892
+ $shell = New-Object -ComObject Shell.Application
1893
+ $windows = $shell.Windows()
1894
+
1895
+ $selectedItems = @()
1896
+ $foundSelection = $false
1897
+
1898
+ foreach ($window in $windows) {
1899
+ if ($foundSelection) { break }
1900
+
1901
+ # Check if this is an Explorer window
1902
+ if ($window.Name -eq "File Explorer" -or $window.FullName -like "*explorer.exe") {
1903
+ try {
1904
+ $items = $window.Document.SelectedItems()
1905
+ if ($items -and $items.Count -gt 0) {
1906
+ foreach ($item in $items) {
1907
+ if ($selectedItems.Count -ge ${maxItems}) {
1908
+ break
1909
+ }
1910
+
1911
+ $isFolder = $false
1912
+ try {
1913
+ $isFolder = $item.IsFolder
1914
+ } catch {
1915
+ # If IsFolder fails, check if it's a directory
1916
+ try {
1917
+ if (Test-Path $item.Path -PathType Container) {
1918
+ $isFolder = $true
1919
+ }
1920
+ } catch {
1921
+ $isFolder = $false
1922
+ }
1923
+ }
1924
+
1925
+ $selectedItems += @{
1926
+ path = if ($item.Path) { $item.Path } else { "" }
1927
+ name = if ($item.Name) { $item.Name } else { "" }
1928
+ isFolder = $isFolder
1929
+ }
1930
+ }
1931
+ $foundSelection = $true
1932
+ }
1933
+ } catch {
1934
+ # Window may not support selection, continue to next window
1935
+ }
1936
+ }
1937
+ }
1938
+
1939
+ $result = @{
1940
+ items = $selectedItems
1941
+ count = $selectedItems.Count
1942
+ }
1943
+
1944
+ $result | ConvertTo-Json -Compress -Depth 3
1945
+ } catch {
1946
+ # COM object creation failed or other error
1947
+ Write-Output '{"items":[],"count":0}'
1948
+ }
1949
+ `;
1950
+ const result = await executeAndParse2(
1951
+ script,
1952
+ (output) => {
1953
+ if (!output) {
1954
+ return { items: [], count: 0 };
1955
+ }
1956
+ const parsed = JSON.parse(output);
1957
+ return {
1958
+ items: parsed.items || [],
1959
+ count: parsed.count || 0
1960
+ };
1961
+ },
1962
+ options
1963
+ );
1964
+ if (!result.success) {
1965
+ return null;
1966
+ }
1967
+ const data = result.data;
1968
+ if (!data || data.count === 0) {
1969
+ return null;
1970
+ }
1971
+ return data;
1972
+ }
1973
+ async function getExplorerCurrentFolder(options) {
1974
+ const script = `
1975
+ $shell = New-Object -ComObject Shell.Application
1976
+ $windows = $shell.Windows()
1977
+
1978
+ foreach ($window in $windows) {
1979
+ # Check if this is an Explorer window
1980
+ if ($window.Name -eq "File Explorer" -or $window.FullName -like "*explorer.exe") {
1981
+ try {
1982
+ $path = $window.Document.Folder.Self.Path
1983
+ if ($path) {
1984
+ Write-Output $path
1985
+ exit
1986
+ }
1987
+ } catch {
1988
+ # Window may not have a valid path
1989
+ }
1990
+ }
1991
+ }
1992
+ `;
1993
+ const result = await executeAndParse2(
1994
+ script,
1995
+ (output) => output || null,
1996
+ options
1997
+ );
1998
+ if (!result.success) {
1999
+ return null;
2000
+ }
2001
+ return result.data ?? null;
2002
+ }
2003
+
2004
+ // src/powershell/scripts/explorerWindows.ts
2005
+ async function getExplorerWindows(options) {
2006
+ const script = `
2007
+ try {
2008
+ Add-Type @"
2009
+ using System;
2010
+ using System.Runtime.InteropServices;
2011
+
2012
+ public class Win32 {
2013
+ [DllImport("user32.dll")]
2014
+ public static extern IntPtr GetForegroundWindow();
2015
+ }
2016
+ "@
2017
+ } catch {
2018
+ # Type may already be loaded, ignore error
2019
+ }
2020
+
2021
+ try {
2022
+ $shell = New-Object -ComObject Shell.Application
2023
+ $windows = $shell.Windows()
2024
+
2025
+ $activeHwnd = [Win32]::GetForegroundWindow()
2026
+
2027
+ $explorerWindows = @()
2028
+
2029
+ foreach ($window in $windows) {
2030
+ # Check if this is an Explorer window
2031
+ if ($window.Name -eq "File Explorer" -or $window.FullName -like "*explorer.exe") {
2032
+ try {
2033
+ $path = $window.Document.Folder.Self.Path
2034
+ if ($path) {
2035
+ $title = $window.LocationName
2036
+ if (-not $title) {
2037
+ $title = Split-Path $path -Leaf
2038
+ }
2039
+
2040
+ # Check if this is the active window
2041
+ $isActive = $false
2042
+ try {
2043
+ $hwnd = $window.HWND
2044
+ if ($hwnd -eq $activeHwnd.ToInt64()) {
2045
+ $isActive = $true
2046
+ }
2047
+ } catch {
2048
+ # HWND may not be accessible
2049
+ }
2050
+
2051
+ $explorerWindows += @{
2052
+ title = if ($title) { $title } else { "" }
2053
+ path = if ($path) { $path } else { "" }
2054
+ isActive = $isActive
2055
+ }
2056
+ }
2057
+ } catch {
2058
+ # Window may not have a valid path, continue to next window
2059
+ }
2060
+ }
2061
+ }
2062
+
2063
+ $result = @{
2064
+ windows = $explorerWindows
2065
+ count = $explorerWindows.Count
2066
+ }
2067
+
2068
+ $result | ConvertTo-Json -Compress -Depth 3
2069
+ } catch {
2070
+ # COM object creation failed or other error
2071
+ Write-Output '{"windows":[],"count":0}'
2072
+ }
2073
+ `;
2074
+ const result = await executeAndParse2(
2075
+ script,
2076
+ (output) => {
2077
+ if (!output) {
2078
+ return { windows: [], count: 0 };
2079
+ }
2080
+ const parsed = JSON.parse(output);
2081
+ return {
2082
+ windows: parsed.windows || [],
2083
+ count: parsed.count || 0
2084
+ };
2085
+ },
2086
+ options
2087
+ );
2088
+ if (!result.success) {
2089
+ return null;
2090
+ }
2091
+ return result.data ?? null;
2092
+ }
2093
+
2094
+ // src/powershell/scripts/clipboard.ts
2095
+ async function getClipboardText2(options) {
2096
+ const script = `
2097
+ try {
2098
+ $text = Get-Clipboard -Format Text -ErrorAction SilentlyContinue
2099
+ if ($text) {
2100
+ Write-Output $text
2101
+ }
2102
+ } catch {
2103
+ # Clipboard may be empty or contain non-text data
2104
+ }
2105
+ `;
2106
+ const result = await executeAndParse2(
2107
+ script,
2108
+ (output) => output || null,
2109
+ options
2110
+ );
2111
+ if (!result.success) {
2112
+ return null;
2113
+ }
2114
+ return result.data ?? null;
2115
+ }
2116
+ async function getClipboardContent2(options) {
2117
+ const script = `
2118
+ try {
2119
+ Add-Type -AssemblyName System.Windows.Forms
2120
+ } catch {
2121
+ # Assembly may already be loaded, ignore error
2122
+ }
2123
+
2124
+ try {
2125
+ $clipboard = [System.Windows.Forms.Clipboard]::GetDataObject()
2126
+ if (-not $clipboard) {
2127
+ Write-Output '{"text":null,"hasFiles":false,"filePaths":[],"hasImage":false}'
2128
+ exit
2129
+ }
2130
+
2131
+ $text = $null
2132
+ $hasFiles = $false
2133
+ $filePaths = @()
2134
+ $hasImage = $false
2135
+
2136
+ # Check for text
2137
+ try {
2138
+ if ($clipboard.GetDataPresent([System.Windows.Forms.DataFormats]::Text)) {
2139
+ $text = $clipboard.GetData([System.Windows.Forms.DataFormats]::Text)
2140
+ }
2141
+ } catch {
2142
+ # Text access failed, continue
2143
+ }
2144
+
2145
+ # Check for files
2146
+ try {
2147
+ if ($clipboard.GetDataPresent([System.Windows.Forms.DataFormats]::FileDrop)) {
2148
+ $hasFiles = $true
2149
+ $files = $clipboard.GetData([System.Windows.Forms.DataFormats]::FileDrop)
2150
+ if ($files) {
2151
+ $filePaths = @($files)
2152
+ }
2153
+ }
2154
+ } catch {
2155
+ # File access failed, continue
2156
+ }
2157
+
2158
+ # Check for image
2159
+ try {
2160
+ if ($clipboard.GetDataPresent([System.Windows.Forms.DataFormats]::Bitmap)) {
2161
+ $hasImage = $true
2162
+ }
2163
+ } catch {
2164
+ # Image check failed, continue
2165
+ }
2166
+
2167
+ $result = @{
2168
+ text = $text
2169
+ hasFiles = $hasFiles
2170
+ filePaths = $filePaths
2171
+ hasImage = $hasImage
2172
+ }
2173
+
2174
+ $result | ConvertTo-Json -Compress
2175
+ } catch {
2176
+ # Clipboard access completely failed
2177
+ Write-Output '{"text":null,"hasFiles":false,"filePaths":[],"hasImage":false}'
2178
+ }
2179
+ `;
2180
+ const result = await executeAndParse2(
2181
+ script,
2182
+ (output) => {
2183
+ if (!output || output === "{}") {
2184
+ return {
2185
+ text: null,
2186
+ hasFiles: false,
2187
+ filePaths: [],
2188
+ hasImage: false
2189
+ };
2190
+ }
2191
+ const parsed = JSON.parse(output);
2192
+ return {
2193
+ text: parsed.text || null,
2194
+ hasFiles: parsed.hasFiles || false,
2195
+ filePaths: parsed.filePaths || [],
2196
+ hasImage: parsed.hasImage || false
2197
+ };
2198
+ },
2199
+ options
2200
+ );
2201
+ if (!result.success) {
2202
+ return null;
2203
+ }
2204
+ return result.data ?? null;
2205
+ }
2206
+
2207
+ // src/powershell/index.ts
2208
+ async function getSystemContext2(options) {
2209
+ if (!isPowerShellAvailable()) {
2210
+ return null;
2211
+ }
2212
+ const frontmostApp = await getFrontmostApp2(options);
2213
+ if (!frontmostApp) {
2214
+ return null;
2215
+ }
2216
+ let explorerSelection = null;
2217
+ let explorerCurrentFolder = null;
2218
+ if (frontmostApp.isExplorer) {
2219
+ [explorerSelection, explorerCurrentFolder] = await Promise.all([
2220
+ getExplorerSelection(options),
2221
+ getExplorerCurrentFolder(options)
2222
+ ]);
2223
+ }
2224
+ const clipboard = await getClipboardContent2(options);
2225
+ return {
2226
+ frontmostApp,
2227
+ explorerSelection,
2228
+ explorerCurrentFolder,
2229
+ clipboard: clipboard ?? { text: null, hasFiles: false, filePaths: [], hasImage: false }
2230
+ };
2231
+ }
2232
+
1350
2233
  // src/index.ts
1351
2234
  var IS_MACOS2 = process.platform === "darwin";
1352
- var IS_WINDOWS = process.platform === "win32";
2235
+ var IS_WINDOWS2 = process.platform === "win32";
1353
2236
  var PLATFORM_PACKAGES = {
1354
2237
  "darwin-arm64": "@simen-keyboard-listener/darwin-arm64",
1355
2238
  "win32-x64": "@simen-keyboard-listener/win32-x64"
@@ -1502,7 +2385,7 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
1502
2385
  }
1503
2386
  };
1504
2387
  function getGlobalKeyboardListener() {
1505
- if (!IS_MACOS2 && !IS_WINDOWS) {
2388
+ if (!IS_MACOS2 && !IS_WINDOWS2) {
1506
2389
  throw new Error(`Unsupported platform for global keyboard listener: ${process.platform}`);
1507
2390
  }
1508
2391
  return NativeKeyboardListener.getInstance();
@@ -1511,7 +2394,7 @@ function createGlobalKeyboardListener() {
1511
2394
  return getGlobalKeyboardListener();
1512
2395
  }
1513
2396
  function checkKeyboardPermission() {
1514
- if (!IS_MACOS2 && !IS_WINDOWS) {
2397
+ if (!IS_MACOS2 && !IS_WINDOWS2) {
1515
2398
  return false;
1516
2399
  }
1517
2400
  try {
@@ -1597,7 +2480,7 @@ function getSelectedTextSmart() {
1597
2480
  }
1598
2481
  }
1599
2482
  function setBlockSystemHotkeys(block) {
1600
- if (!IS_WINDOWS) {
2483
+ if (!IS_WINDOWS2) {
1601
2484
  return;
1602
2485
  }
1603
2486
  try {
@@ -1638,6 +2521,7 @@ export {
1638
2521
  getSystemContext,
1639
2522
  isAppRunning,
1640
2523
  isOsascriptAvailable,
2524
+ powershell_exports as powershell,
1641
2525
  readFileContent,
1642
2526
  readMultipleFiles,
1643
2527
  setBlockSystemHotkeys