nexus-agents 2.26.1 → 2.28.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.
Files changed (49) hide show
  1. package/README.md +7 -7
  2. package/dist/{chunk-X33QNBGA.js → chunk-E7EX2KQJ.js} +3 -5
  3. package/dist/{chunk-X33QNBGA.js.map → chunk-E7EX2KQJ.js.map} +1 -1
  4. package/dist/{chunk-BOWNZMPH.js → chunk-L2SHSW4T.js} +3017 -1300
  5. package/dist/chunk-L2SHSW4T.js.map +1 -0
  6. package/dist/{chunk-ARNVVQ5W.js → chunk-LKSTILEE.js} +1213 -117
  7. package/dist/chunk-LKSTILEE.js.map +1 -0
  8. package/dist/{chunk-L3LQ3RP5.js → chunk-QZEAD6AG.js} +10339 -6289
  9. package/dist/chunk-QZEAD6AG.js.map +1 -0
  10. package/dist/{chunk-LCHCASB7.js → chunk-UGNLR4NZ.js} +2 -2
  11. package/dist/{chunk-UVQ7R4C4.js → chunk-YSDUVCCZ.js} +137 -717
  12. package/dist/chunk-YSDUVCCZ.js.map +1 -0
  13. package/dist/cli.d.ts +8 -1
  14. package/dist/cli.js +644 -216
  15. package/dist/cli.js.map +1 -1
  16. package/dist/{dist-Y5F6UM2N.js → dist-H5XNXVAV.js} +1384 -1295
  17. package/dist/dist-H5XNXVAV.js.map +1 -0
  18. package/dist/doctor-deep-BDE2PHVX.js +11 -0
  19. package/dist/index.d.ts +4299 -7411
  20. package/dist/index.js +588 -132
  21. package/dist/index.js.map +1 -1
  22. package/dist/{setup-command-VNF3KTCJ.js → setup-command-SS7LMN7Y.js} +5 -6
  23. package/dist/setup-config-DSMOOLVW.js +9 -0
  24. package/dist/workflows/templates/code-review.yaml +1 -1
  25. package/dist/workflows/templates/refactoring.yaml +1 -1
  26. package/dist/workflows/templates/research-review.yaml +19 -4
  27. package/dist/workflows/templates/security-audit.yaml +1 -1
  28. package/dist/workflows/templates/standards-review.yaml +1 -1
  29. package/package.json +12 -12
  30. package/src/workflows/templates/code-review.yaml +1 -1
  31. package/src/workflows/templates/refactoring.yaml +1 -1
  32. package/src/workflows/templates/research-review.yaml +19 -4
  33. package/src/workflows/templates/security-audit.yaml +1 -1
  34. package/src/workflows/templates/standards-review.yaml +1 -1
  35. package/dist/chunk-ARNVVQ5W.js.map +0 -1
  36. package/dist/chunk-BOWNZMPH.js.map +0 -1
  37. package/dist/chunk-L3LQ3RP5.js.map +0 -1
  38. package/dist/chunk-LCDOP543.js +0 -365
  39. package/dist/chunk-LCDOP543.js.map +0 -1
  40. package/dist/chunk-PGNRXCYY.js +0 -776
  41. package/dist/chunk-PGNRXCYY.js.map +0 -1
  42. package/dist/chunk-UVQ7R4C4.js.map +0 -1
  43. package/dist/dist-Y5F6UM2N.js.map +0 -1
  44. package/dist/doctor-deep-I2J5CRFG.js +0 -13
  45. package/dist/setup-config-VQSWWJ5O.js +0 -9
  46. /package/dist/{chunk-LCHCASB7.js.map → chunk-UGNLR4NZ.js.map} +0 -0
  47. /package/dist/{doctor-deep-I2J5CRFG.js.map → doctor-deep-BDE2PHVX.js.map} +0 -0
  48. /package/dist/{setup-command-VNF3KTCJ.js.map → setup-command-SS7LMN7Y.js.map} +0 -0
  49. /package/dist/{setup-config-VQSWWJ5O.js.map → setup-config-DSMOOLVW.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -40,6 +40,7 @@ import {
40
40
  createFeedbackIntegration,
41
41
  createFullGitHubProvider,
42
42
  createGatewayServerProxy,
43
+ createHarnessExecutor,
43
44
  createLearnablePolicy,
44
45
  createMockTechLead,
45
46
  createRealWorkflowEngine,
@@ -123,6 +124,7 @@ import {
123
124
  registerResearchCatalogReviewTool,
124
125
  registerResearchDiscoverTool,
125
126
  registerResearchQueryTool,
127
+ registerResearchSynthesizeTool,
126
128
  registerResources,
127
129
  registerRunGraphWorkflowTool,
128
130
  registerRunWorkflowTool,
@@ -134,17 +136,17 @@ import {
134
136
  sanitizeInput,
135
137
  setGlobalToolRateLimiterFactory,
136
138
  shutdownToolMemory,
139
+ synthesizeResearch,
137
140
  validateArgs,
138
141
  validateCommand,
139
142
  validateNexusEnv,
140
143
  validateTimeout,
141
144
  validateWorkflow,
142
145
  wrapInMarkdownFence
143
- } from "./chunk-L3LQ3RP5.js";
146
+ } from "./chunk-QZEAD6AG.js";
144
147
  import {
145
- doctorCommand,
146
148
  setupCommandAsync
147
- } from "./chunk-UVQ7R4C4.js";
149
+ } from "./chunk-YSDUVCCZ.js";
148
150
  import {
149
151
  VERSION,
150
152
  capitalize,
@@ -153,11 +155,13 @@ import {
153
155
  connectTransport,
154
156
  createAllAdapters,
155
157
  createServer,
158
+ doctorCommand,
156
159
  getAvailableClis,
160
+ initDataDirectories,
157
161
  isRecord,
158
162
  truncateSentence
159
- } from "./chunk-ARNVVQ5W.js";
160
- import "./chunk-LCHCASB7.js";
163
+ } from "./chunk-LKSTILEE.js";
164
+ import "./chunk-UGNLR4NZ.js";
161
165
  import {
162
166
  calculateConsensus,
163
167
  countByCategory,
@@ -175,28 +179,23 @@ import {
175
179
  CATEGORY_DISPLAY_NAMES,
176
180
  DEFAULT_PR_REVIEW_CONFIG
177
181
  } from "./chunk-X2M7OF27.js";
178
- import "./chunk-X33QNBGA.js";
179
- import {
180
- getAdaptiveBonus,
181
- parseTierOverrides
182
- } from "./chunk-PGNRXCYY.js";
182
+ import "./chunk-E7EX2KQJ.js";
183
183
  import {
184
184
  API_TIMEOUTS,
185
- CLI_SUBPROCESS_TIMEOUTS,
186
- MCP_TIMEOUTS
187
- } from "./chunk-LCDOP543.js";
188
- import {
189
185
  AgentCapability,
190
186
  AgentError,
191
187
  CLI_NAMES,
188
+ CLI_SUBPROCESS_TIMEOUTS,
192
189
  DEFAULT_CLI,
193
190
  DEFAULT_MODEL_CAPABILITIES,
194
191
  DEFAULT_MODEL_PROFILES,
195
192
  ErrorCode,
196
193
  INPUT_MODALITIES,
197
194
  LinUCBBandit,
195
+ MCP_TIMEOUTS,
198
196
  NexusError,
199
197
  OUTPUT_MODALITIES,
198
+ OutcomeStore,
200
199
  SPECIAL_FEATURES,
201
200
  SecurityError,
202
201
  TASK_CATEGORIES,
@@ -220,6 +219,8 @@ import {
220
219
  formatPercentage,
221
220
  formatStatus,
222
221
  formatZodError,
222
+ generateWeatherReport,
223
+ getAdaptiveBonus,
223
224
  getErrorMessage,
224
225
  getModelCapabilities,
225
226
  getOutcomeStore,
@@ -227,16 +228,18 @@ import {
227
228
  getTimeProvider,
228
229
  logger,
229
230
  ok,
231
+ parseTierOverrides,
230
232
  resetOutcomeStore,
231
233
  runWarmUp,
232
234
  safeRegex,
235
+ setOutcomeStore,
233
236
  summarizeTaskProfile,
234
237
  symbols,
235
238
  taskAnalysisResultToTaskProfile,
236
239
  toError,
237
240
  writeEmptyLine,
238
241
  writeLine
239
- } from "./chunk-BOWNZMPH.js";
242
+ } from "./chunk-L2SHSW4T.js";
240
243
  import "./chunk-UP2VWCW5.js";
241
244
 
242
245
  // src/cli.ts
@@ -420,8 +423,8 @@ function resolveOutputPath(output2) {
420
423
  }
421
424
  return resolve(process.cwd(), DEFAULT_CONFIG_FILE);
422
425
  }
423
- function fileExists(path23) {
424
- return existsSync(path23);
426
+ function fileExists(path24) {
427
+ return existsSync(path24);
425
428
  }
426
429
  async function ensureDirectory(filePath) {
427
430
  const dir = dirname(filePath);
@@ -429,9 +432,9 @@ async function ensureDirectory(filePath) {
429
432
  await mkdir(dir, { recursive: true });
430
433
  }
431
434
  }
432
- async function writeConfigFile(path23) {
433
- await ensureDirectory(path23);
434
- await writeFile(path23, CONFIG_TEMPLATE, "utf-8");
435
+ async function writeConfigFile(path24) {
436
+ await ensureDirectory(path24);
437
+ await writeFile(path24, CONFIG_TEMPLATE, "utf-8");
435
438
  }
436
439
  async function runConfigInit(options = {}) {
437
440
  const outputPath = resolveOutputPath(options.output);
@@ -1400,14 +1403,14 @@ ${colors.dim}Session ended.${colors.reset}
1400
1403
  });
1401
1404
  });
1402
1405
  rl.prompt();
1403
- return new Promise((resolve11) => {
1406
+ return new Promise((resolve12) => {
1404
1407
  rl.on("line", (line) => {
1405
1408
  void (async () => {
1406
1409
  try {
1407
1410
  const shouldExit = await processLine(line, session, logger17);
1408
1411
  if (shouldExit) {
1409
1412
  rl.close();
1410
- resolve11();
1413
+ resolve12();
1411
1414
  return;
1412
1415
  }
1413
1416
  } catch (error) {
@@ -1419,7 +1422,7 @@ ${colors.dim}Session ended.${colors.reset}
1419
1422
  })();
1420
1423
  });
1421
1424
  rl.on("close", () => {
1422
- resolve11();
1425
+ resolve12();
1423
1426
  });
1424
1427
  });
1425
1428
  }
@@ -2413,9 +2416,9 @@ async function evaluateDirectory(target, timeoutMs) {
2413
2416
  }
2414
2417
  const aggregator = createAggregator();
2415
2418
  const results = [];
2416
- for (const [path23, evaluations] of evaluationsByComponent) {
2419
+ for (const [path24, evaluations] of evaluationsByComponent) {
2417
2420
  if (evaluations.length > 0) {
2418
- results.push(aggregator.aggregate(path23, evaluations));
2421
+ results.push(aggregator.aggregate(path24, evaluations));
2419
2422
  }
2420
2423
  }
2421
2424
  const priority = { deprecate: 0, refactor: 1, review: 2, retain: 3 };
@@ -3562,21 +3565,22 @@ function printSuccessMessage(durationMs) {
3562
3565
 
3563
3566
  // src/cli/routing-audit-logic.ts
3564
3567
  var logger5 = createLogger({ component: "routing-audit" });
3568
+ var sharedAnalyzer = createSharedTaskAnalyzer();
3565
3569
  var CLI_NAMES2 = ["claude", "gemini", "codex", "opencode"];
3570
+ var CONTEXT_NORMALIZATION_TOKENS = 1e5;
3566
3571
  function analyzeTaskString(taskStr) {
3567
3572
  const task = {
3568
3573
  id: "audit-" + String(getTimeProvider().now()),
3569
3574
  description: taskStr,
3570
3575
  context: {}
3571
3576
  };
3572
- const analyzer = createSharedTaskAnalyzer();
3573
- const analysis = analyzer.analyze(task);
3577
+ const analysis = sharedAnalyzer.analyze(task);
3574
3578
  return taskAnalysisResultToTaskProfile(analysis);
3575
3579
  }
3576
3580
  function taskProfileToBanditContextFromProfile(profile) {
3577
3581
  return {
3578
3582
  taskComplexity: profile.reasoningComplexity / 10,
3579
- contextLengthNormalized: Math.min(profile.contextRequired / 1e5, 1),
3583
+ contextLengthNormalized: Math.min(profile.contextRequired / CONTEXT_NORMALIZATION_TOKENS, 1),
3580
3584
  isCodeTask: profile.codeGeneration ? 1 : 0,
3581
3585
  isReasoningTask: profile.taskType === "architecture" || profile.reasoningComplexity > 5 ? 1 : 0,
3582
3586
  budgetUtilization: 0.5,
@@ -3926,27 +3930,27 @@ var CliAdapterAgent = class {
3926
3930
  };
3927
3931
 
3928
3932
  // src/cli/orchestrate-puppeteer.ts
3929
- function loadPolicyParameters(path23, logger17) {
3933
+ function loadPolicyParameters(path24, logger17) {
3930
3934
  try {
3931
- if (fs2.existsSync(path23)) {
3932
- const content = fs2.readFileSync(path23, "utf-8");
3935
+ if (fs2.existsSync(path24)) {
3936
+ const content = fs2.readFileSync(path24, "utf-8");
3933
3937
  const params = JSON.parse(content);
3934
- logger17.info("Loaded policy parameters", { path: path23 });
3938
+ logger17.info("Loaded policy parameters", { path: path24 });
3935
3939
  return params;
3936
3940
  }
3937
3941
  } catch (error) {
3938
3942
  const message = getErrorMessage(error);
3939
- logger17.warn("Failed to load policy parameters", { path: path23, error: message });
3943
+ logger17.warn("Failed to load policy parameters", { path: path24, error: message });
3940
3944
  }
3941
3945
  return void 0;
3942
3946
  }
3943
- function savePolicyParameters(path23, params, logger17) {
3947
+ function savePolicyParameters(path24, params, logger17) {
3944
3948
  try {
3945
- fs2.writeFileSync(path23, JSON.stringify(params, null, 2));
3946
- logger17.info("Saved policy parameters", { path: path23 });
3949
+ fs2.writeFileSync(path24, JSON.stringify(params, null, 2));
3950
+ logger17.info("Saved policy parameters", { path: path24 });
3947
3951
  } catch (error) {
3948
3952
  const message = getErrorMessage(error);
3949
- logger17.warn("Failed to save policy parameters", { path: path23, error: message });
3953
+ logger17.warn("Failed to save policy parameters", { path: path24, error: message });
3950
3954
  }
3951
3955
  }
3952
3956
  function createAgentsFromAdapters(adapters) {
@@ -4874,38 +4878,33 @@ async function handleList(args, log) {
4874
4878
  const format = args.includes("--json") ? "json" : "table";
4875
4879
  const result = await sessionList({ limit, format, logger: log });
4876
4880
  if (!result.ok) {
4877
- console.error("Error: " + result.error.message);
4878
- process.exit(1);
4881
+ throw new Error(result.error.message);
4879
4882
  }
4880
4883
  printSessionList(result.value, format);
4881
4884
  }
4882
4885
  async function handleShow(args, log) {
4883
4886
  const sessionId = args[0];
4884
4887
  if (sessionId === void 0) {
4885
- console.error("Error: Session ID required");
4886
- process.exit(1);
4888
+ throw new Error("Session ID required");
4887
4889
  }
4888
4890
  const format = args.includes("--json") ? "json" : "text";
4889
4891
  const result = await sessionShow({ sessionId, format, logger: log });
4890
4892
  if (!result.ok) {
4891
- console.error("Error: " + result.error.message);
4892
- process.exit(1);
4893
+ throw new Error(result.error.message);
4893
4894
  }
4894
4895
  printSessionShow(result.value, format);
4895
4896
  }
4896
4897
  async function handleExport(args, log) {
4897
4898
  const sessionId = args[0];
4898
4899
  if (sessionId === void 0) {
4899
- console.error("Error: Session ID required");
4900
- process.exit(1);
4900
+ throw new Error("Session ID required");
4901
4901
  }
4902
4902
  const outputIdx = args.indexOf("--output");
4903
4903
  const outputPath = outputIdx >= 0 ? args[outputIdx + 1] : void 0;
4904
4904
  const format = args.includes("--markdown") ? "markdown" : "json";
4905
4905
  const result = await sessionExport({ sessionId, output: outputPath, format, logger: log });
4906
4906
  if (!result.ok) {
4907
- console.error("Error: " + result.error.message);
4908
- process.exit(1);
4907
+ throw new Error(result.error.message);
4909
4908
  }
4910
4909
  if (outputPath === void 0) output(result.value);
4911
4910
  else output("Exported to " + outputPath);
@@ -4913,28 +4912,24 @@ async function handleExport(args, log) {
4913
4912
  async function handleDelete(args, log) {
4914
4913
  const sessionId = args[0];
4915
4914
  if (sessionId === void 0) {
4916
- console.error("Error: Session ID required");
4917
- process.exit(1);
4915
+ throw new Error("Session ID required");
4918
4916
  }
4919
4917
  const result = await sessionDelete({ sessionId, logger: log });
4920
4918
  if (!result.ok) {
4921
- console.error("Error: " + result.error.message);
4922
- process.exit(1);
4919
+ throw new Error(result.error.message);
4923
4920
  }
4924
4921
  output(result.value ? "Session deleted." : "Session not found.");
4925
4922
  }
4926
4923
  async function handlePrune(args, log) {
4927
4924
  const daysArg = args[0];
4928
4925
  if (daysArg === void 0) {
4929
- console.error("Error: Days argument required");
4930
- process.exit(1);
4926
+ throw new Error("Days argument required");
4931
4927
  }
4932
4928
  const days = parseInt(daysArg, 10);
4933
4929
  const dryRun = args.includes("--dry-run");
4934
4930
  const result = await sessionPrune({ days, dryRun, logger: log });
4935
4931
  if (!result.ok) {
4936
- console.error("Error: " + result.error.message);
4937
- process.exit(1);
4932
+ throw new Error(result.error.message);
4938
4933
  }
4939
4934
  const count = String(result.value);
4940
4935
  output(dryRun ? "Would delete " + count + " sessions." : "Deleted " + count + " sessions.");
@@ -5129,9 +5124,9 @@ _Generated by \`nexus-agents system-review\`_`;
5129
5124
  }
5130
5125
  function createIssue(result) {
5131
5126
  const date = getTimeProvider().nowDateString();
5132
- const body = createIssueBody(result).replace(/"/g, '\\"');
5127
+ const body = createIssueBody(result).replace(/'/g, "'\\''");
5133
5128
  const out = safeExecSandboxed(
5134
- `gh issue create --title "System Review: ${date}" --body "${body}" --label system-review`,
5129
+ `gh issue create --title 'System Review: ${date}' --body '${body}' --label 'system-review'`,
5135
5130
  { context: "gh" }
5136
5131
  );
5137
5132
  if (out !== null) {
@@ -5658,7 +5653,7 @@ function validateGitHubIssue(issueNumber) {
5658
5653
  return output2 !== null;
5659
5654
  }
5660
5655
  function escapeForShell(text) {
5661
- return text.replace(/"/g, '\\"').replace(/`/g, "\\`").replace(/\$/g, "\\$");
5656
+ return text.replace(/'/g, "'\\''");
5662
5657
  }
5663
5658
  function formatVoteComment(result) {
5664
5659
  const now = new Date(getTimeProvider().now()).toLocaleDateString("en-US", {
@@ -5698,7 +5693,7 @@ function recordVoteToGitHub(issueNumber, result) {
5698
5693
  const comment = formatVoteComment(result);
5699
5694
  const escapedComment = escapeForShell(comment);
5700
5695
  const output2 = safeExecSandboxed(
5701
- `gh issue comment ${String(issueNumber)} --body "${escapedComment}"`,
5696
+ `gh issue comment ${String(issueNumber)} --body '${escapedComment}'`,
5702
5697
  { context: "gh" }
5703
5698
  );
5704
5699
  if (output2 !== null) {
@@ -6526,9 +6521,10 @@ function generateProposal(issues, options) {
6526
6521
  }
6527
6522
  function createSprintIssue(proposal) {
6528
6523
  try {
6529
- const escapedBody = proposal.body.replace(/"/g, '\\"').replace(/`/g, "\\`").replace(/\$/g, "\\$");
6524
+ const escapedTitle = proposal.title.replace(/'/g, "'\\''");
6525
+ const escapedBody = proposal.body.replace(/'/g, "'\\''");
6530
6526
  const output2 = safeExecSandboxed(
6531
- `gh issue create --title "${proposal.title}" --body "${escapedBody}" --label "epic"`,
6527
+ `gh issue create --title '${escapedTitle}' --body '${escapedBody}' --label 'epic'`,
6532
6528
  { context: "gh" }
6533
6529
  );
6534
6530
  if (output2 === null) {
@@ -6818,7 +6814,7 @@ var ResearchPaperSchema = z2.object({
6818
6814
  /** arXiv ID (e.g., '2501.06322') */
6819
6815
  arxiv_id: z2.string().optional(),
6820
6816
  /** URL to the paper */
6821
- url: z2.string().url().optional(),
6817
+ url: z2.url().optional(),
6822
6818
  /** Publication date (YYYY-MM format) */
6823
6819
  publication_date: z2.string().optional(),
6824
6820
  /** Publication venue */
@@ -6865,7 +6861,7 @@ var ResearchTechniqueSchema = z2.object({
6865
6861
  /** Tags for searching */
6866
6862
  tags: z2.array(z2.string()).optional().default([]),
6867
6863
  /** Metrics associated with this technique */
6868
- metrics: z2.record(z2.string()).optional().default({}),
6864
+ metrics: z2.record(z2.string(), z2.string()).optional().default({}),
6869
6865
  /** Implementation status (required) */
6870
6866
  status: TechniqueStatusSchema,
6871
6867
  /** Priority level */
@@ -6887,11 +6883,11 @@ var ResearchTechniqueSchema = z2.object({
6887
6883
  });
6888
6884
  var PapersRegistrySchema = z2.object({
6889
6885
  schema_version: z2.string(),
6890
- papers: z2.record(ResearchPaperSchema)
6886
+ papers: z2.record(z2.string(), ResearchPaperSchema)
6891
6887
  });
6892
6888
  var TechniquesRegistrySchema = z2.object({
6893
6889
  schema_version: z2.string(),
6894
- techniques: z2.record(ResearchTechniqueSchema)
6890
+ techniques: z2.record(z2.string(), ResearchTechniqueSchema)
6895
6891
  });
6896
6892
  function getIntegrationFilePath(file) {
6897
6893
  if (typeof file === "string") {
@@ -7815,9 +7811,20 @@ async function researchIndexCommand(options) {
7815
7811
  }
7816
7812
 
7817
7813
  // src/cli/research-command.ts
7814
+ function optString(options, key) {
7815
+ const val = options[key];
7816
+ return typeof val === "string" ? val : void 0;
7817
+ }
7818
+ function optNumber(options, key) {
7819
+ const val = options[key];
7820
+ return typeof val === "number" ? val : void 0;
7821
+ }
7822
+ function optBoolean(options, key) {
7823
+ return options[key] === true;
7824
+ }
7818
7825
  async function handleStatusCommand(args, options) {
7819
- const status = options["status"] ?? "all";
7820
- const format = options["format"] ?? "table";
7826
+ const status = optString(options, "status") ?? "all";
7827
+ const format = optString(options, "format") ?? "table";
7821
7828
  const statusOptions = {
7822
7829
  techniqueId: args[0],
7823
7830
  status,
@@ -7831,10 +7838,10 @@ async function handleOverlapCommand(args, options) {
7831
7838
  if (techniqueId === void 0 || techniqueId === "") {
7832
7839
  return "Error: technique-id is required for overlap command";
7833
7840
  }
7834
- const format = options["format"] ?? "table";
7841
+ const format = optString(options, "format") ?? "table";
7835
7842
  const overlapOptions = {
7836
7843
  techniqueId,
7837
- threshold: options["threshold"] ?? 0.3,
7844
+ threshold: optNumber(options, "threshold") ?? 0.3,
7838
7845
  format
7839
7846
  };
7840
7847
  const result = await findOverlaps(overlapOptions);
@@ -7847,9 +7854,9 @@ async function handleAddCommand(args, options) {
7847
7854
  }
7848
7855
  const addOptions = {
7849
7856
  arxivId,
7850
- topic: options["topic"],
7851
- priority: options["priority"],
7852
- dryRun: options["dryRun"] ?? false
7857
+ topic: optString(options, "topic"),
7858
+ priority: optString(options, "priority"),
7859
+ dryRun: optBoolean(options, "dryRun")
7853
7860
  };
7854
7861
  const result = await addResearchPaper(addOptions);
7855
7862
  return result.message;
@@ -7898,23 +7905,23 @@ function formatDiscoverResults(topic, items, errors, maxResults) {
7898
7905
  return lines.join("\n");
7899
7906
  }
7900
7907
  async function handleDiscoverCommand(args, options) {
7901
- const topic = args[0] ?? options["topic"];
7908
+ const topic = args[0] ?? optString(options, "topic");
7902
7909
  if (topic === void 0 || topic === "") {
7903
7910
  return "Error: --topic is required for discover command";
7904
7911
  }
7905
- const source = options["source"] ?? "all";
7906
- const maxResults = options["maxResults"] ?? 10;
7912
+ const source = optString(options, "source") ?? "all";
7913
+ const maxResults = optNumber(options, "maxResults") ?? 10;
7907
7914
  const { results, errors } = await queryDiscoverSources(topic, source, maxResults);
7908
7915
  return formatDiscoverResults(topic, results, errors, maxResults);
7909
7916
  }
7910
7917
  async function handleReviewCommand(args, options) {
7911
- const topic = args[0] ?? options["topic"];
7918
+ const topic = args[0] ?? optString(options, "topic");
7912
7919
  if (topic === void 0 || topic === "") {
7913
7920
  return "Error: --topic is required for review command";
7914
7921
  }
7915
- const maxResults = options["maxResults"] ?? 10;
7916
- const createIssues = options["createIssues"] ?? false;
7917
- const vote = options["vote"] ?? false;
7922
+ const maxResults = optNumber(options, "maxResults") ?? 10;
7923
+ const createIssues = optBoolean(options, "createIssues");
7924
+ const vote = optBoolean(options, "vote");
7918
7925
  const result = await executeReview(
7919
7926
  { topic, maxResults, createIssues, vote },
7920
7927
  (t, max) => queryDiscoverSources(t, "all", max)
@@ -7922,10 +7929,89 @@ async function handleReviewCommand(args, options) {
7922
7929
  return formatReviewResults(result);
7923
7930
  }
7924
7931
  async function handlePrioritizeCommand(args, options) {
7925
- const topic = args[0] ?? options["topic"];
7926
- const vote = options["vote"] ?? false;
7932
+ const topic = args[0] ?? optString(options, "topic");
7933
+ const vote = optBoolean(options, "vote");
7927
7934
  return executePrioritize({ topic, vote });
7928
7935
  }
7936
+ async function handleSynthesizeCommand(args, options) {
7937
+ const topic = args[0] ?? optString(options, "topic");
7938
+ const result = await synthesizeResearch(topic);
7939
+ if (!result.ok) {
7940
+ return `Error: ${result.error.message}`;
7941
+ }
7942
+ return formatSynthesisResult(result.value);
7943
+ }
7944
+ function formatSynthesisResult(synthesis) {
7945
+ const lines = [
7946
+ `Research Synthesis: ${String(synthesis.totalPapers)} papers across ${String(synthesis.topicCount)} topics`,
7947
+ ""
7948
+ ];
7949
+ for (const cluster of synthesis.clusters) {
7950
+ formatCluster(cluster, lines);
7951
+ }
7952
+ if (synthesis.crossCuttingThemes.length > 0) {
7953
+ lines.push("## Cross-Cutting Themes");
7954
+ for (const theme of synthesis.crossCuttingThemes) {
7955
+ lines.push(` - ${theme}`);
7956
+ }
7957
+ lines.push("");
7958
+ }
7959
+ formatAlignmentSummary(synthesis.alignmentSummary, lines);
7960
+ formatFeatureGates(synthesis.featureGates, lines);
7961
+ return lines.join("\n");
7962
+ }
7963
+ function formatCluster(cluster, lines) {
7964
+ lines.push(`## ${cluster.topic} (${String(cluster.paperCount)} papers)`);
7965
+ lines.push(`Papers: ${cluster.papers.join(", ")}`);
7966
+ if (cluster.commonThemes.length > 0) lines.push(`Themes: ${cluster.commonThemes.join(", ")}`);
7967
+ if (cluster.keyInsights.length > 0) {
7968
+ lines.push("Key insights:");
7969
+ for (const insight of cluster.keyInsights.slice(0, 5)) lines.push(` - ${insight}`);
7970
+ }
7971
+ if (cluster.implementationOpportunities.length > 0) {
7972
+ lines.push(`Opportunities: ${cluster.implementationOpportunities.join(", ")}`);
7973
+ }
7974
+ if (cluster.gaps.length > 0) lines.push(`Gaps: ${cluster.gaps.join("; ")}`);
7975
+ const partial = cluster.alignedTechniques.filter((a) => a.status === "partial");
7976
+ if (partial.length > 0) {
7977
+ lines.push("Improvement opportunities:");
7978
+ for (const a of partial.slice(0, 3)) {
7979
+ const hint = a.improvementHint !== void 0 ? ` \u2014 ${a.improvementHint}` : "";
7980
+ lines.push(` - ${a.technique} (${a.canonicalPath ?? "unknown"})${hint}`);
7981
+ }
7982
+ }
7983
+ lines.push("");
7984
+ }
7985
+ function formatFeatureGates(gates, lines) {
7986
+ if (gates.length === 0) return;
7987
+ const linked = gates.filter((g) => g.linkedTechniqueCount > 0);
7988
+ const unlinked = gates.filter((g) => g.linkedTechniqueCount === 0);
7989
+ lines.push("");
7990
+ lines.push(
7991
+ `## Feature Gates (${String(gates.length)} total, ${String(linked.length)} research-linked)`
7992
+ );
7993
+ for (const g of linked) {
7994
+ lines.push(
7995
+ ` ${g.envVar}=${g.defaultValue} \u2014 ${g.description} [${String(g.linkedTechniqueCount)} techniques]`
7996
+ );
7997
+ }
7998
+ if (unlinked.length > 0) {
7999
+ lines.push(
8000
+ ` + ${String(unlinked.length)} infrastructure gates (auth, logging, rate limiting, etc.)`
8001
+ );
8002
+ }
8003
+ }
8004
+ function formatAlignmentSummary(summary, lines) {
8005
+ if (summary.total === 0) return;
8006
+ lines.push("## Alignment Summary");
8007
+ lines.push(
8008
+ `Implemented: ${String(summary.implemented)} | Partial: ${String(summary.partial)} | Not started: ${String(summary.notStarted)} | Total: ${String(summary.total)}`
8009
+ );
8010
+ if (summary.topOpportunities.length > 0) {
8011
+ lines.push("Top improvement opportunities:");
8012
+ for (const opp of summary.topOpportunities.slice(0, 5)) lines.push(` - ${opp}`);
8013
+ }
8014
+ }
7929
8015
  var VALID_SUBCOMMANDS = [
7930
8016
  "status",
7931
8017
  "overlap",
@@ -7936,7 +8022,8 @@ var VALID_SUBCOMMANDS = [
7936
8022
  "index",
7937
8023
  "discover",
7938
8024
  "review",
7939
- "prioritize"
8025
+ "prioritize",
8026
+ "synthesize"
7940
8027
  ];
7941
8028
  function isValidResearchSubcommand(value) {
7942
8029
  return value !== void 0 && VALID_SUBCOMMANDS.includes(value);
@@ -7956,7 +8043,8 @@ var SUBCOMMAND_HANDLERS = {
7956
8043
  index: (args) => handleIndexCommand(args),
7957
8044
  discover: handleDiscoverCommand,
7958
8045
  review: handleReviewCommand,
7959
- prioritize: handlePrioritizeCommand
8046
+ prioritize: handlePrioritizeCommand,
8047
+ synthesize: handleSynthesizeCommand
7960
8048
  };
7961
8049
  async function researchCommand(subcommand, args, options) {
7962
8050
  const handler = SUBCOMMAND_HANDLERS[subcommand];
@@ -9030,6 +9118,16 @@ function extractToolsFromFile(sourceFile, relativePath) {
9030
9118
  }
9031
9119
  return tools;
9032
9120
  }
9121
+ function resolvePropertyValue(prop, sourceFile) {
9122
+ const propAssign = prop.asKind(SyntaxKind2.PropertyAssignment);
9123
+ if (propAssign !== void 0) return propAssign.getInitializer();
9124
+ const shorthand = prop.asKind(SyntaxKind2.ShorthandPropertyAssignment);
9125
+ if (shorthand !== void 0 && sourceFile !== void 0) {
9126
+ const varDecl = sourceFile.getVariableDeclaration(shorthand.getName());
9127
+ return varDecl?.getInitializer();
9128
+ }
9129
+ return void 0;
9130
+ }
9033
9131
  function extractToolMeta(callText, args, _sourceFile) {
9034
9132
  let description = "";
9035
9133
  let schemaArg;
@@ -9040,14 +9138,12 @@ function extractToolMeta(callText, args, _sourceFile) {
9040
9138
  if (configObj !== void 0) {
9041
9139
  const descProp = configObj.getProperty("description");
9042
9140
  if (descProp !== void 0) {
9043
- const propAssign = descProp.asKind(SyntaxKind2.PropertyAssignment);
9044
- const init = propAssign?.getInitializer();
9141
+ const init = resolvePropertyValue(descProp, _sourceFile);
9045
9142
  description = init?.getText().replace(/^['"]|['"]$/g, "") ?? "";
9046
9143
  }
9047
9144
  const schemaProp = configObj.getProperty("inputSchema");
9048
9145
  if (schemaProp !== void 0) {
9049
- const propAssign = schemaProp.asKind(SyntaxKind2.PropertyAssignment);
9050
- schemaArg = propAssign?.getInitializer();
9146
+ schemaArg = resolvePropertyValue(schemaProp, _sourceFile);
9051
9147
  }
9052
9148
  }
9053
9149
  }
@@ -9514,8 +9610,9 @@ function getLinkType(url) {
9514
9610
  }
9515
9611
  return "internal";
9516
9612
  }
9613
+ var DANGEROUS_SCHEME_REGEX = /^[\s\x00-\x1f\x7f]*(mailto|javascript|data|file|ftp)[\s\x00-\x1f\x7f]*:/i;
9517
9614
  function shouldSkipUrl(url) {
9518
- return url.startsWith("mailto:") || url.startsWith("javascript:");
9615
+ return DANGEROUS_SCHEME_REGEX.test(url);
9519
9616
  }
9520
9617
  function buildReferenceMap(content) {
9521
9618
  const references = /* @__PURE__ */ new Map();
@@ -9787,7 +9884,8 @@ async function getActualModules(srcPath) {
9787
9884
  try {
9788
9885
  const entries = await fs12.readdir(srcPath, { withFileTypes: true });
9789
9886
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && !e.name.startsWith("__")).map((e) => e.name);
9790
- } catch {
9887
+ } catch (error) {
9888
+ logger9.debug("Failed to read source modules", { srcPath, error: getErrorMessage(error) });
9791
9889
  return [];
9792
9890
  }
9793
9891
  }
@@ -10249,6 +10347,8 @@ async function verifyCommand(options) {
10249
10347
  }
10250
10348
 
10251
10349
  // src/cli/swe-bench-command.ts
10350
+ import * as os2 from "os";
10351
+ import * as path19 from "path";
10252
10352
  function runInfo(options) {
10253
10353
  console.log(`
10254
10354
  SWE-bench Dataset: ${options.variant}`);
@@ -10299,7 +10399,9 @@ function buildConfig(options) {
10299
10399
  ...DEFAULT_SWE_BENCH_CONFIG,
10300
10400
  variant: options.variant,
10301
10401
  output_path: options.output,
10302
- resume: options.resume
10402
+ resume: options.resume,
10403
+ concurrency: options.concurrency,
10404
+ memory_dir: "/tmp/swe-bench-memory"
10303
10405
  };
10304
10406
  return options.limit !== void 0 ? { ...base, limit: options.limit } : base;
10305
10407
  }
@@ -10332,7 +10434,10 @@ async function runBenchmark(options) {
10332
10434
  console.log(`
10333
10435
  SWE-bench Run: ${options.variant}`);
10334
10436
  console.log("=".repeat(40));
10335
- const executorResult = await createExecutor(options.verbose);
10437
+ const executorResult = await createExecutor({
10438
+ verbose: options.verbose,
10439
+ mcpEnabled: options.mcp
10440
+ });
10336
10441
  if (!executorResult.ok) {
10337
10442
  console.error(`
10338
10443
  Error: ${executorResult.error.message}`);
@@ -10355,38 +10460,102 @@ Error: ${executorResult.error.message}`);
10355
10460
  });
10356
10461
  return { success: result.success, message: result.message, details: { ...result } };
10357
10462
  }
10358
- async function commandExists(cmd) {
10359
- const { exec } = await import("child_process");
10360
- const { promisify } = await import("util");
10361
- try {
10362
- await promisify(exec)(`which ${cmd}`);
10363
- return true;
10364
- } catch {
10365
- return false;
10463
+ function isValidRunId(runId) {
10464
+ return /^[a-zA-Z0-9_-]{1,64}$/.test(runId);
10465
+ }
10466
+ function isValidOutputDir(dir) {
10467
+ const resolved = path19.resolve(dir);
10468
+ return !resolved.includes("..") && resolved === path19.normalize(resolved);
10469
+ }
10470
+ function formatProgress(progress) {
10471
+ const pct = progress.totalCount > 0 ? Math.round(progress.completedCount / progress.totalCount * 100) : 0;
10472
+ const base = `[${String(progress.completedCount)}/${String(progress.totalCount)}] ${String(pct)}%`;
10473
+ if (progress.currentInstanceId !== void 0) {
10474
+ return `${base} - ${progress.currentInstanceId}`;
10475
+ }
10476
+ return base;
10477
+ }
10478
+ function buildHarnessConfig(options) {
10479
+ const predictionsPath = options.predictions ?? options.output;
10480
+ const runId = options.runId ?? `eval-${String(Date.now())}`;
10481
+ return {
10482
+ predictionsPath: path19.resolve(predictionsPath),
10483
+ datasetName: options.variant,
10484
+ maxWorkers: options.maxWorkers,
10485
+ runId,
10486
+ timeoutSeconds: 1800,
10487
+ outputDir: path19.resolve(options.outputDir),
10488
+ useDocker: true,
10489
+ cacheLevel: options.cacheLevel
10490
+ };
10491
+ }
10492
+ function validateEvaluateInputs(options) {
10493
+ if (options.runId !== void 0 && !isValidRunId(options.runId)) {
10494
+ return "Invalid run-id: alphanumeric, hyphens, underscores only";
10495
+ }
10496
+ if (!isValidOutputDir(options.outputDir)) {
10497
+ return "Invalid output-dir: path traversal detected";
10498
+ }
10499
+ return null;
10500
+ }
10501
+ function displayEvaluateResults(result, verbose) {
10502
+ console.log("\n");
10503
+ console.log(`Resolved: ${String(result.resolvedInstances)}/${String(result.totalInstances)}`);
10504
+ console.log(`Resolution rate: ${(result.resolutionRate * 100).toFixed(1)}%`);
10505
+ if (result.logPath !== void 0) console.log(`Logs: ${result.logPath}`);
10506
+ if (verbose && result.instanceResults.length > 0) {
10507
+ console.log("\nPer-instance results:");
10508
+ for (const inst of result.instanceResults) {
10509
+ console.log(` [${inst.resolved ? "PASS" : "FAIL"}] ${inst.instanceId}`);
10510
+ }
10366
10511
  }
10367
10512
  }
10368
10513
  async function runEvaluate(options) {
10369
10514
  console.log(`
10370
10515
  SWE-bench Evaluate`);
10371
10516
  console.log("=".repeat(40));
10372
- const idsResult = await getCompletedInstanceIds(options.output);
10517
+ const predictionsPath = options.predictions ?? options.output;
10518
+ const idsResult = await getCompletedInstanceIds(predictionsPath);
10373
10519
  if (!idsResult.ok) {
10374
10520
  console.log('No predictions file. Run "nexus-agents swe-bench run" first.');
10375
10521
  return { success: false, message: "No predictions file" };
10376
10522
  }
10377
10523
  const count = idsResult.value.size;
10378
10524
  if (count === 0) return { success: false, message: "No predictions" };
10379
- console.log("\nChecking dependencies...");
10380
- const hasPython = await commandExists("python3");
10381
- const hasDocker = await commandExists("docker");
10382
- if (!hasPython) return { success: false, message: "python3 not found" };
10383
- if (!hasDocker) return { success: false, message: "docker not found" };
10384
- console.log(" [OK] python3, docker");
10385
- console.log("\nManual evaluation:");
10386
- console.log(` python -m swebench.harness.run_evaluation \\`);
10387
- console.log(` --predictions_path ${options.output} \\`);
10388
- console.log(` --swe_bench_tasks princeton-nlp/SWE-bench_Lite`);
10389
- return { success: true, message: `${String(count)} predictions ready` };
10525
+ const inputError = validateEvaluateInputs(options);
10526
+ if (inputError !== null) return { success: false, message: inputError };
10527
+ console.log(`Predictions: ${String(count)} instances`);
10528
+ console.log(`Cache level: ${options.cacheLevel}`);
10529
+ console.log(`Max workers: ${String(options.maxWorkers)}`);
10530
+ const executor = createHarnessExecutor();
10531
+ const validation = await executor.validate();
10532
+ if (!validation.ready) {
10533
+ console.error("\nEnvironment not ready:");
10534
+ for (const err2 of validation.errors) console.error(` - ${err2}`);
10535
+ return { success: false, message: validation.errors.join("; ") };
10536
+ }
10537
+ console.log(
10538
+ `
10539
+ Environment OK (Python ${validation.pythonVersion ?? "?"}, Docker ${validation.dockerVersion ?? "?"})`
10540
+ );
10541
+ const config = buildHarnessConfig(options);
10542
+ console.log(`
10543
+ Running evaluation (run_id: ${config.runId})...`);
10544
+ const result = await executor.execute(config, (progress) => {
10545
+ if (progress.state === "running") process.stdout.write(`\r ${formatProgress(progress)}`);
10546
+ });
10547
+ displayEvaluateResults(result, options.verbose);
10548
+ const rateStr = (result.resolutionRate * 100).toFixed(1);
10549
+ return {
10550
+ success: true,
10551
+ message: `${String(result.resolvedInstances)}/${String(result.totalInstances)} resolved (${rateStr}%)`,
10552
+ details: {
10553
+ resolved: result.resolvedInstances,
10554
+ total: result.totalInstances,
10555
+ resolutionRate: result.resolutionRate,
10556
+ runId: result.runId
10557
+ }
10558
+ };
10390
10559
  }
10391
10560
  function parseSubcommand(arg) {
10392
10561
  if (arg === "status") return "status";
@@ -10399,13 +10568,53 @@ function parseVariant(arg) {
10399
10568
  if (v === "lite" || v === "verified" || v === "full") return v;
10400
10569
  return "lite";
10401
10570
  }
10571
+ var MAX_WORKERS_CAP = Math.min(Math.floor(os2.cpus().length * 0.75), 24);
10572
+ var VALID_CACHE_LEVELS = /* @__PURE__ */ new Set(["none", "base", "env", "instance"]);
10573
+ var BOOLEAN_FLAGS = {
10574
+ "--resume": "resume",
10575
+ "--verbose": "verbose",
10576
+ "-v": "verbose",
10577
+ "--mcp": "mcp"
10578
+ };
10579
+ function parseCacheLevel(value) {
10580
+ const level = value;
10581
+ return VALID_CACHE_LEVELS.has(level) ? level : "env";
10582
+ }
10583
+ function parseMaxWorkers(value) {
10584
+ const parsed = parseInt(value, 10);
10585
+ if (Number.isNaN(parsed) || parsed < 1) return 4;
10586
+ return Math.min(parsed, MAX_WORKERS_CAP);
10587
+ }
10588
+ var STRING_FLAGS = [
10589
+ ["--output=", "output", (v) => v],
10590
+ ["--predictions=", "predictions", (v) => v],
10591
+ ["--run-id=", "runId", (v) => v],
10592
+ ["--output-dir=", "outputDir", (v) => v],
10593
+ ["--limit=", "limit", (v) => parseInt(v, 10)],
10594
+ ["--concurrency=", "concurrency", (v) => Math.max(1, parseInt(v, 10) || 1)],
10595
+ ["--cache-level=", "cacheLevel", parseCacheLevel],
10596
+ ["--max-workers=", "maxWorkers", parseMaxWorkers]
10597
+ ];
10402
10598
  function parseArg(arg, state) {
10403
- if (arg.startsWith("--variant=")) state.variant = parseVariant(arg);
10404
- else if (arg.startsWith("--limit=")) state.limit = parseInt(arg.slice("--limit=".length), 10);
10405
- else if (arg.startsWith("--output=")) state.output = arg.slice("--output=".length);
10406
- else if (arg === "--resume") state.resume = true;
10407
- else if (arg === "--verbose" || arg === "-v") state.verbose = true;
10408
- else if (arg.startsWith("--instance=")) state.instances.push(arg.slice("--instance=".length));
10599
+ const boolKey = BOOLEAN_FLAGS[arg];
10600
+ if (boolKey !== void 0) {
10601
+ state[boolKey] = true;
10602
+ return;
10603
+ }
10604
+ if (arg.startsWith("--variant=")) {
10605
+ state.variant = parseVariant(arg);
10606
+ return;
10607
+ }
10608
+ if (arg.startsWith("--instance=")) {
10609
+ state.instances.push(arg.slice("--instance=".length));
10610
+ return;
10611
+ }
10612
+ for (const [prefix, key, transform] of STRING_FLAGS) {
10613
+ if (arg.startsWith(prefix)) {
10614
+ state[key] = transform(arg.slice(prefix.length));
10615
+ return;
10616
+ }
10617
+ }
10409
10618
  }
10410
10619
  function parseSweBenchArgs(args) {
10411
10620
  const subcommand = parseSubcommand(args[0]);
@@ -10415,7 +10624,14 @@ function parseSweBenchArgs(args) {
10415
10624
  output: "predictions.jsonl",
10416
10625
  resume: false,
10417
10626
  verbose: false,
10418
- instances: []
10627
+ concurrency: 1,
10628
+ instances: [],
10629
+ mcp: false,
10630
+ predictions: void 0,
10631
+ cacheLevel: "env",
10632
+ maxWorkers: 4,
10633
+ runId: void 0,
10634
+ outputDir: "./logs/run_evaluation"
10419
10635
  };
10420
10636
  for (const arg of args.slice(1)) parseArg(arg, state);
10421
10637
  const base = {
@@ -10424,9 +10640,17 @@ function parseSweBenchArgs(args) {
10424
10640
  output: state.output,
10425
10641
  resume: state.resume,
10426
10642
  verbose: state.verbose,
10427
- instances: state.instances
10643
+ concurrency: state.concurrency,
10644
+ instances: state.instances,
10645
+ mcp: state.mcp,
10646
+ cacheLevel: state.cacheLevel,
10647
+ maxWorkers: state.maxWorkers,
10648
+ outputDir: state.outputDir,
10649
+ ...state.limit !== void 0 ? { limit: state.limit } : {},
10650
+ ...state.predictions !== void 0 ? { predictions: state.predictions } : {},
10651
+ ...state.runId !== void 0 ? { runId: state.runId } : {}
10428
10652
  };
10429
- return state.limit !== void 0 ? { ...base, limit: state.limit } : base;
10653
+ return base;
10430
10654
  }
10431
10655
  function printSweBenchHelp() {
10432
10656
  console.log(`
@@ -10444,7 +10668,16 @@ Options:
10444
10668
  --output=<path> Output predictions file (default: predictions.jsonl)
10445
10669
  --resume Skip already completed instances
10446
10670
  --instance=<id> Run specific instance (can be repeated)
10671
+ --concurrency=<n> Parallel workers (default: 1, sequential)
10672
+ --mcp Enable MCP tools (memory, research) in child sessions
10447
10673
  --verbose, -v Enable verbose output
10674
+
10675
+ Evaluate options:
10676
+ --predictions=<path> Predictions file (default: --output value)
10677
+ --cache-level=<level> Docker cache: none|base|env|instance (default: env)
10678
+ --max-workers=<n> Parallel Docker workers (default: 4, max: ${String(MAX_WORKERS_CAP)})
10679
+ --run-id=<id> Custom run identifier
10680
+ --output-dir=<path> Harness log directory (default: ./logs/run_evaluation)
10448
10681
  `);
10449
10682
  }
10450
10683
  async function sweBenchCommand(args) {
@@ -10834,7 +11067,7 @@ function isValidConfigAction(value) {
10834
11067
 
10835
11068
  // src/cli/config-command-helpers.ts
10836
11069
  import * as fs13 from "fs/promises";
10837
- import * as path19 from "path";
11070
+ import * as path20 from "path";
10838
11071
  import { existsSync as existsSync10 } from "fs";
10839
11072
 
10840
11073
  // src/cli/config-command-formatting.ts
@@ -11102,10 +11335,10 @@ function parseValueFromString(stringValue, defaultValue) {
11102
11335
  }
11103
11336
  function resolveFilePath(filePath, allowedBase) {
11104
11337
  const base = allowedBase ?? process.cwd();
11105
- const resolved = path19.isAbsolute(filePath) ? filePath : path19.resolve(base, filePath);
11106
- const normalizedResolved = path19.normalize(resolved);
11107
- const normalizedBase = path19.normalize(base);
11108
- const isWithinBase = normalizedResolved === normalizedBase || normalizedResolved.startsWith(normalizedBase + path19.sep);
11338
+ const resolved = path20.isAbsolute(filePath) ? filePath : path20.resolve(base, filePath);
11339
+ const normalizedResolved = path20.normalize(resolved);
11340
+ const normalizedBase = path20.normalize(base);
11341
+ const isWithinBase = normalizedResolved === normalizedBase || normalizedResolved.startsWith(normalizedBase + path20.sep);
11109
11342
  if (!isWithinBase) {
11110
11343
  throw new ConfigCommandError(
11111
11344
  "PATH_TRAVERSAL",
@@ -11116,7 +11349,7 @@ function resolveFilePath(filePath, allowedBase) {
11116
11349
  }
11117
11350
  function getDefaultExportPath(format) {
11118
11351
  const extension = format === "json" ? "json" : "yaml";
11119
- return path19.resolve(process.cwd(), `nexus-config.${extension}`);
11352
+ return path20.resolve(process.cwd(), `nexus-config.${extension}`);
11120
11353
  }
11121
11354
 
11122
11355
  // src/cli/config-command-handlers.ts
@@ -11531,20 +11764,20 @@ var SessionEndInputSchema = HookInputBaseSchema.extend({
11531
11764
  var PreToolUseInputSchema = HookInputBaseSchema.extend({
11532
11765
  hook_event_name: z6.literal("PreToolUse"),
11533
11766
  tool_name: z6.string(),
11534
- tool_input: z6.record(z6.unknown()),
11767
+ tool_input: z6.record(z6.string(), z6.unknown()),
11535
11768
  tool_use_id: z6.string()
11536
11769
  });
11537
11770
  var PostToolUseInputSchema = HookInputBaseSchema.extend({
11538
11771
  hook_event_name: z6.literal("PostToolUse"),
11539
11772
  tool_name: z6.string(),
11540
- tool_input: z6.record(z6.unknown()),
11541
- tool_response: z6.record(z6.unknown()),
11773
+ tool_input: z6.record(z6.string(), z6.unknown()),
11774
+ tool_response: z6.record(z6.string(), z6.unknown()),
11542
11775
  tool_use_id: z6.string()
11543
11776
  });
11544
11777
  var PostToolUseFailureInputSchema = HookInputBaseSchema.extend({
11545
11778
  hook_event_name: z6.literal("PostToolUseFailure"),
11546
11779
  tool_name: z6.string(),
11547
- tool_input: z6.record(z6.unknown()),
11780
+ tool_input: z6.record(z6.string(), z6.unknown()),
11548
11781
  tool_use_id: z6.string(),
11549
11782
  error: z6.string().optional()
11550
11783
  });
@@ -11592,7 +11825,7 @@ var SubagentStartInputSchema = HookInputBaseSchema.extend({
11592
11825
  var PermissionRequestInputSchema = HookInputBaseSchema.extend({
11593
11826
  hook_event_name: z6.literal("PermissionRequest"),
11594
11827
  tool_name: z6.string(),
11595
- tool_input: z6.record(z6.unknown()),
11828
+ tool_input: z6.record(z6.string(), z6.unknown()),
11596
11829
  tool_use_id: z6.string()
11597
11830
  });
11598
11831
  var HookInputSchema = z6.discriminatedUnion("hook_event_name", [
@@ -11623,7 +11856,7 @@ var PreToolUseOutputSchema = HookOutputBaseSchema.extend({
11623
11856
  hookEventName: z6.literal("PreToolUse"),
11624
11857
  permissionDecision: PermissionDecision.optional(),
11625
11858
  permissionDecisionReason: z6.string().optional(),
11626
- updatedInput: z6.record(z6.unknown()).optional(),
11859
+ updatedInput: z6.record(z6.string(), z6.unknown()).optional(),
11627
11860
  additionalContext: z6.string().optional()
11628
11861
  }).optional()
11629
11862
  });
@@ -11658,7 +11891,7 @@ var PermissionRequestOutputSchema = HookOutputBaseSchema.extend({
11658
11891
  hookEventName: z6.literal("PermissionRequest"),
11659
11892
  decision: z6.object({
11660
11893
  behavior: z6.enum(["allow", "deny"]),
11661
- updatedInput: z6.record(z6.unknown()).optional(),
11894
+ updatedInput: z6.record(z6.string(), z6.unknown()).optional(),
11662
11895
  message: z6.string().optional(),
11663
11896
  interrupt: z6.boolean().optional()
11664
11897
  })
@@ -11746,34 +11979,35 @@ function writeResultAndExit(result) {
11746
11979
 
11747
11980
  // src/cli/hooks/hook-router.ts
11748
11981
  async function readStdin() {
11749
- return new Promise((resolve11, reject) => {
11982
+ return new Promise((resolve12, reject) => {
11750
11983
  let data = "";
11751
11984
  process.stdin.setEncoding("utf8");
11752
11985
  process.stdin.on("readable", () => {
11753
11986
  let chunk;
11754
11987
  while ((chunk = process.stdin.read()) !== null) {
11988
+ if (typeof chunk !== "string") continue;
11755
11989
  data += chunk;
11756
11990
  }
11757
11991
  });
11758
11992
  process.stdin.on("end", () => {
11759
- resolve11(data);
11993
+ resolve12(data);
11760
11994
  });
11761
11995
  process.stdin.on("error", (err2) => {
11762
11996
  reject(err2);
11763
11997
  });
11764
11998
  if (process.stdin.isTTY) {
11765
- resolve11("");
11999
+ resolve12("");
11766
12000
  }
11767
12001
  });
11768
12002
  }
11769
12003
  async function readStdinWithTimeout(timeoutMs = 5e3) {
11770
- return new Promise((resolve11, reject) => {
12004
+ return new Promise((resolve12, reject) => {
11771
12005
  const timeout2 = setTimeout(() => {
11772
12006
  reject(new Error(`Stdin read timeout after ${String(timeoutMs)}ms`));
11773
12007
  }, timeoutMs);
11774
12008
  readStdin().then((data) => {
11775
12009
  clearTimeout(timeout2);
11776
- resolve11(data);
12010
+ resolve12(data);
11777
12011
  }).catch((err2) => {
11778
12012
  clearTimeout(timeout2);
11779
12013
  reject(err2 instanceof Error ? err2 : new Error(String(err2)));
@@ -11829,7 +12063,7 @@ async function processHook(handlers) {
11829
12063
  return exitError(`Hook processing error: ${message}`);
11830
12064
  }
11831
12065
  }
11832
- var BOOLEAN_FLAGS = /* @__PURE__ */ new Map([
12066
+ var BOOLEAN_FLAGS2 = /* @__PURE__ */ new Map([
11833
12067
  ["--validate", "validate"],
11834
12068
  ["--load-context", "loadContext"],
11835
12069
  ["--track-metrics", "trackMetrics"],
@@ -11850,7 +12084,7 @@ function parseHookArgs(args) {
11850
12084
  for (let i = 1; i < args.length; i++) {
11851
12085
  const arg = args[i];
11852
12086
  if (arg === void 0) continue;
11853
- const booleanKey = BOOLEAN_FLAGS.get(arg);
12087
+ const booleanKey = BOOLEAN_FLAGS2.get(arg);
11854
12088
  if (booleanKey !== void 0) {
11855
12089
  setBooleanOption(options, booleanKey);
11856
12090
  continue;
@@ -13429,7 +13663,8 @@ function getLatestTag() {
13429
13663
  try {
13430
13664
  const result = execSync2("git describe --tags --abbrev=0", {
13431
13665
  encoding: "utf-8",
13432
- stdio: ["pipe", "pipe", "pipe"]
13666
+ stdio: ["pipe", "pipe", "pipe"],
13667
+ timeout: CLI_SUBPROCESS_TIMEOUTS.ghCommandMs
13433
13668
  }).trim();
13434
13669
  return result || void 0;
13435
13670
  } catch {
@@ -13440,7 +13675,8 @@ function getCommitsBetween(from, to = "HEAD") {
13440
13675
  try {
13441
13676
  const result = execSync2(`git log ${from}..${to} --oneline --format="%h %s"`, {
13442
13677
  encoding: "utf-8",
13443
- stdio: ["pipe", "pipe", "pipe"]
13678
+ stdio: ["pipe", "pipe", "pipe"],
13679
+ timeout: CLI_SUBPROCESS_TIMEOUTS.ghCommandMs
13444
13680
  }).trim();
13445
13681
  return result ? result.split("\n").filter(Boolean) : [];
13446
13682
  } catch {
@@ -13485,7 +13721,7 @@ function groupCommitsByCategory(commits) {
13485
13721
  const categoryMap = /* @__PURE__ */ new Map();
13486
13722
  for (const commit of commits) {
13487
13723
  const category = mapTypeToCategory(commit.type);
13488
- const existing = categoryMap.get(category) || [];
13724
+ const existing = categoryMap.get(category) ?? [];
13489
13725
  existing.push(commit);
13490
13726
  categoryMap.set(category, existing);
13491
13727
  }
@@ -13548,8 +13784,8 @@ function generateMarkdownFormat(version, categories) {
13548
13784
  const lines = [];
13549
13785
  lines.push(`# Release ${version}`);
13550
13786
  lines.push("");
13551
- const featCount = categories.find((c) => c.name === "Added")?.commits.length || 0;
13552
- const fixCount = categories.find((c) => c.name === "Fixed")?.commits.length || 0;
13787
+ const featCount = categories.find((c) => c.name === "Added")?.commits.length ?? 0;
13788
+ const fixCount = categories.find((c) => c.name === "Fixed")?.commits.length ?? 0;
13553
13789
  const totalCount = categories.reduce((sum, c) => sum + c.commits.length, 0);
13554
13790
  lines.push("## Highlights");
13555
13791
  lines.push("");
@@ -13695,7 +13931,8 @@ async function validateSecurity(options) {
13695
13931
  try {
13696
13932
  execSync3("npm audit --audit-level=high 2>/dev/null", {
13697
13933
  encoding: "utf-8",
13698
- stdio: ["pipe", "pipe", "pipe"]
13934
+ stdio: ["pipe", "pipe", "pipe"],
13935
+ timeout: CLI_SUBPROCESS_TIMEOUTS.ghCommandMs
13699
13936
  });
13700
13937
  } catch {
13701
13938
  findings.push({
@@ -13718,7 +13955,11 @@ async function validateSecurity(options) {
13718
13955
  try {
13719
13956
  const result = execSync3(
13720
13957
  'git diff HEAD~10..HEAD -- "*.ts" "*.js" | grep -iE "(api[_-]?key|secret|password|token)" | head -5',
13721
- { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
13958
+ {
13959
+ encoding: "utf-8",
13960
+ stdio: ["pipe", "pipe", "pipe"],
13961
+ timeout: CLI_SUBPROCESS_TIMEOUTS.ghCommandMs
13962
+ }
13722
13963
  );
13723
13964
  if (result.trim()) {
13724
13965
  findings.push({
@@ -13745,10 +13986,11 @@ async function validateArchitecture2(options) {
13745
13986
  try {
13746
13987
  const result = execSync3("npx nexus-agents fitness-audit --format=json 2>/dev/null", {
13747
13988
  encoding: "utf-8",
13748
- stdio: ["pipe", "pipe", "pipe"]
13989
+ stdio: ["pipe", "pipe", "pipe"],
13990
+ timeout: CLI_SUBPROCESS_TIMEOUTS.releaseValidateMs
13749
13991
  });
13750
13992
  const audit = JSON.parse(result);
13751
- const fitnessScore = audit.score || 0;
13993
+ const fitnessScore = typeof audit["score"] === "number" ? audit["score"] : 0;
13752
13994
  if (fitnessScore < 90) {
13753
13995
  findings.push({
13754
13996
  severity: "error",
@@ -13765,13 +14007,14 @@ async function validateArchitecture2(options) {
13765
14007
  description: "Fitness score meets release threshold."
13766
14008
  });
13767
14009
  }
13768
- if (audit.findings) {
13769
- for (const finding of audit.findings) {
14010
+ const auditFindings = audit["findings"];
14011
+ if (Array.isArray(auditFindings)) {
14012
+ for (const finding of auditFindings) {
13770
14013
  findings.push({
13771
14014
  severity: "info",
13772
14015
  category: "architecture",
13773
- title: finding.message || "Fitness finding",
13774
- description: finding.suggestion || ""
14016
+ title: typeof finding["message"] === "string" ? finding["message"] : "Fitness finding",
14017
+ description: typeof finding["suggestion"] === "string" ? finding["suggestion"] : ""
13775
14018
  });
13776
14019
  }
13777
14020
  }
@@ -14080,7 +14323,7 @@ function getBlueskyConfig() {
14080
14323
  }
14081
14324
  async function loadAtproto() {
14082
14325
  try {
14083
- const mod = await import("./dist-Y5F6UM2N.js");
14326
+ const mod = await import("./dist-H5XNXVAV.js");
14084
14327
  return { AtpAgent: mod.AtpAgent, RichText: mod.RichText };
14085
14328
  } catch {
14086
14329
  return void 0;
@@ -14146,9 +14389,9 @@ function generateBlogPost(options) {
14146
14389
  return parseConventionalCommit(line.substring(0, spaceIndex), line.substring(spaceIndex + 1));
14147
14390
  });
14148
14391
  const categories = groupCommitsByCategory(parsedCommits);
14149
- const featCount = categories.find((c) => c.name === "Added")?.commits.length || 0;
14150
- const fixCount = categories.find((c) => c.name === "Fixed")?.commits.length || 0;
14151
- const refactorCount = categories.find((c) => c.name === "Changed")?.commits.length || 0;
14392
+ const featCount = categories.find((c) => c.name === "Added")?.commits.length ?? 0;
14393
+ const fixCount = categories.find((c) => c.name === "Fixed")?.commits.length ?? 0;
14394
+ const refactorCount = categories.find((c) => c.name === "Changed")?.commits.length ?? 0;
14152
14395
  const frontmatter = {
14153
14396
  title: `nexus-agents v${options.version} Released: Multi-Agent Orchestration Improvements`,
14154
14397
  date: today,
@@ -14413,7 +14656,7 @@ async function releaseAnnounceCommand(args) {
14413
14656
 
14414
14657
  // src/cli/scaffold.ts
14415
14658
  import * as fs15 from "fs";
14416
- import * as path20 from "path";
14659
+ import * as path21 from "path";
14417
14660
 
14418
14661
  // src/cli/scaffold-templates.ts
14419
14662
  function toolImportsAndSchema(name, pascal) {
@@ -14440,7 +14683,7 @@ import { createSecureHandler, type HandlerContext } from '../middleware/secure-h
14440
14683
  */
14441
14684
  export const ${pascal}InputSchema = z.object({
14442
14685
  input: z.string().min(1).describe('Primary input for ${name} operation'),
14443
- options: z.record(z.unknown()).optional().describe('Additional options'),
14686
+ options: z.record(z.string(), z.unknown()).optional().describe('Additional options'),
14444
14687
  });
14445
14688
 
14446
14689
  export type ${pascal}Input = z.infer<typeof ${pascal}InputSchema>;
@@ -14749,8 +14992,8 @@ ${lines}`;
14749
14992
  function writeFiles(files) {
14750
14993
  const createdPaths = [];
14751
14994
  for (const file of files) {
14752
- const fullPath = path20.resolve(process.cwd(), file.path);
14753
- const dir = path20.dirname(fullPath);
14995
+ const fullPath = path21.resolve(process.cwd(), file.path);
14996
+ const dir = path21.dirname(fullPath);
14754
14997
  fs15.mkdirSync(dir, { recursive: true });
14755
14998
  if (fs15.existsSync(fullPath)) {
14756
14999
  return {
@@ -14865,7 +15108,7 @@ function getCliRole(cli, category) {
14865
15108
  ["devops", "gemini"],
14866
15109
  ["research", "claude"],
14867
15110
  ["documentation", "claude"],
14868
- ["exploration", "claude"]
15111
+ ["exploration", "codex"]
14869
15112
  ]);
14870
15113
  return cli === secondaryMap.get(category) ? "secondary" : "other";
14871
15114
  }
@@ -14945,7 +15188,10 @@ function buildDetails(taskCount, counts, nonZero, score, passed) {
14945
15188
  function runE2EEval(config, logger17) {
14946
15189
  const log = logger17 ?? createLogger({ component: "e2e-eval" });
14947
15190
  const taskCount = config?.taskCount ?? 50;
14948
- if (config?.resetStore !== false) resetOutcomeStore();
15191
+ if (config?.resetStore !== false) {
15192
+ resetOutcomeStore();
15193
+ setOutcomeStore(new OutcomeStore());
15194
+ }
14949
15195
  const counts = generateOutcomes(taskCount);
14950
15196
  log.info("E2E eval: outcomes recorded", { taskCount });
14951
15197
  const { bonuses, nonZeroCount } = checkAdaptiveBonuses();
@@ -15567,6 +15813,7 @@ COMMANDS:
15567
15813
  visualize Generate Mermaid diagrams and ASCII dashboards (architecture, swarm, flow)
15568
15814
  capabilities Show model capabilities matrix (modalities, tools, features)
15569
15815
  status At-a-glance project health dashboard (fitness, adapters, version)
15816
+ health Swarm health metrics dashboard (utilization, routing accuracy, failures)
15570
15817
  auth Manage MCP authentication tokens (init, show, rotate)
15571
15818
 
15572
15819
  OPTIONS:
@@ -15887,6 +16134,8 @@ EXAMPLES:
15887
16134
  nexus-agents capabilities list --format=json Output capabilities as JSON
15888
16135
  nexus-agents status Show project health dashboard
15889
16136
  nexus-agents status --format=json Output status as JSON
16137
+ nexus-agents health Show swarm health metrics
16138
+ nexus-agents health --format=json Output health metrics as JSON
15890
16139
  nexus-agents auth init Generate initial auth token
15891
16140
  nexus-agents auth show Check token status
15892
16141
  nexus-agents auth rotate Rotate to new token
@@ -16033,6 +16282,33 @@ var PARSE_ARGS_CONFIG = {
16033
16282
  type: "boolean",
16034
16283
  default: false
16035
16284
  },
16285
+ concurrency: {
16286
+ type: "string",
16287
+ default: "1"
16288
+ },
16289
+ mcp: {
16290
+ type: "boolean",
16291
+ default: false
16292
+ },
16293
+ // SWE-bench evaluate options
16294
+ predictions: {
16295
+ type: "string"
16296
+ },
16297
+ "cache-level": {
16298
+ type: "string",
16299
+ default: "env"
16300
+ },
16301
+ "max-workers": {
16302
+ type: "string",
16303
+ default: "4"
16304
+ },
16305
+ "run-id": {
16306
+ type: "string"
16307
+ },
16308
+ "output-dir": {
16309
+ type: "string",
16310
+ default: "./logs/run_evaluation"
16311
+ },
16036
16312
  // Learning-metrics command options
16037
16313
  period: {
16038
16314
  type: "string",
@@ -16138,7 +16414,8 @@ function isValidCommand(value) {
16138
16414
  "warm-up",
16139
16415
  "e2e-eval",
16140
16416
  "routing-ab",
16141
- "memory-eval"
16417
+ "memory-eval",
16418
+ "health"
16142
16419
  ];
16143
16420
  return validCommands.includes(value);
16144
16421
  }
@@ -16453,6 +16730,10 @@ function registerResearchTools(ctx) {
16453
16730
  ...researchDeps,
16454
16731
  rateLimiter: ctx.rateLimiterFactory.getForTool("research_catalog_review")
16455
16732
  });
16733
+ registerResearchSynthesizeTool(ctx.server, {
16734
+ ...researchDeps,
16735
+ rateLimiter: ctx.rateLimiterFactory.getForTool("research_synthesize")
16736
+ });
16456
16737
  }
16457
16738
  function registerMemoryTools(ctx) {
16458
16739
  const memoryDeps = {
@@ -16736,7 +17017,7 @@ function logFinalEventBusStats(logger17) {
16736
17017
  // src/cli-orchestrator.ts
16737
17018
  import * as readline2 from "readline";
16738
17019
  function runOrchestratorRepl(options, logger17) {
16739
- return new Promise((resolve11) => {
17020
+ return new Promise((resolve12) => {
16740
17021
  const rl = readline2.createInterface({
16741
17022
  input: process.stdin,
16742
17023
  output: process.stdout,
@@ -16772,7 +17053,7 @@ function runOrchestratorRepl(options, logger17) {
16772
17053
  });
16773
17054
  rl.on("close", () => {
16774
17055
  logger17.info("Orchestrator REPL closed");
16775
- resolve11();
17056
+ resolve12();
16776
17057
  });
16777
17058
  });
16778
17059
  }
@@ -17919,7 +18200,7 @@ function initializeFeedbackIntegration(options) {
17919
18200
 
17920
18201
  // src/cli-server-rest.ts
17921
18202
  import * as fs16 from "fs";
17922
- import * as path21 from "path";
18203
+ import * as path22 from "path";
17923
18204
  import * as crypto3 from "crypto";
17924
18205
  import { homedir as homedir3 } from "os";
17925
18206
  var DEFAULT_REST_CONFIG = {
@@ -17955,12 +18236,12 @@ function extractRestConfig(_config) {
17955
18236
  var AUTH_DIR = "auth";
17956
18237
  var API_KEY_FILE = "rest-api-key";
17957
18238
  function getAuthDir(baseDir) {
17958
- const home = baseDir ?? path21.join(homedir3(), ".nexus-agents");
17959
- return path21.join(home, AUTH_DIR);
18239
+ const home = baseDir ?? path22.join(homedir3(), ".nexus-agents");
18240
+ return path22.join(home, AUTH_DIR);
17960
18241
  }
17961
18242
  function loadOrGenerateApiKey(logger17, baseDir) {
17962
18243
  const authDir = getAuthDir(baseDir);
17963
- const keyPath = path21.join(authDir, API_KEY_FILE);
18244
+ const keyPath = path22.join(authDir, API_KEY_FILE);
17964
18245
  if (fs16.existsSync(keyPath)) {
17965
18246
  const key2 = fs16.readFileSync(keyPath, "utf-8").trim();
17966
18247
  if (key2.length > 0) {
@@ -18611,31 +18892,32 @@ async function handleOrchestrateCommand(args) {
18611
18892
  });
18612
18893
  process.exit(exitCode === 0 ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
18613
18894
  }
18614
- async function handleSweBenchCommand(args) {
18615
- const subArgs = [];
18616
- const subcommand = args.positionals[1] ?? "run";
18617
- subArgs.push(subcommand);
18618
- if (args.options.variant !== void 0) {
18619
- subArgs.push(`--variant=${args.options.variant}`);
18620
- }
18621
- if (args.options.limit !== void 0) {
18622
- subArgs.push(`--limit=${String(args.options.limit)}`);
18623
- }
18624
- if (args.options.output !== void 0) {
18625
- subArgs.push(`--output=${args.options.output}`);
18626
- }
18627
- if (args.options.resume) {
18628
- subArgs.push("--resume");
18629
- }
18630
- if (args.options.verbose) {
18631
- subArgs.push("--verbose");
18632
- }
18633
- if (args.options.instance !== void 0) {
18634
- for (const inst of args.options.instance) {
18635
- subArgs.push(`--instance=${inst}`);
18636
- }
18895
+ function buildSweBenchSubArgs(args) {
18896
+ const opts = args.options;
18897
+ const subArgs = [args.positionals[1] ?? "run"];
18898
+ const valueFlags = [
18899
+ ["variant", "variant"],
18900
+ ["limit", "limit"],
18901
+ ["output", "output"],
18902
+ ["concurrency", "concurrency"],
18903
+ ["predictions", "predictions"],
18904
+ ["cacheLevel", "cache-level"],
18905
+ ["maxWorkers", "max-workers"],
18906
+ ["runId", "run-id"],
18907
+ ["outputDir", "output-dir"]
18908
+ ];
18909
+ for (const [key, flag] of valueFlags) {
18910
+ const val = opts[key];
18911
+ if (val !== void 0) subArgs.push(`--${flag}=${String(val)}`);
18637
18912
  }
18638
- const exitCode = await sweBenchCommand(subArgs);
18913
+ if (opts.resume) subArgs.push("--resume");
18914
+ if (opts.verbose) subArgs.push("--verbose");
18915
+ if (opts.mcp === true) subArgs.push("--mcp");
18916
+ for (const inst of opts.instance ?? []) subArgs.push(`--instance=${inst}`);
18917
+ return subArgs;
18918
+ }
18919
+ async function handleSweBenchCommand(args) {
18920
+ const exitCode = await sweBenchCommand(buildSweBenchSubArgs(args));
18639
18921
  process.exit(exitCode === 0 ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
18640
18922
  }
18641
18923
 
@@ -18827,7 +19109,7 @@ async function handleVerifyCommand(args) {
18827
19109
  async function handleDoctorCommand(args) {
18828
19110
  const exitCode = await doctorCommand({ fix: args.options.fix });
18829
19111
  if (args.options.deep) {
18830
- const { runDeepDiagnostics: runDeepDiagnostics2, formatDeepDiagnostics: formatDeepDiagnostics2 } = await import("./doctor-deep-I2J5CRFG.js");
19112
+ const { runDeepDiagnostics: runDeepDiagnostics2, formatDeepDiagnostics: formatDeepDiagnostics2 } = await import("./doctor-deep-BDE2PHVX.js");
18831
19113
  const diag = runDeepDiagnostics2();
18832
19114
  process.stdout.write(formatDeepDiagnostics2(diag) + "\n");
18833
19115
  }
@@ -19079,13 +19361,13 @@ function handleScaffoldCommand(args) {
19079
19361
 
19080
19362
  // src/cli/visualize-summary.ts
19081
19363
  import * as fs17 from "fs";
19082
- import * as path22 from "path";
19364
+ import * as path23 from "path";
19083
19365
  import { fileURLToPath } from "url";
19084
19366
  function findPackageRoot(startDir) {
19085
19367
  let dir = startDir;
19086
19368
  for (let i = 0; i < 5; i++) {
19087
- if (fs17.existsSync(path22.join(dir, "package.json"))) return dir;
19088
- const parent = path22.dirname(dir);
19369
+ if (fs17.existsSync(path23.join(dir, "package.json"))) return dir;
19370
+ const parent = path23.dirname(dir);
19089
19371
  if (parent === dir) break;
19090
19372
  dir = parent;
19091
19373
  }
@@ -19096,7 +19378,7 @@ function countFiles(dir, pattern) {
19096
19378
  let count = 0;
19097
19379
  for (const entry of fs17.readdirSync(dir, { withFileTypes: true })) {
19098
19380
  if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "dist") {
19099
- count += countFiles(path22.join(dir, entry.name), pattern);
19381
+ count += countFiles(path23.join(dir, entry.name), pattern);
19100
19382
  } else if (entry.isFile() && pattern.test(entry.name)) {
19101
19383
  count++;
19102
19384
  }
@@ -19105,7 +19387,7 @@ function countFiles(dir, pattern) {
19105
19387
  }
19106
19388
  function readVersion(pkgRoot) {
19107
19389
  try {
19108
- const raw = fs17.readFileSync(path22.join(pkgRoot, "package.json"), "utf-8");
19390
+ const raw = fs17.readFileSync(path23.join(pkgRoot, "package.json"), "utf-8");
19109
19391
  const pkg = JSON.parse(raw);
19110
19392
  return pkg.version ?? "unknown";
19111
19393
  } catch {
@@ -19126,13 +19408,13 @@ var LAYER_DIRS = [
19126
19408
  ];
19127
19409
  function gatherSystemSummary() {
19128
19410
  const thisFile = fileURLToPath(import.meta.url);
19129
- const pkgRoot = findPackageRoot(path22.dirname(thisFile));
19130
- const srcDir = path22.resolve(pkgRoot, "src");
19411
+ const pkgRoot = findPackageRoot(path23.dirname(thisFile));
19412
+ const srcDir = path23.resolve(pkgRoot, "src");
19131
19413
  const allTs = countFiles(srcDir, /\.ts$/);
19132
19414
  const testTs = countFiles(srcDir, /\.test\.ts$/);
19133
19415
  const layers = LAYER_DIRS.map(({ name, dir }) => ({
19134
19416
  name,
19135
- files: countFiles(path22.join(srcDir, dir), /\.ts$/)
19417
+ files: countFiles(path23.join(srcDir, dir), /\.ts$/)
19136
19418
  })).filter((l) => l.files > 0);
19137
19419
  return {
19138
19420
  version: readVersion(pkgRoot),
@@ -20281,7 +20563,7 @@ function handleStatusCommand2(args) {
20281
20563
 
20282
20564
  // src/cli/scenario-command.ts
20283
20565
  import { readdir as readdir4 } from "fs/promises";
20284
- import { join as join19, resolve as resolve10 } from "path";
20566
+ import { join as join19, resolve as resolve11 } from "path";
20285
20567
 
20286
20568
  // src/testing/e2e/scenario-runner.ts
20287
20569
  import { readFile as readFile6 } from "fs/promises";
@@ -20412,9 +20694,9 @@ function checkCircularDependencies(workflow) {
20412
20694
  for (const step of workflow.steps) {
20413
20695
  stepMap.set(step.id, step);
20414
20696
  }
20415
- const visit = (stepId, path23) => {
20697
+ const visit = (stepId, path24) => {
20416
20698
  if (visiting.has(stepId)) {
20417
- errors.push(`Circular dependency detected: ${[...path23, stepId].join(" -> ")}`);
20699
+ errors.push(`Circular dependency detected: ${[...path24, stepId].join(" -> ")}`);
20418
20700
  return false;
20419
20701
  }
20420
20702
  if (visited.has(stepId)) return true;
@@ -20422,7 +20704,7 @@ function checkCircularDependencies(workflow) {
20422
20704
  const step = stepMap.get(stepId);
20423
20705
  if (step?.dependsOn) {
20424
20706
  for (const dep of step.dependsOn) {
20425
- if (!visit(dep, [...path23, stepId])) {
20707
+ if (!visit(dep, [...path24, stepId])) {
20426
20708
  return false;
20427
20709
  }
20428
20710
  }
@@ -20441,7 +20723,7 @@ function checkCircularDependencies(workflow) {
20441
20723
  var defaultStubFactory = {
20442
20724
  createAgentStub(agentType, action) {
20443
20725
  return async (inputs) => {
20444
- await new Promise((resolve11) => setTimeout(resolve11, 10));
20726
+ await new Promise((resolve12) => setTimeout(resolve12, 10));
20445
20727
  return {
20446
20728
  stepId: `${agentType}-${action}`,
20447
20729
  status: "success",
@@ -20466,8 +20748,8 @@ var ScenarioRunner = class {
20466
20748
  /**
20467
20749
  * Load a scenario fixture from a YAML file.
20468
20750
  */
20469
- async loadFixture(path23) {
20470
- const content = await readFile6(path23, "utf-8");
20751
+ async loadFixture(path24) {
20752
+ const content = await readFile6(path24, "utf-8");
20471
20753
  const data = yaml7.parse(content);
20472
20754
  return ScenarioFixtureSchema.parse(data);
20473
20755
  }
@@ -20600,7 +20882,7 @@ function createScenarioRunner(stubFactory) {
20600
20882
  }
20601
20883
 
20602
20884
  // src/cli/scenario-command.ts
20603
- var FIXTURES_DIR = resolve10(import.meta.dirname, "../testing/e2e/fixtures");
20885
+ var FIXTURES_DIR = resolve11(import.meta.dirname, "../testing/e2e/fixtures");
20604
20886
  var SCENARIO_SUFFIX = ".scenario.yaml";
20605
20887
  async function listScenarios() {
20606
20888
  try {
@@ -20681,6 +20963,137 @@ async function handleScenarioCommand(args) {
20681
20963
  process.exit(EXIT_CODES.SERVER_START_FAILED);
20682
20964
  }
20683
20965
 
20966
+ // src/cli/health-command.ts
20967
+ function collectHealth() {
20968
+ const report = generateWeatherReport({});
20969
+ return {
20970
+ swarmHealth: report.swarmHealth,
20971
+ overallSuccessRate: report.overall.successRate,
20972
+ totalTasks: report.overall.totalTasks,
20973
+ failureBreakdown: report.failureBreakdown ?? [],
20974
+ cliCount: report.cliWeather.length,
20975
+ cliHealth: report.cliWeather.map(toCliSummary),
20976
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
20977
+ };
20978
+ }
20979
+ function toCliSummary(cw) {
20980
+ return {
20981
+ cli: cw.cli,
20982
+ successRate: cw.successRate,
20983
+ totalTasks: cw.totalTasks,
20984
+ avgDurationMs: cw.avgDurationMs
20985
+ };
20986
+ }
20987
+ function renderMetricBar(value, max) {
20988
+ const width = 20;
20989
+ const filled = Math.round(value / max * width);
20990
+ const bar = "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
20991
+ return bar;
20992
+ }
20993
+ function renderSwarmMetrics(w, health) {
20994
+ const c = colors;
20995
+ const pct = (v) => `${(v * 100).toFixed(1)}%`;
20996
+ w(` ${c.bold}Swarm Health Metrics${c.reset}
20997
+ `);
20998
+ w(
20999
+ ` Agent Utilization: ${renderMetricBar(health.agentUtilization, 1)} ${pct(health.agentUtilization)}
21000
+ `
21001
+ );
21002
+ w(
21003
+ ` Collaboration Efficiency:${renderMetricBar(health.collaborationEfficiency, 1)} ${pct(health.collaborationEfficiency)}
21004
+ `
21005
+ );
21006
+ w(
21007
+ ` Routing Accuracy: ${renderMetricBar(health.routingAccuracy, 1)} ${pct(health.routingAccuracy)}
21008
+ `
21009
+ );
21010
+ w(` Weekly Regret: ${health.weeklyRegret.toFixed(3)}
21011
+ `);
21012
+ w(` Adaptation Speed: ${String(health.adaptationSpeed)} tasks
21013
+ `);
21014
+ w(` Observed Categories: ${String(health.observedCategories)}
21015
+ `);
21016
+ w(` Observed Roles: ${String(health.observedRoles)}
21017
+ `);
21018
+ w("\n");
21019
+ }
21020
+ function renderCliHealth(w, entries) {
21021
+ const c = colors;
21022
+ w(` ${c.bold}Per-CLI Performance${c.reset}
21023
+ `);
21024
+ for (const entry of entries) {
21025
+ const rateColor = entry.successRate >= 0.8 ? c.green : entry.successRate >= 0.6 ? c.yellow : c.red;
21026
+ const pct = `${(entry.successRate * 100).toFixed(0)}%`;
21027
+ const dur = entry.avgDurationMs >= 1e3 ? `${(entry.avgDurationMs / 1e3).toFixed(1)}s` : `${String(Math.round(entry.avgDurationMs))}ms`;
21028
+ w(
21029
+ ` ${entry.cli.padEnd(12)} ${rateColor}${pct.padStart(4)}${c.reset} ${String(entry.totalTasks).padStart(5)} tasks ${c.dim}avg ${dur}${c.reset}
21030
+ `
21031
+ );
21032
+ }
21033
+ w("\n");
21034
+ }
21035
+ function renderFailureBreakdown(w, entries) {
21036
+ const c = colors;
21037
+ if (entries.length === 0) {
21038
+ w(` ${c.green}No failures recorded${c.reset}
21039
+
21040
+ `);
21041
+ return;
21042
+ }
21043
+ w(` ${c.bold}Failure Breakdown${c.reset}
21044
+ `);
21045
+ for (const entry of entries) {
21046
+ const color2 = entry.category === "unknown" ? c.yellow : c.dim;
21047
+ w(
21048
+ ` ${color2}${entry.category.padEnd(22)}${c.reset} ${String(entry.count).padStart(4)} (${String(entry.percentage)}%)
21049
+ `
21050
+ );
21051
+ }
21052
+ w("\n");
21053
+ }
21054
+ function renderTable2(health) {
21055
+ const c = colors;
21056
+ const s = symbols;
21057
+ const w = process.stdout.write.bind(process.stdout);
21058
+ w(`
21059
+ ${c.bold}nexus-agents${c.reset}`);
21060
+ w(` ${c.dim}\u2014 Swarm Health Dashboard${c.reset}
21061
+
21062
+ `);
21063
+ const rateColor = health.overallSuccessRate >= 0.8 ? c.green : health.overallSuccessRate >= 0.6 ? c.yellow : c.red;
21064
+ const rateSym = health.overallSuccessRate >= 0.8 ? s.check : s.warn;
21065
+ const pctStr = `${(health.overallSuccessRate * 100).toFixed(1)}%`;
21066
+ w(` Success Rate: ${rateColor}${pctStr}${c.reset} ${rateSym}
21067
+ `);
21068
+ w(` Total Tasks: ${c.cyan}${String(health.totalTasks)}${c.reset}
21069
+ `);
21070
+ w(` Active CLIs: ${c.cyan}${String(health.cliCount)}${c.reset}
21071
+
21072
+ `);
21073
+ if (health.cliHealth.length > 0) {
21074
+ renderCliHealth(w, health.cliHealth);
21075
+ }
21076
+ if (health.swarmHealth !== void 0) {
21077
+ renderSwarmMetrics(w, health.swarmHealth);
21078
+ } else {
21079
+ w(` ${c.dim}No swarm metrics available (requires task history)${c.reset}
21080
+
21081
+ `);
21082
+ }
21083
+ renderFailureBreakdown(w, health.failureBreakdown);
21084
+ }
21085
+ function renderJson2(health) {
21086
+ process.stdout.write(JSON.stringify(health, null, 2) + "\n");
21087
+ }
21088
+ function handleHealthCommand(args) {
21089
+ const health = collectHealth();
21090
+ if (args.options.format === "json") {
21091
+ renderJson2(health);
21092
+ } else {
21093
+ renderTable2(health);
21094
+ }
21095
+ }
21096
+
20684
21097
  // src/cli-commands.ts
20685
21098
  function printHelp() {
20686
21099
  process.stdout.write(HELP_TEXT + "\n");
@@ -20714,7 +21127,9 @@ var SYNC_COMMAND_HANDLERS = {
20714
21127
  "warm-up": handleWarmUpCommand,
20715
21128
  "e2e-eval": handleE2EEvalCommand,
20716
21129
  "routing-ab": handleRoutingABCommand,
20717
- "memory-eval": handleMemoryEvalCommand
21130
+ "memory-eval": handleMemoryEvalCommand,
21131
+ // Issue #1403: Health Command
21132
+ health: handleHealthCommand
20718
21133
  };
20719
21134
  function handleSyncCommand(args) {
20720
21135
  if (args.command === "help") {
@@ -20769,6 +21184,7 @@ async function handleAsyncCommand(args) {
20769
21184
  }
20770
21185
  }
20771
21186
  async function dispatchCommand(args) {
21187
+ initDataDirectories();
20772
21188
  if (!handleSyncCommand(args)) {
20773
21189
  await handleAsyncCommand(args);
20774
21190
  }
@@ -21051,16 +21467,28 @@ function parseSweBenchVariant(value) {
21051
21467
  }
21052
21468
  return void 0;
21053
21469
  }
21470
+ var SWE_BENCH_STRING_MAPPINGS = [
21471
+ ["predictions", "predictions"],
21472
+ ["cache-level", "cacheLevel"],
21473
+ ["max-workers", "maxWorkers"],
21474
+ ["run-id", "runId"],
21475
+ ["output-dir", "outputDir"]
21476
+ ];
21054
21477
  function buildSweBenchOptions(values) {
21055
21478
  const variant = parseSweBenchVariant(values.variant);
21056
21479
  const limit = parseNumericOption(values.limit);
21057
- const base = {
21058
- resume: values.resume
21059
- };
21480
+ const concurrency = parseNumericOption(values.concurrency);
21481
+ const base = { resume: values.resume };
21060
21482
  if (variant !== void 0) base.variant = variant;
21061
21483
  if (limit !== void 0) base.limit = limit;
21484
+ if (concurrency !== void 0) base.concurrency = concurrency;
21485
+ if (values.mcp) base.mcp = true;
21486
+ for (const [src, tgt] of SWE_BENCH_STRING_MAPPINGS) {
21487
+ const val = values[src];
21488
+ if (val !== void 0) base[tgt] = val;
21489
+ }
21062
21490
  if (values.instance !== void 0 && values.instance.length > 0) {
21063
- return { ...base, instance: values.instance };
21491
+ base.instance = values.instance;
21064
21492
  }
21065
21493
  return base;
21066
21494
  }