@dypai-ai/mcp 1.5.26 → 1.5.27

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/auto-update.js +14 -59
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dypai-ai/mcp",
3
- "version": "1.5.26",
3
+ "version": "1.5.27",
4
4
  "description": "DYPAI MCP Server — AI agent toolkit for building and deploying full-stack apps",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -1,13 +1,11 @@
1
1
  /**
2
2
  * Self-update for @dypai-ai/mcp.
3
3
  *
4
- * On startup, checks the npm registry for a newer version. If found, performs
4
+ * On every startup, checks the npm registry for a newer version. If found, performs
5
5
  * the appropriate update (clear npx cache or `npm install -g`) and exits with
6
6
  * code 0 so the host (Cursor / Claude / Trae / VSCode) re-spawns the process
7
7
  * with the freshly installed version.
8
8
  *
9
- * Throttled to one check every 6h to avoid hammering the registry.
10
- *
11
9
  * Disable with: DYPAI_NO_AUTOUPDATE=1
12
10
  */
13
11
 
@@ -21,13 +19,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
21
19
  const PKG_PATH = join(__dirname, "..", "package.json");
22
20
  const PKG_NAME = "@dypai-ai/mcp";
23
21
  const REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
24
- // Dist-tags endpoint is tiny (<200B) — used to check if there's a CRITICAL
25
- // release the user must upgrade to immediately, bypassing the 6h throttle.
26
- // To mark a version as critical after publish:
27
- // npm dist-tag add @dypai-ai/mcp@1.4.5 critical
28
- const DIST_TAGS_URL = `https://registry.npmjs.org/-/package/${PKG_NAME}/dist-tags`;
29
22
  const CHECK_TIMEOUT_MS = 2000;
30
- const THROTTLE_HOURS = 6;
31
23
  const STATE_FILE = join(tmpdir(), "dypai-mcp-update-state.json");
32
24
 
33
25
  function log(msg) {
@@ -73,32 +65,6 @@ async function fetchLatestManifest() {
73
65
  }
74
66
  }
75
67
 
76
- /**
77
- * Fetch the `critical` dist-tag (if published). Used to bypass the 6h throttle
78
- * when a release is important enough that users must upgrade on next spawn.
79
- *
80
- * Returns the critical version string (e.g. "1.4.5") or null if no critical
81
- * tag is set, the registry is unreachable, or the response is malformed.
82
- *
83
- * Cost: one tiny JSON fetch (~200 bytes) per spawn. Adds ~50-150ms to startup
84
- * but runs in parallel with the rest of the MCP init, so wall-clock impact is
85
- * usually zero.
86
- */
87
- async function fetchCriticalVersion() {
88
- const ctrl = new AbortController();
89
- const timer = setTimeout(() => ctrl.abort(), CHECK_TIMEOUT_MS);
90
- try {
91
- const res = await fetch(DIST_TAGS_URL, { signal: ctrl.signal });
92
- if (!res.ok) return null;
93
- const tags = await res.json();
94
- return typeof tags?.critical === "string" ? tags.critical : null;
95
- } catch {
96
- return null;
97
- } finally {
98
- clearTimeout(timer);
99
- }
100
- }
101
-
102
68
  /**
103
69
  * After npm publish there's a 30s–2min window where the registry knows the
104
70
  * version but the tarball is not yet replicated across the CDN. If we clear
@@ -170,37 +136,21 @@ function installGlobalLatest() {
170
136
  * Main entry point — call once at startup.
171
137
  * Returns quickly. Exits the process if an update was applied.
172
138
  */
173
- export async function checkForUpdates({ force = false } = {}) {
139
+ export async function checkForUpdates() {
174
140
  if (process.env.DYPAI_NO_AUTOUPDATE === "1") return { skipped: "disabled" };
175
141
 
176
142
  const current = getCurrentVersion();
177
143
  if (!current) return { skipped: "no current version" };
178
144
 
179
- // ── Critical release check (bypasses the 6h throttle) ────────────────────
180
- // If an ops person has run `npm dist-tag add @dypai-ai/mcp@X.Y.Z critical`,
181
- // every spawn picks that up and forces an upgrade regardless of when the
182
- // last normal check ran. Used for security / data-loss bug fixes where
183
- // 6-24h propagation is too slow.
184
- const criticalVersion = await fetchCriticalVersion();
185
- const hasCritical = criticalVersion && compareVersions(criticalVersion, current) > 0;
186
- if (hasCritical) {
187
- log(`CRITICAL update required: ${current} → ${criticalVersion} (bypassing throttle)`);
188
- force = true;
189
- }
190
-
191
- // Throttle (skipped when force or critical)
192
- if (!force) {
193
- const state = readState();
194
- if (state.lastCheckAt) {
195
- const hoursAgo = (Date.now() - state.lastCheckAt) / 3_600_000;
196
- if (hoursAgo < THROTTLE_HOURS) return { skipped: "throttled" };
197
- }
198
- }
199
-
200
145
  const manifest = await fetchLatestManifest();
201
146
  const latest = manifest?.version || null;
202
147
  const tarballUrl = manifest?.dist?.tarball || null;
203
- writeState({ lastCheckAt: Date.now(), lastSeenLatest: latest, current });
148
+ writeState({
149
+ ...readState(),
150
+ lastCheckAt: Date.now(),
151
+ lastSeenLatest: latest,
152
+ current,
153
+ });
204
154
 
205
155
  if (!latest) return { skipped: "registry unreachable" };
206
156
  if (compareVersions(latest, current) <= 0) return { uptodate: true, current };
@@ -213,7 +163,7 @@ export async function checkForUpdates({ force = false } = {}) {
213
163
  // If we clear the cache + exit during that window, next spawn fails.
214
164
  const ready = await isTarballReady(tarballUrl);
215
165
  if (!ready) {
216
- log(`new version ${latest} not yet downloadable from CDN; will retry later`);
166
+ log(`new version ${latest} not yet downloadable from CDN; will retry on next spawn`);
217
167
  return { skipped: "tarball not ready" };
218
168
  }
219
169
 
@@ -223,6 +173,11 @@ export async function checkForUpdates({ force = false } = {}) {
223
173
  if (method === "npx") {
224
174
  log(`tarball verified — clearing npx cache so the next spawn pulls ${PKG_NAME}@${latest}`);
225
175
  updated = clearNpxCacheForPackage();
176
+ // Even if no cached dir matched, exit so npx re-resolves @latest on respawn.
177
+ if (!updated) {
178
+ log("no npx cache entry found; exiting anyway so the host re-resolves @latest");
179
+ updated = true;
180
+ }
226
181
  } else if (method === "global") {
227
182
  log(`tarball verified — running: npm install -g ${PKG_NAME}@latest`);
228
183
  updated = installGlobalLatest();