symforge 1.2.1 → 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 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 match = output.match(/(\d+\.\d+\.\d+)/);
56
- return match ? match[1] : null;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "symforge",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "SymForge — in-memory code intelligence for Claude Code, Codex, and Gemini CLI",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -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/tokenizor_agentic_mcp";
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 match = output.match(/(\d+\.\d+\.\d+)/);
94
- return match ? match[1] : null;
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 removePendingIfPresent(pendingPath) {
105
- try {
106
- fsMod.unlinkSync(pendingPath);
107
- } catch {}
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
- removePendingIfPresent(pendingPath);
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
- removePendingIfPresent(pendingPath);
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 tokenizor_agentic_mcp");
421
+ consoleMod.error(" cd symforge");
383
422
  consoleMod.error(" cargo build --release");
384
423
  processMod.exit(1);
385
424
  }