repowisestage 0.0.75 → 0.0.76

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/dist/bin/repowise.js +106 -28
  2. package/package.json +1 -1
@@ -4535,21 +4535,38 @@ async function storeCredentials(credentials) {
4535
4535
  }
4536
4536
  }
4537
4537
  var refreshInFlight = null;
4538
+ var refreshInFlightToken = null;
4539
+ var terminalRefreshTokens = /* @__PURE__ */ new Set();
4540
+ var lastSeenRefreshToken = null;
4538
4541
  async function getValidCredentials(options) {
4539
4542
  const creds = await getStoredCredentials();
4540
4543
  if (!creds) {
4541
4544
  lastRefreshOutcome = "no-creds";
4542
4545
  return null;
4543
4546
  }
4547
+ if (creds.refreshToken !== lastSeenRefreshToken) {
4548
+ terminalRefreshTokens.clear();
4549
+ lastSeenRefreshToken = creds.refreshToken;
4550
+ }
4544
4551
  const now = Date.now();
4545
4552
  const needsRefresh = options?.forceRefresh || now > creds.expiresAt - 5 * 60 * 1e3;
4546
4553
  if (!needsRefresh) {
4547
4554
  lastRefreshOutcome = "success";
4548
4555
  return creds;
4549
4556
  }
4550
- if (!refreshInFlight) {
4551
- refreshInFlight = doRefresh(creds).finally(() => {
4552
- refreshInFlight = null;
4557
+ if (terminalRefreshTokens.has(creds.refreshToken)) {
4558
+ lastRefreshOutcome = "terminal";
4559
+ return null;
4560
+ }
4561
+ if (!refreshInFlight || refreshInFlightToken !== creds.refreshToken) {
4562
+ const inflight = doRefresh(creds);
4563
+ refreshInFlight = inflight;
4564
+ refreshInFlightToken = creds.refreshToken;
4565
+ void inflight.finally(() => {
4566
+ if (refreshInFlight === inflight) {
4567
+ refreshInFlight = null;
4568
+ refreshInFlightToken = null;
4569
+ }
4553
4570
  });
4554
4571
  }
4555
4572
  return refreshInFlight;
@@ -4566,6 +4583,7 @@ async function doRefresh(creds) {
4566
4583
  const message = err instanceof Error ? err.message : String(err);
4567
4584
  if (kind === "terminal") {
4568
4585
  lastRefreshOutcome = "terminal";
4586
+ terminalRefreshTokens.add(creds.refreshToken);
4569
4587
  console.warn(`Token refresh rejected (terminal): ${message}`);
4570
4588
  return null;
4571
4589
  }
@@ -7657,7 +7675,20 @@ async function startMcpServer(options) {
7657
7675
  throw err;
7658
7676
  }
7659
7677
  },
7660
- resumeEndpoint: () => writeEndpointFile(endpointFilePath, endpoint, secretState.value.current)
7678
+ resumeEndpoint: async () => {
7679
+ let lastErr;
7680
+ for (let attempt = 1; attempt <= 3; attempt++) {
7681
+ try {
7682
+ await writeEndpointFile(endpointFilePath, endpoint, secretState.value.current);
7683
+ return;
7684
+ } catch (err) {
7685
+ lastErr = err;
7686
+ if (attempt < 3)
7687
+ await new Promise((r) => setTimeout(r, 100 * attempt));
7688
+ }
7689
+ }
7690
+ throw lastErr;
7691
+ }
7661
7692
  };
7662
7693
  }
7663
7694
  function handleRequest(req, res, options, sessions, secretCtx) {
@@ -8514,6 +8545,9 @@ import { join as join25 } from "path";
8514
8545
  // ../listener/dist/mcp/auto-config/markers.js
8515
8546
  import { promises as fs5 } from "fs";
8516
8547
  import { dirname as dirname15 } from "path";
8548
+ function repoWiseServerName(ctx) {
8549
+ return `RepoWise MCP for ${ctx.repoName}${ctx.envSuffix ?? ""}`;
8550
+ }
8517
8551
  async function writeMergedConfig(params) {
8518
8552
  const current = await readConfig(params.path);
8519
8553
  const servers = { ...current.mcpServers ?? {} };
@@ -8596,14 +8630,14 @@ var claudeCodeWriter = {
8596
8630
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8597
8631
  const status2 = await writeMergedConfig({
8598
8632
  path,
8599
- serverName: `RepoWise MCP for ${ctx.repoName}`,
8633
+ serverName: repoWiseServerName(ctx),
8600
8634
  spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
8601
8635
  });
8602
8636
  return { status: status2, path };
8603
8637
  },
8604
8638
  async remove(ctx) {
8605
8639
  const path = join25(ctx.repoRoot, ".mcp.json");
8606
- await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
8640
+ await removeFromConfig(path, repoWiseServerName(ctx));
8607
8641
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8608
8642
  }
8609
8643
  };
@@ -8657,14 +8691,14 @@ var clineWriter = {
8657
8691
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8658
8692
  const status2 = await writeMergedConfig({
8659
8693
  path,
8660
- serverName: `RepoWise MCP for ${ctx.repoName}`,
8694
+ serverName: repoWiseServerName(ctx),
8661
8695
  spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
8662
8696
  });
8663
8697
  return { status: status2, path };
8664
8698
  },
8665
8699
  async remove(ctx) {
8666
8700
  const path = join27(ctx.home, ".cline", "mcp.json");
8667
- await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
8701
+ await removeFromConfig(path, repoWiseServerName(ctx));
8668
8702
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8669
8703
  }
8670
8704
  };
@@ -8765,14 +8799,14 @@ var codexWriter = {
8765
8799
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8766
8800
  const status2 = await writeMergedConfig({
8767
8801
  path,
8768
- serverName: `RepoWise MCP for ${ctx.repoName}`,
8802
+ serverName: repoWiseServerName(ctx),
8769
8803
  spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
8770
8804
  });
8771
8805
  return { status: status2, path };
8772
8806
  },
8773
8807
  async remove(ctx) {
8774
8808
  const path = join29(ctx.home, ".codex", "mcp.json");
8775
- await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
8809
+ await removeFromConfig(path, repoWiseServerName(ctx));
8776
8810
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8777
8811
  }
8778
8812
  };
@@ -8865,14 +8899,14 @@ var copilotWriter = {
8865
8899
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8866
8900
  const status2 = await writeMergedConfig({
8867
8901
  path,
8868
- serverName: `RepoWise MCP for ${ctx.repoName}`,
8902
+ serverName: repoWiseServerName(ctx),
8869
8903
  spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
8870
8904
  });
8871
8905
  return { status: status2, path };
8872
8906
  },
8873
8907
  async remove(ctx) {
8874
8908
  const path = join31(ctx.repoRoot, ".vscode", "mcp.json");
8875
- await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
8909
+ await removeFromConfig(path, repoWiseServerName(ctx));
8876
8910
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8877
8911
  }
8878
8912
  };
