nexus-agents 2.60.0 → 2.62.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/{chunk-MJ3K4FYS.js → chunk-OJBW4II4.js} +2 -2
- package/dist/{chunk-XRXUCE6K.js → chunk-V7AFOKWC.js} +4 -3
- package/dist/{chunk-5JSMLCCK.js → chunk-X5WDX7L3.js} +2 -2
- package/dist/cli.d.ts +4 -1
- package/dist/cli.js +417 -69
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{setup-command-LIX2S7JD.js → setup-command-FC67SJSP.js} +3 -3
- package/package.json +1 -1
- /package/dist/{chunk-MJ3K4FYS.js.map → chunk-OJBW4II4.js.map} +0 -0
- /package/dist/{chunk-XRXUCE6K.js.map → chunk-V7AFOKWC.js.map} +0 -0
- /package/dist/{chunk-5JSMLCCK.js.map → chunk-X5WDX7L3.js.map} +0 -0
- /package/dist/{setup-command-LIX2S7JD.js.map → setup-command-FC67SJSP.js.map} +0 -0
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-
|
|
19
|
+
} from "./chunk-OJBW4II4.js";
|
|
20
20
|
import "./chunk-QGZBCD2A.js";
|
|
21
21
|
import {
|
|
22
22
|
AuthHandler,
|
|
@@ -142,7 +142,7 @@ import {
|
|
|
142
142
|
validateCommand,
|
|
143
143
|
validateWorkflow,
|
|
144
144
|
wrapInMarkdownFence
|
|
145
|
-
} from "./chunk-
|
|
145
|
+
} from "./chunk-X5WDX7L3.js";
|
|
146
146
|
import "./chunk-ED6VQWNG.js";
|
|
147
147
|
import {
|
|
148
148
|
resolveToken
|
|
@@ -185,6 +185,7 @@ import "./chunk-AP2FD37C.js";
|
|
|
185
185
|
import "./chunk-BQ4YXGGQ.js";
|
|
186
186
|
import {
|
|
187
187
|
CustomExpertDefinitionSchema,
|
|
188
|
+
DATA_SUBDIRECTORIES,
|
|
188
189
|
MAX_SYSTEM_PROMPT_LENGTH,
|
|
189
190
|
VALID_EXPERT_DOMAINS,
|
|
190
191
|
VALID_EXPERT_TIERS,
|
|
@@ -200,7 +201,7 @@ import {
|
|
|
200
201
|
loadConfig,
|
|
201
202
|
runDoctor,
|
|
202
203
|
validateNexusEnv
|
|
203
|
-
} from "./chunk-
|
|
204
|
+
} from "./chunk-V7AFOKWC.js";
|
|
204
205
|
import {
|
|
205
206
|
DEFAULTS
|
|
206
207
|
} from "./chunk-H43PABG4.js";
|
|
@@ -1458,14 +1459,14 @@ ${colors.dim}Session ended.${colors.reset}
|
|
|
1458
1459
|
});
|
|
1459
1460
|
});
|
|
1460
1461
|
rl.prompt();
|
|
1461
|
-
return new Promise((
|
|
1462
|
+
return new Promise((resolve15) => {
|
|
1462
1463
|
rl.on("line", (line) => {
|
|
1463
1464
|
void (async () => {
|
|
1464
1465
|
try {
|
|
1465
1466
|
const shouldExit = await processLine(line, session, logger17);
|
|
1466
1467
|
if (shouldExit) {
|
|
1467
1468
|
rl.close();
|
|
1468
|
-
|
|
1469
|
+
resolve15();
|
|
1469
1470
|
return;
|
|
1470
1471
|
}
|
|
1471
1472
|
} catch (error) {
|
|
@@ -1477,7 +1478,7 @@ ${colors.dim}Session ended.${colors.reset}
|
|
|
1477
1478
|
})();
|
|
1478
1479
|
});
|
|
1479
1480
|
rl.on("close", () => {
|
|
1480
|
-
|
|
1481
|
+
resolve15();
|
|
1481
1482
|
});
|
|
1482
1483
|
});
|
|
1483
1484
|
}
|
|
@@ -12828,7 +12829,7 @@ function writeResultAndExit(result) {
|
|
|
12828
12829
|
|
|
12829
12830
|
// src/cli/hooks/hook-router.ts
|
|
12830
12831
|
async function readStdin() {
|
|
12831
|
-
return new Promise((
|
|
12832
|
+
return new Promise((resolve15, reject) => {
|
|
12832
12833
|
let data = "";
|
|
12833
12834
|
process.stdin.setEncoding("utf8");
|
|
12834
12835
|
process.stdin.on("readable", () => {
|
|
@@ -12839,24 +12840,24 @@ async function readStdin() {
|
|
|
12839
12840
|
}
|
|
12840
12841
|
});
|
|
12841
12842
|
process.stdin.on("end", () => {
|
|
12842
|
-
|
|
12843
|
+
resolve15(data);
|
|
12843
12844
|
});
|
|
12844
12845
|
process.stdin.on("error", (err2) => {
|
|
12845
12846
|
reject(err2);
|
|
12846
12847
|
});
|
|
12847
12848
|
if (process.stdin.isTTY) {
|
|
12848
|
-
|
|
12849
|
+
resolve15("");
|
|
12849
12850
|
}
|
|
12850
12851
|
});
|
|
12851
12852
|
}
|
|
12852
12853
|
async function readStdinWithTimeout(timeoutMs = 5e3) {
|
|
12853
|
-
return new Promise((
|
|
12854
|
+
return new Promise((resolve15, reject) => {
|
|
12854
12855
|
const timeout2 = setTimeout(() => {
|
|
12855
12856
|
reject(new Error(`Stdin read timeout after ${String(timeoutMs)}ms`));
|
|
12856
12857
|
}, timeoutMs);
|
|
12857
12858
|
readStdin().then((data) => {
|
|
12858
12859
|
clearTimeout(timeout2);
|
|
12859
|
-
|
|
12860
|
+
resolve15(data);
|
|
12860
12861
|
}).catch((err2) => {
|
|
12861
12862
|
clearTimeout(timeout2);
|
|
12862
12863
|
reject(err2 instanceof Error ? err2 : new Error(String(err2)));
|
|
@@ -17653,64 +17654,383 @@ var PARSE_ARGS_CONFIG = {
|
|
|
17653
17654
|
},
|
|
17654
17655
|
source: {
|
|
17655
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
|
|
17666
|
+
},
|
|
17667
|
+
// init --portable --mcp-config flag (#2308)
|
|
17668
|
+
"mcp-config": {
|
|
17669
|
+
type: "boolean",
|
|
17670
|
+
default: false
|
|
17656
17671
|
}
|
|
17657
17672
|
},
|
|
17658
17673
|
allowPositionals: true,
|
|
17659
17674
|
strict: true
|
|
17660
17675
|
};
|
|
17676
|
+
var VALID_COMMANDS = [
|
|
17677
|
+
"server",
|
|
17678
|
+
"help",
|
|
17679
|
+
"version",
|
|
17680
|
+
"hello",
|
|
17681
|
+
"config",
|
|
17682
|
+
"expert",
|
|
17683
|
+
"workflow",
|
|
17684
|
+
"doctor",
|
|
17685
|
+
"verify",
|
|
17686
|
+
"review",
|
|
17687
|
+
"routing-audit",
|
|
17688
|
+
"orchestrate",
|
|
17689
|
+
"system-review",
|
|
17690
|
+
"vote",
|
|
17691
|
+
"index",
|
|
17692
|
+
"research",
|
|
17693
|
+
"validation",
|
|
17694
|
+
"learning-metrics",
|
|
17695
|
+
"swe-bench",
|
|
17696
|
+
"atbench",
|
|
17697
|
+
"setup",
|
|
17698
|
+
"hooks",
|
|
17699
|
+
"demo",
|
|
17700
|
+
"sprint",
|
|
17701
|
+
"session",
|
|
17702
|
+
"evaluate",
|
|
17703
|
+
"issue",
|
|
17704
|
+
"fitness-audit",
|
|
17705
|
+
"release-notes",
|
|
17706
|
+
"release-validate",
|
|
17707
|
+
"release-announce",
|
|
17708
|
+
"scaffold",
|
|
17709
|
+
"visualize",
|
|
17710
|
+
"capabilities",
|
|
17711
|
+
"status",
|
|
17712
|
+
"memory-benchmark",
|
|
17713
|
+
"auth",
|
|
17714
|
+
"scenario",
|
|
17715
|
+
"warm-up",
|
|
17716
|
+
"e2e-eval",
|
|
17717
|
+
"routing-ab",
|
|
17718
|
+
"memory-eval",
|
|
17719
|
+
"health",
|
|
17720
|
+
"init",
|
|
17721
|
+
"validate",
|
|
17722
|
+
"registry"
|
|
17723
|
+
];
|
|
17661
17724
|
function isValidCommand(value) {
|
|
17662
|
-
|
|
17663
|
-
"server",
|
|
17664
|
-
"help",
|
|
17665
|
-
"version",
|
|
17666
|
-
"hello",
|
|
17667
|
-
"config",
|
|
17668
|
-
"expert",
|
|
17669
|
-
"workflow",
|
|
17670
|
-
"doctor",
|
|
17671
|
-
"verify",
|
|
17672
|
-
"review",
|
|
17673
|
-
"routing-audit",
|
|
17674
|
-
"orchestrate",
|
|
17675
|
-
"system-review",
|
|
17676
|
-
"vote",
|
|
17677
|
-
"index",
|
|
17678
|
-
"research",
|
|
17679
|
-
"validation",
|
|
17680
|
-
"learning-metrics",
|
|
17681
|
-
"swe-bench",
|
|
17682
|
-
"atbench",
|
|
17683
|
-
"setup",
|
|
17684
|
-
"hooks",
|
|
17685
|
-
"demo",
|
|
17686
|
-
"sprint",
|
|
17687
|
-
"session",
|
|
17688
|
-
"evaluate",
|
|
17689
|
-
"issue",
|
|
17690
|
-
"fitness-audit",
|
|
17691
|
-
"release-notes",
|
|
17692
|
-
"release-validate",
|
|
17693
|
-
"release-announce",
|
|
17694
|
-
"scaffold",
|
|
17695
|
-
"visualize",
|
|
17696
|
-
"capabilities",
|
|
17697
|
-
"status",
|
|
17698
|
-
"memory-benchmark",
|
|
17699
|
-
"auth",
|
|
17700
|
-
"scenario",
|
|
17701
|
-
"warm-up",
|
|
17702
|
-
"e2e-eval",
|
|
17703
|
-
"routing-ab",
|
|
17704
|
-
"memory-eval",
|
|
17705
|
-
"health",
|
|
17706
|
-
"validate",
|
|
17707
|
-
"registry"
|
|
17708
|
-
];
|
|
17709
|
-
return validCommands.includes(value);
|
|
17725
|
+
return VALID_COMMANDS.includes(value);
|
|
17710
17726
|
}
|
|
17711
17727
|
|
|
17712
17728
|
// src/cli-commands-handlers.ts
|
|
17713
|
-
import { existsSync as
|
|
17729
|
+
import { existsSync as existsSync20 } from "fs";
|
|
17730
|
+
|
|
17731
|
+
// src/cli/init-portable.ts
|
|
17732
|
+
import {
|
|
17733
|
+
existsSync as existsSync18,
|
|
17734
|
+
mkdirSync as mkdirSync3,
|
|
17735
|
+
readdirSync as readdirSync2,
|
|
17736
|
+
statSync as statSync3,
|
|
17737
|
+
appendFileSync as appendFileSync2,
|
|
17738
|
+
readFileSync as readFileSync11
|
|
17739
|
+
} from "fs";
|
|
17740
|
+
import { resolve as resolve11, join as join14, isAbsolute as isAbsolute2 } from "path";
|
|
17741
|
+
|
|
17742
|
+
// src/cli/mcp-config-emitter.ts
|
|
17743
|
+
import { existsSync as existsSync17, readFileSync as readFileSync10, writeFileSync as writeFileSync5, appendFileSync } from "fs";
|
|
17744
|
+
import { join as join13 } from "path";
|
|
17745
|
+
var MCP_CONFIG_FILENAME = ".mcp.json";
|
|
17746
|
+
var NEXUS_SERVER_KEY = "nexus-agents";
|
|
17747
|
+
function buildNexusServerEntry(dataDir) {
|
|
17748
|
+
return {
|
|
17749
|
+
command: "nexus-agents",
|
|
17750
|
+
args: ["--mode=server"],
|
|
17751
|
+
env: { NEXUS_DATA_DIR: dataDir }
|
|
17752
|
+
};
|
|
17753
|
+
}
|
|
17754
|
+
function entriesEqual(a, b) {
|
|
17755
|
+
if (a.command !== b.command) return false;
|
|
17756
|
+
if (a.args.length !== b.args.length) return false;
|
|
17757
|
+
for (let i = 0; i < a.args.length; i++) if (a.args[i] !== b.args[i]) return false;
|
|
17758
|
+
const aEnv = a.env ?? {};
|
|
17759
|
+
const bEnv = b.env ?? {};
|
|
17760
|
+
const aKeys = Object.keys(aEnv);
|
|
17761
|
+
const bKeys = Object.keys(bEnv);
|
|
17762
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
17763
|
+
for (const k of aKeys) if (aEnv[k] !== bEnv[k]) return false;
|
|
17764
|
+
return true;
|
|
17765
|
+
}
|
|
17766
|
+
function loadExistingConfig(path23) {
|
|
17767
|
+
if (!existsSync17(path23)) return { ok: true, value: void 0 };
|
|
17768
|
+
let raw;
|
|
17769
|
+
try {
|
|
17770
|
+
raw = readFileSync10(path23, "utf-8");
|
|
17771
|
+
} catch (e) {
|
|
17772
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
17773
|
+
}
|
|
17774
|
+
try {
|
|
17775
|
+
const parsed = JSON.parse(raw);
|
|
17776
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
17777
|
+
return { ok: false, error: `${path23}: top-level JSON must be an object` };
|
|
17778
|
+
}
|
|
17779
|
+
return { ok: true, value: parsed };
|
|
17780
|
+
} catch (e) {
|
|
17781
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
17782
|
+
return { ok: false, error: `${path23}: invalid JSON \u2014 ${msg}` };
|
|
17783
|
+
}
|
|
17784
|
+
}
|
|
17785
|
+
function decideEmission(existing, desired, force) {
|
|
17786
|
+
if (existing === void 0) {
|
|
17787
|
+
return { kind: "write", nextConfig: { mcpServers: { [NEXUS_SERVER_KEY]: desired } } };
|
|
17788
|
+
}
|
|
17789
|
+
const servers = existing.mcpServers ?? {};
|
|
17790
|
+
const current = servers[NEXUS_SERVER_KEY];
|
|
17791
|
+
if (current !== void 0 && entriesEqual(current, desired)) {
|
|
17792
|
+
return { kind: "noop" };
|
|
17793
|
+
}
|
|
17794
|
+
if (current !== void 0 && !force) {
|
|
17795
|
+
return {
|
|
17796
|
+
kind: "refuse",
|
|
17797
|
+
reason: `existing ${NEXUS_SERVER_KEY} entry differs; pass --force to overwrite`
|
|
17798
|
+
};
|
|
17799
|
+
}
|
|
17800
|
+
const nextServers = { ...servers, [NEXUS_SERVER_KEY]: desired };
|
|
17801
|
+
return { kind: "write", nextConfig: { ...existing, mcpServers: nextServers } };
|
|
17802
|
+
}
|
|
17803
|
+
function autoGitignoreMcpConfig(workspaceDir, dryRun) {
|
|
17804
|
+
const gitDir = join13(workspaceDir, ".git");
|
|
17805
|
+
if (!existsSync17(gitDir)) return false;
|
|
17806
|
+
const gitignorePath = join13(workspaceDir, ".gitignore");
|
|
17807
|
+
let existing = "";
|
|
17808
|
+
if (existsSync17(gitignorePath)) {
|
|
17809
|
+
existing = readFileSync10(gitignorePath, "utf-8");
|
|
17810
|
+
const already = existing.split("\n").some((l) => l.trim() === MCP_CONFIG_FILENAME || l.trim() === `/${MCP_CONFIG_FILENAME}`);
|
|
17811
|
+
if (already) return false;
|
|
17812
|
+
}
|
|
17813
|
+
if (!dryRun) {
|
|
17814
|
+
const sep3 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
17815
|
+
appendFileSync(gitignorePath, `${sep3}${MCP_CONFIG_FILENAME}
|
|
17816
|
+
`, "utf-8");
|
|
17817
|
+
}
|
|
17818
|
+
return true;
|
|
17819
|
+
}
|
|
17820
|
+
function emitMcpConfig(options) {
|
|
17821
|
+
const mcpConfigPath = join13(options.workspaceDir, MCP_CONFIG_FILENAME);
|
|
17822
|
+
const dryRun = options.dryRun === true;
|
|
17823
|
+
const force = options.force === true;
|
|
17824
|
+
const desired = buildNexusServerEntry(options.dataDir);
|
|
17825
|
+
const loaded = loadExistingConfig(mcpConfigPath);
|
|
17826
|
+
if (!loaded.ok) return makeFailure(mcpConfigPath, loaded.error);
|
|
17827
|
+
const decision = decideEmission(loaded.value, desired, force);
|
|
17828
|
+
if (decision.kind === "refuse") return makeFailure(mcpConfigPath, decision.reason);
|
|
17829
|
+
if (decision.kind === "noop") {
|
|
17830
|
+
return makeSuccess({
|
|
17831
|
+
mcpConfigPath,
|
|
17832
|
+
written: false,
|
|
17833
|
+
alreadyMatched: true,
|
|
17834
|
+
gitignoreUpdated: false
|
|
17835
|
+
});
|
|
17836
|
+
}
|
|
17837
|
+
if (!dryRun) {
|
|
17838
|
+
writeFileSync5(mcpConfigPath, JSON.stringify(decision.nextConfig, null, 2) + "\n", "utf-8");
|
|
17839
|
+
}
|
|
17840
|
+
const gitignoreUpdated = autoGitignoreMcpConfig(options.workspaceDir, dryRun);
|
|
17841
|
+
return makeSuccess({ mcpConfigPath, written: true, alreadyMatched: false, gitignoreUpdated });
|
|
17842
|
+
}
|
|
17843
|
+
function makeSuccess(opts) {
|
|
17844
|
+
return { success: true, error: null, ...opts };
|
|
17845
|
+
}
|
|
17846
|
+
function makeFailure(mcpConfigPath, error) {
|
|
17847
|
+
return {
|
|
17848
|
+
success: false,
|
|
17849
|
+
mcpConfigPath,
|
|
17850
|
+
written: false,
|
|
17851
|
+
alreadyMatched: false,
|
|
17852
|
+
gitignoreUpdated: false,
|
|
17853
|
+
error
|
|
17854
|
+
};
|
|
17855
|
+
}
|
|
17856
|
+
|
|
17857
|
+
// src/cli/init-portable.ts
|
|
17858
|
+
var DEFAULT_PORTABLE_DIRNAME = ".nexus-agents";
|
|
17859
|
+
var RESTRICTED_SUBDIRS = /* @__PURE__ */ new Set(["auth"]);
|
|
17860
|
+
function resolveTargetPath(rawPath) {
|
|
17861
|
+
if (rawPath === void 0 || rawPath === "") {
|
|
17862
|
+
return resolve11(process.cwd(), DEFAULT_PORTABLE_DIRNAME);
|
|
17863
|
+
}
|
|
17864
|
+
return isAbsolute2(rawPath) ? rawPath : resolve11(process.cwd(), rawPath);
|
|
17865
|
+
}
|
|
17866
|
+
function isNonEmpty(dir) {
|
|
17867
|
+
if (!existsSync18(dir)) return false;
|
|
17868
|
+
const stat2 = statSync3(dir);
|
|
17869
|
+
if (!stat2.isDirectory()) return true;
|
|
17870
|
+
return readdirSync2(dir).length > 0;
|
|
17871
|
+
}
|
|
17872
|
+
function ensureDir(path23, dryRun, created, alreadyExisted, mode) {
|
|
17873
|
+
if (existsSync18(path23)) {
|
|
17874
|
+
alreadyExisted.push(path23);
|
|
17875
|
+
return;
|
|
17876
|
+
}
|
|
17877
|
+
if (!dryRun) {
|
|
17878
|
+
mkdirSync3(path23, { recursive: true, ...mode !== void 0 ? { mode } : {} });
|
|
17879
|
+
}
|
|
17880
|
+
created.push(path23);
|
|
17881
|
+
}
|
|
17882
|
+
function maybeUpdateGitignore(workspaceDir, portableDirName, dryRun) {
|
|
17883
|
+
const gitDir = join14(workspaceDir, ".git");
|
|
17884
|
+
if (!existsSync18(gitDir)) return false;
|
|
17885
|
+
const gitignorePath = join14(workspaceDir, ".gitignore");
|
|
17886
|
+
const entry = `${portableDirName}/`;
|
|
17887
|
+
let existing = "";
|
|
17888
|
+
if (existsSync18(gitignorePath)) {
|
|
17889
|
+
existing = readFileSync11(gitignorePath, "utf-8");
|
|
17890
|
+
if (existing.split("\n").some((l) => l.trim() === entry || l.trim() === portableDirName)) {
|
|
17891
|
+
return false;
|
|
17892
|
+
}
|
|
17893
|
+
}
|
|
17894
|
+
if (!dryRun) {
|
|
17895
|
+
const sep3 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
17896
|
+
appendFileSync2(gitignorePath, `${sep3}${entry}
|
|
17897
|
+
`, "utf-8");
|
|
17898
|
+
}
|
|
17899
|
+
return true;
|
|
17900
|
+
}
|
|
17901
|
+
function inspectTarget(target) {
|
|
17902
|
+
const exists = existsSync18(target);
|
|
17903
|
+
if (!exists) return { exists: false, nonEmpty: false, isExistingNexusDir: false };
|
|
17904
|
+
const nonEmpty = isNonEmpty(target);
|
|
17905
|
+
const stat2 = statSync3(target);
|
|
17906
|
+
const isExistingNexusDir = stat2.isDirectory() && existsSync18(join14(target, "audit"));
|
|
17907
|
+
return { exists, nonEmpty, isExistingNexusDir };
|
|
17908
|
+
}
|
|
17909
|
+
function createDataLayout(target, dryRun, created, alreadyExisted) {
|
|
17910
|
+
ensureDir(target, dryRun, created, alreadyExisted);
|
|
17911
|
+
for (const subdir of DATA_SUBDIRECTORIES) {
|
|
17912
|
+
const mode = RESTRICTED_SUBDIRS.has(subdir) ? 448 : void 0;
|
|
17913
|
+
ensureDir(join14(target, subdir), dryRun, created, alreadyExisted, mode);
|
|
17914
|
+
}
|
|
17915
|
+
}
|
|
17916
|
+
function makeResult(opts) {
|
|
17917
|
+
return {
|
|
17918
|
+
success: opts.success,
|
|
17919
|
+
absolutePath: opts.absolutePath,
|
|
17920
|
+
created: opts.created,
|
|
17921
|
+
alreadyExisted: opts.alreadyExisted,
|
|
17922
|
+
skipped: opts.skipped ?? false,
|
|
17923
|
+
gitignoreUpdated: opts.gitignoreUpdated ?? false,
|
|
17924
|
+
...opts.mcpConfig !== void 0 ? { mcpConfig: opts.mcpConfig } : {},
|
|
17925
|
+
error: opts.error ?? null
|
|
17926
|
+
};
|
|
17927
|
+
}
|
|
17928
|
+
function applyGitignoreOption(target, options, dryRun) {
|
|
17929
|
+
if (options.gitignore !== true) return false;
|
|
17930
|
+
const workspaceDir = resolve11(target, "..");
|
|
17931
|
+
const portableName = target.slice(workspaceDir.length + 1);
|
|
17932
|
+
return maybeUpdateGitignore(workspaceDir, portableName, dryRun);
|
|
17933
|
+
}
|
|
17934
|
+
function applyMcpConfigOption(target, options, dryRun) {
|
|
17935
|
+
if (options.mcpConfig !== true) return void 0;
|
|
17936
|
+
const workspaceDir = resolve11(target, "..");
|
|
17937
|
+
return emitMcpConfig({
|
|
17938
|
+
workspaceDir,
|
|
17939
|
+
dataDir: target,
|
|
17940
|
+
force: options.force === true,
|
|
17941
|
+
dryRun
|
|
17942
|
+
});
|
|
17943
|
+
}
|
|
17944
|
+
function buildSuccessResult(base, flags, mcpConfig) {
|
|
17945
|
+
if (mcpConfig === void 0) {
|
|
17946
|
+
return makeResult({ ...base, ...flags, success: true });
|
|
17947
|
+
}
|
|
17948
|
+
if (mcpConfig.success) {
|
|
17949
|
+
return makeResult({ ...base, ...flags, success: true, mcpConfig });
|
|
17950
|
+
}
|
|
17951
|
+
return makeResult({ ...base, ...flags, success: false, mcpConfig, error: mcpConfig.error });
|
|
17952
|
+
}
|
|
17953
|
+
function initPortable(options = {}) {
|
|
17954
|
+
const created = [];
|
|
17955
|
+
const alreadyExisted = [];
|
|
17956
|
+
const dryRun = options.dryRun === true;
|
|
17957
|
+
const force = options.force === true;
|
|
17958
|
+
const target = resolveTargetPath(options.path);
|
|
17959
|
+
const base = { absolutePath: target, created, alreadyExisted };
|
|
17960
|
+
try {
|
|
17961
|
+
const state = inspectTarget(target);
|
|
17962
|
+
if (state.isExistingNexusDir && !force) {
|
|
17963
|
+
createDataLayout(target, dryRun, created, alreadyExisted);
|
|
17964
|
+
return buildSuccessResult(
|
|
17965
|
+
base,
|
|
17966
|
+
{ skipped: true },
|
|
17967
|
+
applyMcpConfigOption(target, options, dryRun)
|
|
17968
|
+
);
|
|
17969
|
+
}
|
|
17970
|
+
if (state.nonEmpty && !state.isExistingNexusDir && !force) {
|
|
17971
|
+
const error = `target ${target} already exists and is not empty; pass --force to use anyway`;
|
|
17972
|
+
return makeResult({ ...base, success: false, error });
|
|
17973
|
+
}
|
|
17974
|
+
createDataLayout(target, dryRun, created, alreadyExisted);
|
|
17975
|
+
const gitignoreUpdated = applyGitignoreOption(target, options, dryRun);
|
|
17976
|
+
return buildSuccessResult(
|
|
17977
|
+
base,
|
|
17978
|
+
{ gitignoreUpdated },
|
|
17979
|
+
applyMcpConfigOption(target, options, dryRun)
|
|
17980
|
+
);
|
|
17981
|
+
} catch (error) {
|
|
17982
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
17983
|
+
return makeResult({ ...base, success: false, error: msg });
|
|
17984
|
+
}
|
|
17985
|
+
}
|
|
17986
|
+
function renderMcpConfigLines(mcpConfig) {
|
|
17987
|
+
const lines = [];
|
|
17988
|
+
if (mcpConfig.alreadyMatched) {
|
|
17989
|
+
lines.push(`\u2713 .mcp.json already up to date: ${mcpConfig.mcpConfigPath}`);
|
|
17990
|
+
} else if (mcpConfig.written) {
|
|
17991
|
+
lines.push(`\u2713 Wrote MCP config: ${mcpConfig.mcpConfigPath}`);
|
|
17992
|
+
}
|
|
17993
|
+
if (mcpConfig.gitignoreUpdated) {
|
|
17994
|
+
lines.push(`\u2713 Added .mcp.json to .gitignore (per-machine; do not commit)`);
|
|
17995
|
+
}
|
|
17996
|
+
return lines;
|
|
17997
|
+
}
|
|
17998
|
+
function renderMcpConfigCaveat(mcpConfig) {
|
|
17999
|
+
if (mcpConfig?.written !== true) return [];
|
|
18000
|
+
return [
|
|
18001
|
+
"",
|
|
18002
|
+
"Note: .mcp.json contains an absolute path to your local data dir.",
|
|
18003
|
+
"It is per-machine and should NOT be committed \u2014 collaborators should",
|
|
18004
|
+
"run `nexus-agents init --portable --mcp-config` themselves."
|
|
18005
|
+
];
|
|
18006
|
+
}
|
|
18007
|
+
function formatInitPortableMessage(result, dryRun) {
|
|
18008
|
+
if (!result.success) {
|
|
18009
|
+
return `init --portable failed: ${result.error ?? "unknown error"}
|
|
18010
|
+
`;
|
|
18011
|
+
}
|
|
18012
|
+
if (dryRun) {
|
|
18013
|
+
const lines2 = [
|
|
18014
|
+
`(dry-run) would create ${String(result.created.length)} entries under:`,
|
|
18015
|
+
` ${result.absolutePath}`
|
|
18016
|
+
];
|
|
18017
|
+
return lines2.join("\n") + "\n";
|
|
18018
|
+
}
|
|
18019
|
+
const lines = [];
|
|
18020
|
+
lines.push(
|
|
18021
|
+
result.skipped ? `\u2713 Already initialized: ${result.absolutePath}` : `\u2713 Created: ${result.absolutePath}`
|
|
18022
|
+
);
|
|
18023
|
+
if (result.gitignoreUpdated) lines.push(`\u2713 Added entry to .gitignore`);
|
|
18024
|
+
if (result.mcpConfig !== void 0) lines.push(...renderMcpConfigLines(result.mcpConfig));
|
|
18025
|
+
lines.push("");
|
|
18026
|
+
lines.push("Activate by exporting:");
|
|
18027
|
+
lines.push(` export NEXUS_DATA_DIR=${result.absolutePath}`);
|
|
18028
|
+
lines.push("");
|
|
18029
|
+
lines.push("Or one-off:");
|
|
18030
|
+
lines.push(` NEXUS_DATA_DIR=${result.absolutePath} nexus-agents <cmd>`);
|
|
18031
|
+
lines.push(...renderMcpConfigCaveat(result.mcpConfig));
|
|
18032
|
+
return lines.join("\n") + "\n";
|
|
18033
|
+
}
|
|
17714
18034
|
|
|
17715
18035
|
// src/mcp/tools/dev-pipeline-tool.ts
|
|
17716
18036
|
import { z as z9 } from "zod";
|
|
@@ -18668,7 +18988,7 @@ function logFinalEventBusStats(logger17) {
|
|
|
18668
18988
|
// src/cli-orchestrator.ts
|
|
18669
18989
|
import * as readline2 from "readline";
|
|
18670
18990
|
function runOrchestratorRepl(options, logger17) {
|
|
18671
|
-
return new Promise((
|
|
18991
|
+
return new Promise((resolve15) => {
|
|
18672
18992
|
const rl = readline2.createInterface({
|
|
18673
18993
|
input: process.stdin,
|
|
18674
18994
|
output: process.stdout,
|
|
@@ -18704,7 +19024,7 @@ function runOrchestratorRepl(options, logger17) {
|
|
|
18704
19024
|
});
|
|
18705
19025
|
rl.on("close", () => {
|
|
18706
19026
|
logger17.info("Orchestrator REPL closed");
|
|
18707
|
-
|
|
19027
|
+
resolve15();
|
|
18708
19028
|
});
|
|
18709
19029
|
});
|
|
18710
19030
|
}
|
|
@@ -20523,8 +20843,8 @@ function printFirstRunHint() {
|
|
|
20523
20843
|
const isTTY = process.stderr.isTTY;
|
|
20524
20844
|
if (!isTTY) return;
|
|
20525
20845
|
const dataDir = getNexusDataDir();
|
|
20526
|
-
const hasConfig =
|
|
20527
|
-
if (
|
|
20846
|
+
const hasConfig = existsSync20("./nexus-agents.yaml") || existsSync20("./nexus-agents.yml");
|
|
20847
|
+
if (existsSync20(dataDir) || hasConfig) return;
|
|
20528
20848
|
process.stderr.write(
|
|
20529
20849
|
"\n\x1B[36mnexus-agents\x1B[0m: First time? Run \x1B[1mnexus-agents setup\x1B[0m to configure.\n\n"
|
|
20530
20850
|
);
|
|
@@ -20690,6 +21010,24 @@ async function handleDoctorCommand(args) {
|
|
|
20690
21010
|
}
|
|
20691
21011
|
process.exit(exitCode === 0 ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
|
|
20692
21012
|
}
|
|
21013
|
+
function handleInitCommand(args) {
|
|
21014
|
+
if (args.options.portable !== true) {
|
|
21015
|
+
process.stderr.write(
|
|
21016
|
+
"Usage: nexus-agents init --portable [path] [--force] [--dry-run] [--gitignore]\nBootstraps a workspace-local nexus-agents data directory.\n"
|
|
21017
|
+
);
|
|
21018
|
+
process.exit(EXIT_CODES.INVALID_ARGS);
|
|
21019
|
+
}
|
|
21020
|
+
const targetPath = args.positionals[1];
|
|
21021
|
+
const result = initPortable({
|
|
21022
|
+
...targetPath !== void 0 && targetPath !== "" ? { path: targetPath } : {},
|
|
21023
|
+
force: args.options.force,
|
|
21024
|
+
dryRun: args.options.dryRun,
|
|
21025
|
+
gitignore: args.options.gitignore ?? false,
|
|
21026
|
+
mcpConfig: args.options.mcpConfig ?? false
|
|
21027
|
+
});
|
|
21028
|
+
process.stdout.write(formatInitPortableMessage(result, args.options.dryRun));
|
|
21029
|
+
process.exit(result.success ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
|
|
21030
|
+
}
|
|
20693
21031
|
async function handleSetupCommandAsync(args) {
|
|
20694
21032
|
if (args.options.customApi !== void 0 && args.options.customApi !== "") {
|
|
20695
21033
|
const exitCode2 = await runCustomApiSetup(args);
|
|
@@ -22163,7 +22501,7 @@ function handleStatusCommand2(args) {
|
|
|
22163
22501
|
|
|
22164
22502
|
// src/cli/scenario-command.ts
|
|
22165
22503
|
import { readdir as readdir4 } from "fs/promises";
|
|
22166
|
-
import { join as
|
|
22504
|
+
import { join as join16, resolve as resolve14 } from "path";
|
|
22167
22505
|
|
|
22168
22506
|
// src/testing/e2e/scenario-runner.ts
|
|
22169
22507
|
import { readFile as readFile7 } from "fs/promises";
|
|
@@ -22323,7 +22661,7 @@ function checkCircularDependencies(workflow) {
|
|
|
22323
22661
|
var defaultStubFactory = {
|
|
22324
22662
|
createAgentStub(agentType, action) {
|
|
22325
22663
|
return async (inputs) => {
|
|
22326
|
-
await new Promise((
|
|
22664
|
+
await new Promise((resolve15) => setTimeout(resolve15, 10));
|
|
22327
22665
|
return {
|
|
22328
22666
|
stepId: `${agentType}-${action}`,
|
|
22329
22667
|
status: "success",
|
|
@@ -22482,7 +22820,7 @@ function createScenarioRunner(stubFactory) {
|
|
|
22482
22820
|
}
|
|
22483
22821
|
|
|
22484
22822
|
// src/cli/scenario-command.ts
|
|
22485
|
-
var FIXTURES_DIR =
|
|
22823
|
+
var FIXTURES_DIR = resolve14(import.meta.dirname, "../testing/e2e/fixtures");
|
|
22486
22824
|
var SCENARIO_SUFFIX = ".scenario.yaml";
|
|
22487
22825
|
async function listScenarios() {
|
|
22488
22826
|
try {
|
|
@@ -22533,7 +22871,7 @@ async function handleRun(args) {
|
|
|
22533
22871
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
22534
22872
|
}
|
|
22535
22873
|
const runner = createScenarioRunner();
|
|
22536
|
-
const fixturePath =
|
|
22874
|
+
const fixturePath = join16(FIXTURES_DIR, `${name}${SCENARIO_SUFFIX}`);
|
|
22537
22875
|
try {
|
|
22538
22876
|
const fixture = await runner.loadFixture(fixturePath);
|
|
22539
22877
|
const result = await runner.run(fixture);
|
|
@@ -22796,6 +23134,8 @@ var SYNC_COMMAND_HANDLERS = {
|
|
|
22796
23134
|
status: handleStatusCommand2,
|
|
22797
23135
|
// Issue #1023: Warm-Up Command
|
|
22798
23136
|
"warm-up": handleWarmUpCommand,
|
|
23137
|
+
// #2305: Init Portable Command
|
|
23138
|
+
init: handleInitCommand,
|
|
22799
23139
|
"e2e-eval": handleE2EEvalCommand,
|
|
22800
23140
|
"routing-ab": handleRoutingABCommand,
|
|
22801
23141
|
"memory-eval": handleMemoryEvalCommand,
|
|
@@ -23242,7 +23582,15 @@ function buildOptions(values) {
|
|
|
23242
23582
|
...buildSweBenchOptions(values),
|
|
23243
23583
|
...buildAtbenchOptions(values),
|
|
23244
23584
|
...buildLearningMetricsOptions(values),
|
|
23245
|
-
...buildSetupOptions(values)
|
|
23585
|
+
...buildSetupOptions(values),
|
|
23586
|
+
...buildInitOptions(values)
|
|
23587
|
+
};
|
|
23588
|
+
}
|
|
23589
|
+
function buildInitOptions(values) {
|
|
23590
|
+
return {
|
|
23591
|
+
portable: values.portable,
|
|
23592
|
+
gitignore: values.gitignore,
|
|
23593
|
+
mcpConfig: values["mcp-config"]
|
|
23246
23594
|
};
|
|
23247
23595
|
}
|
|
23248
23596
|
function parseCliArgs(args = process.argv.slice(2)) {
|