nexus-agents 2.74.0 → 2.75.0

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.
@@ -70,7 +70,7 @@ import {
70
70
  clampTaskTtl,
71
71
  getAvailabilityCache,
72
72
  resolveFallback
73
- } from "./chunk-WCCTIRSB.js";
73
+ } from "./chunk-QCKKDUNX.js";
74
74
  import {
75
75
  DEFAULTS
76
76
  } from "./chunk-GS3GW7C7.js";
@@ -174,6 +174,7 @@ import {
174
174
  withStep
175
175
  } from "./chunk-Q3RFPJYK.js";
176
176
  import {
177
+ getNexusDataDir,
177
178
  nexusDataPath
178
179
  } from "./chunk-GOT7OAL5.js";
179
180
 
@@ -39754,6 +39755,87 @@ function registerMemoryStatsTool(server, deps) {
39754
39755
 
39755
39756
  // src/mcp/tools/memory-write.ts
39756
39757
  import { z as z74 } from "zod";
39758
+
39759
+ // src/mcp/middleware/tool-prerequisites.ts
39760
+ import { execFile as execFile2 } from "child_process";
39761
+ import { access as access2, constants } from "fs/promises";
39762
+ import { dirname as dirname5 } from "path";
39763
+ import { promisify as promisify2 } from "util";
39764
+ var execFileAsync2 = promisify2(execFile2);
39765
+ async function ghCliAvailable() {
39766
+ try {
39767
+ await execFileAsync2("gh", ["--version"], { timeout: 5e3 });
39768
+ return { ok: true };
39769
+ } catch (err2) {
39770
+ return {
39771
+ ok: false,
39772
+ remediation: `the 'gh' CLI is not available (${getErrorMessage(err2)}) \u2014 install GitHub CLI and authenticate (\`gh auth login\`)`
39773
+ };
39774
+ }
39775
+ }
39776
+ async function dataDirWritable() {
39777
+ const dir = getNexusDataDir();
39778
+ try {
39779
+ await access2(dir, constants.W_OK);
39780
+ return { ok: true };
39781
+ } catch {
39782
+ try {
39783
+ await access2(dirname5(dir), constants.W_OK);
39784
+ return { ok: true };
39785
+ } catch (err2) {
39786
+ return {
39787
+ ok: false,
39788
+ remediation: `NEXUS_DATA_DIR (${dir}) is not writable or creatable (${getErrorMessage(err2)}) \u2014 fix its permissions; run \`nexus-agents doctor\` to diagnose`
39789
+ };
39790
+ }
39791
+ }
39792
+ }
39793
+ var TOOL_PREREQUISITES = {
39794
+ improvement_review: {
39795
+ name: "gh-cli-available",
39796
+ rationale: "improvement_review's fileIssues mode shells out to `gh` to file candidate issues; without it the write path fails mid-operation",
39797
+ check: ghCliAvailable
39798
+ },
39799
+ memory_write: {
39800
+ name: "data-dir-writable",
39801
+ rationale: "memory_write persists entries under NEXUS_DATA_DIR \u2014 an unwritable data dir fails the write confusingly mid-operation",
39802
+ check: dataDirWritable
39803
+ },
39804
+ registry_import: {
39805
+ name: "data-dir-writable",
39806
+ rationale: "registry_import persists a draft registry entry under NEXUS_DATA_DIR when not in dryRun mode",
39807
+ check: dataDirWritable
39808
+ }
39809
+ };
39810
+ function applyPrerequisite(toolName, prereq, handler3) {
39811
+ return async (args, ctx) => {
39812
+ let result;
39813
+ try {
39814
+ result = await prereq.check();
39815
+ } catch (err2) {
39816
+ result = { ok: false, remediation: `prerequisite check threw: ${getErrorMessage(err2)}` };
39817
+ }
39818
+ if (!result.ok) {
39819
+ return toolStructuredError({
39820
+ errorCategory: "permission",
39821
+ message: `${toolName} blocked: prerequisite '${prereq.name}' not satisfied`,
39822
+ detail: {
39823
+ failedPrerequisite: prereq.name,
39824
+ rationale: prereq.rationale,
39825
+ remediation: result.remediation ?? "see .rules/tool-prerequisites.md"
39826
+ }
39827
+ });
39828
+ }
39829
+ return handler3(args, ctx);
39830
+ };
39831
+ }
39832
+ function withPrerequisite(toolName, handler3) {
39833
+ const prereq = TOOL_PREREQUISITES[toolName];
39834
+ if (prereq === void 0) return handler3;
39835
+ return applyPrerequisite(toolName, prereq, handler3);
39836
+ }
39837
+
39838
+ // src/mcp/tools/memory-write.ts
39757
39839
  var MemoryWriteInputSchema = z74.object({
39758
39840
  key: z74.string().min(1).max(200).describe("Memory identifier or subject"),
39759
39841
  content: z74.string().min(1).max(5e3).describe("Memory content to store"),
@@ -39897,8 +39979,9 @@ function registerMemoryWriteTool(server, deps) {
39897
39979
  rateLimiter: deps.rateLimiter,
39898
39980
  logger: logger51
39899
39981
  });
39982
+ const guardedHandler = withPrerequisite("memory_write", secureHandler);
39900
39983
  const timeoutMs = getToolTimeout("memory_write", deps.security);
39901
- const wrappedHandler = wrapToolWithTimeout("memory_write", secureHandler, { timeoutMs, logger: logger51 });
39984
+ const wrappedHandler = wrapToolWithTimeout("memory_write", guardedHandler, { timeoutMs, logger: logger51 });
39902
39985
  const outputSchema = {
39903
39986
  success: z74.boolean(),
39904
39987
  backend: z74.string(),
@@ -40134,8 +40217,9 @@ function registerRegistryImportTool(server, deps) {
40134
40217
  rateLimiter: deps.rateLimiter,
40135
40218
  logger: logger51
40136
40219
  });
40220
+ const guardedHandler = withPrerequisite("registry_import", secureHandler);
40137
40221
  const timeoutMs = getToolTimeout("registry_import", deps.security);
40138
- const wrappedHandler = wrapToolWithTimeout("registry_import", secureHandler, {
40222
+ const wrappedHandler = wrapToolWithTimeout("registry_import", guardedHandler, {
40139
40223
  timeoutMs,
40140
40224
  logger: logger51
40141
40225
  });
@@ -41996,9 +42080,9 @@ var logger33 = createLogger({ component: "security-scan" });
41996
42080
  var SCAN_TIMEOUT_MS = 3e5;
41997
42081
  async function isSemgrepAvailable() {
41998
42082
  try {
41999
- const { execFile: execFile4 } = await import("child_process");
42000
- const { promisify: promisify4 } = await import("util");
42001
- const exec2 = promisify4(execFile4);
42083
+ const { execFile: execFile5 } = await import("child_process");
42084
+ const { promisify: promisify5 } = await import("util");
42085
+ const exec2 = promisify5(execFile5);
42002
42086
  await exec2("semgrep", ["--version"], { timeout: 1e4 });
42003
42087
  return true;
42004
42088
  } catch {
@@ -42006,9 +42090,9 @@ async function isSemgrepAvailable() {
42006
42090
  }
42007
42091
  }
42008
42092
  async function runSemgrep(targetDir, rulesets) {
42009
- const { execFile: execFile4 } = await import("child_process");
42010
- const { promisify: promisify4 } = await import("util");
42011
- const exec2 = promisify4(execFile4);
42093
+ const { execFile: execFile5 } = await import("child_process");
42094
+ const { promisify: promisify5 } = await import("util");
42095
+ const exec2 = promisify5(execFile5);
42012
42096
  const args = ["--sarif", "--quiet", ...rulesets.flatMap((r) => ["--config", r]), targetDir];
42013
42097
  const { stdout } = await exec2("semgrep", args, {
42014
42098
  timeout: SCAN_TIMEOUT_MS,
@@ -44559,8 +44643,8 @@ function registerCompareDataFeedsTool(server, deps) {
44559
44643
  }
44560
44644
 
44561
44645
  // src/mcp/tools/improvement-review.ts
44562
- import { execFile as execFile2 } from "child_process";
44563
- import { promisify as promisify2 } from "util";
44646
+ import { execFile as execFile3 } from "child_process";
44647
+ import { promisify as promisify3 } from "util";
44564
44648
  import { z as z94 } from "zod";
44565
44649
 
44566
44650
  // src/governance/fitness-score.ts
@@ -45104,7 +45188,7 @@ function calculateFitnessScore(version) {
45104
45188
  }
45105
45189
 
45106
45190
  // src/mcp/tools/improvement-review.ts
45107
- var execFileAsync2 = promisify2(execFile2);
45191
+ var execFileAsync3 = promisify3(execFile3);
45108
45192
  var ImprovementReviewInputSchema = z94.object({
45109
45193
  lookbackDays: z94.number().int().min(1).max(90).optional().default(7).describe("Lookback window for outcome data, in days. Default 7."),
45110
45194
  fileIssues: z94.boolean().optional().default(false).describe(
@@ -45247,7 +45331,7 @@ function detectFitnessSignals(audit, fitnessFloor) {
45247
45331
  }
45248
45332
  async function existingIssueForSignal(signalKey) {
45249
45333
  try {
45250
- const { stdout } = await execFileAsync2("gh", [
45334
+ const { stdout } = await execFileAsync3("gh", [
45251
45335
  "issue",
45252
45336
  "list",
45253
45337
  "--state",
@@ -45276,7 +45360,7 @@ async function fileIssueForSignal(signal) {
45276
45360
  _Signal key (do not edit): \`${signal.signalKey}\` \xB7 Generated by \`improvement_review\` (#2402) \xB7 Severity: ${signal.severity}_`;
45277
45361
  const labels = signal.category === "security" ? "security" : signal.category;
45278
45362
  try {
45279
- const { stdout } = await execFileAsync2("gh", [
45363
+ const { stdout } = await execFileAsync3("gh", [
45280
45364
  "issue",
45281
45365
  "create",
45282
45366
  "--title",
@@ -45393,8 +45477,9 @@ function registerImprovementReviewTool(server, deps) {
45393
45477
  rateLimiter: deps.rateLimiter,
45394
45478
  logger: logger51
45395
45479
  });
45480
+ const guardedHandler = withPrerequisite("improvement_review", secureHandler);
45396
45481
  const timeoutMs = getToolTimeout("improvement_review", deps.security);
45397
- const wrappedHandler = wrapToolWithTimeout("improvement_review", secureHandler, {
45482
+ const wrappedHandler = wrapToolWithTimeout("improvement_review", guardedHandler, {
45398
45483
  timeoutMs,
45399
45484
  logger: logger51
45400
45485
  });
@@ -48766,10 +48851,10 @@ function getPolicy(id) {
48766
48851
  }
48767
48852
 
48768
48853
  // src/security/sandbox/sandbox-executor.ts
48769
- import { execFile as execFile3 } from "child_process";
48770
- import { promisify as promisify3 } from "util";
48854
+ import { execFile as execFile4 } from "child_process";
48855
+ import { promisify as promisify4 } from "util";
48771
48856
  import { resolve as resolve17, normalize as normalize2, sep as sep6 } from "path";
48772
- var execFileAsync3 = promisify3(execFile3);
48857
+ var execFileAsync4 = promisify4(execFile4);
48773
48858
  var logger45 = createLogger({ component: "sandbox-executor" });
48774
48859
  function parseExecError(error) {
48775
48860
  const execError = error;
@@ -48878,7 +48963,7 @@ var PolicySandboxExecutor = class {
48878
48963
  * Executes command with resource limits.
48879
48964
  */
48880
48965
  async executeWithLimits(command, args, cwd, env, limits) {
48881
- const { stdout, stderr } = await execFileAsync3(command, [...args], {
48966
+ const { stdout, stderr } = await execFileAsync4(command, [...args], {
48882
48967
  cwd: cwd ?? process.cwd(),
48883
48968
  timeout: limits.maxWallTimeMs,
48884
48969
  maxBuffer: limits.maxOutputBytes,
@@ -49205,9 +49290,9 @@ import * as fs14 from "fs";
49205
49290
  import * as path13 from "path";
49206
49291
  var logger50 = createLogger({ component: "task-tracker" });
49207
49292
  async function exec(cmd, args, timeout = 15e3) {
49208
- const { execFile: execFile4 } = await import("child_process");
49209
- const { promisify: promisify4 } = await import("util");
49210
- const run = promisify4(execFile4);
49293
+ const { execFile: execFile5 } = await import("child_process");
49294
+ const { promisify: promisify5 } = await import("util");
49295
+ const run = promisify5(execFile5);
49211
49296
  const { stdout } = await run(cmd, [...args], { timeout });
49212
49297
  return stdout.trim();
49213
49298
  }
@@ -49922,4 +50007,4 @@ export {
49922
50007
  detectBackend,
49923
50008
  createTaskTracker
49924
50009
  };
49925
- //# sourceMappingURL=chunk-BYKS53GW.js.map
50010
+ //# sourceMappingURL=chunk-G5NSRX6Z.js.map