@@ -8959,14 +8993,14 @@ var cursorWriter = {
8959
8993
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8960
8994
  const status2 = await writeMergedConfig({
8961
8995
  path,
8962
- serverName: `RepoWise MCP for ${ctx.repoName}`,
8996
+ serverName: repoWiseServerName(ctx),
8963
8997
  spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
8964
8998
  });
8965
8999
  return { status: status2, path };
8966
9000
  },
8967
9001
  async remove(ctx) {
8968
9002
  const path = join33(ctx.repoRoot, ".cursor", "mcp.json");
8969
- await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
9003
+ await removeFromConfig(path, repoWiseServerName(ctx));
8970
9004
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8971
9005
  }
8972
9006
  };
@@ -8992,14 +9026,14 @@ var geminiCliWriter = {
8992
9026
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
8993
9027
  const status2 = await writeMergedConfig({
8994
9028
  path,
8995
- serverName: `RepoWise MCP for ${ctx.repoName}`,
9029
+ serverName: repoWiseServerName(ctx),
8996
9030
  spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
8997
9031
  });
8998
9032
  return { status: status2, path };
8999
9033
  },
9000
9034
  async remove(ctx) {
9001
9035
  const path = join34(ctx.home, ".gemini", "settings.json");
9002
- await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
9036
+ await removeFromConfig(path, repoWiseServerName(ctx));
9003
9037
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
9004
9038
  }
9005
9039
  };
