@humain/terminal 0.0.3-beta.0 → 0.0.3-beta.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +4 -3
  4. package/dist/config.js.map +1 -1
  5. package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +13 -0
  6. package/dist/humain/mcp-adapter/vendor/README.md +4 -1
  7. package/dist/humain/mcp-adapter/vendor/agent-dir.ts +12 -4
  8. package/dist/humain/mcp-adapter/vendor/cli.js +25 -4
  9. package/dist/humain/mcp-adapter/vendor/config.ts +4 -4
  10. package/dist/humain/mcp-adapter/vendor/direct-tools.ts +18 -15
  11. package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +416 -60
  12. package/dist/humain/mcp-adapter/vendor/mcp-setup-panel.ts +2 -1
  13. package/dist/humain/mcp-adapter/vendor/metadata-cache.ts +18 -8
  14. package/dist/humain/mcp-adapter/vendor/package.json +177 -176
  15. package/dist/humain/mcp-adapter/vendor/request-headers-command.ts +336 -0
  16. package/dist/humain/mcp-adapter/vendor/server-manager.ts +5 -0
  17. package/dist/humain/mcp-adapter/vendor/tool-metadata.ts +38 -18
  18. package/dist/humain/mcp-adapter/vendor/types.ts +93 -10
  19. package/dist/humain/web-access/vendor/auth-fetch.d.ts +13 -0
  20. package/dist/humain/web-access/vendor/auth-fetch.d.ts.map +1 -0
  21. package/dist/humain/web-access/vendor/auth-fetch.js +134 -0
  22. package/dist/humain/web-access/vendor/auth-fetch.js.map +1 -0
  23. package/dist/humain/web-access/vendor/chrome-cookies.d.ts +13 -0
  24. package/dist/humain/web-access/vendor/chrome-cookies.d.ts.map +1 -1
  25. package/dist/humain/web-access/vendor/chrome-cookies.js +106 -22
  26. package/dist/humain/web-access/vendor/chrome-cookies.js.map +1 -1
  27. package/dist/humain/web-access/vendor/curator-page.d.ts +1 -0
  28. package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -1
  29. package/dist/humain/web-access/vendor/curator-page.js +3 -1
  30. package/dist/humain/web-access/vendor/curator-page.js.map +1 -1
  31. package/dist/humain/web-access/vendor/curator-server.d.ts +1 -0
  32. package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -1
  33. package/dist/humain/web-access/vendor/curator-server.js +2 -0
  34. package/dist/humain/web-access/vendor/curator-server.js.map +1 -1
  35. package/dist/humain/web-access/vendor/extract.d.ts +2 -0
  36. package/dist/humain/web-access/vendor/extract.d.ts.map +1 -1
  37. package/dist/humain/web-access/vendor/extract.js +79 -17
  38. package/dist/humain/web-access/vendor/extract.js.map +1 -1
  39. package/dist/humain/web-access/vendor/fetch-params.d.ts +2 -0
  40. package/dist/humain/web-access/vendor/fetch-params.d.ts.map +1 -1
  41. package/dist/humain/web-access/vendor/fetch-params.js +17 -3
  42. package/dist/humain/web-access/vendor/fetch-params.js.map +1 -1
  43. package/dist/humain/web-access/vendor/firecrawl.d.ts +7 -0
  44. package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -1
  45. package/dist/humain/web-access/vendor/firecrawl.js +141 -10
  46. package/dist/humain/web-access/vendor/firecrawl.js.map +1 -1
  47. package/dist/humain/web-access/vendor/gemini-search.d.ts +2 -2
  48. package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -1
  49. package/dist/humain/web-access/vendor/gemini-search.js +22 -4
  50. package/dist/humain/web-access/vendor/gemini-search.js.map +1 -1
  51. package/dist/humain/web-access/vendor/index.d.ts.map +1 -1
  52. package/dist/humain/web-access/vendor/index.js +122 -48
  53. package/dist/humain/web-access/vendor/index.js.map +1 -1
  54. package/dist/humain/web-access/vendor/summary-review.d.ts +3 -1
  55. package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -1
  56. package/dist/humain/web-access/vendor/summary-review.js +6 -3
  57. package/dist/humain/web-access/vendor/summary-review.js.map +1 -1
  58. package/dist/humain/web-access/vendor/youtube-extract.d.ts.map +1 -1
  59. package/dist/humain/web-access/vendor/youtube-extract.js +2 -2
  60. package/dist/humain/web-access/vendor/youtube-extract.js.map +1 -1
  61. package/dist/utils/clipboard-image.d.ts.map +1 -1
  62. package/dist/utils/clipboard-image.js +2 -0
  63. package/dist/utils/clipboard-image.js.map +1 -1
  64. package/npm-shrinkwrap.json +7 -7
  65. package/package.json +6 -6
  66. package/src/humain/mcp-adapter/UPSTREAM.md +1 -1
  67. package/src/humain/mcp-adapter/upstream.json +3 -3
  68. package/src/humain/mcp-adapter/vendor/CHANGELOG.md +13 -0
  69. package/src/humain/web-access/UPSTREAM.md +1 -1
  70. package/src/humain/web-access/upstream.json +4 -4
@@ -205,6 +205,14 @@ function globToRegExp(pattern) {
205
205
  const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
206
206
  return new RegExp(`^${escaped}$`);
207
207
  }
