fraim 2.0.299 → 2.0.301

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.
@@ -45,6 +45,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.getNpmMajorVersion = getNpmMajorVersion;
46
46
  exports.diagnoseFraimMcpLaunchPlan = diagnoseFraimMcpLaunchPlan;
47
47
  exports.spawnAndHandshake = spawnAndHandshake;
48
+ exports.testStdioMCPServer = testStdioMCPServer;
48
49
  exports.getStdioMCPRuntimeChecks = getStdioMCPRuntimeChecks;
49
50
  exports.getMCPConnectivityChecks = getMCPConnectivityChecks;
50
51
  const fs_1 = __importDefault(require("fs"));
@@ -646,7 +647,11 @@ async function testFraimLocalProxyTroubleshooting() {
646
647
  // ============================================================
647
648
  // Issue #532: Stdio MCP Runtime Connectivity Check
648
649
  // ============================================================
649
- const STDIO_HANDSHAKE_TIMEOUT_MS = 15000;
650
+ // Issue #1474: raised from 15000. A reporter's own *warm*-cache measurements were ~9.4-10s,
651
+ // already 63-67% of the old budget; a cold first `npx -y <package>` fetch routinely exceeds it
652
+ // outright. This does not remove the ambiguity a timeout can't resolve on its own (see the
653
+ // 'warning' status below) but reduces how often it's hit in the first place.
654
+ const STDIO_HANDSHAKE_TIMEOUT_MS = 30000;
650
655
  /**
651
656
  * Spawn a stdio MCP server, perform a two-phase JSON-RPC handshake
652
657
  * (initialize then tools/list), and return a structured result.
@@ -730,11 +735,16 @@ async function spawnAndHandshake(command, args, timeoutMs = STDIO_HANDSHAKE_TIME
730
735
  child.kill('SIGKILL');
731
736
  }
732
737
  catch { /* best effort */ }
738
+ // Issue #1474: a timeout is 'warning', not 'error' -- this check cannot distinguish a
739
+ // server that is genuinely broken from one that is merely slow to start (a cold npx cache
740
+ // downloading the package for the first time), so it reports the honest uncertainty rather
741
+ // than a false-confident failure. A warning that persists across retries still signals
742
+ // something is wrong; a one-off warning on first run does not.
733
743
  settle({
734
- status: 'error',
744
+ status: 'warning',
735
745
  phase: initializeResponse ? 'tools-list' : 'initialize',
736
746
  message: `MCP server did not respond within ${timeoutMs}ms`,
737
- suggestion: 'The server may be slow to start. Check that the package is installed and npx cache is warm.',
747
+ suggestion: 'This may mean the package is still installing on a cold npx cache. Retry once the cache is warm; if it keeps timing out, treat it as broken.',
738
748
  details: { command, args, timeoutMs, elapsed: Date.now() - startTime }
739
749
  });
740
750
  }, timeoutMs);
@@ -914,8 +924,12 @@ async function spawnAndHandshake(command, args, timeoutMs = STDIO_HANDSHAKE_TIME
914
924
  }
915
925
  /**
916
926
  * Run a connectivity check for a single named stdio MCP server.
927
+ *
928
+ * `timeoutMs` defaults to STDIO_HANDSHAKE_TIMEOUT_MS; it is exposed as a parameter (mirroring
929
+ * spawnAndHandshake's own signature) so tests can exercise the real timeout/warning path quickly
930
+ * without waiting on the full production budget.
917
931
  */
918
- async function testStdioMCPServer(serverName, command, args) {
932
+ async function testStdioMCPServer(serverName, command, args, timeoutMs = STDIO_HANDSHAKE_TIMEOUT_MS) {
919
933
  if (process.env.NODE_ENV === 'test') {
920
934
  return {
921
935
  status: 'warning',
@@ -923,7 +937,7 @@ async function testStdioMCPServer(serverName, command, args) {
923
937
  details: { testMode: true, skipped: true, serverName }
924
938
  };
925
939
  }
926
- const result = await spawnAndHandshake(command, args, STDIO_HANDSHAKE_TIMEOUT_MS);
940
+ const result = await spawnAndHandshake(command, args, timeoutMs);
927
941
  if (result.status === 'passed') {
928
942
  return {
929
943
  status: 'passed',
@@ -931,6 +945,16 @@ async function testStdioMCPServer(serverName, command, args) {
931
945
  details: result.details
932
946
  };
933
947
  }
948
+ // Issue #1474: preserve spawnAndHandshake's 'warning' (ambiguous timeout) as a doctor 'warning'
949
+ // rather than collapsing it into the same hard 'error' used for unambiguous failures below.
950
+ if (result.status === 'warning') {
951
+ return {
952
+ status: 'warning',
953
+ message: `${serverName} stdio MCP connectivity uncertain (phase: ${result.phase}): ${result.message}`,
954
+ suggestion: result.suggestion,
955
+ details: { ...result.details, phase: result.phase }
956
+ };
957
+ }
934
958
  return {
935
959
  status: 'error',
936
960
  message: `${serverName} stdio MCP connectivity failed (phase: ${result.phase}): ${result.message}`,
@@ -304,6 +304,13 @@ function ensureFraimMcpLatestLauncher() {
304
304
  }
305
305
  writeFileIfChanged(fraimMcpShimPath, packagedFraimShimSource('mcp', packagedRuntime), process.platform === 'win32' ? undefined : 0o755);
306
306
  writeFileIfChanged(fraimCliShimPath, packagedFraimShimSource('cli', packagedRuntime), process.platform === 'win32' ? undefined : 0o755);
307
+ // Issue #1474: keep the npx companion shim in parity with the non-packaged branch below.
308
+ // The packaged fraim-mcp shim itself never invokes npx, but git/playwright base MCP servers
309
+ // (added later via the connect-mcp skill once a system npm is available) and doctor's
310
+ // launch-plan diagnostic both expect this file to exist alongside the stable fraim shim.
311
+ // Without it, doctor's "stable shim missing on disk" check could never be satisfied on a
312
+ // packaged install, and --fix-mcp/add-ide (which call this same function) could never fix it.
313
+ writeFileIfChanged(fraimNpxShimPath, process.platform === 'win32' ? windowsFraimNpxShimSource : posixFraimNpxShimSource, process.platform === 'win32' ? undefined : 0o755);
307
314
  return {
308
315
  command: fraimMcpShimPath,
309
316
  args: [],
@@ -55,6 +55,7 @@ exports.HUMAN_MANAGER_PROFILES = {
55
55
  procella: { humanTitle: 'Procurement Manager', keywords: ['"Procurement Manager"', '"Head of Procurement"', '"Sourcing Lead"'] },
56
56
  banke: { humanTitle: 'KYC Operations Manager', keywords: ['"KYC Operations Manager"', '"AML Compliance Manager"', '"Banking Compliance Lead"'] },
57
57
  auditya: { humanTitle: 'Audit Manager', keywords: ['"Audit Manager"', '"Internal Audit Lead"', '"Compliance Audit Manager"'] },
58
+ travis: { humanTitle: 'Travel Operations Manager', keywords: ['"Travel Operations Manager"', '"Corporate Travel Manager"', '"Travel Program Manager"'] },
58
59
  };
59
60
  function getHumanManagerProfile(roleKey) {
60
61
  return exports.HUMAN_MANAGER_PROFILES[roleKey] ?? GENERALIST_PROFILE;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim",
3
- "version": "2.0.299",
3
+ "version": "2.0.301",
4
4
  "description": "FRAIM core CLI and MCP package.",
5
5
  "main": "index.js",
6
6
  "bin": {