tokenizor-mcp 0.3.0 → 0.3.2

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.
@@ -1,19 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
 
4
- const { execFileSync } = require("child_process");
5
4
  const fs = require("fs");
6
5
  const path = require("path");
7
6
 
8
7
  const ext = process.platform === "win32" ? ".exe" : "";
9
8
  const binPath = path.join(__dirname, "tokenizor-mcp" + ext);
9
+ const pendingPath = path.join(__dirname, "tokenizor-mcp.pending" + ext);
10
+
11
+ // Apply pending update if one was staged (binary was locked during npm update)
12
+ if (fs.existsSync(pendingPath)) {
13
+ try {
14
+ fs.renameSync(pendingPath, binPath);
15
+ console.error("tokenizor-mcp: applied pending update.");
16
+ } catch {
17
+ // Still locked — will try again next launch
18
+ }
19
+ }
10
20
 
11
21
  if (!fs.existsSync(binPath)) {
12
22
  console.error("tokenizor-mcp binary not found. Running install...");
13
23
  try {
14
- execFileSync(process.execPath, [path.join(__dirname, "..", "scripts", "install.js")], {
15
- stdio: "inherit",
16
- });
24
+ require("child_process").execFileSync(
25
+ process.execPath,
26
+ [path.join(__dirname, "..", "scripts", "install.js")],
27
+ { stdio: "inherit" }
28
+ );
17
29
  } catch {
18
30
  process.exit(1);
19
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokenizor-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Tokenizor MCP — in-memory code intelligence with parasitic hook integration for Claude Code",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,11 +30,15 @@ function getVersion() {
30
30
  }
31
31
 
32
32
  function getBinaryPath() {
33
- const artifact = getPlatformArtifact();
34
33
  const ext = process.platform === "win32" ? ".exe" : "";
35
34
  return path.join(BIN_DIR, "tokenizor-mcp" + ext);
36
35
  }
37
36
 
37
+ function getPendingPath() {
38
+ const ext = process.platform === "win32" ? ".exe" : "";
39
+ return path.join(BIN_DIR, "tokenizor-mcp.pending" + ext);
40
+ }
41
+
38
42
  function download(url) {
39
43
  return new Promise((resolve, reject) => {
40
44
  const client = url.startsWith("https") ? https : http;
@@ -53,16 +57,38 @@ function download(url) {
53
57
  });
54
58
  }
55
59
 
60
+ function getInstalledVersion(binPath) {
61
+ try {
62
+ const output = execSync(`"${binPath}" --version`, {
63
+ encoding: "utf8",
64
+ timeout: 5000,
65
+ }).trim();
66
+ const match = output.match(/(\d+\.\d+\.\d+)/);
67
+ return match ? match[1] : null;
68
+ } catch {
69
+ return null;
70
+ }
71
+ }
72
+
56
73
  async function main() {
57
74
  const binPath = getBinaryPath();
75
+ const pendingPath = getPendingPath();
76
+ const version = getVersion();
58
77
 
59
- // Skip if binary already exists
78
+ // Skip only if binary exists AND matches the expected version
60
79
  if (fs.existsSync(binPath)) {
61
- console.log("tokenizor-mcp binary already installed.");
62
- return;
80
+ const installed = getInstalledVersion(binPath);
81
+ if (installed === version) {
82
+ // Clean up any stale pending file
83
+ try { fs.unlinkSync(pendingPath); } catch {}
84
+ console.log(`tokenizor-mcp v${version} already installed.`);
85
+ return;
86
+ }
87
+ console.log(
88
+ `tokenizor-mcp binary exists (v${installed || "unknown"}) but package wants v${version}. Updating...`
89
+ );
63
90
  }
64
91
 
65
- const version = getVersion();
66
92
  const artifact = getPlatformArtifact();
67
93
  const url = `https://github.com/${REPO}/releases/download/v${version}/${artifact}`;
68
94
 
@@ -71,12 +97,27 @@ async function main() {
71
97
 
72
98
  try {
73
99
  const data = await download(url);
74
-
75
100
  fs.mkdirSync(BIN_DIR, { recursive: true });
76
- fs.writeFileSync(binPath, data);
77
- fs.chmodSync(binPath, 0o755);
78
101
 
79
- console.log(`Installed: ${binPath}`);
102
+ // Try writing directly to the target path
103
+ try {
104
+ fs.writeFileSync(binPath, data);
105
+ fs.chmodSync(binPath, 0o755);
106
+ // Clean up any stale pending file
107
+ try { fs.unlinkSync(pendingPath); } catch {}
108
+ console.log(`Installed: ${binPath}`);
109
+ } catch (writeErr) {
110
+ // On Windows the binary may be locked by a running MCP server.
111
+ // Write to a .pending file — the JS wrapper will swap it in on next launch.
112
+ if (writeErr.code === "EPERM" || writeErr.code === "EBUSY") {
113
+ fs.writeFileSync(pendingPath, data);
114
+ fs.chmodSync(pendingPath, 0o755);
115
+ console.log(`Binary is locked (MCP server running). Staged update at: ${pendingPath}`);
116
+ console.log(`The update will apply automatically on next launch.`);
117
+ } else {
118
+ throw writeErr;
119
+ }
120
+ }
80
121
  } catch (err) {
81
122
  console.error(`Failed to download binary: ${err.message}`);
82
123
  console.error("");