208
+ function createToolSelectorCandidateIndex(allCurrentCandidates, additionalCurrentCandidatesByToolName) {
209
+ return {
210
+ allCurrentCandidates,
211
+ matchingCountByPattern: /* @__PURE__ */ new Map(),
212
+ matcherByPattern: /* @__PURE__ */ new Map(),
213
+ ...additionalCurrentCandidatesByToolName ? { additionalCurrentCandidatesByToolName } : {}
214
+ };
215
+ }
208
216
  function matchesToolPattern(candidates, patterns) {
209
217
  if (!Array.isArray(patterns) || patterns.length === 0) return false;
210
218
  for (const pattern of patterns) {
@@ -218,16 +226,51 @@ function matchesToolPattern(candidates, patterns) {
218
226
  }
219
227
  return false;
220
228
  }
229
+ function indexHasOtherCurrentMatch(index, toolName, currentCandidates, pattern) {
230
+ const additionalCandidates = index.additionalCurrentCandidatesByToolName?.get(toolName);
231
+ const hasCandidate = (candidate) => index.allCurrentCandidates.has(candidate) || additionalCandidates?.has(candidate) === true;
232
+ const isGlob = pattern.includes("*") || pattern.includes("?");
233
+ if (!isGlob) {
234
+ return hasCandidate(pattern) && !currentCandidates.has(pattern);
235
+ }
236
+ let matcher = index.matcherByPattern.get(pattern);
237
+ if (!matcher) {
238
+ matcher = globToRegExp(pattern);
239
+ index.matcherByPattern.set(pattern, matcher);
240
+ }
241
+ let matchingCount = index.matchingCountByPattern.get(pattern);
242
+ if (matchingCount === void 0) {
243
+ matchingCount = 0;
244
+ for (const candidate of index.allCurrentCandidates) {
245
+ if (matcher.test(candidate)) matchingCount++;
246
+ }
247
+ index.matchingCountByPattern.set(pattern, matchingCount);
248
+ }
249
+ let totalMatchingCount = matchingCount;
250
+ if (additionalCandidates) {
251
+ for (const candidate of additionalCandidates) {
252
+ if (!index.allCurrentCandidates.has(candidate) && matcher.test(candidate)) totalMatchingCount++;
253
+ }
254
+ }
255
+ if (totalMatchingCount === 0) return false;
256
+ let currentMatchingCount = 0;
257
+ for (const candidate of currentCandidates) {
258
+ if (hasCandidate(candidate) && matcher.test(candidate)) currentMatchingCount++;
259
+ }
260
+ return totalMatchingCount > currentMatchingCount;
261
+ }
221
262
  function matchesToolSelector(toolName, serverName, prefix, patterns, otherCurrentCandidates) {
263
+ if (!Array.isArray(patterns) || patterns.length === 0) return false;
222
264
  const currentCandidates = getToolNameCandidates(toolName, serverName, prefix, false);
223
265
  if (matchesToolPattern(currentCandidates, patterns)) return true;
224
266
  if (!otherCurrentCandidates) return matchesToolPattern(getToolNameCandidates(toolName, serverName, prefix), patterns);
225
267
  const legacyCandidates = getToolNameCandidates(toolName, serverName, prefix);
226
268
  for (const candidate of currentCandidates) legacyCandidates.delete(candidate);
227
- if (!Array.isArray(patterns)) return false;
228
- return patterns.some(
229
- (pattern) => typeof pattern === "string" && !matchesToolPattern(otherCurrentCandidates, [pattern]) && matchesToolPattern(legacyCandidates, [pattern])
230
- );
269
+ return patterns.some((pattern) => {
270
+ if (typeof pattern !== "string" || !matchesToolPattern(legacyCandidates, [pattern])) return false;
271
+ const hasCollision = otherCurrentCandidates instanceof Set ? matchesToolPattern(otherCurrentCandidates, [pattern]) : indexHasOtherCurrentMatch(otherCurrentCandidates, toolName, currentCandidates, pattern);
272
+ return !hasCollision;
273
+ });
231
274
  }
232
275
  function isToolIncluded(toolName, serverName, prefix, includeTools, otherCurrentCandidates) {
233
276
  if (!Array.isArray(includeTools) || includeTools.length === 0) return true;
@@ -254,10 +297,17 @@ var init_types = __esm({
254
297
  import { readFileSync } from "node:fs";
255
298
  import { homedir } from "node:os";
256
299
  import { join, resolve } from "node:path";
300
+ function getConfigDirName() {
301
+ const configDir = readPiConfig()?.configDir;
302
+ return typeof configDir === "string" && configDir.trim() ? configDir.trim() : ".pi";
303
+ }
257
304
  function getAgentDir() {
258
- const configured = process.env.PI_CODING_AGENT_DIR?.trim();
305
+ const piConfig = readPiConfig();
306
+ const name = piConfig?.name;
307
+ const appName = typeof name === "string" && name.trim() ? name.trim() : "pi";
308
+ const configured = process.env[`${appName.toUpperCase()}_CODING_AGENT_DIR`]?.trim();
259
309
  if (!configured) {
260
- return join(homedir(), ".pi", "agent");
310
+ return join(homedir(), getConfigDirName(), "agent");
261
311
  }
262
312
  if (configured === "~") {
263
313
  return homedir();
@@ -859,7 +909,7 @@ function getProjectConfigPath(cwd = process.cwd()) {
859
909
  return resolve3(cwd, PROJECT_CONFIG_NAME);
860
910
  }
861
911
  function getProjectPiConfigPath(cwd = process.cwd()) {
862
- return resolve3(cwd, PROJECT_PI_CONFIG_NAME);
912
+ return resolve3(cwd, getConfigDirName(), PROJECT_PI_CONFIG_NAME);
863
913
  }
864
914
  function getConfigSourceSummaries(sourceSpecs) {
865
915
  return sourceSpecs.map((source) => {
@@ -1706,7 +1756,7 @@ var init_config = __esm({
1706
1756
  join3(homedir3(), ".agents", "mcp", "mcp.json")
1707
1757
  ];
1708
1758
  PROJECT_CONFIG_NAME = ".mcp.json";
1709
- PROJECT_PI_CONFIG_NAME = ".pi/mcp.json";
1759
+ PROJECT_PI_CONFIG_NAME = "mcp.json";
1710
1760
  REPOPROMPT_BINARY_CANDIDATES = [
1711
1761
  join3(homedir3(), "RepoPrompt", "repoprompt_cli"),
1712
1762
  "/Applications/Repo Prompt.app/Contents/MacOS/repoprompt-mcp"
@@ -1762,7 +1812,7 @@ var init_config = __esm({
1762
1812
  windsurf: [join3(homedir3(), ".windsurf", "mcp.json")],
1763
1813
  vscode: [".vscode/mcp.json"]
1764
1814
  };
1765
- URL_BOUND_AUTH_FIELDS = ["headers", "bearerToken", "bearerTokenEnv"];
1815
+ URL_BOUND_AUTH_FIELDS = ["headers", "bearerToken", "bearerTokenEnv", "requestHeadersCommand"];
1766
1816
  }
1767
1817
  });
1768
1818
 
@@ -1894,6 +1944,12 @@ function computeServerHash(definition) {
1894
1944
  cwd: resolveConfigPath(definition.cwd),
1895
1945
  url: resolveServerUrl(definition),
1896
1946
  headers: interpolateEnvRecord(definition.headers),
1947
+ requestHeadersCommand: definition.requestHeadersCommand ? {
1948
+ command: interpolateEnvVars(definition.requestHeadersCommand.command),
1949
+ args: definition.requestHeadersCommand.args?.map(interpolateEnvVars),
1950
+ env: interpolateEnvRecord(definition.requestHeadersCommand.env),
1951
+ timeoutMs: definition.requestHeadersCommand.timeoutMs
1952
+ } : void 0,
1897
1953
  auth: definition.auth,
1898
1954
  protocolVersion: definition.protocolVersion,
1899
1955
  bearerToken: resolveBearerToken(definition),
@@ -1956,8 +2012,8 @@ function reconstructToolMetadata(serverName, entry, prefix, definition, configur
1956
2012
  const metadata = [];
1957
2013
  const seenNames = /* @__PURE__ */ new Set();
1958
2014
  const effectivePrefix = resolveToolPrefix(definition, prefix);
1959
- const getOtherCurrentCandidates = (toolName) => {
1960
- if (!configuredServers || !cache) return void 0;
2015
+ const hasToolFilters = Array.isArray(definition.includeTools) && definition.includeTools.length > 0 || Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0;
2016
+ const selectorCandidateIndex = hasToolFilters && configuredServers && cache ? (() => {
1961
2017
  const candidates = /* @__PURE__ */ new Set();
1962
2018
  for (const [otherServerName, otherDefinition] of Object.entries(configuredServers)) {
1963
2019
  const otherEntry = cache.servers[otherServerName];
@@ -1974,15 +2030,14 @@ function reconstructToolMetadata(serverName, entry, prefix, definition, configur
1974
2030
  }
1975
2031
  }
1976
2032
  }
1977
- for (const candidate of getToolNameCandidates(toolName, serverName, effectivePrefix, false)) candidates.delete(candidate);
1978
- return candidates;
1979
- };
2033
+ return createToolSelectorCandidateIndex(candidates);
2034
+ })() : void 0;
1980
2035
  for (const tool of entry.tools ?? []) {
1981
2036
  if (!tool?.name) continue;
1982
2037
  if (!isUiToolVisibleToModel(tool.uiVisibility)) {
1983
2038
  continue;
1984
2039
  }
1985
- if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(tool.name))) {
2040
+ if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) {
1986
2041
  continue;
1987
2042
  }
1988
2043
  const name = formatToolName(tool.name, serverName, effectivePrefix);
@@ -2004,7 +2059,7 @@ function reconstructToolMetadata(serverName, entry, prefix, definition, configur
2004
2059
  for (const resource of entry.resources ?? []) {
2005
2060
  if (!resource?.name || !resource?.uri) continue;
2006
2061
  const baseName = `read_${resourceNameToToolName(resource.name)}`;
2007
- if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(baseName))) {
2062
+ if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) {
2008
2063
  continue;
2009
2064
  }
2010
2065
  const name = formatToolName(baseName, serverName, effectivePrefix);
@@ -2177,6 +2232,7 @@ var init_mcp_setup_panel = __esm({
2177
2232
  "packages/coding-agent/src/humain/mcp-adapter/vendor/mcp-setup-panel.ts"() {
2178
2233
  "use strict";
2179
2234
  init_panel_keys();
2235
+ init_agent_dir();
2180
2236
  init_config();
2181
2237
  DEFAULT_THEME = {
2182
2238
  border: "2",
@@ -2607,7 +2663,7 @@ var init_mcp_setup_panel = __esm({
2607
2663
  "3. ~/.agents/mcp/mcp.json",
2608
2664
  "4. <Pi agent dir>/mcp.json",
2609
2665
  "5. .mcp.json",
2610
- "6. .pi/mcp.json",
2666
+ `6. ${getConfigDirName()}/mcp.json`,
2611
2667
  `Host discovery: ${this.discovery.hostConfigDiscovery}. Conflicts reported: ${this.discovery.conflicts.length}.`,
2612
2668
  ...this.discovery.conflicts.slice(0, 8).map(
2613
2669
  (conflict) => `${conflict.serverName}: ${conflict.sources.map((source) => source.path).join(" -> ")} (winner: ${conflict.winner.path})`
@@ -2752,7 +2808,7 @@ var init_clipboard_image = __esm({
2752
2808
  });
2753
2809
 
2754
2810
  // packages/coding-agent/src/utils/clipboard.ts
2755
- import { execFileSync, execSync, spawn } from "child_process";
2811
+ import { execFileSync, execSync, spawn as spawn2 } from "child_process";
2756
2812
  import { platform as platform2 } from "os";
2757
2813
  function copyToX11Clipboard(options) {
2758
2814
  try {
@@ -2811,7 +2867,7 @@ async function copyToClipboard(text) {
2811
2867
  try {
2812
2868
  execSync("which wl-copy", { stdio: "ignore" });
2813
2869
  const wlCopyExit = await new Promise((resolve6) => {
2814
- const proc = spawn("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
2870
+ const proc = spawn2("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
2815
2871
  proc.on("error", () => resolve6(1));
2816
2872
  proc.on("close", (code) => resolve6(code ?? 1));
2817
2873
  proc.stdin.on("error", () => {
@@ -7681,6 +7737,292 @@ function traceTransportKind(definition, transport) {
7681
7737
  return definition.url ? "streamable-http" : "unknown";
7682
7738
  }
7683
7739
 
7740
+ // packages/coding-agent/src/humain/mcp-adapter/vendor/request-headers-command.ts
7741
+ init_utils();
7742
+ import { spawn, spawnSync as spawnSync3 } from "node:child_process";
7743
+ import { randomUUID } from "node:crypto";
7744
+ var DEFAULT_TIMEOUT_MS = 1e4;
7745
+ var MAX_OUTPUT_BYTES = 64 * 1024;
7746
+ var USE_PROCESS_GROUP = process.platform !== "win32";
7747
+ var CLEANUP_TOKEN_ENV = "PI_MCP_REQUEST_HEADERS_CLEANUP_TOKEN";
7748
+ function isNoSuchProcessError(error) {
7749
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ESRCH";
7750
+ }
7751
+ function runPosixPs(args) {
7752
+ if (process.env.PI_MCP_ADAPTER_TEST_FAIL_PS === "1") return { status: 1, stdout: "" };
7753
+ return spawnSync3("ps", args, { encoding: "utf8" });
7754
+ }
7755
+ function collectPosixDescendantPids(rootPid) {
7756
+ const result = runPosixPs(["-axo", "pid=,ppid="]);
7757
+ if (result.status !== 0) {
7758
+ throw new Error(`HTTP request headers command cleanup failed: ps exited with code ${result.status ?? "unknown"}`);
7759
+ }
7760
+ const childrenByParent = /* @__PURE__ */ new Map();
7761
+ for (const line of result.stdout.split("\n")) {
7762
+ const [pidText, ppidText] = line.trim().split(/\s+/, 2);
7763
+ const pid = Number(pidText);
7764
+ const ppid = Number(ppidText);
7765
+ if (!Number.isInteger(pid) || !Number.isInteger(ppid)) continue;
7766
+ const children = childrenByParent.get(ppid);
7767
+ if (children) children.push(pid);
7768
+ else childrenByParent.set(ppid, [pid]);
7769
+ }
7770
+ const descendants = [];
7771
+ const stack = [...childrenByParent.get(rootPid) ?? []];
7772
+ while (stack.length > 0) {
7773
+ const pid = stack.pop();
7774
+ descendants.push(pid);
7775
+ stack.push(...childrenByParent.get(pid) ?? []);
7776
+ }
7777
+ return descendants;
7778
+ }
7779
+ function collectPosixCleanupTokenPids(cleanupToken) {
7780
+ const result = runPosixPs(["axeww", "-o", "pid=,command="]);
7781
+ if (result.status !== 0) {
7782
+ throw new Error(`HTTP request headers command cleanup failed: ps exited with code ${result.status ?? "unknown"}`);
7783
+ }
7784
+ const needle = `${CLEANUP_TOKEN_ENV}=${cleanupToken}`;
7785
+ const pids = [];
7786
+ for (const line of result.stdout.split("\n")) {
7787
+ const trimmed = line.trim();
7788
+ if (!trimmed.includes(needle)) continue;
7789
+ const [pidText] = trimmed.split(/\s+/, 1);
7790
+ const pid = Number(pidText);
7791
+ if (Number.isInteger(pid) && pid !== process.pid) pids.push(pid);
7792
+ }
7793
+ return pids;
7794
+ }
7795
+ function assertPosixProcessDiscoveryAvailable() {
7796
+ collectPosixDescendantPids(process.pid);
7797
+ collectPosixCleanupTokenPids(`${process.pid}-preflight`);
7798
+ }
7799
+ function isTaskkillNoSuchProcess(result) {
7800
+ return `${result.stdout ?? ""}
7801
+ ${result.stderr ?? ""}`.toLowerCase().includes("not found");
7802
+ }
7803
+ function signalPid(pid, signal) {
7804
+ try {
7805
+ process.kill(pid, signal);
7806
+ } catch (error) {
7807
+ if (!isNoSuchProcessError(error)) throw error;
7808
+ }
7809
+ }
7810
+ function signalProcessGroup(pid, signal) {
7811
+ try {
7812
+ process.kill(-pid, signal);
7813
+ } catch (error) {
7814
+ if (!isNoSuchProcessError(error)) throw error;
7815
+ }
7816
+ }
7817
+ function killRequestHeadersCommand(child, trackedPosixDescendantPids = /* @__PURE__ */ new Set(), cleanupToken) {
7818
+ if (process.platform === "win32" && child.pid !== void 0) {
7819
+ const result = spawnSync3("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
7820
+ encoding: "utf8",
7821
+ windowsHide: true
7822
+ });
7823
+ if (result.status === 0 || isTaskkillNoSuchProcess(result)) return;
7824
+ throw new Error(`HTTP request headers command cleanup failed: taskkill exited with code ${result.status ?? "unknown"}`);
7825
+ }
7826
+ if (USE_PROCESS_GROUP && child.pid !== void 0) {
7827
+ const frozenPids = /* @__PURE__ */ new Set();
7828
+ let cleanupError;
7829
+ try {
7830
+ signalProcessGroup(child.pid, "SIGSTOP");
7831
+ for (const pid of trackedPosixDescendantPids) {
7832
+ signalPid(pid, "SIGSTOP");
7833
+ frozenPids.add(pid);
7834
+ }
7835
+ let stablePasses = 0;
7836
+ for (let pass = 0; pass < 16; pass++) {
7837
+ const candidates = [
7838
+ ...collectPosixDescendantPids(child.pid),
7839
+ ...cleanupToken ? collectPosixCleanupTokenPids(cleanupToken) : []
7840
+ ];
7841
+ const newPids = candidates.filter((pid) => !frozenPids.has(pid));
7842
+ if (newPids.length === 0) {
7843
+ stablePasses++;
7844
+ if (stablePasses >= 2) return;
7845
+ continue;
7846
+ }
7847
+ stablePasses = 0;
7848
+ for (const pid of newPids) {
7849
+ signalPid(pid, "SIGSTOP");
7850
+ frozenPids.add(pid);
7851
+ }
7852
+ }
7853
+ cleanupError = new Error("HTTP request headers command cleanup failed: descendant process tree did not stabilize");
7854
+ } catch (error) {
7855
+ cleanupError = error instanceof Error ? error : new Error(String(error));
7856
+ } finally {
7857
+ signalProcessGroup(child.pid, "SIGKILL");
7858
+ for (const pid of frozenPids) signalPid(pid, "SIGKILL");
7859
+ }
7860
+ if (cleanupError) throw cleanupError;
7861
+ return;
7862
+ }
7863
+ child.kill("SIGKILL");
7864
+ }
7865
+ function resolvedCommand(config) {
7866
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
7867
+ throw new Error("HTTP request headers command must be an object");
7868
+ }
7869
+ if (typeof config.command !== "string" || config.command.trim() === "") {
7870
+ throw new Error("HTTP request headers command requires a non-empty command");
7871
+ }
7872
+ if (config.args !== void 0 && (!Array.isArray(config.args) || config.args.some((arg) => typeof arg !== "string"))) {
7873
+ throw new Error("HTTP request headers command args must be strings");
7874
+ }
7875
+ if (config.env !== void 0 && (typeof config.env !== "object" || Array.isArray(config.env) || Object.values(config.env).some((value) => typeof value !== "string"))) {
7876
+ throw new Error("HTTP request headers command env values must be strings");
7877
+ }
7878
+ const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
7879
+ if (!Number.isInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > 6e4) {
7880
+ throw new Error("HTTP request headers command timeoutMs must be an integer between 1 and 60000");
7881
+ }
7882
+ return {
7883
+ command: interpolateEnvVars(config.command),
7884
+ args: (config.args ?? []).map(interpolateEnvVars),
7885
+ env: {
7886
+ ...process.env,
7887
+ ...Object.fromEntries(
7888
+ Object.entries(config.env ?? {}).map(([key, value]) => [key, interpolateEnvVars(value)])
7889
+ )
7890
+ },
7891
+ timeoutMs
7892
+ };
7893
+ }
7894
+ async function invokeRequestHeadersCommand(config, envelope, signal) {
7895
+ const resolved = resolvedCommand(config);
7896
+ if (USE_PROCESS_GROUP) assertPosixProcessDiscoveryAvailable();
7897
+ return new Promise((resolve6, reject) => {
7898
+ let stdout = Buffer.alloc(0);
7899
+ let settled = false;
7900
+ const cleanupToken = randomUUID();
7901
+ const child = spawn(resolved.command, resolved.args, {
7902
+ env: { ...resolved.env, [CLEANUP_TOKEN_ENV]: cleanupToken },
7903
+ stdio: ["pipe", "pipe", "ignore"],
7904
+ windowsHide: true,
7905
+ detached: USE_PROCESS_GROUP
7906
+ });
7907
+ const trackedPosixDescendantPids = /* @__PURE__ */ new Set();
7908
+ let trackingError;
7909
+ const trackPosixDescendants = () => {
7910
+ if (!USE_PROCESS_GROUP || child.pid === void 0 || settled || trackingError) return;
7911
+ try {
7912
+ for (const pid of collectPosixDescendantPids(child.pid)) trackedPosixDescendantPids.add(pid);
7913
+ for (const pid of collectPosixCleanupTokenPids(cleanupToken)) trackedPosixDescendantPids.add(pid);
7914
+ } catch (error) {
7915
+ trackingError = error instanceof Error ? error : new Error(String(error));
7916
+ }
7917
+ };
7918
+ const descendantTracker = USE_PROCESS_GROUP ? setInterval(trackPosixDescendants, 50) : void 0;
7919
+ descendantTracker?.unref();
7920
+ const finish = (result) => {
7921
+ if (settled) return;
7922
+ settled = true;
7923
+ clearTimeout(timer);
7924
+ if (descendantTracker) clearInterval(descendantTracker);
7925
+ signal.removeEventListener("abort", abort);
7926
+ if (result.status === "error") reject(result.error);
7927
+ else resolve6(result.headers);
7928
+ };
7929
+ const finishAfterKill = (result) => {
7930
+ try {
7931
+ killRequestHeadersCommand(child, trackedPosixDescendantPids, cleanupToken);
7932
+ finish(result);
7933
+ } catch (cleanupError) {
7934
+ finish({ status: "error", error: cleanupError instanceof Error ? cleanupError : new Error(String(cleanupError)) });
7935
+ }
7936
+ };
7937
+ const failAfterKill = (message) => {
7938
+ finishAfterKill({ status: "error", error: trackingError ?? new Error(message) });
7939
+ };
7940
+ const abort = () => {
7941
+ failAfterKill("HTTP request headers command aborted");
7942
+ };
7943
+ const timer = setTimeout(() => {
7944
+ failAfterKill(`HTTP request headers command timed out after ${resolved.timeoutMs}ms`);
7945
+ }, resolved.timeoutMs);
7946
+ signal.addEventListener("abort", abort, { once: true });
7947
+ if (signal.aborted) {
7948
+ abort();
7949
+ return;
7950
+ }
7951
+ child.on("error", () => finish({ status: "error", error: new Error("HTTP request headers command failed to start") }));
7952
+ child.stdout.on("data", (chunk) => {
7953
+ if (settled) return;
7954
+ stdout = Buffer.concat([stdout, Buffer.from(chunk)]);
7955
+ if (stdout.byteLength > MAX_OUTPUT_BYTES) {
7956
+ failAfterKill("HTTP request headers command output exceeded 64 KiB");
7957
+ }
7958
+ });
7959
+ child.on("close", (code) => {
7960
+ if (settled) return;
7961
+ if (trackingError) {
7962
+ failAfterKill(trackingError.message);
7963
+ return;
7964
+ }
7965
+ if (code !== 0) {
7966
+ failAfterKill(`HTTP request headers command exited with code ${code ?? "unknown"}`);
7967
+ return;
7968
+ }
7969
+ let parsed;
7970
+ try {
7971
+ parsed = JSON.parse(stdout.toString("utf8"));
7972
+ } catch {
7973
+ finishAfterKill({ status: "error", error: new Error("HTTP request headers command returned invalid JSON") });
7974
+ return;
7975
+ }
7976
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
7977
+ finishAfterKill({ status: "error", error: new Error("HTTP request headers command must return a JSON object") });
7978
+ return;
7979
+ }
7980
+ const entries = Object.entries(parsed);
7981
+ if (entries.some(([, value]) => typeof value !== "string")) {
7982
+ finishAfterKill({ status: "error", error: new Error("HTTP request headers command values must be strings") });
7983
+ return;
7984
+ }
7985
+ try {
7986
+ finishAfterKill({ status: "success", headers: new Headers(entries) });
7987
+ } catch {
7988
+ finishAfterKill({ status: "error", error: new Error("HTTP request headers command returned an invalid header") });
7989
+ }
7990
+ });
7991
+ child.stdin.on("error", () => {
7992
+ });
7993
+ child.stdin.end(JSON.stringify(envelope));
7994
+ });
7995
+ }
7996
+ function createRequestHeadersCommandFetch(config, delegate = globalThis.fetch) {
7997
+ resolvedCommand(config);
7998
+ return async (input, init) => {
7999
+ const request = new Request(input, init);
8000
+ const body = Buffer.from(await request.clone().arrayBuffer());
8001
+ const derived = await invokeRequestHeadersCommand(config, {
8002
+ version: 1,
8003
+ method: request.method.toUpperCase(),
8004
+ url: request.url,
8005
+ bodyBase64: body.toString("base64")
8006
+ }, request.signal);
8007
+ const headers = new Headers(request.headers);
8008
+ derived.forEach((value, name) => headers.set(name, value));
8009
+ return delegate(new URL(request.url), {
8010
+ method: request.method,
8011
+ headers,
8012
+ ...request.method === "GET" || request.method === "HEAD" ? {} : { body },
8013
+ signal: request.signal,
8014
+ cache: request.cache,
8015
+ credentials: request.credentials,
8016
+ integrity: request.integrity,
8017
+ keepalive: request.keepalive,
8018
+ mode: request.mode,
8019
+ redirect: request.redirect,
8020
+ referrer: request.referrer,
8021
+ referrerPolicy: request.referrerPolicy
8022
+ });
8023
+ };
8024
+ }
8025
+
7684
8026
  // packages/coding-agent/src/humain/mcp-adapter/vendor/server-manager.ts
7685
8027
  var MAX_CAPTURED_STDERR_BYTES = 8 * 1024;
7686
8028
  var MAX_CAPTURED_STDERR_LINES = 3;
@@ -8187,6 +8529,7 @@ var McpServerManager = class {
8187
8529
  }
8188
8530
  }
8189
8531
  const requestInit = Object.keys(headers).length > 0 ? { headers } : void 0;
8532
+ const requestFetch = definition.requestHeadersCommand ? createRequestHeadersCommandFetch(definition.requestHeadersCommand) : void 0;
8190
8533
  const createAuthProvider = () => new McpOAuthProvider(
8191
8534
  serverName,
8192
8535
  serverUrl,
@@ -8201,6 +8544,7 @@ var McpServerManager = class {
8201
8544
  const authProvider = "provider" in authState ? authState.provider : void 0;
8202
8545
  const transportOptions = {
8203
8546
  ...requestInit !== void 0 ? { requestInit } : {},
8547
+ ...requestFetch !== void 0 ? { fetch: requestFetch } : {},
8204
8548
  ...authProvider !== void 0 ? { authProvider } : {},
8205
8549
  ...authProvider !== void 0 && definition.oauth !== false && definition.oauth?.skipIssuerMetadataValidation === true ? { skipIssuerMetadataValidation: true } : {}
8206
8550
  };
@@ -8493,46 +8837,59 @@ function buildToolMetadata(tools, resources, definition, serverName, prefix, con
8493
8837
  const failedTools = [];
8494
8838
  const seenNames = /* @__PURE__ */ new Set();
8495
8839
  const effectivePrefix = resolveToolPrefix(definition, prefix);
8496
- const getOtherCurrentCandidates = (toolName) => {
8497
- if (!configuredServers) return void 0;
8840
+ const hasToolFilters = Array.isArray(definition.includeTools) && definition.includeTools.length > 0 || Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0;
8841
+ const selectorCandidateIndex = hasToolFilters && configuredServers ? (() => {
8498
8842
  const candidates = /* @__PURE__ */ new Set();
8499
- const addCandidates = (originalName, candidateServerName, candidatePrefix) => {
8500
- for (const candidate of getToolNameCandidates(originalName, candidateServerName, candidatePrefix, false)) candidates.add(candidate);
8843
+ const additionalCandidatesByToolName = /* @__PURE__ */ new Map();
8844
+ const evaluatedToolNames = /* @__PURE__ */ new Set();
8845
+ const addCandidates = (target, originalName, candidateServerName, candidatePrefix) => {
8846
+ for (const candidate of getToolNameCandidates(originalName, candidateServerName, candidatePrefix, false)) target.add(candidate);
8501
8847
  };
8502
8848
  for (const tool of tools) {
8503
- if (tool?.name) addCandidates(tool.name, serverName, effectivePrefix);
8849
+ if (!tool?.name) continue;
8850
+ evaluatedToolNames.add(tool.name);
8851
+ addCandidates(candidates, tool.name, serverName, effectivePrefix);
8504
8852
  }
8505
8853
  if (definition.exposeResources !== false) {
8506
8854
  for (const resource of resources) {
8507
- if (resource?.name && resource?.uri) addCandidates(`read_${resourceNameToToolName(resource.name)}`, serverName, effectivePrefix);
8855
+ const baseName = `read_${resourceNameToToolName(resource.name)}`;
8856
+ evaluatedToolNames.add(baseName);
8857
+ if (resource?.name && resource?.uri) addCandidates(candidates, baseName, serverName, effectivePrefix);
8508
8858
  }
8509
8859
  }
8510
8860
  for (const [otherServerName, otherDefinition] of Object.entries(configuredServers)) {
8511
8861
  if (otherServerName === serverName) continue;
8862
+ const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
8512
8863
  const knownTools = knownMetadata?.get(otherServerName);
8513
8864
  if (knownTools) {
8514
- const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
8515
8865
  for (const tool of knownTools) {
8516
8866
  candidates.add(tool.name);
8517
- addCandidates(tool.originalName, otherServerName, otherPrefix);
8867
+ addCandidates(candidates, tool.originalName, otherServerName, otherPrefix);
8518
8868
  }
8519
8869
  } else if (!knownMetadata || includeMissingConfiguredCandidates) {
8520
- const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
8521
- addCandidates(toolName, otherServerName, otherPrefix);
8522
- if (includeMissingConfiguredCandidates) {
8523
- for (const candidate of getToolNameCandidates(toolName, otherServerName, otherPrefix, false)) candidates.add(candidate.replace(/-/g, "_"));
8870
+ for (const toolName of evaluatedToolNames) {
8871
+ let additionalCandidates = additionalCandidatesByToolName.get(toolName);
8872
+ if (!additionalCandidates) {
8873
+ additionalCandidates = /* @__PURE__ */ new Set();
8874
+ additionalCandidatesByToolName.set(toolName, additionalCandidates);
8875
+ }
8876
+ addCandidates(additionalCandidates, toolName, otherServerName, otherPrefix);
8877
+ if (includeMissingConfiguredCandidates) {
8878
+ for (const candidate of getToolNameCandidates(toolName, otherServerName, otherPrefix, false)) {
8879
+ additionalCandidates.add(candidate.replace(/-/g, "_"));
8880
+ }
8881
+ }
8524
8882
  }
8525
8883
  }
8526
8884
  }
8527
- for (const candidate of getToolNameCandidates(toolName, serverName, effectivePrefix, false)) candidates.delete(candidate);
8528
- return candidates;
8529
- };
8885
+ return createToolSelectorCandidateIndex(candidates, additionalCandidatesByToolName);
8886
+ })() : void 0;
8530
8887
  for (const tool of tools) {
8531
8888
  if (!tool?.name) {
8532
8889
  failedTools.push("(unnamed)");
8533
8890
  continue;
8534
8891
  }
8535
- if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(tool.name))) {
8892
+ if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) {
8536
8893
  continue;
8537
8894
  }
8538
8895
  const name = formatToolName(tool.name, serverName, effectivePrefix);
@@ -8564,7 +8921,7 @@ function buildToolMetadata(tools, resources, definition, serverName, prefix, con
8564
8921
  if (definition.exposeResources !== false) {
8565
8922
  for (const resource of resources) {
8566
8923
  const baseName = `read_${resourceNameToToolName(resource.name)}`;
8567
- if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(baseName))) {
8924
+ if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) {
8568
8925
  continue;
8569
8926
  }
8570
8927
  const name = formatToolName(baseName, serverName, effectivePrefix);
@@ -10640,7 +10997,7 @@ function formatSize(bytes) {
10640
10997
  // packages/coding-agent/src/humain/mcp-adapter/vendor/ui-session.ts
10641
10998
  init_types();
10642
10999
  import { execFile } from "node:child_process";
10643
- import { randomUUID as randomUUID3 } from "node:crypto";
11000
+ import { randomUUID as randomUUID4 } from "node:crypto";
10644
11001
  import net from "node:net";
10645
11002
  import { UrlElicitationRequiredError as UrlElicitationRequiredError2 } from "@modelcontextprotocol/client";
10646
11003
 
@@ -10649,7 +11006,7 @@ init_ui_app_bridge_helpers();
10649
11006
  import http from "node:http";
10650
11007
  import fs2 from "node:fs/promises";
10651
11008
  import path from "node:path";
10652
- import { randomUUID as randomUUID2 } from "node:crypto";
11009
+ import { randomUUID as randomUUID3 } from "node:crypto";
10653
11010
  import { ContentBlockSchema } from "@modelcontextprotocol/core";
10654
11011
  init_utils();
10655
11012
 
@@ -11070,7 +11427,7 @@ function escapeHtml2(value) {
11070
11427
  }
11071
11428
 
11072
11429
  // packages/coding-agent/src/humain/mcp-adapter/vendor/tool-approval.ts
11073
- import { randomUUID } from "node:crypto";
11430
+ import { randomUUID as randomUUID2 } from "node:crypto";
11074
11431
  init_types();
11075
11432
  init_utils();
11076
11433
  function isToolCallApprovalRequired(config, serverName, toolMeta, toolMetadata) {
@@ -11127,7 +11484,7 @@ async function requestBrokerApproval(state, serverName, toolMeta, args, origin,
11127
11484
  let acceptingClaim = true;
11128
11485
  let handler;
11129
11486
  const request = {
11130
- requestId: randomUUID(),
11487
+ requestId: randomUUID2(),
11131
11488
  serverName,
11132
11489
  originalToolName: toolMeta.originalName,
11133
11490
  prefixedToolName: toolMeta.name,
@@ -11208,8 +11565,8 @@ var MOSHI_DISCOVERY_PORT_START = 8377;
11208
11565
  var MOSHI_DISCOVERY_PORT_END = 8396;
11209
11566
  var nextMoshiDiscoveryPort = MOSHI_DISCOVERY_PORT_START;
11210
11567
  async function startUiServer(options) {
11211
- const sessionToken = options.sessionToken ?? randomUUID2();
11212
- const uiResourceToken = randomUUID2();
11568
+ const sessionToken = options.sessionToken ?? randomUUID3();
11569
+ const uiResourceToken = randomUUID3();
11213
11570
  const log = logger.child({
11214
11571
  component: "UiServer",
11215
11572
  server: options.serverName,
@@ -12051,8 +12408,8 @@ async function maybeStartUiSession(state, request) {
12051
12408
  if (state.uiServer && state.uiServer.serverName === request.serverName && state.uiServer.toolName === request.toolName) {
12052
12409
  const existingHandle = state.uiServer;
12053
12410
  const streamMode2 = request.streamMode;
12054
- const streamId2 = streamMode2 ? randomUUID3() : void 0;
12055
- const streamToken2 = streamMode2 ? randomUUID3() : void 0;
12411
+ const streamId2 = streamMode2 ? randomUUID4() : void 0;
12412
+ const streamToken2 = streamMode2 ? randomUUID4() : void 0;
12056
12413
  let active2 = true;
12057
12414
  let nextStreamSequence2 = 0;
12058
12415
  const cleanupStreamListener2 = () => {
@@ -12128,8 +12485,8 @@ async function maybeStartUiSession(state, request) {
12128
12485
  activeGlimpseWindow = null;
12129
12486
  }
12130
12487
  const streamMode = request.streamMode;
12131
- const streamId = streamMode ? randomUUID3() : void 0;
12132
- const streamToken = streamMode ? randomUUID3() : void 0;
12488
+ const streamId = streamMode ? randomUUID4() : void 0;
12489
+ const streamToken = streamMode ? randomUUID4() : void 0;
12133
12490
  const hostContext = streamMode && streamId ? {
12134
12491
  [UI_STREAM_HOST_CONTEXT_KEY]: {
12135
12492
  mode: streamMode,
@@ -12470,7 +12827,8 @@ function resolveDirectTools(config, cache, prefix, envOverride) {
12470
12827
  }
12471
12828
  if (!toolFilter) continue;
12472
12829
  const effectivePrefix = resolveToolPrefix(definition, prefix);
12473
- const getOtherCurrentCandidates = (toolName) => {
12830
+ const hasToolFilters = Array.isArray(definition.includeTools) && definition.includeTools.length > 0 || Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0;
12831
+ const selectorCandidateIndex = hasToolFilters ? (() => {
12474
12832
  const candidates = /* @__PURE__ */ new Set();
12475
12833
  for (const [otherServerName, otherDefinition] of Object.entries(config.mcpServers)) {
12476
12834
  const otherCache = cache.servers[otherServerName];
@@ -12487,13 +12845,12 @@ function resolveDirectTools(config, cache, prefix, envOverride) {
12487
12845
  }
12488
12846
  }
12489
12847
  }
12490
- for (const candidate of getToolNameCandidates(toolName, serverName, effectivePrefix, false)) candidates.delete(candidate);
12491
- return candidates;
12492
- };
12848
+ return createToolSelectorCandidateIndex(candidates);
12849
+ })() : void 0;
12493
12850
  for (const tool of serverCache.tools ?? []) {
12494
12851
  if (!isUiToolVisibleToModel(tool.uiVisibility)) continue;
12495
12852
  if (toolFilter !== true && !toolFilter.includes(tool.name)) continue;
12496
- if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(tool.name))) continue;
12853
+ if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) continue;
12497
12854
  const prefixedName = formatToolName(tool.name, serverName, effectivePrefix);
12498
12855
  if (BUILTIN_NAMES.has(prefixedName)) {
12499
12856
  console.warn(`MCP: skipping direct tool "${prefixedName}" (collides with builtin)`);
@@ -12518,7 +12875,7 @@ function resolveDirectTools(config, cache, prefix, envOverride) {
12518
12875
  for (const resource of serverCache.resources ?? []) {
12519
12876
  const baseName = `read_${resourceNameToToolName(resource.name)}`;
12520
12877
  if (toolFilter !== true && !toolFilter.includes(baseName)) continue;
12521
- if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(baseName))) continue;
12878
+ if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) continue;
12522
12879
  const prefixedName = formatToolName(baseName, serverName, effectivePrefix);
12523
12880
  if (BUILTIN_NAMES.has(prefixedName)) {
12524
12881
  console.warn(`MCP: skipping direct resource tool "${prefixedName}" (collides with builtin)`);
@@ -12539,7 +12896,7 @@ function resolveDirectTools(config, cache, prefix, envOverride) {
12539
12896
  }
12540
12897
  }
12541
12898
  }
12542
- if (specs.length >= DIRECT_TOOLS_ADVISORY_THRESHOLD) {
12899
+ if (config.settings?.warnOnLargeDirectTools !== false && specs.length >= DIRECT_TOOLS_ADVISORY_THRESHOLD) {
12543
12900
  console.warn(`MCP: ${specs.length} direct tools resolved. Each direct tool adds prompt context; README guidance recommends targeted sets of 5-20 tools and using the proxy or an explicit string[] when 75+ direct tools would be registered.`);
12544
12901
  }
12545
12902
  return specs;
@@ -12567,8 +12924,8 @@ Direct tools available (call as normal tools): ${parts.join(", ")}
12567
12924
  const cachedEntry = cache?.servers?.[serverName];
12568
12925
  const entry = cachedEntry && isServerCacheValid(cachedEntry, definition) ? cachedEntry : void 0;
12569
12926
  const effectivePrefix = resolveToolPrefix(definition, prefix);
12570
- const getOtherCurrentCandidates = (toolName) => {
12571
- if (!cache) return void 0;
12927
+ const hasToolFilters = Array.isArray(definition.includeTools) && definition.includeTools.length > 0 || Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0;
12928
+ const selectorCandidateIndex = hasToolFilters && cache ? (() => {
12572
12929
  const candidates = /* @__PURE__ */ new Set();
12573
12930
  for (const [otherServerName, otherDefinition] of Object.entries(config.mcpServers)) {
12574
12931
  const otherEntry = cache.servers[otherServerName];
@@ -12585,15 +12942,14 @@ Direct tools available (call as normal tools): ${parts.join(", ")}
12585
12942
  }
12586
12943
  }
12587
12944
  }
12588
- for (const candidate of getToolNameCandidates(toolName, serverName, effectivePrefix, false)) candidates.delete(candidate);
12589
- return candidates;
12590
- };
12945
+ return createToolSelectorCandidateIndex(candidates);
12946
+ })() : void 0;
12591
12947
  const toolCount = (entry?.tools ?? []).filter(
12592
- (tool) => isUiToolVisibleToModel(tool.uiVisibility) && isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(tool.name))
12948
+ (tool) => isUiToolVisibleToModel(tool.uiVisibility) && isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)
12593
12949
  ).length;
12594
12950
  const resourceCount = definition?.exposeResources !== false ? (entry?.resources ?? []).filter((resource) => {
12595
12951
  const baseName = `read_${resourceNameToToolName(resource.name)}`;
12596
- return isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(baseName));
12952
+ return isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex);
12597
12953
  }).length : 0;
12598
12954
  const totalItems = toolCount + resourceCount;
12599
12955
  if (totalItems === 0) continue;