@@ -9102,7 +9136,7 @@ var rooWriter = {
9102
9136
  const homeConfig = join36(ctx.home, ".roo", "mcp.json");
9103
9137
  const homeSettings = join36(ctx.home, ".roo", "settings.json");
9104
9138
  for (const path of [repoConfig, homeConfig, homeSettings]) {
9105
- await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`).catch(() => {
9139
+ await removeFromConfig(path, repoWiseServerName(ctx)).catch(() => {
9106
9140
  });
9107
9141
  await removeFromConfig(path, `repowise-${ctx.repoId}`).catch(() => {
9108
9142
  });
@@ -9138,14 +9172,14 @@ var windsurfWriter = {
9138
9172
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
9139
9173
  const status2 = await writeMergedConfig({
9140
9174
  path,
9141
- serverName: `RepoWise MCP for ${ctx.repoName}`,
9175
+ serverName: repoWiseServerName(ctx),
9142
9176
  spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
9143
9177
  });
9144
9178
  return { status: status2, path };
9145
9179
  },
9146
9180
  async remove(ctx) {
9147
9181
  const path = join37(ctx.home, ".codeium", "windsurf", "mcp_config.json");
9148
- await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
9182
+ await removeFromConfig(path, repoWiseServerName(ctx));
9149
9183
  await removeFromConfig(path, `repowise-${ctx.repoId}`);
9150
9184
  }
9151
9185
  };
@@ -9205,7 +9239,8 @@ async function runAutoConfig(opts) {
9205
9239
  home,
9206
9240
  contextFolder: opts.contextFolder,
9207
9241
  selectedTools: opts.selectedTools,
9208
- variant: opts.variant
9242
+ variant: opts.variant,
9243
+ envSuffix: opts.envSuffix
9209
9244
  });
9210
9245
  results.push({ tool: writer.tool, detected: true, outcome });
9211
9246
  } catch (err) {
@@ -11302,6 +11337,7 @@ function mcpAiToolsKey(aiTools) {
11302
11337
  }
11303
11338
  async function reconcileMcpConfigs(repos, packageName) {
11304
11339
  const shimCmd = packageName;
11340
+ const envSuffix = getConfigDir().endsWith("-staging") ? " (staging)" : "";
11305
11341
  const { contextFolder, aiTools, graphOnly } = await readRawToolConfig();
11306
11342
  for (const repo of repos) {
11307
11343
  if (!repo.localPath)
@@ -11322,7 +11358,8 @@ async function reconcileMcpConfigs(repos, packageName) {
11322
11358
  shimCmd,
11323
11359
  contextFolder,
11324
11360
  selectedTools: aiTools,
11325
- variant
11361
+ variant,
11362
+ envSuffix
11326
11363
  });
11327
11364
  const written = results.filter((r) => r.detected && r.outcome?.status === "written");
11328
11365
  if (written.length > 0) {
@@ -11744,10 +11781,25 @@ async function startListener() {
11744
11781
  proactiveRefreshTimer.unref();
11745
11782
  }
11746
11783
  let lastCycleAt = Date.now();
11784
+ let endpointResumeFailed = false;
11785
+ let endpointResumeRetries = 0;
11747
11786
  while (running) {
11748
11787
  const wakeDrift = Date.now() - lastCycleAt;
11749
11788
  await maybeRefreshOnWake(wakeDrift, pollIntervalMs);
11750
11789
  lastCycleAt = Date.now();
11790
+ if (endpointResumeFailed) {
11791
+ try {
11792
+ await mcpRuntime?.server?.resumeEndpoint();
11793
+ endpointResumeFailed = false;
11794
+ endpointResumeRetries = 0;
11795
+ console.log("[mcp] endpoint file restored on retry");
11796
+ } catch {
11797
+ endpointResumeRetries++;
11798
+ if (endpointResumeRetries % 12 === 0) {
11799
+ console.warn(`[mcp] endpoint file still not restored after ${endpointResumeRetries.toString()} retries \u2014 MCP remains unreachable`);
11800
+ }
11801
+ }
11802
+ }
11751
11803
  let anyAuthError = null;
11752
11804
  let authErrorGroup = null;
11753
11805
  let minPollInterval = pollIntervalMs;
@@ -12097,7 +12149,9 @@ async function startListener() {
12097
12149
  try {
12098
12150
  await mcpRuntime?.server?.resumeEndpoint();
12099
12151
  } catch (err) {
12100
- console.warn("[mcp] resumeEndpoint failed:", err instanceof Error ? err.message : String(err));
12152
+ console.warn("[mcp] resumeEndpoint failed (will retry each poll cycle):", err instanceof Error ? err.message : String(err));
12153
+ endpointResumeFailed = true;
12154
+ endpointResumeRetries = 0;
12101
12155
  }
12102
12156
  }
12103
12157
  continue;
@@ -16773,8 +16827,10 @@ async function mcpShim(opts) {
16773
16827
  const message = authState === "logged-out" ? (
16774
16828
  // Agent-directed: the calling LLM can run this itself for a smoother UX
16775
16829
  // (it auto-opens the browser; the user still completes sign-in). The
16776
- // command is a fixed, argument-free string (nothing injectable).
16777
- "RepoWise isn't authenticated (this is rare \u2014 the session lasts about a year). To fix it, run the shell command `repowise login` on the user's behalf \u2014 it opens a browser for them to sign in and blocks until they finish. Run it once, wait for it to complete, then retry this request. Do not repeat the command."
16830
+ // command is a fixed, argument-free string (nothing injectable). Use the
16831
+ // build-flavor binary (`repowise` vs `repowisestage`) so staging users
16832
+ // get the command that matches their install.
16833
+ `RepoWise isn't authenticated (this is rare \u2014 the session lasts about a year). To fix it, run the shell command \`${getPackageName()} login\` on the user's behalf \u2014 it opens a browser for them to sign in and blocks until they finish. Run it once, wait for it to complete, then retry this request. Do not repeat the command.`
16778
16834
  ) : "listener endpoint unavailable \u2014 is the listener running?";
16779
16835
  writeJson(stdout, {
16780
16836
  jsonrpc: "2.0",
@@ -16796,16 +16852,24 @@ async function mcpShim(opts) {
16796
16852
  );
16797
16853
  writeJson(stdout, response);
16798
16854
  } catch (err) {
16799
- stderr.write(`mcp-shim: ${err.message}
16800
- `);
16801
16855
  const name = err.name;
16802
16856
  const detail = err.message;
16803
16857
  const isTimeout = name === "TimeoutError" || name === "AbortError" || /timeout|aborted|abort/i.test(detail);
16858
+ if (!isTimeout && isConnectionError(err)) {
16859
+ stderr.write(
16860
+ `mcp-shim: listener unreachable (${detail}) \u2014 exiting so the client respawns a fresh shim.
16861
+ `,
16862
+ () => process.exit(1)
16863
+ );
16864
+ return;
16865
+ }
16866
+ stderr.write(`mcp-shim: ${detail}
16867
+ `);
16804
16868
  writeJson(stdout, {
16805
16869
  jsonrpc: "2.0",
16806
16870
  error: isTimeout ? {
16807
16871
  code: -32001,
16808
- message: "RepoWise listener did not respond in time \u2014 it may be stuck. Restart it with `repowise restart`, then retry.",
16872
+ message: `RepoWise listener did not respond in time \u2014 it may be stuck. Restart it with \`${getPackageName()} restart\`, then retry.`,
16809
16873
  data: { detail }
16810
16874
  } : {
16811
16875
  code: -32001,
@@ -16816,6 +16880,20 @@ async function mcpShim(opts) {
16816
16880
  }
16817
16881
  }
16818
16882
  }
