@youdie006/prodex 0.39.3 → 0.39.4

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/dist/mcp-tools.js CHANGED
@@ -199,3 +199,27 @@ function assertMcpFiles(files) {
199
199
  assertMcpTextField(file.path, `files[${index}].path`, MAX_MCP_SHORT_TEXT_BYTES);
200
200
  }
201
201
  }
202
+ /**
203
+ * A running MCP server keeps the code it loaded at startup: Node reads a module
204
+ * once. So installing a newer prodex changes nothing for a server that is
205
+ * already up, and the fixes in it look like they did not work. Measured on one
206
+ * machine, three servers serving consults had been running since the middle of
207
+ * the previous month, two releases behind, with nothing saying so.
208
+ */
209
+ export function staleServerWarning(input) {
210
+ const running = input.running?.trim();
211
+ const installed = input.installed?.trim();
212
+ if (!running || !installed || running === installed)
213
+ return undefined;
214
+ return (`server_outdated: this prodex MCP server is running ${running}, but ${installed} is installed on this machine. ` +
215
+ `A server keeps the code it loaded when it started, so anything fixed since ${running} is not in this one. ` +
216
+ `Restart it - restart the agent session that launched it - to pick up ${installed}.`);
217
+ }
218
+ /** Carries a server-version notice back on a tool result that has room for it. */
219
+ export function withServerVersionNotice(result, warning) {
220
+ if (!warning || typeof result !== "object" || result === null)
221
+ return result;
222
+ const existing = result.warnings;
223
+ const warnings = Array.isArray(existing) ? existing : [];
224
+ return { ...result, warnings: [warning, ...warnings] };
225
+ }
package/dist/mcp.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { readFileSync } from "node:fs";
2
3
  import { createRequire } from "node:module";
3
4
  import process from "node:process";
4
5
  import { serializeMessage } from "@modelcontextprotocol/sdk/shared/stdio.js";
5
6
  import { JSONRPCMessageSchema } from "@modelcontextprotocol/sdk/types.js";
6
7
  import { z } from "zod";
7
- import { createMcpToolHandlers, MAX_MCP_BRIDGE_TEXT_BYTES, MAX_MCP_SHORT_TEXT_BYTES } from "./mcp-tools.js";
8
+ import { createMcpToolHandlers, MAX_MCP_BRIDGE_TEXT_BYTES, MAX_MCP_SHORT_TEXT_BYTES, staleServerWarning, withServerVersionNotice } from "./mcp-tools.js";
8
9
  import { ReceiptKindSchema } from "./schema.js";
9
10
  const McpBridgeTextSchema = z.string().max(MAX_MCP_BRIDGE_TEXT_BYTES);
10
11
  const McpShortTextSchema = z.string().max(MAX_MCP_SHORT_TEXT_BYTES);
@@ -25,6 +26,29 @@ function asText(value) {
25
26
  };
26
27
  }
27
28
  const mcpPackageJson = createRequire(import.meta.url)("../package.json");
29
+ /**
30
+ * The version on disk right now, which is NOT what this process is running:
31
+ * `mcpPackageJson` was read once, when the server started. Comparing the two is
32
+ * how a server that has been up for weeks can say so. Read per browser call
33
+ * (those take seconds at least, so one small file read is nothing) and never
34
+ * allowed to break the call it decorates.
35
+ */
36
+ function installedVersionOnDisk() {
37
+ try {
38
+ const path = createRequire(import.meta.url).resolve("../package.json");
39
+ return JSON.parse(readFileSync(path, "utf8")).version;
40
+ }
41
+ catch {
42
+ return undefined;
43
+ }
44
+ }
45
+ function serverVersionNotice() {
46
+ const installed = installedVersionOnDisk();
47
+ return staleServerWarning({
48
+ ...(mcpPackageJson.version !== undefined ? { running: mcpPackageJson.version } : {}),
49
+ ...(installed !== undefined ? { installed } : {})
50
+ });
51
+ }
28
52
  export function createServer(cwd = process.cwd(), options = {}) {
29
53
  const server = new McpServer({ name: "prodex", version: mcpPackageJson.version ?? "0.0.0" });
30
54
  const handlers = createMcpToolHandlers({ cwd, source: options.source, claimedBy: options.claimedBy });
@@ -184,7 +208,7 @@ export function createServer(cwd = process.cwd(), options = {}) {
184
208
  // Progress delivery must never break the consult.
185
209
  });
186
210
  };
187
- return asText(await browserConsult(input, onProgress));
211
+ return asText(withServerVersionNotice(await browserConsult(input, onProgress), serverVersionNotice()));
188
212
  });
189
213
  }
190
214
  const browserRecover = options.browserRecover;
@@ -195,7 +219,7 @@ export function createServer(cwd = process.cwd(), options = {}) {
195
219
  thread: McpShortTextSchema.min(1).describe("The ChatGPT conversation URL from the blocker (its `thread` field)."),
196
220
  timeout_ms: z.number().int().positive().max(600_000).optional()
197
221
  }
198
- }, async (input) => asText(await browserRecover(input)));
222
+ }, async (input) => asText(withServerVersionNotice(await browserRecover(input), serverVersionNotice())));
199
223
  }
200
224
  return server;
201
225
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youdie006/prodex",
3
- "version": "0.39.3",
3
+ "version": "0.39.4",
4
4
  "description": "Local receipt bus for coordinating Codex execution with ChatGPT Pro/Projects consultation.",
5
5
  "author": "youdie006",
6
6
  "license": "MIT",