nexus-agents 2.59.0 → 2.61.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.
package/dist/cli.js CHANGED
@@ -16,7 +16,7 @@ import "./chunk-6QU4DJYW.js";
16
16
  import {
17
17
  setupCommandAsync,
18
18
  verifyCommand
19
- } from "./chunk-ZOQQGA3L.js";
19
+ } from "./chunk-KNAPTURC.js";
20
20
  import "./chunk-QGZBCD2A.js";
21
21
  import {
22
22
  AuthHandler,
@@ -142,7 +142,8 @@ import {
142
142
  validateCommand,
143
143
  validateWorkflow,
144
144
  wrapInMarkdownFence
145
- } from "./chunk-V2Z7EHSY.js";
145
+ } from "./chunk-TRWIEUI2.js";
146
+ import "./chunk-ED6VQWNG.js";
146
147
  import {
147
148
  resolveToken
148
149
  } from "./chunk-EZXOJZYE.js";
@@ -150,6 +151,7 @@ import {
150
151
  CATEGORY_DISPLAY_NAMES,
151
152
  DEFAULT_PR_REVIEW_CONFIG
152
153
  } from "./chunk-X2M7OF27.js";
154
+ import "./chunk-JKDHWOQL.js";
153
155
  import {
154
156
  DEFAULT_VOTE_TIMEOUT_MS,
155
157
  THRESHOLD_MAP,
@@ -161,7 +163,7 @@ import {
161
163
  registerConsensusVoteTool,
162
164
  shutdownToolMemory,
163
165
  validateTimeout
164
- } from "./chunk-L3NHOUEX.js";
166
+ } from "./chunk-FEWWXGFE.js";
165
167
  import "./chunk-YU4NABXM.js";
166
168
  import {
167
169
  loadPapersRegistry,
@@ -181,9 +183,9 @@ import "./chunk-V5CGWMYL.js";
181
183
  import "./chunk-BC3M4VLP.js";
182
184
  import "./chunk-AP2FD37C.js";
183
185
  import "./chunk-BQ4YXGGQ.js";
184
- import "./chunk-ED6VQWNG.js";
185
186
  import {
186
187
  CustomExpertDefinitionSchema,
188
+ DATA_SUBDIRECTORIES,
187
189
  MAX_SYSTEM_PROMPT_LENGTH,
188
190
  VALID_EXPERT_DOMAINS,
189
191
  VALID_EXPERT_TIERS,
@@ -199,11 +201,15 @@ import {
199
201
  loadConfig,
200
202
  runDoctor,
201
203
  validateNexusEnv
202
- } from "./chunk-7USAZET2.js";
204
+ } from "./chunk-NB6IYTMN.js";
203
205
  import {
204
206
  DEFAULTS
205
207
  } from "./chunk-H43PABG4.js";
206
208
  import "./chunk-NUBSJGQZ.js";
209
+ import {
210
+ getNexusDataDir,
211
+ nexusDataPath
212
+ } from "./chunk-FDNWRZNJ.js";
207
213
  import "./chunk-GJVHRJO2.js";
208
214
  import "./chunk-7Y36JLES.js";
209
215
  import {
@@ -216,7 +222,6 @@ import {
216
222
  } from "./chunk-633WH2ML.js";
217
223
  import "./chunk-EDGG3RQE.js";
218
224
  import "./chunk-PTGBJFSD.js";
219
- import "./chunk-JKDHWOQL.js";
220
225
  import {
221
226
  createAllAdapters,
222
227
  getAvailableClis,
@@ -1454,14 +1459,14 @@ ${colors.dim}Session ended.${colors.reset}
1454
1459
  });
1455
1460
  });
1456
1461
  rl.prompt();
