nexrall-code 0.5.187 → 0.5.188

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/index.js +52 -11
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -10094,7 +10094,7 @@ var require_client = __commonJS({
10094
10094
  }
10095
10095
  var MAX_TOTAL_ATTEMPTS = (MAX_RETRIES + 1) * (MAX_RETRIES + 1);
10096
10096
  async function streamChat(messages, options, onEvent) {
10097
- const { model, env: env3, editorContext, nexrallMd, mode, effort, clientType, abortSignal, extraTools, agents, skills, allowRestartAfterRender, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents, canBrowseWeb, toolAllowlist } = options;
10097
+ const { model, env: env3, editorContext, nexrallMd, mode, effort, clientType, abortSignal, extraTools, agents, skills, allowRestartAfterRender, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents, canBrowseWeb, toolAllowlist, alwaysLoadServers } = options;
10098
10098
  let turnId = (0, crypto_1.randomUUID)();
10099
10099
  const controller = new AbortController();
10100
10100
  if (abortSignal?.aborted)
@@ -10141,6 +10141,7 @@ var require_client = __commonJS({
10141
10141
  canSpawnSubAgents,
10142
10142
  canBrowseWeb,
10143
10143
  toolAllowlist,
10144
+ alwaysLoadServers,
10144
10145
  ...billingOverrideFields3()
10145
10146
  });
10146
10147
  chatBody = gzipRequestsEnabled() && json.length >= GZIP_MIN_BYTES ? { data: (0, zlib_1.gzipSync)(json, { level: 5 }), gzip: true, turnId } : { data: json, gzip: false, turnId };
@@ -25392,6 +25393,11 @@ ${ctx}
25392
25393
  options.nexrallMd ?? null
25393
25394
  ].filter((s2) => s2 !== null).join("\n\n---\n\n") || void 0;
25394
25395
  const mcpInstructionsBlock = () => (0, instructions_1.formatMcpInstructions)((options.mcpManager?.serverInstructions() ?? []).filter((e2) => !options._mcpServerAllowlist || options._mcpServerAllowlist.has(e2.server)));
25396
+ const alwaysLoadServerNames = (() => {
25397
+ const named = options.mcpManager?.alwaysLoadServers() ?? [];
25398
+ const scoped = named.filter((n) => !options._mcpServerAllowlist || options._mcpServerAllowlist.has(n));
25399
+ return scoped.length ? scoped : void 0;
25400
+ })();
25395
25401
  const chatRequestOptions = () => ({
25396
25402
  model,
25397
25403
  mode: options.mode,
@@ -25438,6 +25444,10 @@ ${ctx}
25438
25444
  // (and gets refused on) write, office and image tools. Sorted so the tools cache
25439
25445
  // prefix is identical for every run of the same agent type.
25440
25446
  toolAllowlist: options._allowedTools ? [...options._allowedTools].sort() : void 0,
25447
+ // Servers the user pinned with `alwaysLoad: true` (computed above). The backend
25448
+ // keeps their `<server>__*` tools out of the tool cap and both deferral paths;
25449
+ // undefined (not []) when nothing is pinned so older backends see the same body.
25450
+ alwaysLoadServers: alwaysLoadServerNames,
25441
25451
  // Withholds the `task` schema and its instructions when this run cannot
25442
25452
  // delegate — see canSpawnSubAgents.
25443
25453
  canSpawnSubAgents: maySpawn,
@@ -27705,6 +27715,21 @@ var require_manager = __commonJS({
27705
27715
  get toolCount() {
27706
27716
  return this._toolMap.size;
27707
27717
  }
27718
+ /**
27719
+ * Names of configured servers whose entry sets `alwaysLoad: true` (CC parity).
27720
+ * The agent loop sends this per request; the backend keeps those servers' tools
27721
+ * out of BOTH deferral paths (tool-search `defer_loading` and the cap selector's
27722
+ * droppable set). Config-level — a server that failed to connect still contributes
27723
+ * an inert name, since it sends no tools to protect. Sorted because the list rides
27724
+ * in the request body, which is part of the tools-cache key.
27725
+ */
27726
+ alwaysLoadServers() {
27727
+ const names = [];
27728
+ for (const [name, cfg] of this._configs)
27729
+ if (cfg.alwaysLoad === true)
27730
+ names.push(name);
27731
+ return names.sort();
27732
+ }
27708
27733
  static transportOf(cfg) {
27709
27734
  if (cfg?.type)
27710
27735
  return cfg.type;
@@ -27724,7 +27749,8 @@ var require_manager = __commonJS({
27724
27749
  // insufficient_scope challenge — the row says so, the detail says which scope.
27725
27750
  needsAuth: this._needsAuth.has(name),
27726
27751
  missingScope: this.missingScope(name) || void 0,
27727
- protocolVersion: client.protocolVersion
27752
+ protocolVersion: client.protocolVersion,
27753
+ alwaysLoad: this._configs.get(name)?.alwaysLoad === true
27728
27754
  });
27729
27755
  }
27730
27756
  for (const name of this._configs.keys()) {
@@ -27738,7 +27764,8 @@ var require_manager = __commonJS({
27738
27764
  transport: _McpManager.transportOf(this._configs.get(name)),
27739
27765
  tools: [],
27740
27766
  connected: false,
27741
- disabled: true
27767
+ disabled: true,
27768
+ alwaysLoad: this._configs.get(name)?.alwaysLoad === true
27742
27769
  });
27743
27770
  continue;
27744
27771
  }
@@ -27750,7 +27777,8 @@ var require_manager = __commonJS({
27750
27777
  disabled,
27751
27778
  error,
27752
27779
  needsAuth: this._needsAuth.has(name),
27753
- missingScope: this.missingScope(name) || void 0
27780
+ missingScope: this.missingScope(name) || void 0,
27781
+ alwaysLoad: this._configs.get(name)?.alwaysLoad === true
27754
27782
  });
27755
27783
  }
27756
27784
  return out.sort((a, b) => a.name.localeCompare(b.name));
@@ -67748,6 +67776,8 @@ function buildServer(input) {
67748
67776
  cfg2.clientId = input.clientId.trim();
67749
67777
  if (input.clientSecret)
67750
67778
  cfg2.clientSecret = input.clientSecret;
67779
+ if (input.alwaysLoad)
67780
+ cfg2.alwaysLoad = true;
67751
67781
  return { ok: true, value: cfg2 };
67752
67782
  }
67753
67783
  if (input.clientId || input.clientSecret)
@@ -67759,6 +67789,8 @@ function buildServer(input) {
67759
67789
  cfg.args = rest.slice(1);
67760
67790
  if (Object.keys(env3.value).length)
67761
67791
  cfg.env = env3.value;
67792
+ if (input.alwaysLoad)
67793
+ cfg.alwaysLoad = true;
67762
67794
  return { ok: true, value: cfg };
67763
67795
  }
67764
67796
  function parseServerJson(text) {
@@ -67777,6 +67809,8 @@ function parseServerJson(text) {
67777
67809
  return { ok: false, error: 'A server is either stdio ("command") or http/sse ("url"), not both.' };
67778
67810
  if (s2.args !== void 0 && (!Array.isArray(s2.args) || s2.args.some((a) => typeof a !== "string")))
67779
67811
  return { ok: false, error: '"args" must be an array of strings.' };
67812
+ if (s2.alwaysLoad !== void 0 && typeof s2.alwaysLoad !== "boolean")
67813
+ return { ok: false, error: '"alwaysLoad" must be true or false.' };
67780
67814
  return { ok: true, value: s2 };
67781
67815
  }
67782
67816
  function describeServer(name, s2) {
@@ -67785,7 +67819,8 @@ function describeServer(name, s2) {
67785
67819
  const env3 = s2.env && Object.keys(s2.env).length ? ` env: ${Object.keys(s2.env).join(", ")}` : "";
67786
67820
  const hdr = s2.headers && Object.keys(s2.headers).length ? ` headers: ${Object.keys(s2.headers).join(", ")}` : "";
67787
67821
  const client = s2.clientId ? ` client-id: ${s2.clientId}` : "";
67788
- return `${name} [${kind}] ${target}${env3}${hdr}${client}`;
67822
+ const pinned = s2.alwaysLoad ? " always-load" : "";
67823
+ return `${name} [${kind}] ${target}${env3}${hdr}${client}${pinned}`;
67789
67824
  }
67790
67825
  function redactUrl(u) {
67791
67826
  try {
@@ -67820,7 +67855,8 @@ function mcpAddCommand(name, rest, opts, workDir = process.cwd()) {
67820
67855
  env: opts.env,
67821
67856
  header: opts.header,
67822
67857
  clientId: opts.clientId,
67823
- clientSecret: opts.clientSecret
67858
+ clientSecret: opts.clientSecret,
67859
+ alwaysLoad: opts.alwaysLoad
67824
67860
  });
67825
67861
  if (!b.ok) {
67826
67862
  console.error(b.error);
@@ -67885,7 +67921,8 @@ function mcpListCommand(workDir = process.cwd(), json = false) {
67885
67921
  url: s2.url ? redactUrl(s2.url) : void 0,
67886
67922
  env_keys: Object.keys(s2.env ?? {}),
67887
67923
  header_keys: Object.keys(s2.headers ?? {}),
67888
- disabled: disabled.has(n)
67924
+ disabled: disabled.has(n),
67925
+ alwaysLoad: s2.alwaysLoad === true
67889
67926
  };
67890
67927
  }),
67891
67928
  null,
@@ -95181,14 +95218,15 @@ function statusDot(row2) {
95181
95218
  return row2.connected ? "\u25CF" : "\u25CB";
95182
95219
  }
95183
95220
  function describeRow(row2) {
95221
+ const pin = row2.alwaysLoad ? " \xB7 always-load" : "";
95184
95222
  if (row2.disabled)
95185
95223
  return "switched off \u2014 /mcp enable " + row2.name;
95186
95224
  if (row2.connected && row2.needsAuth) {
95187
95225
  const why = row2.missingScope ? "needs more permissions" : "needs re-auth";
95188
- return `${row2.toolCount} tool${row2.toolCount === 1 ? "" : "s"} \xB7 ${why} \u2014 /mcp auth ${row2.name}`;
95226
+ return `${row2.toolCount} tool${row2.toolCount === 1 ? "" : "s"}${pin} \xB7 ${why} \u2014 /mcp auth ${row2.name}`;
95189
95227
  }
95190
95228
  if (row2.connected)
95191
- return `${row2.toolCount} tool${row2.toolCount === 1 ? "" : "s"}`;
95229
+ return `${row2.toolCount} tool${row2.toolCount === 1 ? "" : "s"}${pin}`;
95192
95230
  if (row2.needsAuth)
95193
95231
  return "needs authentication \u2014 /mcp auth " + row2.name + " (signs in)";
95194
95232
  return row2.error && row2.error !== "disconnected" ? row2.error : "disconnected";
@@ -95218,6 +95256,8 @@ function formatMcpDetail(input) {
95218
95256
  out.push(` state: ${state}`);
95219
95257
  if (row2.connected && row2.protocolVersion)
95220
95258
  out.push(` protocol: ${row2.protocolVersion}`);
95259
+ if (row2.alwaysLoad)
95260
+ out.push(" always-load: on \u2014 tools are never deferred or dropped by the tool cap");
95221
95261
  if (scope && scope !== "none") {
95222
95262
  const where = scope === "project" ? ".nexrall/mcp.json" : scope === "user" ? "~/.nexrall/mcp.json" : "a plugin (its definition cannot be edited here)";
95223
95263
  out.push(` defined in: ${where}`);
@@ -99834,7 +99874,8 @@ ${text}` : "");
99834
99874
  missingScope: st.missingScope,
99835
99875
  error: st.error,
99836
99876
  toolCount: st.tools.length,
99837
- protocolVersion: st.protocolVersion
99877
+ protocolVersion: st.protocolVersion,
99878
+ alwaysLoad: st.alwaysLoad
99838
99879
  }));
99839
99880
  const matchMcpRows = (rows, name) => {
99840
99881
  const exact = rows.filter((r2) => r2.name === name);
@@ -104312,7 +104353,7 @@ program2.command("update").description("Update nex to the latest version").optio
104312
104353
  var mcp = program2.command("mcp").description("Manage MCP servers (add, list, get, remove) \u2014 same files as /mcp");
104313
104354
  mcp.command("add <name> [target...]").description(
104314
104355
  "Add a server. stdio: nex mcp add fs -- npx -y @modelcontextprotocol/server-filesystem . http/sse: nex mcp add --transport http docs https://example.com/mcp"
104315
- ).option("-t, --transport <type>", "stdio (default) | http | sse").option("-e, --env <KEY=value...>", "Environment variable for a stdio server (repeatable)").option("-H, --header <header...>", 'Header for an http/sse server, "Name: value" (repeatable)').option("--client-id <id>", "OAuth client id for an http/sse server without dynamic registration").option("--client-secret <secret>", "OAuth client secret (sent client_secret_post; stored in mcp.json)").option("-s, --scope <scope>", "project (default, ./.nexrall/mcp.json) | user (~/.nexrall/mcp.json)").action((name, target, opts) => {
104356
+ ).option("-t, --transport <type>", "stdio (default) | http | sse").option("-e, --env <KEY=value...>", "Environment variable for a stdio server (repeatable)").option("-H, --header <header...>", 'Header for an http/sse server, "Name: value" (repeatable)').option("--client-id <id>", "OAuth client id for an http/sse server without dynamic registration").option("--client-secret <secret>", "OAuth client secret (sent client_secret_post; stored in mcp.json)").option("--always-load", "Keep this server's tools out of the backend tool cap (never deferred or dropped)").option("-s, --scope <scope>", "project (default, ./.nexrall/mcp.json) | user (~/.nexrall/mcp.json)").action((name, target, opts) => {
104316
104357
  process.exit(mcpAddCommand(name, target, opts));
104317
104358
  });
104318
104359
  mcp.command("add-json <name> <json>").description(`Add a server from a JSON definition, e.g. '{"command":"npx","args":["-y","pkg"]}'`).option("-s, --scope <scope>", "project (default) | user").action((name, json, opts) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nexrall-code",
3
- "version": "0.5.187",
4
- "description": "Nexrall Code \u2014 AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
3
+ "version": "0.5.188",
4
+ "description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
5
5
  "keywords": [
6
6
  "ai",
7
7
  "cli",