symforge 1.2.2 → 1.2.3
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/bin/launcher.js +42 -2
- package/package.json +1 -1
- package/scripts/install.js +49 -10
package/bin/launcher.js
CHANGED
|
@@ -32,6 +32,8 @@ function createLauncher(overrides = {}) {
|
|
|
32
32
|
const installDir = resolveInstallDir();
|
|
33
33
|
const binPath = pathMod.join(installDir, "symforge" + ext);
|
|
34
34
|
const pendingPath = pathMod.join(installDir, "symforge.pending" + ext);
|
|
35
|
+
const versionPath = pathMod.join(installDir, "symforge.version");
|
|
36
|
+
const pendingVersionPath = pathMod.join(installDir, "symforge.pending.version");
|
|
35
37
|
|
|
36
38
|
function relayInstallerOutput(output) {
|
|
37
39
|
if (!output) {
|
|
@@ -45,15 +47,48 @@ function createLauncher(overrides = {}) {
|
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
function parseVersion(text) {
|
|
51
|
+
if (!text) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const match = String(text).match(/(\d+\.\d+\.\d+)/);
|
|
55
|
+
return match ? match[1] : null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function readRecordedVersion(targetPath) {
|
|
59
|
+
try {
|
|
60
|
+
return parseVersion(fsMod.readFileSync(targetPath, "utf8").trim());
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function writeRecordedVersion(targetPath, version) {
|
|
67
|
+
if (!version) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
fsMod.writeFileSync(targetPath, `${version}\n`);
|
|
72
|
+
} catch {
|
|
73
|
+
// Best-effort metadata only.
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
48
77
|
function getInstalledVersion() {
|
|
78
|
+
const recordedVersion = readRecordedVersion(versionPath);
|
|
79
|
+
if (recordedVersion) {
|
|
80
|
+
return recordedVersion;
|
|
81
|
+
}
|
|
82
|
+
|
|
49
83
|
try {
|
|
50
84
|
const output = execFileSyncFn(binPath, ["--version"], {
|
|
51
85
|
encoding: "utf8",
|
|
52
86
|
timeout: 5000,
|
|
53
87
|
env: processMod.env,
|
|
54
88
|
}).trim();
|
|
55
|
-
const
|
|
56
|
-
|
|
89
|
+
const parsedVersion = parseVersion(output);
|
|
90
|
+
writeRecordedVersion(versionPath, parsedVersion);
|
|
91
|
+
return parsedVersion;
|
|
57
92
|
} catch {
|
|
58
93
|
return null;
|
|
59
94
|
}
|
|
@@ -66,6 +101,11 @@ function createLauncher(overrides = {}) {
|
|
|
66
101
|
|
|
67
102
|
try {
|
|
68
103
|
fsMod.renameSync(pendingPath, binPath);
|
|
104
|
+
if (fsMod.existsSync(pendingVersionPath)) {
|
|
105
|
+
fsMod.renameSync(pendingVersionPath, versionPath);
|
|
106
|
+
} else {
|
|
107
|
+
writeRecordedVersion(versionPath, packageJson.version);
|
|
108
|
+
}
|
|
69
109
|
consoleMod.error("symforge: applied pending update.");
|
|
70
110
|
return true;
|
|
71
111
|
} catch {
|
package/package.json
CHANGED
package/scripts/install.js
CHANGED
|
@@ -8,7 +8,7 @@ const os = require("os");
|
|
|
8
8
|
const https = require("https");
|
|
9
9
|
const http = require("http");
|
|
10
10
|
|
|
11
|
-
const REPO = "special-place-administrator/
|
|
11
|
+
const REPO = "special-place-administrator/symforge";
|
|
12
12
|
|
|
13
13
|
function createInstaller(overrides = {}) {
|
|
14
14
|
const fsMod = overrides.fs || fs;
|
|
@@ -34,6 +34,8 @@ function createInstaller(overrides = {}) {
|
|
|
34
34
|
// Binary lives outside node_modules so npm can update the JS wrapper
|
|
35
35
|
// even while the MCP server holds a lock on the running .exe (Windows).
|
|
36
36
|
const installDir = resolveInstallDir();
|
|
37
|
+
const versionPath = pathMod.join(installDir, "symforge.version");
|
|
38
|
+
const pendingVersionPath = pathMod.join(installDir, "symforge.pending.version");
|
|
37
39
|
|
|
38
40
|
function getPlatformArtifact() {
|
|
39
41
|
const platform = processMod.platform;
|
|
@@ -63,6 +65,33 @@ function createInstaller(overrides = {}) {
|
|
|
63
65
|
return pathMod.join(installDir, "symforge.pending" + ext);
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
function parseVersion(text) {
|
|
69
|
+
if (!text) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const match = String(text).match(/(\d+\.\d+\.\d+)/);
|
|
73
|
+
return match ? match[1] : null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function readRecordedVersion(targetPath) {
|
|
77
|
+
try {
|
|
78
|
+
return parseVersion(fsMod.readFileSync(targetPath, "utf8").trim());
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function writeRecordedVersion(targetPath, version) {
|
|
85
|
+
if (!version) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
fsMod.writeFileSync(targetPath, `${version}\n`);
|
|
90
|
+
} catch {
|
|
91
|
+
// Best-effort metadata only.
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
66
95
|
function download(url) {
|
|
67
96
|
if (overrides.download) {
|
|
68
97
|
return overrides.download(url);
|
|
@@ -85,13 +114,19 @@ function createInstaller(overrides = {}) {
|
|
|
85
114
|
}
|
|
86
115
|
|
|
87
116
|
function getInstalledVersion(binPath) {
|
|
117
|
+
const recordedVersion = readRecordedVersion(versionPath);
|
|
118
|
+
if (recordedVersion) {
|
|
119
|
+
return recordedVersion;
|
|
120
|
+
}
|
|
121
|
+
|
|
88
122
|
try {
|
|
89
123
|
const output = execFileSyncFn(binPath, ["--version"], {
|
|
90
124
|
encoding: "utf8",
|
|
91
125
|
timeout: 5000,
|
|
92
126
|
}).trim();
|
|
93
|
-
const
|
|
94
|
-
|
|
127
|
+
const parsedVersion = parseVersion(output);
|
|
128
|
+
writeRecordedVersion(versionPath, parsedVersion);
|
|
129
|
+
return parsedVersion;
|
|
95
130
|
} catch {
|
|
96
131
|
return null;
|
|
97
132
|
}
|
|
@@ -101,16 +136,19 @@ function createInstaller(overrides = {}) {
|
|
|
101
136
|
return error && (error.code === "EPERM" || error.code === "EBUSY");
|
|
102
137
|
}
|
|
103
138
|
|
|
104
|
-
function
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
139
|
+
function removePendingArtifacts(pendingPath) {
|
|
140
|
+
for (const target of [pendingPath, pendingVersionPath]) {
|
|
141
|
+
try {
|
|
142
|
+
fsMod.unlinkSync(target);
|
|
143
|
+
} catch {}
|
|
144
|
+
}
|
|
108
145
|
}
|
|
109
146
|
|
|
110
147
|
function writeInstalledBinary(binPath, pendingPath, data) {
|
|
111
148
|
fsMod.writeFileSync(binPath, data);
|
|
112
149
|
fsMod.chmodSync(binPath, 0o755);
|
|
113
|
-
|
|
150
|
+
writeRecordedVersion(versionPath, getVersion());
|
|
151
|
+
removePendingArtifacts(pendingPath);
|
|
114
152
|
consoleMod.log(`Installed: ${binPath}`);
|
|
115
153
|
}
|
|
116
154
|
|
|
@@ -242,6 +280,7 @@ function createInstaller(overrides = {}) {
|
|
|
242
280
|
|
|
243
281
|
fsMod.writeFileSync(pendingPath, data);
|
|
244
282
|
fsMod.chmodSync(pendingPath, 0o755);
|
|
283
|
+
writeRecordedVersion(pendingVersionPath, getVersion());
|
|
245
284
|
consoleMod.log(`Binary is locked (MCP server running). Staged update at: ${pendingPath}`);
|
|
246
285
|
consoleMod.log(`Update will apply automatically on next launch.`);
|
|
247
286
|
return { status: "staged", stoppedProcessIds };
|
|
@@ -314,7 +353,7 @@ function createInstaller(overrides = {}) {
|
|
|
314
353
|
if (fsMod.existsSync(binPath)) {
|
|
315
354
|
const installed = getInstalledVersion(binPath);
|
|
316
355
|
if (installed === version) {
|
|
317
|
-
|
|
356
|
+
removePendingArtifacts(pendingPath);
|
|
318
357
|
consoleMod.log(`symforge v${version} already installed at ${binPath}`);
|
|
319
358
|
// Still run init to ensure config is up to date
|
|
320
359
|
runAutoInit(binPath);
|
|
@@ -379,7 +418,7 @@ function createInstaller(overrides = {}) {
|
|
|
379
418
|
consoleMod.error("");
|
|
380
419
|
consoleMod.error("You can build from source instead:");
|
|
381
420
|
consoleMod.error(" git clone https://github.com/" + REPO);
|
|
382
|
-
consoleMod.error(" cd
|
|
421
|
+
consoleMod.error(" cd symforge");
|
|
383
422
|
consoleMod.error(" cargo build --release");
|
|
384
423
|
processMod.exit(1);
|
|
385
424
|
}
|