1457
- return new Promise((resolve14) => {
1462
+ return new Promise((resolve15) => {
1458
1463
  rl.on("line", (line) => {
1459
1464
  void (async () => {
1460
1465
  try {
1461
1466
  const shouldExit = await processLine(line, session, logger17);
1462
1467
  if (shouldExit) {
1463
1468
  rl.close();
1464
- resolve14();
1469
+ resolve15();
1465
1470
  return;
1466
1471
  }
1467
1472
  } catch (error) {
@@ -1473,7 +1478,7 @@ ${colors.dim}Session ended.${colors.reset}
1473
1478
  })();
1474
1479
  });
1475
1480
  rl.on("close", () => {
1476
- resolve14();
1481
+ resolve15();
1477
1482
  });
1478
1483
  });
1479
1484
  }
@@ -4384,7 +4389,6 @@ async function orchestrateCommand(options) {
4384
4389
  // src/cli/session-commands.ts
4385
4390
  import * as fs3 from "fs";
4386
4391
  import * as path2 from "path";
4387
- import * as os from "os";
4388
4392
 
4389
4393
  // src/cli/session-storage-types.ts
4390
4394
  import { z } from "zod";
@@ -4827,7 +4831,7 @@ function createSessionStorage(config) {
4827
4831
 
4828
4832
  // src/cli/session-commands.ts
4829
4833
  function getDefaultDbPath() {
4830
- return path2.join(os.homedir(), ".nexus-agents", "sessions.db");
4834
+ return nexusDataPath("sessions.db");
4831
4835
  }
4832
4836
  function ensureDbDirectory(dbPath) {
4833
4837
  const dir = path2.dirname(dbPath);
@@ -10674,7 +10678,7 @@ function parseValidationArgs(positionals, format, verbose) {
10674
10678
  }
10675
10679
 
10676
10680
  // src/cli/swe-bench-command.ts
10677
- import * as os2 from "os";
10681
+ import * as os from "os";
10678
10682
  import * as path18 from "path";
10679
10683
  function runInfo(options) {
10680
10684
  console.log(`
@@ -10896,7 +10900,7 @@ function parseVariant(arg) {
10896
10900
  if (v === "lite" || v === "verified" || v === "full") return v;
10897
10901
  return "lite";
10898
10902
  }
10899
- var MAX_WORKERS_CAP = Math.min(Math.floor(os2.cpus().length * 0.75), 24);
10903
+ var MAX_WORKERS_CAP = Math.min(Math.floor(os.cpus().length * 0.75), 24);
10900
10904
  var VALID_CACHE_LEVELS = /* @__PURE__ */ new Set(["none", "base", "env", "instance"]);
10901
10905
  var BOOLEAN_FLAGS = {
10902
10906
  "--resume": "resume",
@@ -12825,7 +12829,7 @@ function writeResultAndExit(result) {
12825
12829
 
12826
12830
  // src/cli/hooks/hook-router.ts
12827
12831
  async function readStdin() {
12828
- return new Promise((resolve14, reject) => {
12832
+ return new Promise((resolve15, reject) => {
12829
12833
  let data = "";
12830
12834
  process.stdin.setEncoding("utf8");
12831
12835
  process.stdin.on("readable", () => {
@@ -12836,24 +12840,24 @@ async function readStdin() {
12836
12840
  }
12837
12841
  });
12838
12842
  process.stdin.on("end", () => {
12839
- resolve14(data);
12843
+ resolve15(data);
12840
12844
  });
12841
12845
  process.stdin.on("error", (err2) => {
12842
12846
  reject(err2);
12843
12847
  });
12844
12848
  if (process.stdin.isTTY) {
12845
- resolve14("");
12849
+ resolve15("");
12846
12850
  }
12847
12851
  });
12848
12852
  }
12849
12853
  async function readStdinWithTimeout(timeoutMs = 5e3) {
12850
- return new Promise((resolve14, reject) => {
12854
+ return new Promise((resolve15, reject) => {
12851
12855
  const timeout2 = setTimeout(() => {
12852
12856
  reject(new Error(`Stdin read timeout after ${String(timeoutMs)}ms`));
12853
12857
  }, timeoutMs);
12854
12858
  readStdin().then((data) => {
12855
12859
  clearTimeout(timeout2);
12856
- resolve14(data);
12860
+ resolve15(data);
12857
12861
  }).catch((err2) => {
12858
12862
  clearTimeout(timeout2);
12859
12863
  reject(err2 instanceof Error ? err2 : new Error(String(err2)));
@@ -12984,10 +12988,8 @@ function setStringOption(options, key, value) {
12984
12988
  }
12985
12989
 
12986
12990
  // src/cli/hooks/handlers/handler-utils.ts
12987
- import { homedir as homedir2 } from "os";
12988
- import { join as join13 } from "path";
12989
12991
  function getDefaultDbPath2() {
12990
- return join13(homedir2(), ".nexus-agents", "sessions.db");
12992
+ return nexusDataPath("sessions.db");
12991
12993
  }
12992
12994
  var HookEnvVars = {
12993
12995
  /** Override the default database path */
@@ -14171,23 +14173,23 @@ async function demoCommand(subcommand, args, options) {
14171
14173
 
14172
14174
  // src/governance/fitness-score.ts
14173
14175
  import { existsSync as existsSync12, readFileSync as readFileSync6, readdirSync, statSync } from "fs";
14174
- import { join as join14 } from "path";
14176
+ import { join as join12 } from "path";
14175
14177
  function findPkgRoot() {
14176
14178
  let dir = import.meta.dirname;
14177
14179
  for (let i = 0; i < 10; i++) {
14178
- const pkgPath = join14(dir, "package.json");
14180
+ const pkgPath = join12(dir, "package.json");
14179
14181
  if (existsSync12(pkgPath)) {
14180
14182
  const content = readFileSync6(pkgPath, "utf-8");
14181
14183
  if (content.includes('"nexus-agents"')) return dir;
14182
14184
  }
14183
- dir = join14(dir, "..");
14185
+ dir = join12(dir, "..");
14184
14186
  }
14185
- return join14(import.meta.dirname, "../..");
14187
+ return join12(import.meta.dirname, "../..");
14186
14188
  }
14187
14189
  var PKG_ROOT = findPkgRoot();
14188
- var SRC_ROOT = join14(PKG_ROOT, "src");
14189
- var REPO_ROOT = join14(PKG_ROOT, "../..");
14190
- var DOCS_ROOT = join14(REPO_ROOT, "docs");
14190
+ var SRC_ROOT = join12(PKG_ROOT, "src");
14191
+ var REPO_ROOT = join12(PKG_ROOT, "../..");
14192
+ var DOCS_ROOT = join12(REPO_ROOT, "docs");
14191
14193
  var DETERMINISM_EXCLUDES = [
14192
14194
  /\.test\.ts$/,
14193
14195
  /\.spec\.ts$/,
@@ -14198,7 +14200,7 @@ function countFiles(dir, pattern) {
14198
14200
  if (!existsSync12(dir)) return 0;
14199
14201
  let count = 0;
14200
14202
  for (const entry of readdirSync(dir)) {
14201
- const fullPath = join14(dir, entry);
14203
+ const fullPath = join12(dir, entry);
14202
14204
  const stat2 = statSync(fullPath);
14203
14205
  if (stat2.isDirectory() && !entry.startsWith(".")) {
14204
14206
  count += countFiles(fullPath, pattern);
@@ -14223,7 +14225,7 @@ function countPatternInDir(dir, filePattern, contentPattern, excludePatterns) {
14223
14225
  if (!existsSync12(dir)) return 0;
14224
14226
  let count = 0;
14225
14227
  for (const entry of readdirSync(dir)) {
14226
- const fullPath = join14(dir, entry);
14228
+ const fullPath = join12(dir, entry);
14227
14229
  const stat2 = statSync(fullPath);
14228
14230
  if (stat2.isDirectory() && !entry.startsWith(".") && entry !== "node_modules") {
14229
14231
  count += countPatternInDir(fullPath, filePattern, contentPattern, excludePatterns);
@@ -14313,7 +14315,7 @@ var FitnessScoreCalculator = class {
14313
14315
  checkCanonicalPaths() {
14314
14316
  const findings = [];
14315
14317
  let score = 20;
14316
- const routerCount = countFiles(join14(SRC_ROOT, "cli-adapters"), /router\.ts$/);
14318
+ const routerCount = countFiles(join12(SRC_ROOT, "cli-adapters"), /router\.ts$/);
14317
14319
  const ROUTER_COUNT_THRESHOLD = 6;
14318
14320
  if (routerCount > ROUTER_COUNT_THRESHOLD) {
14319
14321
  const excess = routerCount - ROUTER_COUNT_THRESHOLD;
@@ -14329,7 +14331,7 @@ var FitnessScoreCalculator = class {
14329
14331
  )
14330
14332
  );
14331
14333
  }
14332
- if (existsSync12(join14(SRC_ROOT, "cli-adapters/composite-router.ts"))) {
14334
+ if (existsSync12(join12(SRC_ROOT, "cli-adapters/composite-router.ts"))) {
14333
14335
  score += 2;
14334
14336
  } else {
14335
14337
  score -= 3;
@@ -14347,7 +14349,7 @@ var FitnessScoreCalculator = class {
14347
14349
  }
14348
14350
  /** Sub-check for IOrchestrator interface and adapter wiring. */
14349
14351
  checkOrchestratorInterface(score, findings) {
14350
- const orchPath = join14(SRC_ROOT, "core/types/orchestrator.ts");
14352
+ const orchPath = join12(SRC_ROOT, "core/types/orchestrator.ts");
14351
14353
  if (existsSync12(orchPath) && fileContains(orchPath, /interface IOrchestrator/)) {
14352
14354
  score += 3;
14353
14355
  } else {
@@ -14356,7 +14358,7 @@ var FitnessScoreCalculator = class {
14356
14358
  this.finding("canonicalPaths", "warning", "No IOrchestrator interface in core/types", 2)
14357
14359
  );
14358
14360
  }
14359
- const adapterPath = join14(SRC_ROOT, "orchestration/orchestrator-adapters.ts");
14361
+ const adapterPath = join12(SRC_ROOT, "orchestration/orchestrator-adapters.ts");
14360
14362
  if (existsSync12(adapterPath) && fileContains(adapterPath, /TechLeadAdapter|PuppeteerAdapter/)) {
14361
14363
  score += 2;
14362
14364
  }
@@ -14446,7 +14448,7 @@ var FitnessScoreCalculator = class {
14446
14448
  } else if (randomCount === 0) {
14447
14449
  score += 2;
14448
14450
  }
14449
- if (existsSync12(join14(SRC_ROOT, "core/random-provider.ts"))) {
14451
+ if (existsSync12(join12(SRC_ROOT, "core/random-provider.ts"))) {
14450
14452
  score += 1;
14451
14453
  }
14452
14454
  const randomUsage = countPatternInDir(
@@ -14480,7 +14482,7 @@ var FitnessScoreCalculator = class {
14480
14482
  )
14481
14483
  );
14482
14484
  }
14483
- if (existsSync12(join14(SRC_ROOT, "core/time-provider.ts"))) {
14485
+ if (existsSync12(join12(SRC_ROOT, "core/time-provider.ts"))) {
14484
14486
  score += 1;
14485
14487
  }
14486
14488
  const timeUsage = countPatternInDir(
@@ -14498,7 +14500,7 @@ var FitnessScoreCalculator = class {
14498
14500
  checkObservability() {
14499
14501
  const findings = [];
14500
14502
  let score = 15;
14501
- if (existsSync12(join14(SRC_ROOT, "observability/swarm-observer.ts"))) {
14503
+ if (existsSync12(join12(SRC_ROOT, "observability/swarm-observer.ts"))) {
14502
14504
  score += 3;
14503
14505
  } else {
14504
14506
  score -= 3;
@@ -14512,7 +14514,7 @@ var FitnessScoreCalculator = class {
14512
14514
  )
14513
14515
  );
14514
14516
  }
14515
- if (existsSync12(join14(SRC_ROOT, "core/trace.ts"))) {
14517
+ if (existsSync12(join12(SRC_ROOT, "core/trace.ts"))) {
14516
14518
  score += 2;
14517
14519
  }
14518
14520
  const loggerCount = countPatternInDir(SRC_ROOT, /\.ts$/, /createLogger\(/g);
@@ -14528,7 +14530,7 @@ var FitnessScoreCalculator = class {
14528
14530
  )
14529
14531
  );
14530
14532
  }
14531
- if (existsSync12(join14(SRC_ROOT, "audit"))) {
14533
+ if (existsSync12(join12(SRC_ROOT, "audit"))) {
14532
14534
  score += 2;
14533
14535
  }
14534
14536
  return { score: clamp2(score, 15), findings };
@@ -14537,7 +14539,7 @@ var FitnessScoreCalculator = class {
14537
14539
  checkConfigSimplicity() {
14538
14540
  const findings = [];
14539
14541
  let score = 10;
14540
- const schemaCount = countFiles(join14(SRC_ROOT, "config"), /schema.*\.ts$/);
14542
+ const schemaCount = countFiles(join12(SRC_ROOT, "config"), /schema.*\.ts$/);
14541
14543
  if (schemaCount > 10) {
14542
14544
  score -= 2;
14543
14545
  findings.push(
@@ -14552,10 +14554,10 @@ var FitnessScoreCalculator = class {
14552
14554
  } else {
14553
14555
  score += 1;
14554
14556
  }
14555
- if (existsSync12(join14(SRC_ROOT, "config/config-loader.ts"))) {
14557
+ if (existsSync12(join12(SRC_ROOT, "config/config-loader.ts"))) {
14556
14558
  score += 2;
14557
14559
  }
14558
- if (existsSync12(join14(SRC_ROOT, "config/config-manager.ts"))) {
14560
+ if (existsSync12(join12(SRC_ROOT, "config/config-manager.ts"))) {
14559
14561
  score += 1;
14560
14562
  }
14561
14563
  return { score: clamp2(score, 10), findings };
@@ -14565,7 +14567,7 @@ var FitnessScoreCalculator = class {
14565
14567
  const findings = [];
14566
14568
  let score = 10;
14567
14569
  const adapterAgentImports = countPatternInDir(
14568
- join14(SRC_ROOT, "adapters"),
14570
+ join12(SRC_ROOT, "adapters"),
14569
14571
  /\.ts$/,
14570
14572
  /from ['"]\.\.\/agents\//g
14571
14573
  );
@@ -14585,7 +14587,7 @@ var FitnessScoreCalculator = class {
14585
14587
  score += 2;
14586
14588
  }
14587
14589
  const coreMcpImports = countPatternInDir(
14588
- join14(SRC_ROOT, "core"),
14590
+ join12(SRC_ROOT, "core"),
14589
14591
  /\.ts$/,
14590
14592
  /from ['"]\.\.\/mcp\//g
14591
14593
  );
@@ -14610,7 +14612,7 @@ var FitnessScoreCalculator = class {
14610
14612
  checkOperatorErgonomics() {
14611
14613
  const findings = [];
14612
14614
  let score = 10;
14613
- const commandCount = countFiles(join14(SRC_ROOT, "cli"), /\.ts$/);
14615
+ const commandCount = countFiles(join12(SRC_ROOT, "cli"), /\.ts$/);
14614
14616
  if (commandCount >= 20) {
14615
14617
  score += 3;
14616
14618
  } else {
@@ -14635,7 +14637,7 @@ var FitnessScoreCalculator = class {
14635
14637
  ["cli/config-command.ts", "Config command", 1]
14636
14638
  ];
14637
14639
  for (const [path23, name, bonus] of commands) {
14638
- if (existsSync12(join14(SRC_ROOT, path23))) {
14640
+ if (existsSync12(join12(SRC_ROOT, path23))) {
14639
14641
  score += bonus;
14640
14642
  } else {
14641
14643
  findings.push(this.finding("operatorErgonomics", "info", `Missing ${name} (${path23})`, 0));
@@ -14653,7 +14655,7 @@ var FitnessScoreCalculator = class {
14653
14655
  }
14654
14656
  /** Sub-check for governance documentation artifacts. */
14655
14657
  checkGovernanceDocs(score, findings) {
14656
- if (!existsSync12(join14(REPO_ROOT, "CLAUDE.md"))) {
14658
+ if (!existsSync12(join12(REPO_ROOT, "CLAUDE.md"))) {
14657
14659
  score -= 3;
14658
14660
  findings.push(
14659
14661
  this.finding("governanceIntegration", "critical", "No CLAUDE.md governance document", 3)
@@ -14661,10 +14663,10 @@ var FitnessScoreCalculator = class {
14661
14663
  } else {
14662
14664
  score += 1;
14663
14665
  }
14664
- if (existsSync12(join14(DOCS_ROOT, "architecture/wiring-graph.json"))) {
14666
+ if (existsSync12(join12(DOCS_ROOT, "architecture/wiring-graph.json"))) {
14665
14667
  score += 1;
14666
14668
  }
14667
- if (existsSync12(join14(DOCS_ROOT, "adr"))) {
14669
+ if (existsSync12(join12(DOCS_ROOT, "adr"))) {
14668
14670
  score += 1;
14669
14671
  } else {
14670
14672
  findings.push(this.finding("governanceIntegration", "info", "No ADR directory", 0));
@@ -14673,7 +14675,7 @@ var FitnessScoreCalculator = class {
14673
14675
  }
14674
14676
  /** Sub-check for governance runtime infrastructure. */
14675
14677
  checkGovernanceInfra(score, findings) {
14676
- const hasPolicyFirewall = countPatternInDir(join14(SRC_ROOT, "security"), /\.ts$/, /PolicyGate|policyFirewall/g) > 0;
14678
+ const hasPolicyFirewall = countPatternInDir(join12(SRC_ROOT, "security"), /\.ts$/, /PolicyGate|policyFirewall/g) > 0;
14677
14679
  if (hasPolicyFirewall) {
14678
14680
  score += 1;
14679
14681
  } else {
@@ -17652,66 +17654,212 @@ var PARSE_ARGS_CONFIG = {
17652
17654
  },
17653
17655
  source: {
17654
17656
  type: "string"
17657
+ },
17658
+ // init --portable command options (#2305)
17659
+ portable: {
17660
+ type: "boolean",
17661
+ default: false
17662
+ },
17663
+ gitignore: {
17664
+ type: "boolean",
17665
+ default: false
17655
17666
  }
17656
17667
  },
17657
17668
  allowPositionals: true,
17658
17669
  strict: true
17659
17670
  };
17671
+ var VALID_COMMANDS = [
17672
+ "server",
17673
+ "help",
17674
+ "version",
17675
+ "hello",
17676
+ "config",
17677
+ "expert",
17678
+ "workflow",
17679
+ "doctor",
17680
+ "verify",
17681
+ "review",
17682
+ "routing-audit",
17683
+ "orchestrate",
17684
+ "system-review",
17685
+ "vote",
17686
+ "index",
17687
+ "research",
17688
+ "validation",
17689
+ "learning-metrics",
17690
+ "swe-bench",
17691
+ "atbench",
17692
+ "setup",
17693
+ "hooks",
17694
+ "demo",
17695
+ "sprint",
17696
+ "session",
17697
+ "evaluate",
17698
+ "issue",
17699
+ "fitness-audit",
17700
+ "release-notes",
17701
+ "release-validate",
17702
+ "release-announce",
17703
+ "scaffold",
17704
+ "visualize",
17705
+ "capabilities",
17706
+ "status",
17707
+ "memory-benchmark",
17708
+ "auth",
17709
+ "scenario",
17710
+ "warm-up",
17711
+ "e2e-eval",
17712
+ "routing-ab",
17713
+ "memory-eval",
17714
+ "health",
17715
+ "init",
17716
+ "validate",
17717
+ "registry"
17718
+ ];
17660
17719
  function isValidCommand(value) {
17661
- const validCommands = [
17662
- "server",
17663
- "help",
17664
- "version",
17665
- "hello",
17666
- "config",
17667
- "expert",
17668
- "workflow",
17669
- "doctor",
17670
- "verify",
17671
- "review",
17672
- "routing-audit",
17673
- "orchestrate",
17674
- "system-review",
17675
- "vote",
17676
- "index",
17677
- "research",
17678
- "validation",
17679
- "learning-metrics",
17680
- "swe-bench",
17681
- "atbench",
17682
- "setup",
17683
- "hooks",
17684
- "demo",
17685
- "sprint",
17686
- "session",
17687
- "evaluate",
17688
- "issue",
17689
- "fitness-audit",
17690
- "release-notes",
17691
- "release-validate",
17692
- "release-announce",
17693
- "scaffold",
17694
- "visualize",
17695
- "capabilities",
17696
- "status",
17697
- "memory-benchmark",
17698
- "auth",
17699
- "scenario",
17700
- "warm-up",
17701
- "e2e-eval",
17702
- "routing-ab",
17703
- "memory-eval",
17704
- "health",
17705
- "validate",
17706
- "registry"
17707
- ];
17708
- return validCommands.includes(value);
17720
+ return VALID_COMMANDS.includes(value);
17709
17721
  }
17710
17722
 
17711
17723
  // src/cli-commands-handlers.ts
17712
- import { existsSync as existsSync18 } from "fs";
17713
- import { join as join16 } from "path";
17714
- import { homedir as homedir4 } from "os";
17724
+ import { existsSync as existsSync19 } from "fs";
17725
+
17726
+ // src/cli/init-portable.ts
17727
+ import {
17728
+ existsSync as existsSync17,
17729
+ mkdirSync as mkdirSync3,
17730
+ readdirSync as readdirSync2,
17731
+ statSync as statSync3,
17732
+ appendFileSync,
17733
+ readFileSync as readFileSync10
17734
+ } from "fs";
17735
+ import { resolve as resolve11, join as join13, isAbsolute as isAbsolute2 } from "path";
17736
+ var DEFAULT_PORTABLE_DIRNAME = ".nexus-agents";
17737
+ var RESTRICTED_SUBDIRS = /* @__PURE__ */ new Set(["auth"]);
17738
+ function resolveTargetPath(rawPath) {
17739
+ if (rawPath === void 0 || rawPath === "") {
17740
+ return resolve11(process.cwd(), DEFAULT_PORTABLE_DIRNAME);
17741
+ }
17742
+ return isAbsolute2(rawPath) ? rawPath : resolve11(process.cwd(), rawPath);
17743
+ }
17744
+ function isNonEmpty(dir) {
17745
+ if (!existsSync17(dir)) return false;
17746
+ const stat2 = statSync3(dir);
17747
+ if (!stat2.isDirectory()) return true;
17748
+ return readdirSync2(dir).length > 0;
17749
+ }
17750
+ function ensureDir(path23, dryRun, created, alreadyExisted, mode) {
17751
+ if (existsSync17(path23)) {
17752
+ alreadyExisted.push(path23);
17753
+ return;
17754
+ }
17755
+ if (!dryRun) {
17756
+ mkdirSync3(path23, { recursive: true, ...mode !== void 0 ? { mode } : {} });
17757
+ }
17758
+ created.push(path23);
17759
+ }
17760
+ function maybeUpdateGitignore(workspaceDir, portableDirName, dryRun) {
17761
+ const gitDir = join13(workspaceDir, ".git");
17762
+ if (!existsSync17(gitDir)) return false;
17763
+ const gitignorePath = join13(workspaceDir, ".gitignore");
17764
+ const entry = `${portableDirName}/`;
17765
+ let existing = "";
17766
+ if (existsSync17(gitignorePath)) {
17767
+ existing = readFileSync10(gitignorePath, "utf-8");
17768
+ if (existing.split("\n").some((l) => l.trim() === entry || l.trim() === portableDirName)) {
17769
+ return false;
17770
+ }
17771
+ }
17772
+ if (!dryRun) {
17773
+ const sep3 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
17774
+ appendFileSync(gitignorePath, `${sep3}${entry}
17775
+ `, "utf-8");
17776
+ }
17777
+ return true;
17778
+ }
17779
+ function inspectTarget(target) {
17780
+ const exists = existsSync17(target);
17781
+ if (!exists) return { exists: false, nonEmpty: false, isExistingNexusDir: false };
17782
+ const nonEmpty = isNonEmpty(target);
17783
+ const stat2 = statSync3(target);
17784
+ const isExistingNexusDir = stat2.isDirectory() && existsSync17(join13(target, "audit"));
17785
+ return { exists, nonEmpty, isExistingNexusDir };
17786
+ }
17787
+ function createDataLayout(target, dryRun, created, alreadyExisted) {
17788
+ ensureDir(target, dryRun, created, alreadyExisted);
17789
+ for (const subdir of DATA_SUBDIRECTORIES) {
17790
+ const mode = RESTRICTED_SUBDIRS.has(subdir) ? 448 : void 0;
17791
+ ensureDir(join13(target, subdir), dryRun, created, alreadyExisted, mode);
17792
+ }
17793
+ }
17794
+ function makeResult(opts) {
17795
+ return {
17796
+ success: opts.success,
17797
+ absolutePath: opts.absolutePath,
17798
+ created: opts.created,
17799
+ alreadyExisted: opts.alreadyExisted,
17800
+ skipped: opts.skipped ?? false,
17801
+ gitignoreUpdated: opts.gitignoreUpdated ?? false,
17802
+ error: opts.error ?? null
17803
+ };
17804
+ }
17805
+ function applyGitignoreOption(target, options, dryRun) {
17806
+ if (options.gitignore !== true) return false;
17807
+ const workspaceDir = resolve11(target, "..");
17808
+ const portableName = target.slice(workspaceDir.length + 1);
17809
+ return maybeUpdateGitignore(workspaceDir, portableName, dryRun);
17810
+ }
17811
+ function initPortable(options = {}) {
17812
+ const created = [];
17813
+ const alreadyExisted = [];
17814
+ const dryRun = options.dryRun === true;
17815
+ const force = options.force === true;
17816
+ const target = resolveTargetPath(options.path);
17817
+ const base = { absolutePath: target, created, alreadyExisted };
17818
+ try {
17819
+ const state = inspectTarget(target);
17820
+ if (state.isExistingNexusDir && !force) {
17821
+ createDataLayout(target, dryRun, created, alreadyExisted);
17822
+ return makeResult({ ...base, success: true, skipped: true });
17823
+ }
17824
+ if (state.nonEmpty && !state.isExistingNexusDir && !force) {
17825
+ const error = `target ${target} already exists and is not empty; pass --force to use anyway`;
17826
+ return makeResult({ ...base, success: false, error });
17827
+ }
17828
+ createDataLayout(target, dryRun, created, alreadyExisted);
17829
+ const gitignoreUpdated = applyGitignoreOption(target, options, dryRun);
17830
+ return makeResult({ ...base, success: true, gitignoreUpdated });
17831
+ } catch (error) {
17832
+ const msg = error instanceof Error ? error.message : String(error);
17833
+ return makeResult({ ...base, success: false, error: msg });
17834
+ }
17835
+ }
17836
+ function formatInitPortableMessage(result, dryRun) {
17837
+ if (!result.success) {
17838
+ return `init --portable failed: ${result.error ?? "unknown error"}
17839
+ `;
17840
+ }
17841
+ const lines = [];
17842
+ if (dryRun) {
17843
+ lines.push(`(dry-run) would create ${String(result.created.length)} entries under:`);
17844
+ lines.push(` ${result.absolutePath}`);
17845
+ return lines.join("\n") + "\n";
17846
+ }
17847
+ if (result.skipped) {
17848
+ lines.push(`\u2713 Already initialized: ${result.absolutePath}`);
17849
+ } else {
17850
+ lines.push(`\u2713 Created: ${result.absolutePath}`);
17851
+ }
17852
+ if (result.gitignoreUpdated) {
17853
+ lines.push(`\u2713 Added entry to .gitignore`);
17854
+ }
17855
+ lines.push("");
17856
+ lines.push("Activate by exporting:");
17857
+ lines.push(` export NEXUS_DATA_DIR=${result.absolutePath}`);
17858
+ lines.push("");
17859
+ lines.push("Or one-off:");
17860
+ lines.push(` NEXUS_DATA_DIR=${result.absolutePath} nexus-agents <cmd>`);
17861
+ return lines.join("\n") + "\n";
17862
+ }
17715
17863
 
17716
17864
  // src/mcp/tools/dev-pipeline-tool.ts
17717
17865
  import { z as z9 } from "zod";
@@ -18669,7 +18817,7 @@ function logFinalEventBusStats(logger17) {
18669
18817
  // src/cli-orchestrator.ts
18670
18818
  import * as readline2 from "readline";
18671
18819
  function runOrchestratorRepl(options, logger17) {
18672
- return new Promise((resolve14) => {
18820
+ return new Promise((resolve15) => {
18673
18821
  const rl = readline2.createInterface({
18674
18822
  input: process.stdin,
18675
18823
  output: process.stdout,
@@ -18705,7 +18853,7 @@ function runOrchestratorRepl(options, logger17) {
18705
18853
  });
18706
18854
  rl.on("close", () => {
18707
18855
  logger17.info("Orchestrator REPL closed");
18708
- resolve14();
18856
+ resolve15();
18709
18857
  });
18710
18858
  });
18711
18859
  }
@@ -19894,9 +20042,7 @@ function initializeAuth(config, logger17) {
19894
20042
  }
19895
20043
 
19896
20044
  // src/cli-server-audit.ts
19897
- import { join as join15 } from "path";
19898
- import { homedir as homedir3 } from "os";
19899
- var DEFAULT_AUDIT_DIR = join15(homedir3(), ".nexus-agents", "audit");
20045
+ var DEFAULT_AUDIT_DIR = nexusDataPath("audit");
19900
20046
  function initializeAuditLogger(securityConfig, logger17) {
19901
20047
  if (securityConfig?.audit?.enabled !== true) {
19902
20048
  logger17.debug("Audit logging disabled (set security.audit.enabled: true to enable)");
@@ -20525,9 +20671,9 @@ function buildOrchestratorOptions(args) {
20525
20671
  function printFirstRunHint() {
20526
20672
  const isTTY = process.stderr.isTTY;
20527
20673
  if (!isTTY) return;
20528
- const dataDir = join16(homedir4(), ".nexus-agents");
20529
- const hasConfig = existsSync18("./nexus-agents.yaml") || existsSync18("./nexus-agents.yml");
20530
- if (existsSync18(dataDir) || hasConfig) return;
20674
+ const dataDir = getNexusDataDir();
20675
+ const hasConfig = existsSync19("./nexus-agents.yaml") || existsSync19("./nexus-agents.yml");
20676
+ if (existsSync19(dataDir) || hasConfig) return;
20531
20677
  process.stderr.write(
20532
20678
  "\n\x1B[36mnexus-agents\x1B[0m: First time? Run \x1B[1mnexus-agents setup\x1B[0m to configure.\n\n"
20533
20679
  );
@@ -20639,7 +20785,7 @@ async function handleResearchCommand(args) {
20639
20785
  }
20640
20786
  }
20641
20787
  async function handleRegistryCommand(args) {
20642
- const { registryCommand, isValidRegistrySubcommand, formatRegistryUsage } = await import("./registry-command-S46JJ2SX.js");
20788
+ const { registryCommand, isValidRegistrySubcommand, formatRegistryUsage } = await import("./registry-command-TTXAUCOK.js");
20643
20789
  const subcommand = args.subcommand;
20644
20790
  if (!isValidRegistrySubcommand(subcommand)) {
20645
20791
  process.stdout.write(`${formatRegistryUsage()}
@@ -20693,6 +20839,23 @@ async function handleDoctorCommand(args) {
20693
20839
  }
20694
20840
  process.exit(exitCode === 0 ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
20695
20841
  }
20842
+ function handleInitCommand(args) {
20843
+ if (args.options.portable !== true) {
20844
+ process.stderr.write(
20845
+ "Usage: nexus-agents init --portable [path] [--force] [--dry-run] [--gitignore]\nBootstraps a workspace-local nexus-agents data directory.\n"
20846
+ );
20847
+ process.exit(EXIT_CODES.INVALID_ARGS);
20848
+ }
20849
+ const targetPath = args.positionals[1];
20850
+ const result = initPortable({
20851
+ ...targetPath !== void 0 && targetPath !== "" ? { path: targetPath } : {},
20852
+ force: args.options.force,
20853
+ dryRun: args.options.dryRun,
20854
+ gitignore: args.options.gitignore ?? false
20855
+ });
20856
+ process.stdout.write(formatInitPortableMessage(result, args.options.dryRun));
20857
+ process.exit(result.success ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
20858
+ }
20696
20859
  async function handleSetupCommandAsync(args) {
20697
20860
  if (args.options.customApi !== void 0 && args.options.customApi !== "") {
20698
20861
  const exitCode2 = await runCustomApiSetup(args);
@@ -22166,7 +22329,7 @@ function handleStatusCommand2(args) {
22166
22329
 
22167
22330
  // src/cli/scenario-command.ts
22168
22331
  import { readdir as readdir4 } from "fs/promises";
22169
- import { join as join18, resolve as resolve13 } from "path";
22332
+ import { join as join15, resolve as resolve14 } from "path";
22170
22333
 
22171
22334
  // src/testing/e2e/scenario-runner.ts
22172
22335
  import { readFile as readFile7 } from "fs/promises";
@@ -22326,7 +22489,7 @@ function checkCircularDependencies(workflow) {
22326
22489
  var defaultStubFactory = {
22327
22490
  createAgentStub(agentType, action) {
22328
22491
  return async (inputs) => {
22329
- await new Promise((resolve14) => setTimeout(resolve14, 10));
22492
+ await new Promise((resolve15) => setTimeout(resolve15, 10));
22330
22493
  return {
22331
22494
  stepId: `${agentType}-${action}`,
22332
22495
  status: "success",
@@ -22485,7 +22648,7 @@ function createScenarioRunner(stubFactory) {
22485
22648
  }
22486
22649
 
22487
22650
  // src/cli/scenario-command.ts
22488
- var FIXTURES_DIR = resolve13(import.meta.dirname, "../testing/e2e/fixtures");
22651
+ var FIXTURES_DIR = resolve14(import.meta.dirname, "../testing/e2e/fixtures");
22489
22652
  var SCENARIO_SUFFIX = ".scenario.yaml";
22490
22653
  async function listScenarios() {
22491
22654
  try {
@@ -22536,7 +22699,7 @@ async function handleRun(args) {
22536
22699
  process.exit(EXIT_CODES.SERVER_START_FAILED);
22537
22700
  }
22538
22701
  const runner = createScenarioRunner();
22539
- const fixturePath = join18(FIXTURES_DIR, `${name}${SCENARIO_SUFFIX}`);
22702
+ const fixturePath = join15(FIXTURES_DIR, `${name}${SCENARIO_SUFFIX}`);
22540
22703
  try {
22541
22704
  const fixture = await runner.loadFixture(fixturePath);
22542
22705
  const result = await runner.run(fixture);
@@ -22799,6 +22962,8 @@ var SYNC_COMMAND_HANDLERS = {
22799
22962
  status: handleStatusCommand2,
22800
22963
  // Issue #1023: Warm-Up Command
22801
22964
  "warm-up": handleWarmUpCommand,
22965
+ // #2305: Init Portable Command
22966
+ init: handleInitCommand,
22802
22967
  "e2e-eval": handleE2EEvalCommand,
22803
22968
  "routing-ab": handleRoutingABCommand,
22804
22969
  "memory-eval": handleMemoryEvalCommand,