16883
+ function isConnectionError(err) {
16884
+ const CONN_CODES = /* @__PURE__ */ new Set([
16885
+ "ECONNREFUSED",
16886
+ "ECONNRESET",
16887
+ "EHOSTUNREACH",
16888
+ "ENETUNREACH",
16889
+ "ECONNABORTED"
16890
+ ]);
16891
+ const e = err;
16892
+ if (e && typeof e.code === "string" && CONN_CODES.has(e.code)) return true;
16893
+ if (e && e.cause && typeof e.cause.code === "string" && CONN_CODES.has(e.cause.code)) return true;
16894
+ const msg = err instanceof Error ? err.message : String(err);
16895
+ return /ECONNREFUSED|ECONNRESET|EHOSTUNREACH|ENETUNREACH|fetch failed|socket hang up/i.test(msg);
16896
+ }
16819
16897
  async function readEndpoint(path) {
16820
16898
  try {
16821
16899
  const raw = (await fs30.readFile(path, "utf-8")).trim();
@@ -16866,7 +16944,7 @@ async function routeMessage(endpoint, repoId, message, postJson, getJson, header
16866
16944
  id: rpcId,
16867
16945
  result: {
16868
16946
  protocolVersion: "2024-11-05",
16869
- serverInfo: { name: "repowise", version: "0.0.0" },
16947
+ serverInfo: { name: getPackageName(), version: "0.0.0" },
16870
16948
  capabilities: { tools: { listChanged: false } }
16871
16949
  }
16872
16950
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repowisestage",
3
- "version": "0.0.75",
3
+ "version": "0.0.76",
4
4
  "type": "module",
5
5
  "description": "AI-optimized codebase context generator",
6
6
  "bin": {