nexus-agents 2.79.4 → 2.80.1
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/{child-mcp-config-DFRYTRBK.js → child-mcp-config-Q6UMCPGZ.js} +3 -3
- package/dist/{chunk-UWDVEMYZ.js → chunk-23XU4LE2.js} +4 -4
- package/dist/chunk-2JQXC3CK.js +317 -0
- package/dist/chunk-2JQXC3CK.js.map +1 -0
- package/dist/{chunk-DOI7RE3X.js → chunk-33LDLZCC.js} +2 -2
- package/dist/{chunk-UNRTM43V.js → chunk-54UT2JUQ.js} +2 -2
- package/dist/{chunk-OGV7J5WG.js → chunk-5WN3WGXG.js} +3 -3
- package/dist/{chunk-NJPFN75N.js → chunk-7UM5XRGG.js} +2 -2
- package/dist/{chunk-JMRCMMZ5.js → chunk-7ZKZ7K7J.js} +2 -2
- package/dist/{chunk-45NUO4FE.js → chunk-ALDKPBOZ.js} +2 -2
- package/dist/{chunk-DW3UTO43.js → chunk-D3MQ4U2R.js} +51 -21
- package/dist/chunk-D3MQ4U2R.js.map +1 -0
- package/dist/{chunk-NVSJXN4S.js → chunk-D4NEYNBO.js} +8 -5
- package/dist/chunk-D4NEYNBO.js.map +1 -0
- package/dist/{chunk-42MM7GKW.js → chunk-D5C5N5Q4.js} +2 -2
- package/dist/{chunk-BIH2CBC5.js → chunk-EPZMFIAX.js} +105 -10
- package/dist/chunk-EPZMFIAX.js.map +1 -0
- package/dist/{chunk-ACP4YARI.js → chunk-GODRGVF4.js} +3 -3
- package/dist/{chunk-IPDUZJPH.js → chunk-HR7C4DSA.js} +4 -4
- package/dist/{chunk-PAKVXGS2.js → chunk-I5KYDT23.js} +2 -2
- package/dist/{chunk-PDCLBWH5.js → chunk-L7433REX.js} +4 -4
- package/dist/{chunk-3ENBGGYA.js → chunk-LDD272PW.js} +959 -885
- package/dist/chunk-LDD272PW.js.map +1 -0
- package/dist/{chunk-OFRDE7MK.js → chunk-MUIA32LU.js} +2 -2
- package/dist/{chunk-TN5ZKSGC.js → chunk-MVIYQMQM.js} +2 -2
- package/dist/{chunk-NXNNT5XW.js → chunk-NALIFUBD.js} +4 -4
- package/dist/{chunk-LFTK5ZQG.js → chunk-NCBWA6RU.js} +2 -2
- package/dist/{chunk-BXI6DKBU.js → chunk-O2ECPTFH.js} +3 -3
- package/dist/{chunk-UNFS6YBY.js → chunk-Q4DXTNGR.js} +2 -2
- package/dist/{chunk-BSQ4KTY4.js → chunk-SX3P2PD2.js} +2 -2
- package/dist/{chunk-UQOSVOEU.js → chunk-T4E6UFFC.js} +16 -14
- package/dist/chunk-T4E6UFFC.js.map +1 -0
- package/dist/{chunk-UOR2JWFH.js → chunk-TFTP7EUQ.js} +82 -57
- package/dist/chunk-TFTP7EUQ.js.map +1 -0
- package/dist/{chunk-PHBRELUK.js → chunk-UEKTTIDA.js} +7 -7
- package/dist/{chunk-SU3Y6LU2.js → chunk-WZ2T4T7N.js} +32 -6
- package/dist/chunk-WZ2T4T7N.js.map +1 -0
- package/dist/{cli-circuit-breaker-T75HOLZK.js → cli-circuit-breaker-EUERR2HK.js} +5 -5
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +618 -567
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-OPSK5FCQ.js → composite-router-ZP72LQFH.js} +3 -3
- package/dist/{consensus-vote-CYUPIJXR.js → consensus-vote-TU3TQ4VH.js} +12 -12
- package/dist/{context-retriever-6AWHCHRP.js → context-retriever-OTLV46DF.js} +6 -6
- package/dist/{doctor-deep-XBPRQ6ZP.js → doctor-deep-ZMBSG2DF.js} +4 -4
- package/dist/expert-bridge-IK4TY7HA.js +11 -0
- package/dist/{factory-Y3TMP4OQ.js → factory-45NHZFLK.js} +5 -5
- package/dist/factory-QDHYIYVE.js +14 -0
- package/dist/index.d.ts +40 -5
- package/dist/index.js +25 -25
- package/dist/{init-opencode-RV6IQEMS.js → init-opencode-WFL4OXMB.js} +6 -6
- package/dist/issue-triage-UHFCGTEJ.js +15 -0
- package/dist/{learning-persistence-Q3HTOGTU.js → learning-persistence-TGOBRUUU.js} +2 -2
- package/dist/{registry-command-6KJWW3W7.js → registry-command-YMZPSW7S.js} +3 -3
- package/dist/{repo-security-plan-HNLMF7J7.js → repo-security-plan-TGDXTSHS.js} +4 -4
- package/dist/{research-helpers-synthesize-77TLYSW4.js → research-helpers-synthesize-5BAN353Y.js} +4 -4
- package/dist/{routing-memory-6DV6ZPAH.js → routing-memory-RG3U2MC2.js} +3 -3
- package/dist/{session-memory-XZ3NJIR4.js → session-memory-C5GC2JAX.js} +4 -4
- package/dist/{setup-command-QOXG36UV.js → setup-command-OXJ32UAI.js} +13 -11
- package/dist/setup-config-KNMVMGDD.js +10 -0
- package/dist/{setup-custom-api-PJ6TGHJH.js → setup-custom-api-4EYRKCHB.js} +5 -5
- package/dist/{tool-memory-K2QPTPKV.js → tool-memory-LUXUOE6Q.js} +5 -5
- package/dist/{weather-report-ZB4AKOIA.js → weather-report-3KSDTC7T.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-3ENBGGYA.js.map +0 -1
- package/dist/chunk-7BMOZJYS.js +0 -83
- package/dist/chunk-7BMOZJYS.js.map +0 -1
- package/dist/chunk-BIH2CBC5.js.map +0 -1
- package/dist/chunk-DW3UTO43.js.map +0 -1
- package/dist/chunk-NVSJXN4S.js.map +0 -1
- package/dist/chunk-SU3Y6LU2.js.map +0 -1
- package/dist/chunk-UOR2JWFH.js.map +0 -1
- package/dist/chunk-UQOSVOEU.js.map +0 -1
- package/dist/expert-bridge-5YOPK5IT.js +0 -11
- package/dist/factory-DN7SJZ5Z.js +0 -14
- package/dist/issue-triage-UTWKXLKC.js +0 -15
- package/dist/setup-config-B4V4QHDP.js +0 -10
- /package/dist/{child-mcp-config-DFRYTRBK.js.map → child-mcp-config-Q6UMCPGZ.js.map} +0 -0
- /package/dist/{chunk-UWDVEMYZ.js.map → chunk-23XU4LE2.js.map} +0 -0
- /package/dist/{chunk-DOI7RE3X.js.map → chunk-33LDLZCC.js.map} +0 -0
- /package/dist/{chunk-UNRTM43V.js.map → chunk-54UT2JUQ.js.map} +0 -0
- /package/dist/{chunk-OGV7J5WG.js.map → chunk-5WN3WGXG.js.map} +0 -0
- /package/dist/{chunk-NJPFN75N.js.map → chunk-7UM5XRGG.js.map} +0 -0
- /package/dist/{chunk-JMRCMMZ5.js.map → chunk-7ZKZ7K7J.js.map} +0 -0
- /package/dist/{chunk-45NUO4FE.js.map → chunk-ALDKPBOZ.js.map} +0 -0
- /package/dist/{chunk-42MM7GKW.js.map → chunk-D5C5N5Q4.js.map} +0 -0
- /package/dist/{chunk-ACP4YARI.js.map → chunk-GODRGVF4.js.map} +0 -0
- /package/dist/{chunk-IPDUZJPH.js.map → chunk-HR7C4DSA.js.map} +0 -0
- /package/dist/{chunk-PAKVXGS2.js.map → chunk-I5KYDT23.js.map} +0 -0
- /package/dist/{chunk-PDCLBWH5.js.map → chunk-L7433REX.js.map} +0 -0
- /package/dist/{chunk-OFRDE7MK.js.map → chunk-MUIA32LU.js.map} +0 -0
- /package/dist/{chunk-TN5ZKSGC.js.map → chunk-MVIYQMQM.js.map} +0 -0
- /package/dist/{chunk-NXNNT5XW.js.map → chunk-NALIFUBD.js.map} +0 -0
- /package/dist/{chunk-LFTK5ZQG.js.map → chunk-NCBWA6RU.js.map} +0 -0
- /package/dist/{chunk-BXI6DKBU.js.map → chunk-O2ECPTFH.js.map} +0 -0
- /package/dist/{chunk-UNFS6YBY.js.map → chunk-Q4DXTNGR.js.map} +0 -0
- /package/dist/{chunk-BSQ4KTY4.js.map → chunk-SX3P2PD2.js.map} +0 -0
- /package/dist/{chunk-PHBRELUK.js.map → chunk-UEKTTIDA.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-T75HOLZK.js.map → cli-circuit-breaker-EUERR2HK.js.map} +0 -0
- /package/dist/{composite-router-OPSK5FCQ.js.map → composite-router-ZP72LQFH.js.map} +0 -0
- /package/dist/{consensus-vote-CYUPIJXR.js.map → consensus-vote-TU3TQ4VH.js.map} +0 -0
- /package/dist/{context-retriever-6AWHCHRP.js.map → context-retriever-OTLV46DF.js.map} +0 -0
- /package/dist/{doctor-deep-XBPRQ6ZP.js.map → doctor-deep-ZMBSG2DF.js.map} +0 -0
- /package/dist/{expert-bridge-5YOPK5IT.js.map → expert-bridge-IK4TY7HA.js.map} +0 -0
- /package/dist/{factory-DN7SJZ5Z.js.map → factory-45NHZFLK.js.map} +0 -0
- /package/dist/{factory-Y3TMP4OQ.js.map → factory-QDHYIYVE.js.map} +0 -0
- /package/dist/{init-opencode-RV6IQEMS.js.map → init-opencode-WFL4OXMB.js.map} +0 -0
- /package/dist/{issue-triage-UTWKXLKC.js.map → issue-triage-UHFCGTEJ.js.map} +0 -0
- /package/dist/{learning-persistence-Q3HTOGTU.js.map → learning-persistence-TGOBRUUU.js.map} +0 -0
- /package/dist/{registry-command-6KJWW3W7.js.map → registry-command-YMZPSW7S.js.map} +0 -0
- /package/dist/{repo-security-plan-HNLMF7J7.js.map → repo-security-plan-TGDXTSHS.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-77TLYSW4.js.map → research-helpers-synthesize-5BAN353Y.js.map} +0 -0
- /package/dist/{routing-memory-6DV6ZPAH.js.map → routing-memory-RG3U2MC2.js.map} +0 -0
- /package/dist/{session-memory-XZ3NJIR4.js.map → session-memory-C5GC2JAX.js.map} +0 -0
- /package/dist/{setup-command-QOXG36UV.js.map → setup-command-OXJ32UAI.js.map} +0 -0
- /package/dist/{setup-config-B4V4QHDP.js.map → setup-config-KNMVMGDD.js.map} +0 -0
- /package/dist/{setup-custom-api-PJ6TGHJH.js.map → setup-custom-api-4EYRKCHB.js.map} +0 -0
- /package/dist/{tool-memory-K2QPTPKV.js.map → tool-memory-LUXUOE6Q.js.map} +0 -0
- /package/dist/{weather-report-ZB4AKOIA.js.map → weather-report-3KSDTC7T.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -12,18 +12,18 @@ import {
|
|
|
12
12
|
parseFindings,
|
|
13
13
|
sumFindings
|
|
14
14
|
} from "./chunk-3RZWLQSC.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-7ZKZ7K7J.js";
|
|
16
16
|
import {
|
|
17
17
|
buildOpenAICompatAdapters,
|
|
18
18
|
loadUsageEvents,
|
|
19
19
|
readOpenAICompatEnv,
|
|
20
20
|
rollupByModel
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-HR7C4DSA.js";
|
|
22
22
|
import {
|
|
23
23
|
setupCommandAsync,
|
|
24
24
|
verifyCommand
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
import "./chunk-
|
|
25
|
+
} from "./chunk-WZ2T4T7N.js";
|
|
26
|
+
import "./chunk-D4NEYNBO.js";
|
|
27
27
|
import {
|
|
28
28
|
AuthHandler,
|
|
29
29
|
DEFAULT_EXPERTS,
|
|
@@ -153,56 +153,61 @@ import {
|
|
|
153
153
|
validateCommand,
|
|
154
154
|
validateWorkflow,
|
|
155
155
|
wrapInMarkdownFence
|
|
156
|
-
} from "./chunk-
|
|
156
|
+
} from "./chunk-LDD272PW.js";
|
|
157
157
|
import "./chunk-AP2FD37C.js";
|
|
158
158
|
import "./chunk-ED6VQWNG.js";
|
|
159
159
|
import {
|
|
160
160
|
resolveToken
|
|
161
|
-
} from "./chunk-
|
|
161
|
+
} from "./chunk-NCBWA6RU.js";
|
|
162
162
|
import {
|
|
163
163
|
CATEGORY_DISPLAY_NAMES,
|
|
164
164
|
DEFAULT_PR_REVIEW_CONFIG
|
|
165
165
|
} from "./chunk-X2M7OF27.js";
|
|
166
|
-
import "./chunk-
|
|
167
|
-
import "./chunk-
|
|
168
|
-
import "./chunk-
|
|
166
|
+
import "./chunk-5WN3WGXG.js";
|
|
167
|
+
import "./chunk-GODRGVF4.js";
|
|
168
|
+
import "./chunk-UEKTTIDA.js";
|
|
169
169
|
import {
|
|
170
170
|
DEFAULT_VOTE_TIMEOUT_MS,
|
|
171
171
|
ErrorPolicySchema,
|
|
172
172
|
VOTER_ROLES,
|
|
173
173
|
VoteThresholdSchema,
|
|
174
174
|
createDefaultPolicyFirewall,
|
|
175
|
+
createSecureHandler,
|
|
175
176
|
createUnifiedRegistry,
|
|
176
177
|
executeVoting,
|
|
177
178
|
getToolAnnotations,
|
|
179
|
+
getToolTimeout,
|
|
178
180
|
registerConsensusVoteTool,
|
|
181
|
+
toSdkCallback,
|
|
179
182
|
toolStructuredError,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
toolSuccessStructured,
|
|
184
|
+
warnIfSimulatedOutsideTests,
|
|
185
|
+
wrapToolWithTimeout
|
|
186
|
+
} from "./chunk-D3MQ4U2R.js";
|
|
187
|
+
import "./chunk-I5KYDT23.js";
|
|
188
|
+
import "./chunk-33LDLZCC.js";
|
|
184
189
|
import {
|
|
185
190
|
loadPapersRegistry,
|
|
186
191
|
loadTechniquesRegistry,
|
|
187
192
|
savePapersRegistry,
|
|
188
193
|
synthesizeResearch
|
|
189
|
-
} from "./chunk-
|
|
194
|
+
} from "./chunk-Q4DXTNGR.js";
|
|
190
195
|
import {
|
|
191
196
|
classifyTrust,
|
|
192
197
|
createFullGitHubProvider,
|
|
193
198
|
evaluatePolicy,
|
|
194
199
|
parsePRUrl,
|
|
195
200
|
sanitizeInput
|
|
196
|
-
} from "./chunk-
|
|
197
|
-
import "./chunk-
|
|
198
|
-
import "./chunk-
|
|
201
|
+
} from "./chunk-O2ECPTFH.js";
|
|
202
|
+
import "./chunk-SX3P2PD2.js";
|
|
203
|
+
import "./chunk-MVIYQMQM.js";
|
|
199
204
|
import "./chunk-7J7PNOJQ.js";
|
|
200
205
|
import "./chunk-BQ4YXGGQ.js";
|
|
201
|
-
import "./chunk-
|
|
206
|
+
import "./chunk-L7433REX.js";
|
|
202
207
|
import {
|
|
203
208
|
MemoryError,
|
|
204
209
|
shutdownToolMemory
|
|
205
|
-
} from "./chunk-
|
|
210
|
+
} from "./chunk-NALIFUBD.js";
|
|
206
211
|
import {
|
|
207
212
|
CustomExpertDefinitionSchema,
|
|
208
213
|
DATA_SUBDIRECTORIES,
|
|
@@ -221,12 +226,12 @@ import {
|
|
|
221
226
|
loadConfig,
|
|
222
227
|
runDoctor,
|
|
223
228
|
validateNexusEnv
|
|
224
|
-
} from "./chunk-
|
|
225
|
-
import "./chunk-
|
|
226
|
-
import "./chunk-
|
|
229
|
+
} from "./chunk-TFTP7EUQ.js";
|
|
230
|
+
import "./chunk-MUIA32LU.js";
|
|
231
|
+
import "./chunk-D5C5N5Q4.js";
|
|
227
232
|
import {
|
|
228
233
|
DEFAULTS
|
|
229
|
-
} from "./chunk-
|
|
234
|
+
} from "./chunk-54UT2JUQ.js";
|
|
230
235
|
import "./chunk-NUBSJGQZ.js";
|
|
231
236
|
import {
|
|
232
237
|
capitalize,
|
|
@@ -238,11 +243,11 @@ import {
|
|
|
238
243
|
getAvailableClis,
|
|
239
244
|
isRecord,
|
|
240
245
|
probeAllClis
|
|
241
|
-
} from "./chunk-
|
|
242
|
-
import "./chunk-
|
|
246
|
+
} from "./chunk-EPZMFIAX.js";
|
|
247
|
+
import "./chunk-7UM5XRGG.js";
|
|
243
248
|
import "./chunk-ZM4O442V.js";
|
|
244
249
|
import "./chunk-PQHVC4BD.js";
|
|
245
|
-
import "./chunk-
|
|
250
|
+
import "./chunk-ALDKPBOZ.js";
|
|
246
251
|
import {
|
|
247
252
|
API_TIMEOUTS,
|
|
248
253
|
AgentCapability,
|
|
@@ -310,125 +315,19 @@ import {
|
|
|
310
315
|
validateTimeout,
|
|
311
316
|
writeEmptyLine,
|
|
312
317
|
writeLine
|
|
313
|
-
} from "./chunk-
|
|
318
|
+
} from "./chunk-T4E6UFFC.js";
|
|
314
319
|
import {
|
|
320
|
+
applyPortableMode,
|
|
315
321
|
detectSandbox,
|
|
322
|
+
findRepoRoot,
|
|
316
323
|
getNexusDataDir,
|
|
324
|
+
getPerRepoSubdirs,
|
|
317
325
|
nexusDataPath
|
|
318
|
-
} from "./chunk-
|
|
326
|
+
} from "./chunk-2JQXC3CK.js";
|
|
319
327
|
import "./chunk-UP2VWCW5.js";
|
|
320
328
|
|
|
321
329
|
// src/cli/cli-log-bootstrap.ts
|
|
322
330
|
import { argv, env } from "process";
|
|
323
|
-
|
|
324
|
-
// src/config/portable-mode.ts
|
|
325
|
-
import { accessSync, constants, existsSync, readFileSync, appendFileSync, statSync } from "fs";
|
|
326
|
-
import { homedir } from "os";
|
|
327
|
-
import { join, resolve } from "path";
|
|
328
|
-
var SANDBOX_ENV_VARS = [
|
|
329
|
-
"KUBERNETES_SERVICE_HOST",
|
|
330
|
-
"DOCKER_CONTAINER",
|
|
331
|
-
"ECS_CONTAINER_METADATA_URI",
|
|
332
|
-
"ECS_CONTAINER_METADATA_URI_V4",
|
|
333
|
-
"SANDBOX",
|
|
334
|
-
"NEXUS_SANDBOX"
|
|
335
|
-
];
|
|
336
|
-
var DETECTED = false;
|
|
337
|
-
function isHomeWritable() {
|
|
338
|
-
try {
|
|
339
|
-
const home = homedir();
|
|
340
|
-
if (!existsSync(home)) return false;
|
|
341
|
-
accessSync(home, constants.W_OK);
|
|
342
|
-
return true;
|
|
343
|
-
} catch {
|
|
344
|
-
return false;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
function inSandboxEnv() {
|
|
348
|
-
for (const v of SANDBOX_ENV_VARS) {
|
|
349
|
-
const val = process.env[v];
|
|
350
|
-
if (val !== void 0 && val !== "") return true;
|
|
351
|
-
}
|
|
352
|
-
return false;
|
|
353
|
-
}
|
|
354
|
-
function checkExplicitEnv(cwd) {
|
|
355
|
-
const fromEnv = process.env["NEXUS_DATA_DIR"]?.trim();
|
|
356
|
-
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
357
|
-
return { portable: false, dataDir: resolve(fromEnv), reason: "env-data-dir" };
|
|
358
|
-
}
|
|
359
|
-
const portableEnv = process.env["NEXUS_PORTABLE_MODE"];
|
|
360
|
-
if (portableEnv === "0" || portableEnv === "false") {
|
|
361
|
-
return { portable: false, dataDir: join(homedir(), ".nexus-agents"), reason: "env-opt-out" };
|
|
362
|
-
}
|
|
363
|
-
if (portableEnv === "1" || portableEnv === "true") {
|
|
364
|
-
return { portable: true, dataDir: join(cwd, ".nexus-agents"), reason: "env-opt-in" };
|
|
365
|
-
}
|
|
366
|
-
return null;
|
|
367
|
-
}
|
|
368
|
-
function checkHeuristics(cwd) {
|
|
369
|
-
if (!isHomeWritable()) {
|
|
370
|
-
return { portable: true, dataDir: join(cwd, ".nexus-agents"), reason: "home-unwritable" };
|
|
371
|
-
}
|
|
372
|
-
if (inSandboxEnv()) {
|
|
373
|
-
return { portable: true, dataDir: join(cwd, ".nexus-agents"), reason: "container-env" };
|
|
374
|
-
}
|
|
375
|
-
return null;
|
|
376
|
-
}
|
|
377
|
-
function detectPortableMode(cwd = process.cwd()) {
|
|
378
|
-
return checkExplicitEnv(cwd) ?? checkHeuristics(cwd) ?? {
|
|
379
|
-
portable: false,
|
|
380
|
-
dataDir: join(homedir(), ".nexus-agents"),
|
|
381
|
-
reason: "default"
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
function applyPortableMode(cwd = process.cwd()) {
|
|
385
|
-
if (DETECTED) return;
|
|
386
|
-
DETECTED = true;
|
|
387
|
-
const result = detectPortableMode(cwd);
|
|
388
|
-
if (!result.portable) return;
|
|
389
|
-
if (result.reason === "home-unwritable" || result.reason === "container-env") {
|
|
390
|
-
process.stderr.write(
|
|
391
|
-
`[portable-mode] Sandbox detected (${result.reason}). Using ${result.dataDir} for all nexus-agents data.
|
|
392
|
-
Set NEXUS_PORTABLE_MODE=0 to override; see docs/guides/SANDBOXED-USAGE.md
|
|
393
|
-
`
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
process.env["NEXUS_DATA_DIR"] = result.dataDir;
|
|
397
|
-
if (isInsideGitRepo(cwd)) {
|
|
398
|
-
ensureGitignored(cwd, ".nexus-agents/");
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
function isInsideGitRepo(cwd) {
|
|
402
|
-
try {
|
|
403
|
-
const gitDir = join(cwd, ".git");
|
|
404
|
-
return existsSync(gitDir) && statSync(gitDir).isDirectory();
|
|
405
|
-
} catch {
|
|
406
|
-
return false;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
function ensureGitignored(cwd, entry) {
|
|
410
|
-
const path22 = join(cwd, ".gitignore");
|
|
411
|
-
try {
|
|
412
|
-
const existing = existsSync(path22) ? readFileSync(path22, "utf-8") : "";
|
|
413
|
-
const lines = existing.split("\n").map((l) => l.trim());
|
|
414
|
-
if (lines.includes(entry) || lines.includes(entry.replace(/\/$/, ""))) return;
|
|
415
|
-
const sep3 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
416
|
-
appendFileSync(path22, `${sep3}${entry}
|
|
417
|
-
`, "utf-8");
|
|
418
|
-
process.stderr.write(
|
|
419
|
-
`[portable-mode] Added '${entry}' to ${path22} so nexus-agents data is gitignored.
|
|
420
|
-
`
|
|
421
|
-
);
|
|
422
|
-
} catch (e) {
|
|
423
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
424
|
-
process.stderr.write(
|
|
425
|
-
`[portable-mode] Could not auto-update ${path22} (${msg}). Add '${entry}' manually if you don't want nexus-agents data tracked by git.
|
|
426
|
-
`
|
|
427
|
-
);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// src/cli/cli-log-bootstrap.ts
|
|
432
331
|
var SERVER_COMMANDS = /* @__PURE__ */ new Set(["server"]);
|
|
433
332
|
var VERBOSE_FLAGS = /* @__PURE__ */ new Set(["--verbose", "-v", "--debug"]);
|
|
434
333
|
function findSubcommand(args) {
|
|
@@ -512,10 +411,11 @@ function helloCommand() {
|
|
|
512
411
|
}
|
|
513
412
|
|
|
514
413
|
// src/cli/config-init.ts
|
|
515
|
-
import { existsSync
|
|
414
|
+
import { existsSync } from "fs";
|
|
516
415
|
import { writeFile, mkdir } from "fs/promises";
|
|
517
|
-
import { dirname, resolve
|
|
416
|
+
import { dirname, resolve } from "path";
|
|
518
417
|
var DEFAULT_CONFIG_FILE = "nexus-agents.yaml";
|
|
418
|
+
var DEFAULT_CONFIG_REL_PATH = `.nexus-agents/${DEFAULT_CONFIG_FILE}`;
|
|
519
419
|
function qualifiesPowerful(m) {
|
|
520
420
|
return (m.qualityScores?.reasoning ?? 0) >= 9;
|
|
521
421
|
}
|
|
@@ -692,16 +592,20 @@ logging:
|
|
|
692
592
|
`;
|
|
693
593
|
function resolveOutputPath(output2) {
|
|
694
594
|
if (output2 !== void 0 && output2 !== "") {
|
|
695
|
-
return
|
|
595
|
+
return resolve(process.cwd(), output2);
|
|
696
596
|
}
|
|
697
|
-
|
|
597
|
+
const legacyPath = resolve(process.cwd(), DEFAULT_CONFIG_FILE);
|
|
598
|
+
if (existsSync(legacyPath)) {
|
|
599
|
+
return legacyPath;
|
|
600
|
+
}
|
|
601
|
+
return resolve(process.cwd(), DEFAULT_CONFIG_REL_PATH);
|
|
698
602
|
}
|
|
699
603
|
function fileExists(path22) {
|
|
700
|
-
return
|
|
604
|
+
return existsSync(path22);
|
|
701
605
|
}
|
|
702
606
|
async function ensureDirectory(filePath) {
|
|
703
607
|
const dir = dirname(filePath);
|
|
704
|
-
if (dir !== "." && !
|
|
608
|
+
if (dir !== "." && !existsSync(dir)) {
|
|
705
609
|
await mkdir(dir, { recursive: true });
|
|
706
610
|
}
|
|
707
611
|
}
|
|
@@ -765,10 +669,10 @@ async function configInitCommand(options = {}) {
|
|
|
765
669
|
}
|
|
766
670
|
|
|
767
671
|
// src/cli/custom-expert-validation.ts
|
|
768
|
-
import { resolve as
|
|
672
|
+
import { resolve as resolve2, sep } from "path";
|
|
769
673
|
function validateConfigPath(userPath, allowedRoot) {
|
|
770
|
-
const resolvedRoot =
|
|
771
|
-
const resolved =
|
|
674
|
+
const resolvedRoot = resolve2(allowedRoot);
|
|
675
|
+
const resolved = resolve2(allowedRoot, userPath);
|
|
772
676
|
if (!resolved.startsWith(resolvedRoot + sep) && resolved !== resolvedRoot) {
|
|
773
677
|
return err(
|
|
774
678
|
new SecurityError("Path traversal detected: config path escapes allowed root directory", {
|
|
@@ -836,8 +740,8 @@ function formatValidationErrors(errors) {
|
|
|
836
740
|
}
|
|
837
741
|
|
|
838
742
|
// src/cli/custom-expert-parsing.ts
|
|
839
|
-
import { readFileSync
|
|
840
|
-
import { resolve as
|
|
743
|
+
import { readFileSync, existsSync as existsSync2 } from "fs";
|
|
744
|
+
import { resolve as resolve3 } from "path";
|
|
841
745
|
import * as yaml from "yaml";
|
|
842
746
|
var DEFAULT_CONFIG_FILE2 = "nexus-agents.yaml";
|
|
843
747
|
function findConfigPath() {
|
|
@@ -848,12 +752,12 @@ function findConfigPath() {
|
|
|
848
752
|
if (!validation.ok) {
|
|
849
753
|
return { securityError: validation.error };
|
|
850
754
|
}
|
|
851
|
-
if (
|
|
755
|
+
if (existsSync2(validation.value)) {
|
|
852
756
|
return { path: validation.value };
|
|
853
757
|
}
|
|
854
758
|
}
|
|
855
|
-
const cwdPath =
|
|
856
|
-
if (
|
|
759
|
+
const cwdPath = resolve3(cwd, DEFAULT_CONFIG_FILE2);
|
|
760
|
+
if (existsSync2(cwdPath)) {
|
|
857
761
|
return { path: cwdPath };
|
|
858
762
|
}
|
|
859
763
|
return {};
|
|
@@ -956,7 +860,7 @@ function resolveConfigPath(configPath) {
|
|
|
956
860
|
}
|
|
957
861
|
function readConfigContent(configPath) {
|
|
958
862
|
try {
|
|
959
|
-
return { content:
|
|
863
|
+
return { content: readFileSync(configPath, "utf-8") };
|
|
960
864
|
} catch (error) {
|
|
961
865
|
return {
|
|
962
866
|
error: {
|
|
@@ -1604,10 +1508,10 @@ async function handleBuiltInCommand(input, session) {
|
|
|
1604
1508
|
}
|
|
1605
1509
|
return { handled: false, exit: false };
|
|
1606
1510
|
}
|
|
1607
|
-
function handleTask(input, session,
|
|
1511
|
+
function handleTask(input, session, logger18) {
|
|
1608
1512
|
const trimmed = input.trim();
|
|
1609
1513
|
if (session.verbose) {
|
|
1610
|
-
|
|
1514
|
+
logger18.debug("Processing task", { task: trimmed, sessionId: session.sessionId });
|
|
1611
1515
|
}
|
|
1612
1516
|
process.stdout.write(`
|
|
1613
1517
|
${colors.bold}Task Analysis:${colors.reset}
|
|
@@ -1651,7 +1555,7 @@ function createReadlineInterface() {
|
|
|
1651
1555
|
historySize: 100
|
|
1652
1556
|
});
|
|
1653
1557
|
}
|
|
1654
|
-
async function processLine(line, session,
|
|
1558
|
+
async function processLine(line, session, logger18) {
|
|
1655
1559
|
const trimmed = line.trim();
|
|
1656
1560
|
if (trimmed === "") {
|
|
1657
1561
|
return false;
|
|
@@ -1665,36 +1569,36 @@ async function processLine(line, session, logger17) {
|
|
|
1665
1569
|
}
|
|
1666
1570
|
return result.exit;
|
|
1667
1571
|
}
|
|
1668
|
-
handleTask(trimmed, session,
|
|
1572
|
+
handleTask(trimmed, session, logger18);
|
|
1669
1573
|
return false;
|
|
1670
1574
|
}
|
|
1671
1575
|
async function startRepl(options = {}) {
|
|
1672
|
-
const
|
|
1576
|
+
const logger18 = createLogger({ component: "repl" });
|
|
1673
1577
|
const session = createSession(options.verbose ?? false);
|
|
1674
1578
|
if (session.verbose) {
|
|
1675
|
-
|
|
1579
|
+
logger18.setLevel("debug");
|
|
1676
1580
|
}
|
|
1677
|
-
|
|
1581
|
+
logger18.info("Starting interactive REPL", { sessionId: session.sessionId });
|
|
1678
1582
|
printBanner();
|
|
1679
1583
|
const rl = createReadlineInterface();
|
|
1680
1584
|
rl.on("close", () => {
|
|
1681
1585
|
process.stdout.write(`
|
|
1682
1586
|
${colors.dim}Session ended.${colors.reset}
|
|
1683
1587
|
`);
|
|
1684
|
-
|
|
1588
|
+
logger18.info("REPL session ended", {
|
|
1685
1589
|
sessionId: session.sessionId,
|
|
1686
1590
|
commandsRun: session.history.length
|
|
1687
1591
|
});
|
|
1688
1592
|
});
|
|
1689
1593
|
rl.prompt();
|
|
1690
|
-
return new Promise((
|
|
1594
|
+
return new Promise((resolve14) => {
|
|
1691
1595
|
rl.on("line", (line) => {
|
|
1692
1596
|
void (async () => {
|
|
1693
1597
|
try {
|
|
1694
|
-
const shouldExit = await processLine(line, session,
|
|
1598
|
+
const shouldExit = await processLine(line, session, logger18);
|
|
1695
1599
|
if (shouldExit) {
|
|
1696
1600
|
rl.close();
|
|
1697
|
-
|
|
1601
|
+
resolve14();
|
|
1698
1602
|
return;
|
|
1699
1603
|
}
|
|
1700
1604
|
} catch (error) {
|
|
@@ -1706,7 +1610,7 @@ ${colors.dim}Session ended.${colors.reset}
|
|
|
1706
1610
|
})();
|
|
1707
1611
|
});
|
|
1708
1612
|
rl.on("close", () => {
|
|
1709
|
-
|
|
1613
|
+
resolve14();
|
|
1710
1614
|
});
|
|
1711
1615
|
});
|
|
1712
1616
|
}
|
|
@@ -1724,7 +1628,7 @@ async function replCommand(options = {}) {
|
|
|
1724
1628
|
|
|
1725
1629
|
// src/self-eval/component-scanner.ts
|
|
1726
1630
|
import { readdir, readFile, stat } from "fs/promises";
|
|
1727
|
-
import { join
|
|
1631
|
+
import { join, basename, extname, relative } from "path";
|
|
1728
1632
|
var DEFAULT_EXTENSIONS = [".ts"];
|
|
1729
1633
|
var DEFAULT_MAX_FILE_SIZE = 1024 * 1024;
|
|
1730
1634
|
var COMPLEXITY_PATTERNS = [
|
|
@@ -1789,7 +1693,7 @@ var ComponentScanner = class {
|
|
|
1789
1693
|
const files = [];
|
|
1790
1694
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
1791
1695
|
for (const entry of entries) {
|
|
1792
|
-
const fullPath =
|
|
1696
|
+
const fullPath = join(directory, entry.name);
|
|
1793
1697
|
if (entry.isDirectory()) {
|
|
1794
1698
|
const subFiles = await this.findFiles(fullPath);
|
|
1795
1699
|
files.push(...subFiles);
|
|
@@ -3339,6 +3243,9 @@ function safeExecSandboxed(commandString, options = {}) {
|
|
|
3339
3243
|
if (options.cwd !== void 0) {
|
|
3340
3244
|
execOptions.cwd = options.cwd;
|
|
3341
3245
|
}
|
|
3246
|
+
if (options.stdin !== void 0) {
|
|
3247
|
+
execOptions.input = options.stdin;
|
|
3248
|
+
}
|
|
3342
3249
|
const result = execSync(commandString, execOptions);
|
|
3343
3250
|
return typeof result === "string" ? result.trim() : result.toString("utf-8").trim();
|
|
3344
3251
|
} catch (error) {
|
|
@@ -4214,27 +4121,27 @@ var CliAdapterAgent = class {
|
|
|
4214
4121
|
};
|
|
4215
4122
|
|
|
4216
4123
|
// src/cli/orchestrate-puppeteer.ts
|
|
4217
|
-
function loadPolicyParameters(path22,
|
|
4124
|
+
function loadPolicyParameters(path22, logger18) {
|
|
4218
4125
|
try {
|
|
4219
4126
|
if (fs2.existsSync(path22)) {
|
|
4220
4127
|
const content = fs2.readFileSync(path22, "utf-8");
|
|
4221
4128
|
const params = JSON.parse(content);
|
|
4222
|
-
|
|
4129
|
+
logger18.info("Loaded policy parameters", { path: path22 });
|
|
4223
4130
|
return params;
|
|
4224
4131
|
}
|
|
4225
4132
|
} catch (error) {
|
|
4226
4133
|
const message = getErrorMessage(error);
|
|
4227
|
-
|
|
4134
|
+
logger18.warn("Failed to load policy parameters", { path: path22, error: message });
|
|
4228
4135
|
}
|
|
4229
4136
|
return void 0;
|
|
4230
4137
|
}
|
|
4231
|
-
function savePolicyParameters(path22, params,
|
|
4138
|
+
function savePolicyParameters(path22, params, logger18) {
|
|
4232
4139
|
try {
|
|
4233
4140
|
fs2.writeFileSync(path22, JSON.stringify(params, null, 2));
|
|
4234
|
-
|
|
4141
|
+
logger18.info("Saved policy parameters", { path: path22 });
|
|
4235
4142
|
} catch (error) {
|
|
4236
4143
|
const message = getErrorMessage(error);
|
|
4237
|
-
|
|
4144
|
+
logger18.warn("Failed to save policy parameters", { path: path22, error: message });
|
|
4238
4145
|
}
|
|
4239
4146
|
}
|
|
4240
4147
|
function createAgentsFromAdapters(adapters) {
|
|
@@ -4244,7 +4151,7 @@ function createAgentsFromAdapters(adapters) {
|
|
|
4244
4151
|
}
|
|
4245
4152
|
return agents;
|
|
4246
4153
|
}
|
|
4247
|
-
function createPolicyEngine(options,
|
|
4154
|
+
function createPolicyEngine(options, logger18) {
|
|
4248
4155
|
const useLearnable = options.learn === true;
|
|
4249
4156
|
if (useLearnable) {
|
|
4250
4157
|
const learnablePolicy = createLearnablePolicy({
|
|
@@ -4252,7 +4159,7 @@ function createPolicyEngine(options, logger17) {
|
|
|
4252
4159
|
warmupUpdates: 5
|
|
4253
4160
|
});
|
|
4254
4161
|
if (options.policyPath !== void 0) {
|
|
4255
|
-
const savedParams = loadPolicyParameters(options.policyPath,
|
|
4162
|
+
const savedParams = loadPolicyParameters(options.policyPath, logger18);
|
|
4256
4163
|
if (savedParams !== void 0) {
|
|
4257
4164
|
learnablePolicy.loadParameters(savedParams);
|
|
4258
4165
|
}
|
|
@@ -4293,7 +4200,7 @@ function buildPuppeteerResult(puppeteerResult, startTime, policyEngine, useLearn
|
|
|
4293
4200
|
}
|
|
4294
4201
|
return result;
|
|
4295
4202
|
}
|
|
4296
|
-
async function executeWithPuppeteer(taskContent, adapters, options,
|
|
4203
|
+
async function executeWithPuppeteer(taskContent, adapters, options, logger18) {
|
|
4297
4204
|
const startTime = getTimeProvider().now();
|
|
4298
4205
|
const useLearnable = options.learn === true;
|
|
4299
4206
|
const agents = createAgentsFromAdapters(adapters);
|
|
@@ -4305,14 +4212,14 @@ async function executeWithPuppeteer(taskContent, adapters, options, logger17) {
|
|
|
4305
4212
|
durationMs: getTimeProvider().now() - startTime
|
|
4306
4213
|
};
|
|
4307
4214
|
}
|
|
4308
|
-
const policyEngine = createPolicyEngine(options,
|
|
4215
|
+
const policyEngine = createPolicyEngine(options, logger18);
|
|
4309
4216
|
const orchestrator = createOrchestrator(policyEngine, agents, options);
|
|
4310
4217
|
const task = {
|
|
4311
4218
|
id: `cli-${String(getTimeProvider().now())}`,
|
|
4312
4219
|
description: taskContent,
|
|
4313
4220
|
context: { workingDirectory: process.cwd() }
|
|
4314
4221
|
};
|
|
4315
|
-
|
|
4222
|
+
logger18.info("Executing with PuppeteerOrchestrator", {
|
|
4316
4223
|
agents: agents.map((a) => a.id),
|
|
4317
4224
|
learnable: useLearnable,
|
|
4318
4225
|
maxSteps: options.maxSteps ?? 5
|
|
@@ -4329,7 +4236,7 @@ async function executeWithPuppeteer(taskContent, adapters, options, logger17) {
|
|
|
4329
4236
|
const puppeteerResult = execResult.value;
|
|
4330
4237
|
if (useLearnable && options.policyPath !== void 0) {
|
|
4331
4238
|
const learnablePolicy = policyEngine;
|
|
4332
|
-
savePolicyParameters(options.policyPath, learnablePolicy.getParameters(),
|
|
4239
|
+
savePolicyParameters(options.policyPath, learnablePolicy.getParameters(), logger18);
|
|
4333
4240
|
}
|
|
4334
4241
|
return buildPuppeteerResult(puppeteerResult, startTime, policyEngine, useLearnable);
|
|
4335
4242
|
}
|
|
@@ -4408,9 +4315,9 @@ function formatPct(value) {
|
|
|
4408
4315
|
}
|
|
4409
4316
|
|
|
4410
4317
|
// src/cli/orchestrate-command.ts
|
|
4411
|
-
async function runWithAdapter(task, decision,
|
|
4318
|
+
async function runWithAdapter(task, decision, logger18, startTime) {
|
|
4412
4319
|
const time = getTimeProvider();
|
|
4413
|
-
|
|
4320
|
+
logger18.info("Executing task...", { model: decision.cliName });
|
|
4414
4321
|
const execResult = await decision.adapter.execute(task);
|
|
4415
4322
|
if (!execResult.ok) {
|
|
4416
4323
|
return {
|
|
@@ -4429,7 +4336,7 @@ async function runWithAdapter(task, decision, logger17, startTime) {
|
|
|
4429
4336
|
durationMs: time.now() - startTime
|
|
4430
4337
|
};
|
|
4431
4338
|
}
|
|
4432
|
-
async function executeWithRouting(task, adapters, options,
|
|
4339
|
+
async function executeWithRouting(task, adapters, options, logger18) {
|
|
4433
4340
|
const time = getTimeProvider();
|
|
4434
4341
|
const startTime = time.now();
|
|
4435
4342
|
const configResult = getConfig();
|
|
@@ -4443,7 +4350,7 @@ async function executeWithRouting(task, adapters, options, logger17) {
|
|
|
4443
4350
|
...routingConfig,
|
|
4444
4351
|
budgetConstraints
|
|
4445
4352
|
});
|
|
4446
|
-
|
|
4353
|
+
logger18.info("Routing task...", { task: task.content.slice(0, 50) });
|
|
4447
4354
|
const routingResult = await router.route(task);
|
|
4448
4355
|
if (!routingResult.ok) {
|
|
4449
4356
|
return {
|
|
@@ -4463,9 +4370,9 @@ async function executeWithRouting(task, adapters, options, logger17) {
|
|
|
4463
4370
|
durationMs: time.now() - startTime
|
|
4464
4371
|
};
|
|
4465
4372
|
}
|
|
4466
|
-
return runWithAdapter(task, decision,
|
|
4373
|
+
return runWithAdapter(task, decision, logger18, startTime);
|
|
4467
4374
|
}
|
|
4468
|
-
async function executeWithModel(task, model, adapters,
|
|
4375
|
+
async function executeWithModel(task, model, adapters, logger18) {
|
|
4469
4376
|
const time = getTimeProvider();
|
|
4470
4377
|
const startTime = time.now();
|
|
4471
4378
|
const adapter = adapters.get(model);
|
|
@@ -4477,7 +4384,7 @@ async function executeWithModel(task, model, adapters, logger17) {
|
|
|
4477
4384
|
durationMs: time.now() - startTime
|
|
4478
4385
|
};
|
|
4479
4386
|
}
|
|
4480
|
-
|
|
4387
|
+
logger18.info("Executing task...", { model });
|
|
4481
4388
|
const execResult = await adapter.execute(task);
|
|
4482
4389
|
if (!execResult.ok) {
|
|
4483
4390
|
return {
|
|
@@ -4575,7 +4482,7 @@ function formatResult(result, format) {
|
|
|
4575
4482
|
return format === "json" ? formatResultJson(result) : formatResultText(result);
|
|
4576
4483
|
}
|
|
4577
4484
|
async function orchestrateCommand(options) {
|
|
4578
|
-
const
|
|
4485
|
+
const logger18 = createLogger({ component: "orchestrate", verbose: options.verbose });
|
|
4579
4486
|
const availableClis = await getAvailableClis();
|
|
4580
4487
|
if (availableClis.length === 0) {
|
|
4581
4488
|
console.error("No CLI tools available.");
|
|
@@ -4587,23 +4494,23 @@ async function orchestrateCommand(options) {
|
|
|
4587
4494
|
console.log(`Available CLIs: ${availableClis.join(", ")}`);
|
|
4588
4495
|
}
|
|
4589
4496
|
const codexTransport = options.engine === "puppeteer" ? "subprocess" : "mcp";
|
|
4590
|
-
const adapters = createAllAdapters(
|
|
4497
|
+
const adapters = createAllAdapters(logger18, codexTransport);
|
|
4591
4498
|
if (adapters.size === 0) {
|
|
4592
4499
|
console.error("Failed to create CLI adapters.");
|
|
4593
4500
|
return 1;
|
|
4594
4501
|
}
|
|
4595
4502
|
let result;
|
|
4596
4503
|
if (options.engine === "puppeteer") {
|
|
4597
|
-
result = await executeWithPuppeteer(options.task, adapters, options,
|
|
4504
|
+
result = await executeWithPuppeteer(options.task, adapters, options, logger18);
|
|
4598
4505
|
} else {
|
|
4599
4506
|
const task = {
|
|
4600
4507
|
content: options.task,
|
|
4601
4508
|
systemPrompt: "You are a helpful assistant."
|
|
4602
4509
|
};
|
|
4603
4510
|
if (options.model !== void 0) {
|
|
4604
|
-
result = await executeWithModel(task, options.model, adapters,
|
|
4511
|
+
result = await executeWithModel(task, options.model, adapters, logger18);
|
|
4605
4512
|
} else {
|
|
4606
|
-
result = await executeWithRouting(task, adapters, options,
|
|
4513
|
+
result = await executeWithRouting(task, adapters, options, logger18);
|
|
4607
4514
|
}
|
|
4608
4515
|
}
|
|
4609
4516
|
const output2 = formatResult(result, options.format ?? "text");
|
|
@@ -5295,8 +5202,8 @@ async function handlePrune(args, log) {
|
|
|
5295
5202
|
const count = String(result.value);
|
|
5296
5203
|
output(dryRun ? "Would delete " + count + " sessions." : "Deleted " + count + " sessions.");
|
|
5297
5204
|
}
|
|
5298
|
-
async function sessionCommand(subcommand, args,
|
|
5299
|
-
const log =
|
|
5205
|
+
async function sessionCommand(subcommand, args, logger18) {
|
|
5206
|
+
const log = logger18 ?? createLogger({ component: "SessionCommand" });
|
|
5300
5207
|
const handlers = {
|
|
5301
5208
|
list: handleList,
|
|
5302
5209
|
show: handleShow,
|
|
@@ -6052,9 +5959,6 @@ function validateGitHubIssue(issueNumber) {
|
|
|
6052
5959
|
});
|
|
6053
5960
|
return output2 !== null;
|
|
6054
5961
|
}
|
|
6055
|
-
function escapeForShell(text) {
|
|
6056
|
-
return text.replace(/'/g, "'\\''");
|
|
6057
|
-
}
|
|
6058
5962
|
function formatVoteComment(result) {
|
|
6059
5963
|
const now = new Date(getTimeProvider().now()).toLocaleDateString("en-US", {
|
|
6060
5964
|
timeZone: "America/New_York",
|
|
@@ -6091,11 +5995,10 @@ ${voteRows}
|
|
|
6091
5995
|
}
|
|
6092
5996
|
function recordVoteToGitHub(issueNumber, result) {
|
|
6093
5997
|
const comment = formatVoteComment(result);
|
|
6094
|
-
const
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
);
|
|
5998
|
+
const output2 = safeExecSandboxed(`gh issue comment ${String(issueNumber)} --body-file -`, {
|
|
5999
|
+
context: "gh",
|
|
6000
|
+
stdin: comment
|
|
6001
|
+
});
|
|
6099
6002
|
if (output2 !== null) {
|
|
6100
6003
|
writeLine(
|
|
6101
6004
|
`${colors.green}${symbols.check}${colors.reset} Vote recorded to issue #${String(issueNumber)}
|
|
@@ -6129,8 +6032,8 @@ async function runVote(options) {
|
|
|
6129
6032
|
...options.threshold !== void 0 && { threshold: options.threshold },
|
|
6130
6033
|
...options.errorPolicy !== void 0 && { errorPolicy: options.errorPolicy }
|
|
6131
6034
|
};
|
|
6132
|
-
const
|
|
6133
|
-
const result = await executeVoting(input,
|
|
6035
|
+
const logger18 = createLogger({ component: "cli-vote" });
|
|
6036
|
+
const result = await executeVoting(input, logger18, { voteTimeoutMs: timeoutMs });
|
|
6134
6037
|
return {
|
|
6135
6038
|
proposal: result.proposal,
|
|
6136
6039
|
threshold: result.threshold,
|
|
@@ -6831,7 +6734,7 @@ function generateSprintTitle(duration) {
|
|
|
6831
6734
|
month: "2-digit",
|
|
6832
6735
|
day: "2-digit"
|
|
6833
6736
|
});
|
|
6834
|
-
return `sprint: ${dateStr}
|
|
6737
|
+
return `sprint: ${dateStr} - ${duration}`;
|
|
6835
6738
|
}
|
|
6836
6739
|
function formatIssueForBody(issue) {
|
|
6837
6740
|
const effort = issue.estimatedEffort !== void 0 ? ` (${issue.estimatedEffort})` : "";
|
|
@@ -6913,10 +6816,9 @@ function generateProposal(issues, options) {
|
|
|
6913
6816
|
function createSprintIssue(proposal) {
|
|
6914
6817
|
try {
|
|
6915
6818
|
const escapedTitle = proposal.title.replace(/'/g, "'\\''");
|
|
6916
|
-
const escapedBody = proposal.body.replace(/'/g, "'\\''");
|
|
6917
6819
|
const output2 = safeExecSandboxed(
|
|
6918
|
-
`gh issue create --title '${escapedTitle}' --body
|
|
6919
|
-
{ context: "gh" }
|
|
6820
|
+
`gh issue create --title '${escapedTitle}' --body-file - --label epic`,
|
|
6821
|
+
{ context: "gh", stdin: proposal.body }
|
|
6920
6822
|
);
|
|
6921
6823
|
if (output2 === null) {
|
|
6922
6824
|
return null;
|
|
@@ -8231,7 +8133,7 @@ async function researchIndexCommand(options) {
|
|
|
8231
8133
|
|
|
8232
8134
|
// src/cli/research-import-command.ts
|
|
8233
8135
|
import * as fs9 from "fs/promises";
|
|
8234
|
-
import { resolve as
|
|
8136
|
+
import { resolve as resolve5 } from "path";
|
|
8235
8137
|
var VALID_TYPES = ["paper", "repo", "tool", "blog"];
|
|
8236
8138
|
function parseCsvLine(line) {
|
|
8237
8139
|
const fields = [];
|
|
@@ -8335,7 +8237,7 @@ function mapToSourceType(csvType) {
|
|
|
8335
8237
|
}
|
|
8336
8238
|
}
|
|
8337
8239
|
async function executeImport(options) {
|
|
8338
|
-
const csvPath =
|
|
8240
|
+
const csvPath = resolve5(options.csvPath);
|
|
8339
8241
|
let content;
|
|
8340
8242
|
try {
|
|
8341
8243
|
content = await fs9.readFile(csvPath, "utf-8");
|
|
@@ -8540,8 +8442,8 @@ async function handleAddCommand(args, options) {
|
|
|
8540
8442
|
...topic !== void 0 && { topic },
|
|
8541
8443
|
...priority !== void 0 && { priority }
|
|
8542
8444
|
};
|
|
8543
|
-
const
|
|
8544
|
-
const result = await executeResearchAdd(input,
|
|
8445
|
+
const logger18 = createLogger({ component: "cli-research-add" });
|
|
8446
|
+
const result = await executeResearchAdd(input, logger18);
|
|
8545
8447
|
return result.message;
|
|
8546
8448
|
}
|
|
8547
8449
|
var SOURCE_PROVIDERS = [
|
|
@@ -8606,8 +8508,8 @@ async function handleDiscoverCommand(args, options) {
|
|
|
8606
8508
|
if (!parsed.success) {
|
|
8607
8509
|
return `Error: ${parsed.error.issues.map((i) => i.message).join("; ")}`;
|
|
8608
8510
|
}
|
|
8609
|
-
const
|
|
8610
|
-
const response = await executeDiscovery(parsed.data,
|
|
8511
|
+
const logger18 = createLogger({ component: "cli-research-discover" });
|
|
8512
|
+
const response = await executeDiscovery(parsed.data, logger18);
|
|
8611
8513
|
return renderDiscoverResponse(response);
|
|
8612
8514
|
}
|
|
8613
8515
|
async function handleReviewCommand(args, options) {
|
|
@@ -9643,6 +9545,11 @@ var COMMAND_CATALOG = [
|
|
|
9643
9545
|
description: "Inspect + refresh the dynamic model registry (doctor / refresh)",
|
|
9644
9546
|
audience: "advanced"
|
|
9645
9547
|
},
|
|
9548
|
+
{
|
|
9549
|
+
command: "migrate",
|
|
9550
|
+
description: "Relocate homedir state (sessions, checkpoints, traces, runs, audit, pipeline, tasks) into <repo>/.nexus-agents/ for users adopting NEXUS_REPO_PREFERRED=1. Cross-repo state stays homedir. --dry-run for a no-op plan. Epic #2872.",
|
|
9551
|
+
audience: "advanced"
|
|
9552
|
+
},
|
|
9646
9553
|
{
|
|
9647
9554
|
command: "review",
|
|
9648
9555
|
description: "Review a GitHub PR (dogfooding helper)",
|
|
@@ -11359,7 +11266,7 @@ function isValidConfigAction(value) {
|
|
|
11359
11266
|
// src/cli/config-command-helpers.ts
|
|
11360
11267
|
import * as fs14 from "fs/promises";
|
|
11361
11268
|
import * as path18 from "path";
|
|
11362
|
-
import { existsSync as
|
|
11269
|
+
import { existsSync as existsSync10 } from "fs";
|
|
11363
11270
|
|
|
11364
11271
|
// src/cli/config-command-formatting.ts
|
|
11365
11272
|
function formatSource(source) {
|
|
@@ -11645,7 +11552,7 @@ function getDefaultExportPath(format) {
|
|
|
11645
11552
|
|
|
11646
11553
|
// src/cli/config-command-handlers.ts
|
|
11647
11554
|
import * as fs15 from "fs/promises";
|
|
11648
|
-
import { existsSync as
|
|
11555
|
+
import { existsSync as existsSync11 } from "fs";
|
|
11649
11556
|
async function handleGet(key) {
|
|
11650
11557
|
const parsed = parseConfigKey(key);
|
|
11651
11558
|
const config = getConfigManager();
|
|
@@ -11767,7 +11674,7 @@ async function handleExport2(file, format = "json") {
|
|
|
11767
11674
|
};
|
|
11768
11675
|
}
|
|
11769
11676
|
async function readImportFile(filePath) {
|
|
11770
|
-
if (!
|
|
11677
|
+
if (!existsSync11(filePath)) {
|
|
11771
11678
|
throw new ConfigCommandError("FILE_NOT_FOUND", `File not found: ${filePath}`);
|
|
11772
11679
|
}
|
|
11773
11680
|
const format = filePath.endsWith(".yaml") || filePath.endsWith(".yml") ? "yaml" : "json";
|
|
@@ -12270,7 +12177,7 @@ function writeResultAndExit(result) {
|
|
|
12270
12177
|
|
|
12271
12178
|
// src/cli/hooks/hook-router.ts
|
|
12272
12179
|
async function readStdin() {
|
|
12273
|
-
return new Promise((
|
|
12180
|
+
return new Promise((resolve14, reject) => {
|
|
12274
12181
|
let data = "";
|
|
12275
12182
|
process.stdin.setEncoding("utf8");
|
|
12276
12183
|
process.stdin.on("readable", () => {
|
|
@@ -12281,24 +12188,24 @@ async function readStdin() {
|
|
|
12281
12188
|
}
|
|
12282
12189
|
});
|
|
12283
12190
|
process.stdin.on("end", () => {
|
|
12284
|
-
|
|
12191
|
+
resolve14(data);
|
|
12285
12192
|
});
|
|
12286
12193
|
process.stdin.on("error", (err2) => {
|
|
12287
12194
|
reject(err2);
|
|
12288
12195
|
});
|
|
12289
12196
|
if (process.stdin.isTTY) {
|
|
12290
|
-
|
|
12197
|
+
resolve14("");
|
|
12291
12198
|
}
|
|
12292
12199
|
});
|
|
12293
12200
|
}
|
|
12294
12201
|
async function readStdinWithTimeout(timeoutMs = 5e3) {
|
|
12295
|
-
return new Promise((
|
|
12202
|
+
return new Promise((resolve14, reject) => {
|
|
12296
12203
|
const timeout2 = setTimeout(() => {
|
|
12297
12204
|
reject(new Error(`Stdin read timeout after ${String(timeoutMs)}ms`));
|
|
12298
12205
|
}, timeoutMs);
|
|
12299
12206
|
readStdin().then((data) => {
|
|
12300
12207
|
clearTimeout(timeout2);
|
|
12301
|
-
|
|
12208
|
+
resolve14(data);
|
|
12302
12209
|
}).catch((err2) => {
|
|
12303
12210
|
clearTimeout(timeout2);
|
|
12304
12211
|
reject(err2 instanceof Error ? err2 : new Error(String(err2)));
|
|
@@ -14045,11 +13952,11 @@ async function releaseNotesCommand(args) {
|
|
|
14045
13952
|
}
|
|
14046
13953
|
|
|
14047
13954
|
// src/cli/release-validate-command.ts
|
|
14048
|
-
import { readFileSync as
|
|
13955
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
14049
13956
|
|
|
14050
13957
|
// src/cli/release-validate-helpers.ts
|
|
14051
13958
|
import { execSync as execSync2 } from "child_process";
|
|
14052
|
-
import { existsSync as
|
|
13959
|
+
import { existsSync as existsSync12, readFileSync as readFileSync6 } from "fs";
|
|
14053
13960
|
async function validateSecurity(options) {
|
|
14054
13961
|
const startTime = Date.now();
|
|
14055
13962
|
const findings = [];
|
|
@@ -14068,7 +13975,7 @@ async function validateSecurity(options) {
|
|
|
14068
13975
|
remediation: "Run npm audit fix or review and update vulnerable dependencies."
|
|
14069
13976
|
});
|
|
14070
13977
|
}
|
|
14071
|
-
if (
|
|
13978
|
+
if (existsSync12(".env")) {
|
|
14072
13979
|
findings.push({
|
|
14073
13980
|
severity: "error",
|
|
14074
13981
|
category: "security",
|
|
@@ -14164,7 +14071,7 @@ async function validateArchitecture2(options) {
|
|
|
14164
14071
|
async function validateDocumentation(options) {
|
|
14165
14072
|
const startTime = Date.now();
|
|
14166
14073
|
const findings = [];
|
|
14167
|
-
if (!
|
|
14074
|
+
if (!existsSync12("CHANGELOG.md")) {
|
|
14168
14075
|
findings.push({
|
|
14169
14076
|
severity: "error",
|
|
14170
14077
|
category: "docs",
|
|
@@ -14172,7 +14079,7 @@ async function validateDocumentation(options) {
|
|
|
14172
14079
|
description: "No CHANGELOG.md found in repository root.",
|
|
14173
14080
|
remediation: "Create CHANGELOG.md following Keep a Changelog format."
|
|
14174
14081
|
});
|
|
14175
|
-
} else if (!
|
|
14082
|
+
} else if (!readFileSync6("CHANGELOG.md", "utf-8").includes(options.version)) {
|
|
14176
14083
|
findings.push({
|
|
14177
14084
|
severity: "warning",
|
|
14178
14085
|
category: "docs",
|
|
@@ -14182,7 +14089,7 @@ async function validateDocumentation(options) {
|
|
|
14182
14089
|
});
|
|
14183
14090
|
}
|
|
14184
14091
|
const pkgCl = "packages/nexus-agents/CHANGELOG.md";
|
|
14185
|
-
if (
|
|
14092
|
+
if (existsSync12(pkgCl) && !readFileSync6(pkgCl, "utf-8").includes(options.version)) {
|
|
14186
14093
|
findings.push({
|
|
14187
14094
|
severity: "warning",
|
|
14188
14095
|
category: "docs",
|
|
@@ -14191,7 +14098,7 @@ async function validateDocumentation(options) {
|
|
|
14191
14098
|
remediation: "Run pnpm changeset:version to generate changelog from pending changesets."
|
|
14192
14099
|
});
|
|
14193
14100
|
}
|
|
14194
|
-
if (!
|
|
14101
|
+
if (!existsSync12("README.md")) {
|
|
14195
14102
|
findings.push({
|
|
14196
14103
|
severity: "error",
|
|
14197
14104
|
category: "docs",
|
|
@@ -14200,8 +14107,8 @@ async function validateDocumentation(options) {
|
|
|
14200
14107
|
remediation: "Create README.md with project overview and usage instructions."
|
|
14201
14108
|
});
|
|
14202
14109
|
}
|
|
14203
|
-
if (
|
|
14204
|
-
const claudeMd =
|
|
14110
|
+
if (existsSync12("CLAUDE.md")) {
|
|
14111
|
+
const claudeMd = readFileSync6("CLAUDE.md", "utf-8");
|
|
14205
14112
|
const match = claudeMd.match(/Governance Version: (\d{4}-\d{2}-\d{2})/);
|
|
14206
14113
|
if (match?.[1]) {
|
|
14207
14114
|
const governanceDate = new Date(match[1]);
|
|
@@ -14309,7 +14216,7 @@ var DEFAULT_OPTIONS2 = {
|
|
|
14309
14216
|
};
|
|
14310
14217
|
function readVersionFromPackage() {
|
|
14311
14218
|
try {
|
|
14312
|
-
const raw = JSON.parse(
|
|
14219
|
+
const raw = JSON.parse(readFileSync7("package.json", "utf-8"));
|
|
14313
14220
|
if (typeof raw === "object" && raw !== null && "version" in raw) {
|
|
14314
14221
|
const pkg = raw;
|
|
14315
14222
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
@@ -14423,7 +14330,7 @@ async function releaseValidateCommand(args) {
|
|
|
14423
14330
|
}
|
|
14424
14331
|
|
|
14425
14332
|
// src/cli/release-announce-command.ts
|
|
14426
|
-
import { readFileSync as
|
|
14333
|
+
import { readFileSync as readFileSync8, existsSync as existsSync13 } from "fs";
|
|
14427
14334
|
|
|
14428
14335
|
// src/cli/release-announce-types.ts
|
|
14429
14336
|
var BLUESKY_LIMITS = {
|
|
@@ -14490,8 +14397,8 @@ var DEFAULT_OPTIONS3 = {
|
|
|
14490
14397
|
verbose: false
|
|
14491
14398
|
};
|
|
14492
14399
|
function extractHighlightsFromChangelog(version) {
|
|
14493
|
-
if (!
|
|
14494
|
-
const changelog =
|
|
14400
|
+
if (!existsSync13("CHANGELOG.md")) return [];
|
|
14401
|
+
const changelog = readFileSync8("CHANGELOG.md", "utf-8");
|
|
14495
14402
|
const escaped = version.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14496
14403
|
const versionRegex = new RegExp(`## \\[${escaped}\\][^#]*`, "s");
|
|
14497
14404
|
const match = changelog.match(versionRegex);
|
|
@@ -14753,7 +14660,7 @@ async function releaseAnnounceCommand(args) {
|
|
|
14753
14660
|
version = args.options.version;
|
|
14754
14661
|
} else {
|
|
14755
14662
|
try {
|
|
14756
|
-
const pkg = JSON.parse(
|
|
14663
|
+
const pkg = JSON.parse(readFileSync8("package.json", "utf-8"));
|
|
14757
14664
|
if (!pkg.version) {
|
|
14758
14665
|
console.error(`${colors.red}Error: Could not determine version${colors.reset}`);
|
|
14759
14666
|
return 1;
|
|
@@ -15320,8 +15227,8 @@ function buildDetails(taskCount, counts, nonZero, score, passed) {
|
|
|
15320
15227
|
lines.push(`Result: ${passed ? "PASSED" : "FAILED"}`);
|
|
15321
15228
|
return lines;
|
|
15322
15229
|
}
|
|
15323
|
-
function runE2EEval(config,
|
|
15324
|
-
const log =
|
|
15230
|
+
function runE2EEval(config, logger18) {
|
|
15231
|
+
const log = logger18 ?? createLogger({ component: "e2e-eval" });
|
|
15325
15232
|
const taskCount = config?.taskCount ?? 50;
|
|
15326
15233
|
if (config?.resetStore !== false) {
|
|
15327
15234
|
resetOutcomeStore();
|
|
@@ -15685,13 +15592,13 @@ function formatEvalDetails(baseline, reflective, improvement, datasetSize) {
|
|
|
15685
15592
|
}
|
|
15686
15593
|
|
|
15687
15594
|
// src/cli/auth-command.ts
|
|
15688
|
-
import { existsSync as
|
|
15595
|
+
import { existsSync as existsSync15, statSync, chmodSync } from "fs";
|
|
15689
15596
|
function isValidAuthSubcommand(value) {
|
|
15690
15597
|
return value === "init" || value === "show" || value === "rotate" || value === "help" || value === "status";
|
|
15691
15598
|
}
|
|
15692
15599
|
function getFilePermissions(filePath) {
|
|
15693
15600
|
try {
|
|
15694
|
-
const stats =
|
|
15601
|
+
const stats = statSync(filePath);
|
|
15695
15602
|
return (stats.mode & 511).toString(8);
|
|
15696
15603
|
} catch {
|
|
15697
15604
|
return void 0;
|
|
@@ -15705,7 +15612,7 @@ function fixPermissions(filePath) {
|
|
|
15705
15612
|
}
|
|
15706
15613
|
function runAuthInit(options) {
|
|
15707
15614
|
const tokenFile = options.tokenFile ?? getDefaultTokenPath();
|
|
15708
|
-
const tokenExists =
|
|
15615
|
+
const tokenExists = existsSync15(tokenFile);
|
|
15709
15616
|
if (tokenExists && options.force !== true) {
|
|
15710
15617
|
return {
|
|
15711
15618
|
success: false,
|
|
@@ -15729,7 +15636,7 @@ function runAuthInit(options) {
|
|
|
15729
15636
|
}
|
|
15730
15637
|
function runAuthShow(options) {
|
|
15731
15638
|
const tokenFile = options.tokenFile ?? getDefaultTokenPath();
|
|
15732
|
-
const tokenExists =
|
|
15639
|
+
const tokenExists = existsSync15(tokenFile);
|
|
15733
15640
|
const token = readStoredToken(tokenFile);
|
|
15734
15641
|
if (!tokenExists || token === void 0) {
|
|
15735
15642
|
return {
|
|
@@ -15750,7 +15657,7 @@ function runAuthShow(options) {
|
|
|
15750
15657
|
}
|
|
15751
15658
|
function runAuthRotate(options) {
|
|
15752
15659
|
const tokenFile = options.tokenFile ?? getDefaultTokenPath();
|
|
15753
|
-
const tokenExists =
|
|
15660
|
+
const tokenExists = existsSync15(tokenFile);
|
|
15754
15661
|
if (!tokenExists) {
|
|
15755
15662
|
return {
|
|
15756
15663
|
success: false,
|
|
@@ -15786,14 +15693,14 @@ function runAuthCommand(options) {
|
|
|
15786
15693
|
success: true,
|
|
15787
15694
|
operation: "help",
|
|
15788
15695
|
tokenFile: getDefaultTokenPath(),
|
|
15789
|
-
tokenExists:
|
|
15696
|
+
tokenExists: existsSync15(getDefaultTokenPath())
|
|
15790
15697
|
};
|
|
15791
15698
|
default:
|
|
15792
15699
|
return {
|
|
15793
15700
|
success: false,
|
|
15794
15701
|
operation: "help",
|
|
15795
15702
|
tokenFile: getDefaultTokenPath(),
|
|
15796
|
-
tokenExists:
|
|
15703
|
+
tokenExists: existsSync15(getDefaultTokenPath()),
|
|
15797
15704
|
error: `Unknown subcommand: ${subcommand}`
|
|
15798
15705
|
};
|
|
15799
15706
|
}
|
|
@@ -16163,8 +16070,12 @@ var PARSE_ARGS_CONFIG = {
|
|
|
16163
16070
|
type: "string"
|
|
16164
16071
|
},
|
|
16165
16072
|
"output-dir": {
|
|
16166
|
-
type: "string"
|
|
16167
|
-
default:
|
|
16073
|
+
type: "string"
|
|
16074
|
+
// No default: the only consumer (handleSweBenchCommand) is a
|
|
16075
|
+
// deprecation shim that ignores it. Live callers should pass an
|
|
16076
|
+
// explicit path or resolve through getNexusDataDir() at use time.
|
|
16077
|
+
// Removed the './logs/run_evaluation' default per epic #2872 to
|
|
16078
|
+
// stop the parser from advertising a sprawl-creating fallback.
|
|
16168
16079
|
},
|
|
16169
16080
|
// ATBench command options (#1981)
|
|
16170
16081
|
fixture: {
|
|
@@ -16349,29 +16260,30 @@ var VALID_COMMANDS = [
|
|
|
16349
16260
|
"registry",
|
|
16350
16261
|
"login",
|
|
16351
16262
|
"usage",
|
|
16352
|
-
"improvement-review"
|
|
16263
|
+
"improvement-review",
|
|
16264
|
+
"migrate"
|
|
16353
16265
|
];
|
|
16354
16266
|
function isValidCommand(value) {
|
|
16355
16267
|
return VALID_COMMANDS.includes(value);
|
|
16356
16268
|
}
|
|
16357
16269
|
|
|
16358
16270
|
// src/cli-commands-handlers.ts
|
|
16359
|
-
import { existsSync as
|
|
16271
|
+
import { existsSync as existsSync20 } from "fs";
|
|
16360
16272
|
|
|
16361
16273
|
// src/cli/init-portable.ts
|
|
16362
16274
|
import {
|
|
16363
|
-
existsSync as
|
|
16275
|
+
existsSync as existsSync19,
|
|
16364
16276
|
mkdirSync as mkdirSync5,
|
|
16365
16277
|
readdirSync,
|
|
16366
|
-
statSync as
|
|
16367
|
-
appendFileSync as
|
|
16368
|
-
readFileSync as
|
|
16278
|
+
statSync as statSync2,
|
|
16279
|
+
appendFileSync as appendFileSync2,
|
|
16280
|
+
readFileSync as readFileSync11
|
|
16369
16281
|
} from "fs";
|
|
16370
|
-
import { resolve as
|
|
16282
|
+
import { resolve as resolve10, join as join15, isAbsolute as isAbsolute2 } from "path";
|
|
16371
16283
|
|
|
16372
16284
|
// src/cli/mcp-config-emitter.ts
|
|
16373
|
-
import { existsSync as
|
|
16374
|
-
import { join as
|
|
16285
|
+
import { existsSync as existsSync16, readFileSync as readFileSync9, writeFileSync as writeFileSync5, appendFileSync } from "fs";
|
|
16286
|
+
import { join as join12 } from "path";
|
|
16375
16287
|
var MCP_CONFIG_FILENAME = ".mcp.json";
|
|
16376
16288
|
var NEXUS_SERVER_KEY = "nexus-agents";
|
|
16377
16289
|
function buildNexusServerEntry(dataDir, commandPath) {
|
|
@@ -16394,10 +16306,10 @@ function entriesEqual(a, b) {
|
|
|
16394
16306
|
return true;
|
|
16395
16307
|
}
|
|
16396
16308
|
function loadExistingConfig(path22) {
|
|
16397
|
-
if (!
|
|
16309
|
+
if (!existsSync16(path22)) return { ok: true, value: void 0 };
|
|
16398
16310
|
let raw;
|
|
16399
16311
|
try {
|
|
16400
|
-
raw =
|
|
16312
|
+
raw = readFileSync9(path22, "utf-8");
|
|
16401
16313
|
} catch (e) {
|
|
16402
16314
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
16403
16315
|
}
|
|
@@ -16431,24 +16343,24 @@ function decideEmission(existing, desired, force) {
|
|
|
16431
16343
|
return { kind: "write", nextConfig: { ...existing, mcpServers: nextServers } };
|
|
16432
16344
|
}
|
|
16433
16345
|
function autoGitignoreMcpConfig(workspaceDir, dryRun) {
|
|
16434
|
-
const gitDir =
|
|
16435
|
-
if (!
|
|
16436
|
-
const gitignorePath =
|
|
16346
|
+
const gitDir = join12(workspaceDir, ".git");
|
|
16347
|
+
if (!existsSync16(gitDir)) return false;
|
|
16348
|
+
const gitignorePath = join12(workspaceDir, ".gitignore");
|
|
16437
16349
|
let existing = "";
|
|
16438
|
-
if (
|
|
16439
|
-
existing =
|
|
16350
|
+
if (existsSync16(gitignorePath)) {
|
|
16351
|
+
existing = readFileSync9(gitignorePath, "utf-8");
|
|
16440
16352
|
const already = existing.split("\n").some((l) => l.trim() === MCP_CONFIG_FILENAME || l.trim() === `/${MCP_CONFIG_FILENAME}`);
|
|
16441
16353
|
if (already) return false;
|
|
16442
16354
|
}
|
|
16443
16355
|
if (!dryRun) {
|
|
16444
16356
|
const sep3 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
16445
|
-
|
|
16357
|
+
appendFileSync(gitignorePath, `${sep3}${MCP_CONFIG_FILENAME}
|
|
16446
16358
|
`, "utf-8");
|
|
16447
16359
|
}
|
|
16448
16360
|
return true;
|
|
16449
16361
|
}
|
|
16450
16362
|
function emitMcpConfig(options) {
|
|
16451
|
-
const mcpConfigPath =
|
|
16363
|
+
const mcpConfigPath = join12(options.workspaceDir, MCP_CONFIG_FILENAME);
|
|
16452
16364
|
const dryRun = options.dryRun === true;
|
|
16453
16365
|
const force = options.force === true;
|
|
16454
16366
|
const desired = buildNexusServerEntry(options.dataDir, options.commandPath);
|
|
@@ -16486,13 +16398,13 @@ function makeFailure(mcpConfigPath, error) {
|
|
|
16486
16398
|
|
|
16487
16399
|
// src/cli/portable-installer.ts
|
|
16488
16400
|
import { execFile } from "child_process";
|
|
16489
|
-
import { existsSync as
|
|
16490
|
-
import { join as
|
|
16401
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync4, rmSync, writeFileSync as writeFileSync7 } from "fs";
|
|
16402
|
+
import { join as join14 } from "path";
|
|
16491
16403
|
import { promisify } from "util";
|
|
16492
16404
|
|
|
16493
16405
|
// src/cli/bin-shim.ts
|
|
16494
|
-
import { existsSync as
|
|
16495
|
-
import { join as
|
|
16406
|
+
import { existsSync as existsSync17, readFileSync as readFileSync10, writeFileSync as writeFileSync6, chmodSync as chmodSync2, mkdirSync as mkdirSync3 } from "fs";
|
|
16407
|
+
import { join as join13 } from "path";
|
|
16496
16408
|
var SHIM_BASENAME = "nexus-agents";
|
|
16497
16409
|
var SHIM_MODE = 493;
|
|
16498
16410
|
function buildShimContents(cliEntryPath) {
|
|
@@ -16506,18 +16418,18 @@ function buildShimContents(cliEntryPath) {
|
|
|
16506
16418
|
return lines.join("\n");
|
|
16507
16419
|
}
|
|
16508
16420
|
function writeBinShim(options) {
|
|
16509
|
-
const shimPath =
|
|
16421
|
+
const shimPath = join13(options.binDir, SHIM_BASENAME);
|
|
16510
16422
|
const desired = buildShimContents(options.cliEntryPath);
|
|
16511
16423
|
const dryRun = options.dryRun === true;
|
|
16512
16424
|
try {
|
|
16513
|
-
if (
|
|
16514
|
-
const current =
|
|
16425
|
+
if (existsSync17(shimPath)) {
|
|
16426
|
+
const current = readFileSync10(shimPath, "utf-8");
|
|
16515
16427
|
if (current === desired) {
|
|
16516
16428
|
return { success: true, shimPath, written: false, alreadyMatched: true, error: null };
|
|
16517
16429
|
}
|
|
16518
16430
|
}
|
|
16519
16431
|
if (!dryRun) {
|
|
16520
|
-
if (!
|
|
16432
|
+
if (!existsSync17(options.binDir)) mkdirSync3(options.binDir, { recursive: true });
|
|
16521
16433
|
writeFileSync6(shimPath, desired, "utf-8");
|
|
16522
16434
|
chmodSync2(shimPath, SHIM_MODE);
|
|
16523
16435
|
}
|
|
@@ -16552,10 +16464,10 @@ function writeInstallManifest(cliDir, version) {
|
|
|
16552
16464
|
description: "Local install root for portable nexus-agents (generated; do not commit)",
|
|
16553
16465
|
dependencies: { "nexus-agents": version }
|
|
16554
16466
|
};
|
|
16555
|
-
writeFileSync7(
|
|
16467
|
+
writeFileSync7(join14(cliDir, "package.json"), JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
16556
16468
|
}
|
|
16557
16469
|
function isAlreadyInstalled(cliDir) {
|
|
16558
|
-
return
|
|
16470
|
+
return existsSync18(join14(cliDir, "node_modules", "nexus-agents", "package.json"));
|
|
16559
16471
|
}
|
|
16560
16472
|
async function spawnNpmInstall(cliDir) {
|
|
16561
16473
|
await execFileAsync("npm", ["install", "--no-audit", "--no-fund", "--silent"], {
|
|
@@ -16571,7 +16483,7 @@ function cleanupOnFailure(cliDir) {
|
|
|
16571
16483
|
}
|
|
16572
16484
|
async function runNpmStep(ctx) {
|
|
16573
16485
|
try {
|
|
16574
|
-
if (!
|
|
16486
|
+
if (!existsSync18(ctx.cliDir)) mkdirSync4(ctx.cliDir, { recursive: true });
|
|
16575
16487
|
writeInstallManifest(ctx.cliDir, ctx.version);
|
|
16576
16488
|
await spawnNpmInstall(ctx.cliDir);
|
|
16577
16489
|
return void 0;
|
|
@@ -16582,8 +16494,8 @@ async function runNpmStep(ctx) {
|
|
|
16582
16494
|
}
|
|
16583
16495
|
}
|
|
16584
16496
|
async function installPortable(options) {
|
|
16585
|
-
const cliDir =
|
|
16586
|
-
const binDir =
|
|
16497
|
+
const cliDir = join14(options.dataDir, CLI_SUBDIR);
|
|
16498
|
+
const binDir = join14(options.dataDir, BIN_SUBDIR);
|
|
16587
16499
|
const versionResolution = resolveInstallVersion(options.version);
|
|
16588
16500
|
if (!versionResolution.ok) {
|
|
16589
16501
|
return {
|
|
@@ -16604,7 +16516,7 @@ async function installPortable(options) {
|
|
|
16604
16516
|
}
|
|
16605
16517
|
const npmFailure = await runNpmStep(ctx);
|
|
16606
16518
|
if (npmFailure !== void 0) return npmFailure;
|
|
16607
|
-
const shim = writeBinShim({ binDir, cliEntryPath:
|
|
16519
|
+
const shim = writeBinShim({ binDir, cliEntryPath: join14(cliDir, CLI_ENTRY_RELATIVE) });
|
|
16608
16520
|
if (!shim.success) {
|
|
16609
16521
|
cleanupOnFailure(cliDir);
|
|
16610
16522
|
return {
|
|
@@ -16618,14 +16530,14 @@ async function installPortable(options) {
|
|
|
16618
16530
|
return { success: true, ...ctx, shim, skipped: false, error: null };
|
|
16619
16531
|
}
|
|
16620
16532
|
function uninstallPortable(options) {
|
|
16621
|
-
const cliDir =
|
|
16622
|
-
const binDir =
|
|
16533
|
+
const cliDir = join14(options.dataDir, CLI_SUBDIR);
|
|
16534
|
+
const binDir = join14(options.dataDir, BIN_SUBDIR);
|
|
16623
16535
|
const removed = [];
|
|
16624
16536
|
const notPresent = [];
|
|
16625
16537
|
const dryRun = options.dryRun === true;
|
|
16626
16538
|
try {
|
|
16627
16539
|
for (const dir of [cliDir, binDir]) {
|
|
16628
|
-
if (!
|
|
16540
|
+
if (!existsSync18(dir)) {
|
|
16629
16541
|
notPresent.push(dir);
|
|
16630
16542
|
continue;
|
|
16631
16543
|
}
|
|
@@ -16639,8 +16551,8 @@ function uninstallPortable(options) {
|
|
|
16639
16551
|
}
|
|
16640
16552
|
}
|
|
16641
16553
|
function findBinShim(dataDir) {
|
|
16642
|
-
const shimPath =
|
|
16643
|
-
return
|
|
16554
|
+
const shimPath = join14(dataDir, BIN_SUBDIR, "nexus-agents");
|
|
16555
|
+
return existsSync18(shimPath) ? shimPath : void 0;
|
|
16644
16556
|
}
|
|
16645
16557
|
|
|
16646
16558
|
// src/cli/init-portable.ts
|
|
@@ -16648,18 +16560,18 @@ var DEFAULT_PORTABLE_DIRNAME = ".nexus-agents";
|
|
|
16648
16560
|
var RESTRICTED_SUBDIRS = /* @__PURE__ */ new Set(["auth"]);
|
|
16649
16561
|
function resolveTargetPath(rawPath) {
|
|
16650
16562
|
if (rawPath === void 0 || rawPath === "") {
|
|
16651
|
-
return
|
|
16563
|
+
return resolve10(process.cwd(), DEFAULT_PORTABLE_DIRNAME);
|
|
16652
16564
|
}
|
|
16653
|
-
return isAbsolute2(rawPath) ? rawPath :
|
|
16565
|
+
return isAbsolute2(rawPath) ? rawPath : resolve10(process.cwd(), rawPath);
|
|
16654
16566
|
}
|
|
16655
16567
|
function isNonEmpty(dir) {
|
|
16656
|
-
if (!
|
|
16657
|
-
const stat2 =
|
|
16568
|
+
if (!existsSync19(dir)) return false;
|
|
16569
|
+
const stat2 = statSync2(dir);
|
|
16658
16570
|
if (!stat2.isDirectory()) return true;
|
|
16659
16571
|
return readdirSync(dir).length > 0;
|
|
16660
16572
|
}
|
|
16661
16573
|
function ensureDir(path22, dryRun, created, alreadyExisted, mode) {
|
|
16662
|
-
if (
|
|
16574
|
+
if (existsSync19(path22)) {
|
|
16663
16575
|
alreadyExisted.push(path22);
|
|
16664
16576
|
return;
|
|
16665
16577
|
}
|
|
@@ -16669,37 +16581,37 @@ function ensureDir(path22, dryRun, created, alreadyExisted, mode) {
|
|
|
16669
16581
|
created.push(path22);
|
|
16670
16582
|
}
|
|
16671
16583
|
function maybeUpdateGitignore(workspaceDir, portableDirName, dryRun) {
|
|
16672
|
-
const gitDir =
|
|
16673
|
-
if (!
|
|
16674
|
-
const gitignorePath =
|
|
16584
|
+
const gitDir = join15(workspaceDir, ".git");
|
|
16585
|
+
if (!existsSync19(gitDir)) return false;
|
|
16586
|
+
const gitignorePath = join15(workspaceDir, ".gitignore");
|
|
16675
16587
|
const entry = `${portableDirName}/`;
|
|
16676
16588
|
let existing = "";
|
|
16677
|
-
if (
|
|
16678
|
-
existing =
|
|
16589
|
+
if (existsSync19(gitignorePath)) {
|
|
16590
|
+
existing = readFileSync11(gitignorePath, "utf-8");
|
|
16679
16591
|
if (existing.split("\n").some((l) => l.trim() === entry || l.trim() === portableDirName)) {
|
|
16680
16592
|
return false;
|
|
16681
16593
|
}
|
|
16682
16594
|
}
|
|
16683
16595
|
if (!dryRun) {
|
|
16684
16596
|
const sep3 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
16685
|
-
|
|
16597
|
+
appendFileSync2(gitignorePath, `${sep3}${entry}
|
|
16686
16598
|
`, "utf-8");
|
|
16687
16599
|
}
|
|
16688
16600
|
return true;
|
|
16689
16601
|
}
|
|
16690
16602
|
function inspectTarget(target) {
|
|
16691
|
-
const exists =
|
|
16603
|
+
const exists = existsSync19(target);
|
|
16692
16604
|
if (!exists) return { exists: false, nonEmpty: false, isExistingNexusDir: false };
|
|
16693
16605
|
const nonEmpty = isNonEmpty(target);
|
|
16694
|
-
const stat2 =
|
|
16695
|
-
const isExistingNexusDir = stat2.isDirectory() &&
|
|
16606
|
+
const stat2 = statSync2(target);
|
|
16607
|
+
const isExistingNexusDir = stat2.isDirectory() && existsSync19(join15(target, "audit"));
|
|
16696
16608
|
return { exists, nonEmpty, isExistingNexusDir };
|
|
16697
16609
|
}
|
|
16698
16610
|
function createDataLayout(target, dryRun, created, alreadyExisted) {
|
|
16699
16611
|
ensureDir(target, dryRun, created, alreadyExisted);
|
|
16700
16612
|
for (const subdir of DATA_SUBDIRECTORIES) {
|
|
16701
16613
|
const mode = RESTRICTED_SUBDIRS.has(subdir) ? 448 : void 0;
|
|
16702
|
-
ensureDir(
|
|
16614
|
+
ensureDir(join15(target, subdir), dryRun, created, alreadyExisted, mode);
|
|
16703
16615
|
}
|
|
16704
16616
|
}
|
|
16705
16617
|
function makeResult(opts) {
|
|
@@ -16718,13 +16630,13 @@ function makeResult(opts) {
|
|
|
16718
16630
|
}
|
|
16719
16631
|
function applyGitignoreOption(target, options, dryRun) {
|
|
16720
16632
|
if (options.gitignore !== true) return false;
|
|
16721
|
-
const workspaceDir =
|
|
16633
|
+
const workspaceDir = resolve10(target, "..");
|
|
16722
16634
|
const portableName = target.slice(workspaceDir.length + 1);
|
|
16723
16635
|
return maybeUpdateGitignore(workspaceDir, portableName, dryRun);
|
|
16724
16636
|
}
|
|
16725
16637
|
function applyMcpConfigOption(target, options, dryRun) {
|
|
16726
16638
|
if (options.mcpConfig !== true) return void 0;
|
|
16727
|
-
const workspaceDir =
|
|
16639
|
+
const workspaceDir = resolve10(target, "..");
|
|
16728
16640
|
const shimPath = findBinShim(target);
|
|
16729
16641
|
return emitMcpConfig({
|
|
16730
16642
|
workspaceDir,
|
|
@@ -16981,7 +16893,45 @@ function buildStructuredOutput(result) {
|
|
|
16981
16893
|
};
|
|
16982
16894
|
}
|
|
16983
16895
|
var RUN_DEV_PIPELINE_DESCRIPTION = "Run the multi-agent development pipeline. Accepts direct task instructions, a plan file, or a spec file. Supports dry-run (plan+vote only).";
|
|
16984
|
-
function
|
|
16896
|
+
async function runDevPipelineHandler(args, logger18) {
|
|
16897
|
+
const parsed = DevPipelineInputSchema.safeParse(args);
|
|
16898
|
+
if (!parsed.success) {
|
|
16899
|
+
return toolStructuredError({
|
|
16900
|
+
errorCategory: "validation",
|
|
16901
|
+
message: `Invalid input: ${formatZodError(parsed.error)}`
|
|
16902
|
+
});
|
|
16903
|
+
}
|
|
16904
|
+
const input = parsed.data;
|
|
16905
|
+
if (input.simulateVotes) {
|
|
16906
|
+
warnIfSimulatedOutsideTests("run_dev_pipeline", logger18);
|
|
16907
|
+
}
|
|
16908
|
+
try {
|
|
16909
|
+
const taskText = await resolveTaskInput(input);
|
|
16910
|
+
const stages = await createStages(input);
|
|
16911
|
+
const pipelineOptions = {
|
|
16912
|
+
...input.sessionId !== void 0 ? { sessionId: input.sessionId } : {},
|
|
16913
|
+
...input.dryRun ? { dryRun: true } : {},
|
|
16914
|
+
...input.mode === "harness" ? { mode: "harness" } : {}
|
|
16915
|
+
};
|
|
16916
|
+
const hasOptions = Object.keys(pipelineOptions).length > 0;
|
|
16917
|
+
const result = await runDevPipeline(taskText, stages, hasOptions ? pipelineOptions : void 0);
|
|
16918
|
+
flushPipelineMemory();
|
|
16919
|
+
return toolSuccessStructured(buildStructuredOutput(result));
|
|
16920
|
+
} catch (error) {
|
|
16921
|
+
return toolStructuredError({
|
|
16922
|
+
errorCategory: "internal",
|
|
16923
|
+
message: `Pipeline error: ${getErrorMessage(error)}`
|
|
16924
|
+
});
|
|
16925
|
+
}
|
|
16926
|
+
}
|
|
16927
|
+
function registerDevPipelineTool(server, deps) {
|
|
16928
|
+
const logger18 = deps.logger ?? createLogger({ tool: "run_dev_pipeline" });
|
|
16929
|
+
const secureHandler = createSecureHandler(
|
|
16930
|
+
(args) => runDevPipelineHandler(args, logger18),
|
|
16931
|
+
{ toolName: "run_dev_pipeline", rateLimiter: deps.rateLimiter, logger: logger18 }
|
|
16932
|
+
);
|
|
16933
|
+
const timeoutMs = getToolTimeout("run_dev_pipeline", deps.security);
|
|
16934
|
+
const wrapped = wrapToolWithTimeout("run_dev_pipeline", secureHandler, { timeoutMs, logger: logger18 });
|
|
16985
16935
|
server.registerTool(
|
|
16986
16936
|
"run_dev_pipeline",
|
|
16987
16937
|
{
|
|
@@ -16989,41 +16939,9 @@ function registerDevPipelineTool(server, _deps) {
|
|
|
16989
16939
|
inputSchema: DevPipelineInputSchema.shape,
|
|
16990
16940
|
annotations: getToolAnnotations("run_dev_pipeline")
|
|
16991
16941
|
},
|
|
16992
|
-
|
|
16993
|
-
const input = DevPipelineInputSchema.parse(args);
|
|
16994
|
-
if (input.simulateVotes) {
|
|
16995
|
-
warnIfSimulatedOutsideTests("run_dev_pipeline", createLogger({ tool: "run_dev_pipeline" }));
|
|
16996
|
-
}
|
|
16997
|
-
try {
|
|
16998
|
-
const taskText = await resolveTaskInput(input);
|
|
16999
|
-
const stages = await createStages(input);
|
|
17000
|
-
const pipelineOptions = {
|
|
17001
|
-
...input.sessionId !== void 0 ? { sessionId: input.sessionId } : {},
|
|
17002
|
-
...input.dryRun ? { dryRun: true } : {},
|
|
17003
|
-
...input.mode === "harness" ? { mode: "harness" } : {}
|
|
17004
|
-
};
|
|
17005
|
-
const hasOptions = Object.keys(pipelineOptions).length > 0;
|
|
17006
|
-
const result = await runDevPipeline(
|
|
17007
|
-
taskText,
|
|
17008
|
-
stages,
|
|
17009
|
-
hasOptions ? pipelineOptions : void 0
|
|
17010
|
-
);
|
|
17011
|
-
flushPipelineMemory();
|
|
17012
|
-
const structured = buildStructuredOutput(result);
|
|
17013
|
-
return {
|
|
17014
|
-
content: [{ type: "text", text: JSON.stringify(structured, null, 2) }],
|
|
17015
|
-
structuredContent: structured
|
|
17016
|
-
};
|
|
17017
|
-
} catch (error) {
|
|
17018
|
-
return {
|
|
17019
|
-
...toolStructuredError({
|
|
17020
|
-
errorCategory: "internal",
|
|
17021
|
-
message: `Pipeline error: ${getErrorMessage(error)}`
|
|
17022
|
-
})
|
|
17023
|
-
};
|
|
17024
|
-
}
|
|
17025
|
-
}
|
|
16942
|
+
toSdkCallback(wrapped)
|
|
17026
16943
|
);
|
|
16944
|
+
logger18.info("Registered run_dev_pipeline tool");
|
|
17027
16945
|
}
|
|
17028
16946
|
|
|
17029
16947
|
// src/cli-server-stpa.ts
|
|
@@ -17136,7 +17054,7 @@ var StpaSafetyError = class extends NexusError {
|
|
|
17136
17054
|
this.analysisResult = analysisResult;
|
|
17137
17055
|
}
|
|
17138
17056
|
};
|
|
17139
|
-
function logToolResults(
|
|
17057
|
+
function logToolResults(logger18, result) {
|
|
17140
17058
|
for (const toolResult of result.toolResults) {
|
|
17141
17059
|
if (toolResult.hazards.length === 0) continue;
|
|
17142
17060
|
const criticalCount = toolResult.hazards.filter(
|
|
@@ -17144,7 +17062,7 @@ function logToolResults(logger17, result) {
|
|
|
17144
17062
|
).length;
|
|
17145
17063
|
const highCount = toolResult.hazards.filter((h) => h.severity === "high" /* HIGH */).length;
|
|
17146
17064
|
if (criticalCount > 0 || highCount > 0) {
|
|
17147
|
-
|
|
17065
|
+
logger18.warn(`STPA hazards for tool '${toolResult.toolName}'`, {
|
|
17148
17066
|
riskLevel: toolResult.riskLevel,
|
|
17149
17067
|
riskScore: toolResult.riskScore,
|
|
17150
17068
|
criticalHazards: criticalCount,
|
|
@@ -17152,7 +17070,7 @@ function logToolResults(logger17, result) {
|
|
|
17152
17070
|
safetyConstraints: toolResult.safetyConstraints.length
|
|
17153
17071
|
});
|
|
17154
17072
|
} else {
|
|
17155
|
-
|
|
17073
|
+
logger18.debug(`STPA analysis for tool '${toolResult.toolName}'`, {
|
|
17156
17074
|
riskLevel: toolResult.riskLevel,
|
|
17157
17075
|
hazards: toolResult.hazards.length
|
|
17158
17076
|
});
|
|
@@ -17170,7 +17088,7 @@ function checkHighSeverityTools(result, failOnHighSeverity) {
|
|
|
17170
17088
|
result
|
|
17171
17089
|
);
|
|
17172
17090
|
}
|
|
17173
|
-
function runStpaSafetyAnalysis(
|
|
17091
|
+
function runStpaSafetyAnalysis(logger18, failOnHighSeverity) {
|
|
17174
17092
|
const analysisResult = analyzeTools(TOOL_DEFINITIONS);
|
|
17175
17093
|
if (!analysisResult.ok) {
|
|
17176
17094
|
const errorMsg = analysisResult.error.message;
|
|
@@ -17179,12 +17097,12 @@ function runStpaSafetyAnalysis(logger17, failOnHighSeverity) {
|
|
|
17179
17097
|
code: ErrorCode.SECURITY_ERROR
|
|
17180
17098
|
});
|
|
17181
17099
|
}
|
|
17182
|
-
|
|
17100
|
+
logger18.warn("STPA safety analysis failed", { error: errorMsg });
|
|
17183
17101
|
return;
|
|
17184
17102
|
}
|
|
17185
17103
|
const result = analysisResult.value;
|
|
17186
17104
|
const { summary } = result;
|
|
17187
|
-
|
|
17105
|
+
logger18.info("STPA safety analysis completed", {
|
|
17188
17106
|
toolsAnalyzed: summary.totalTools,
|
|
17189
17107
|
hazardsIdentified: summary.totalHazards,
|
|
17190
17108
|
unsafeControlActions: summary.totalUnsafeControlActions,
|
|
@@ -17192,10 +17110,10 @@ function runStpaSafetyAnalysis(logger17, failOnHighSeverity) {
|
|
|
17192
17110
|
averageRiskScore: summary.averageRiskScore.toFixed(1),
|
|
17193
17111
|
toolsByRiskLevel: summary.toolsByRiskLevel
|
|
17194
17112
|
});
|
|
17195
|
-
logToolResults(
|
|
17113
|
+
logToolResults(logger18, result);
|
|
17196
17114
|
checkHighSeverityTools(result, failOnHighSeverity);
|
|
17197
17115
|
if (result.interactions.length > 0) {
|
|
17198
|
-
|
|
17116
|
+
logger18.info("STPA cross-tool hazard interactions detected", {
|
|
17199
17117
|
interactionCount: result.interactions.length,
|
|
17200
17118
|
interactions: result.interactions.map((i) => ({
|
|
17201
17119
|
tools: i.involvedTools,
|
|
@@ -17232,10 +17150,10 @@ var UpstreamClient = class {
|
|
|
17232
17150
|
transport = null;
|
|
17233
17151
|
state = "disconnected";
|
|
17234
17152
|
tools = [];
|
|
17235
|
-
constructor(config,
|
|
17153
|
+
constructor(config, logger18) {
|
|
17236
17154
|
this.name = config.name;
|
|
17237
17155
|
this.config = config;
|
|
17238
|
-
this.log =
|
|
17156
|
+
this.log = logger18 ?? createLogger({ component: `upstream:${config.name}` });
|
|
17239
17157
|
}
|
|
17240
17158
|
/** Connect to the upstream server. Idempotent. */
|
|
17241
17159
|
async connect() {
|
|
@@ -17335,8 +17253,8 @@ var UpstreamClient = class {
|
|
|
17335
17253
|
var UpstreamClientManager = class {
|
|
17336
17254
|
clients = /* @__PURE__ */ new Map();
|
|
17337
17255
|
log;
|
|
17338
|
-
constructor(
|
|
17339
|
-
this.log =
|
|
17256
|
+
constructor(logger18) {
|
|
17257
|
+
this.log = logger18 ?? createLogger({ component: "UpstreamClientManager" });
|
|
17340
17258
|
}
|
|
17341
17259
|
/** Register upstream servers from config. */
|
|
17342
17260
|
registerServers(configs) {
|
|
@@ -17444,11 +17362,11 @@ var REGISTERED_TOOLS = [
|
|
|
17444
17362
|
"improvement_review"
|
|
17445
17363
|
];
|
|
17446
17364
|
var MOCK_ORCHESTRATION_ENV = "NEXUS_ALLOW_MOCK_ORCHESTRATION";
|
|
17447
|
-
function createOrchestratorForOrchestration(modelAdapter,
|
|
17365
|
+
function createOrchestratorForOrchestration(modelAdapter, logger18, useMockTechLead) {
|
|
17448
17366
|
if (modelAdapter !== void 0) {
|
|
17449
|
-
const orchestratorAgent = new Orchestrator({ adapter: modelAdapter, logger:
|
|
17367
|
+
const orchestratorAgent = new Orchestrator({ adapter: modelAdapter, logger: logger18 });
|
|
17450
17368
|
const factory = new OrchestratorFactory({
|
|
17451
|
-
logger:
|
|
17369
|
+
logger: logger18,
|
|
17452
17370
|
techLead: orchestratorAgent
|
|
17453
17371
|
});
|
|
17454
17372
|
return factory.create("orchestrator");
|
|
@@ -17457,7 +17375,7 @@ function createOrchestratorForOrchestration(modelAdapter, logger17, useMockTechL
|
|
|
17457
17375
|
const mockEnabled = useMockTechLead === true || envMockEnabled;
|
|
17458
17376
|
if (mockEnabled) {
|
|
17459
17377
|
const source = envMockEnabled ? `${MOCK_ORCHESTRATION_ENV} env var` : "config";
|
|
17460
|
-
|
|
17378
|
+
logger18.warn(
|
|
17461
17379
|
`Using mock orchestrator as explicitly configured via ${source} (no real adapter available)`
|
|
17462
17380
|
);
|
|
17463
17381
|
return createMockOrchestrator();
|
|
@@ -17611,14 +17529,14 @@ function registerOrchestrateToolSafe(ctx) {
|
|
|
17611
17529
|
});
|
|
17612
17530
|
}
|
|
17613
17531
|
}
|
|
17614
|
-
async function initUpstreamServers(gatewayConfig, server,
|
|
17532
|
+
async function initUpstreamServers(gatewayConfig, server, logger18) {
|
|
17615
17533
|
const upstreamServers = gatewayConfig?.["upstreamServers"];
|
|
17616
17534
|
if (upstreamServers === void 0 || upstreamServers.length === 0) return;
|
|
17617
|
-
const manager = new UpstreamClientManager(
|
|
17535
|
+
const manager = new UpstreamClientManager(logger18);
|
|
17618
17536
|
manager.registerServers(upstreamServers);
|
|
17619
17537
|
await manager.connectEager();
|
|
17620
17538
|
const tools = manager.getAllTools();
|
|
17621
|
-
|
|
17539
|
+
logger18.info("Upstream MCP servers initialized", {
|
|
17622
17540
|
servers: upstreamServers.length,
|
|
17623
17541
|
tools: tools.length
|
|
17624
17542
|
});
|
|
@@ -17638,11 +17556,11 @@ async function initUpstreamServers(gatewayConfig, server, logger17) {
|
|
|
17638
17556
|
);
|
|
17639
17557
|
}
|
|
17640
17558
|
}
|
|
17641
|
-
function maybeRunStpaAnalysis(options,
|
|
17559
|
+
function maybeRunStpaAnalysis(options, logger18) {
|
|
17642
17560
|
const enableStpa = options.enableStpaSafetyAnalysis ?? false;
|
|
17643
17561
|
if (!enableStpa) return;
|
|
17644
|
-
|
|
17645
|
-
runStpaSafetyAnalysis(
|
|
17562
|
+
logger18.info("Running STPA safety analysis on registered tools");
|
|
17563
|
+
runStpaSafetyAnalysis(logger18, options.failOnHighSeverityHazards ?? false);
|
|
17646
17564
|
}
|
|
17647
17565
|
function copyOptionalProps(opts) {
|
|
17648
17566
|
const result = {};
|
|
@@ -17668,16 +17586,16 @@ function createToolContext(options, toolInfra, rateLimiterFactory) {
|
|
|
17668
17586
|
}
|
|
17669
17587
|
};
|
|
17670
17588
|
}
|
|
17671
|
-
function logToolRegistration(
|
|
17589
|
+
function logToolRegistration(logger18, allowlist, info) {
|
|
17672
17590
|
const activeTools = allowlist ? REGISTERED_TOOLS.filter((t) => allowlist.has(t)) : [...REGISTERED_TOOLS];
|
|
17673
17591
|
if (allowlist !== void 0) {
|
|
17674
|
-
|
|
17592
|
+
logger18.info("Tool allowlist active", {
|
|
17675
17593
|
allowed: activeTools.length,
|
|
17676
17594
|
total: REGISTERED_TOOLS.length,
|
|
17677
17595
|
blocked: REGISTERED_TOOLS.filter((t) => !allowlist.has(t))
|
|
17678
17596
|
});
|
|
17679
17597
|
}
|
|
17680
|
-
|
|
17598
|
+
logger18.info("Tools registered with per-tool rate limiting", {
|
|
17681
17599
|
registeredTools: activeTools,
|
|
17682
17600
|
rateLimitingEnabled: info.rateLimiterFactory.isEnabled(),
|
|
17683
17601
|
customRateLimitsConfigured: info.perToolConfig !== void 0,
|
|
@@ -17733,13 +17651,13 @@ function registerToolCategories(ctx) {
|
|
|
17733
17651
|
if (allowed(tool.name)) tool.register(ctx.server, buildStandardDeps(ctx, tool.name));
|
|
17734
17652
|
}
|
|
17735
17653
|
}
|
|
17736
|
-
function initV2PipelineSubsystems(
|
|
17654
|
+
function initV2PipelineSubsystems(logger18) {
|
|
17737
17655
|
const pluginRegistry = getPipelinePluginRegistry();
|
|
17738
17656
|
const pipelineEventBus = getPipelineEventBus();
|
|
17739
17657
|
const bridge = createEventBusBridge({ source: pipelineEventBus });
|
|
17740
17658
|
const policyEngine = createDefaultPolicyEngine();
|
|
17741
17659
|
const v2Config = resolveV2Config();
|
|
17742
|
-
|
|
17660
|
+
logger18.info("V2 Pipeline OS initialized", {
|
|
17743
17661
|
plugins: pluginRegistry.listEnabled().length,
|
|
17744
17662
|
bridged: bridge.forwarded(),
|
|
17745
17663
|
policyRules: policyEngine.listRules().length,
|
|
@@ -17750,7 +17668,7 @@ function initV2PipelineSubsystems(logger17) {
|
|
|
17750
17668
|
function registerMcpTools(options) {
|
|
17751
17669
|
const {
|
|
17752
17670
|
server,
|
|
17753
|
-
logger:
|
|
17671
|
+
logger: logger18,
|
|
17754
17672
|
builtInTemplates,
|
|
17755
17673
|
modelAdapter,
|
|
17756
17674
|
policyFirewall,
|
|
@@ -17761,7 +17679,7 @@ function registerMcpTools(options) {
|
|
|
17761
17679
|
const gatewayServer = gatewayConfig !== void 0 ? createGatewayServerProxy(server, gatewayConfig) : server;
|
|
17762
17680
|
const annotatedServer = createAnnotationsProxy(gatewayServer);
|
|
17763
17681
|
const observableServer = createToolObservabilityProxy(annotatedServer, getPipelineEventBus());
|
|
17764
|
-
const toolInfra = registerTools(observableServer, { logger:
|
|
17682
|
+
const toolInfra = registerTools(observableServer, { logger: logger18 });
|
|
17765
17683
|
const rateLimitConfig = securityConfig?.rateLimit;
|
|
17766
17684
|
const perToolConfig = rateLimitConfig?.perTool;
|
|
17767
17685
|
const rateLimiterFactory = createToolRateLimiterFactory({
|
|
@@ -17770,14 +17688,14 @@ function registerMcpTools(options) {
|
|
|
17770
17688
|
logger: toolInfra.logger
|
|
17771
17689
|
});
|
|
17772
17690
|
setGlobalToolRateLimiterFactory(rateLimiterFactory);
|
|
17773
|
-
initV2PipelineSubsystems(
|
|
17691
|
+
initV2PipelineSubsystems(logger18);
|
|
17774
17692
|
const gatewayOptions = { ...options, server: observableServer };
|
|
17775
17693
|
const ctx = createToolContext(gatewayOptions, toolInfra, rateLimiterFactory);
|
|
17776
17694
|
registerToolCategories(ctx);
|
|
17777
|
-
void initUpstreamServers(gatewayConfig, observableServer,
|
|
17778
|
-
registerPrompts(observableServer,
|
|
17779
|
-
registerResources(observableServer,
|
|
17780
|
-
logToolRegistration(
|
|
17695
|
+
void initUpstreamServers(gatewayConfig, observableServer, logger18);
|
|
17696
|
+
registerPrompts(observableServer, logger18);
|
|
17697
|
+
registerResources(observableServer, logger18);
|
|
17698
|
+
logToolRegistration(logger18, ctx.toolAllowlist, {
|
|
17781
17699
|
rateLimiterFactory,
|
|
17782
17700
|
perToolConfig,
|
|
17783
17701
|
builtInTemplates,
|
|
@@ -17785,34 +17703,34 @@ function registerMcpTools(options) {
|
|
|
17785
17703
|
policyFirewall,
|
|
17786
17704
|
executionMode
|
|
17787
17705
|
});
|
|
17788
|
-
maybeRunStpaAnalysis(options,
|
|
17706
|
+
maybeRunStpaAnalysis(options, logger18);
|
|
17789
17707
|
}
|
|
17790
17708
|
|
|
17791
17709
|
// src/cli-server.ts
|
|
17792
17710
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17793
17711
|
|
|
17794
17712
|
// src/cli-server-lifecycle.ts
|
|
17795
|
-
function initializeSwarmObserver(
|
|
17713
|
+
function initializeSwarmObserver(logger18, options) {
|
|
17796
17714
|
const maxEvents = options?.maxEvents ?? 1e4;
|
|
17797
17715
|
const observer = getSwarmObserver({
|
|
17798
17716
|
maxEvents
|
|
17799
17717
|
});
|
|
17800
|
-
|
|
17718
|
+
logger18.info("SwarmObserver initialized for interaction tracing", {
|
|
17801
17719
|
maxEvents,
|
|
17802
17720
|
configuredFromYaml: options?.maxEvents !== void 0
|
|
17803
17721
|
});
|
|
17804
17722
|
return observer;
|
|
17805
17723
|
}
|
|
17806
|
-
function initializeEventBus(observer,
|
|
17724
|
+
function initializeEventBus(observer, logger18, config) {
|
|
17807
17725
|
const envEnabled = process.env["NEXUS_EVENTBUS_ENABLED"];
|
|
17808
17726
|
const enabled = envEnabled !== void 0 ? envEnabled === "true" : config?.enabled ?? true;
|
|
17809
17727
|
const effectiveConfig = {
|
|
17810
17728
|
...config,
|
|
17811
17729
|
enabled
|
|
17812
17730
|
};
|
|
17813
|
-
const result = initializeEventBusBridge(observer,
|
|
17731
|
+
const result = initializeEventBusBridge(observer, logger18, effectiveConfig);
|
|
17814
17732
|
if (result.initialized) {
|
|
17815
|
-
|
|
17733
|
+
logger18.info("EventBus bridge initialized for A2A visibility", {
|
|
17816
17734
|
subscriptionCount: result.subscriptionCount,
|
|
17817
17735
|
eventBusEnabled: enabled
|
|
17818
17736
|
});
|
|
@@ -17857,17 +17775,17 @@ function recordServerShutdown(observer, context) {
|
|
|
17857
17775
|
}
|
|
17858
17776
|
});
|
|
17859
17777
|
}
|
|
17860
|
-
function logFinalHealthMetrics(observer,
|
|
17778
|
+
function logFinalHealthMetrics(observer, logger18) {
|
|
17861
17779
|
const healthMetrics = observer.getHealthMetrics();
|
|
17862
|
-
|
|
17780
|
+
logger18.info("Final swarm health metrics", {
|
|
17863
17781
|
activeAgents: healthMetrics.activeAgents,
|
|
17864
17782
|
totalAgents: healthMetrics.totalAgents,
|
|
17865
17783
|
totalInteractions: healthMetrics.totalInteractions
|
|
17866
17784
|
});
|
|
17867
17785
|
}
|
|
17868
|
-
function logFinalEventBusStats(
|
|
17786
|
+
function logFinalEventBusStats(logger18) {
|
|
17869
17787
|
const finalStats = getEventBusStats();
|
|
17870
|
-
|
|
17788
|
+
logger18.info("Final EventBus statistics", {
|
|
17871
17789
|
eventsEmitted: finalStats.eventsEmitted,
|
|
17872
17790
|
activeSubscriptions: finalStats.activeSubscriptions,
|
|
17873
17791
|
historySize: finalStats.historySize,
|
|
@@ -17877,14 +17795,14 @@ function logFinalEventBusStats(logger17) {
|
|
|
17877
17795
|
|
|
17878
17796
|
// src/cli-orchestrator.ts
|
|
17879
17797
|
import * as readline2 from "readline";
|
|
17880
|
-
function runOrchestratorRepl(options,
|
|
17881
|
-
return new Promise((
|
|
17798
|
+
function runOrchestratorRepl(options, logger18) {
|
|
17799
|
+
return new Promise((resolve14) => {
|
|
17882
17800
|
const rl = readline2.createInterface({
|
|
17883
17801
|
input: process.stdin,
|
|
17884
17802
|
output: process.stdout,
|
|
17885
17803
|
prompt: "nexus> "
|
|
17886
17804
|
});
|
|
17887
|
-
|
|
17805
|
+
logger18.info('Orchestrator REPL started (type "exit" to quit)');
|
|
17888
17806
|
process.stdout.write("\n");
|
|
17889
17807
|
rl.prompt();
|
|
17890
17808
|
rl.on("line", (line) => {
|
|
@@ -17913,15 +17831,15 @@ function runOrchestratorRepl(options, logger17) {
|
|
|
17913
17831
|
})();
|
|
17914
17832
|
});
|
|
17915
17833
|
rl.on("close", () => {
|
|
17916
|
-
|
|
17917
|
-
|
|
17834
|
+
logger18.info("Orchestrator REPL closed");
|
|
17835
|
+
resolve14();
|
|
17918
17836
|
});
|
|
17919
17837
|
});
|
|
17920
17838
|
}
|
|
17921
17839
|
async function startOrchestratorMode(options) {
|
|
17922
|
-
const
|
|
17923
|
-
if (options.verbose)
|
|
17924
|
-
|
|
17840
|
+
const logger18 = createLogger({ component: "orchestrator" });
|
|
17841
|
+
if (options.verbose) logger18.setLevel("debug");
|
|
17842
|
+
logger18.info("Starting Nexus Agents in orchestrator mode", {
|
|
17925
17843
|
version: VERSION,
|
|
17926
17844
|
hasTask: options.task !== void 0
|
|
17927
17845
|
});
|
|
@@ -17939,17 +17857,17 @@ async function startOrchestratorMode(options) {
|
|
|
17939
17857
|
process.exit(exitCode2);
|
|
17940
17858
|
}
|
|
17941
17859
|
if (process.stdin.isTTY) {
|
|
17942
|
-
await runOrchestratorRepl(options,
|
|
17860
|
+
await runOrchestratorRepl(options, logger18);
|
|
17943
17861
|
process.exit(EXIT_CODES.SUCCESS);
|
|
17944
17862
|
}
|
|
17945
|
-
|
|
17863
|
+
logger18.info("Reading task from stdin...");
|
|
17946
17864
|
const chunks = [];
|
|
17947
17865
|
for await (const chunk of process.stdin) {
|
|
17948
17866
|
chunks.push(String(chunk));
|
|
17949
17867
|
}
|
|
17950
17868
|
const task = chunks.join("").trim();
|
|
17951
17869
|
if (task.length === 0) {
|
|
17952
|
-
|
|
17870
|
+
logger18.error("No task provided. Use --task or pipe input via stdin.");
|
|
17953
17871
|
process.exit(EXIT_CODES.INVALID_ARGS);
|
|
17954
17872
|
}
|
|
17955
17873
|
const orchestrateOptions = {
|
|
@@ -18015,50 +17933,50 @@ function convertCustomExpert(id, def) {
|
|
|
18015
17933
|
}
|
|
18016
17934
|
};
|
|
18017
17935
|
}
|
|
18018
|
-
function createBuiltInExperts(
|
|
17936
|
+
function createBuiltInExperts(logger18, options) {
|
|
18019
17937
|
const result = ExpertFactory.createAllBuiltIn(options);
|
|
18020
17938
|
if (!result.ok) {
|
|
18021
|
-
|
|
17939
|
+
logger18.warn("Failed to create built-in experts", { error: result.error.message });
|
|
18022
17940
|
return { count: 0, ids: [] };
|
|
18023
17941
|
}
|
|
18024
17942
|
const registry = getExpertRegistry();
|
|
18025
17943
|
const registerResult = registry.registerMany(result.value, { replace: true });
|
|
18026
17944
|
if (!registerResult.ok) {
|
|
18027
|
-
|
|
17945
|
+
logger18.warn("Failed to register built-in experts", { error: registerResult.error.message });
|
|
18028
17946
|
return { count: 0, ids: [] };
|
|
18029
17947
|
}
|
|
18030
17948
|
const ids = result.value.map((e) => e.id);
|
|
18031
|
-
|
|
17949
|
+
logger18.info("Registered built-in experts", { count: result.value.length, ids });
|
|
18032
17950
|
return { count: result.value.length, ids };
|
|
18033
17951
|
}
|
|
18034
|
-
function createCustomExperts(customDefs,
|
|
17952
|
+
function createCustomExperts(customDefs, logger18, options) {
|
|
18035
17953
|
const registry = getExpertRegistry();
|
|
18036
17954
|
const ids = [];
|
|
18037
17955
|
for (const [id, def] of Object.entries(customDefs)) {
|
|
18038
17956
|
if (!def.available) {
|
|
18039
|
-
|
|
17957
|
+
logger18.debug("Skipping unavailable custom expert", { id });
|
|
18040
17958
|
continue;
|
|
18041
17959
|
}
|
|
18042
17960
|
const config = convertCustomExpert(id, def);
|
|
18043
17961
|
const result = ExpertFactory.create(config, options);
|
|
18044
17962
|
if (!result.ok) {
|
|
18045
|
-
|
|
17963
|
+
logger18.warn("Failed to create custom expert", { id, error: result.error.message });
|
|
18046
17964
|
continue;
|
|
18047
17965
|
}
|
|
18048
17966
|
const registerResult = registry.register(result.value, { replace: true });
|
|
18049
17967
|
if (!registerResult.ok) {
|
|
18050
|
-
|
|
17968
|
+
logger18.warn("Failed to register custom expert", { id, error: registerResult.error.message });
|
|
18051
17969
|
continue;
|
|
18052
17970
|
}
|
|
18053
17971
|
ids.push(id);
|
|
18054
17972
|
}
|
|
18055
17973
|
if (ids.length > 0) {
|
|
18056
|
-
|
|
17974
|
+
logger18.info("Registered custom experts", { count: ids.length, ids });
|
|
18057
17975
|
}
|
|
18058
17976
|
return { count: ids.length, ids };
|
|
18059
17977
|
}
|
|
18060
17978
|
function initializeExperts(options) {
|
|
18061
|
-
const { expertConfig, logger:
|
|
17979
|
+
const { expertConfig, logger: logger18, modelAdapter } = options;
|
|
18062
17980
|
const createOptions = {};
|
|
18063
17981
|
if (modelAdapter !== void 0) {
|
|
18064
17982
|
createOptions.adapter = modelAdapter;
|
|
@@ -18068,19 +17986,19 @@ function initializeExperts(options) {
|
|
|
18068
17986
|
const registeredIds = [];
|
|
18069
17987
|
const shouldCreateBuiltIn = expertConfig?.builtin !== false;
|
|
18070
17988
|
if (shouldCreateBuiltIn) {
|
|
18071
|
-
const builtInResult = createBuiltInExperts(
|
|
17989
|
+
const builtInResult = createBuiltInExperts(logger18, createOptions);
|
|
18072
17990
|
builtInCount = builtInResult.count;
|
|
18073
17991
|
registeredIds.push(...builtInResult.ids);
|
|
18074
17992
|
} else {
|
|
18075
|
-
|
|
17993
|
+
logger18.info("Built-in experts disabled by configuration");
|
|
18076
17994
|
}
|
|
18077
17995
|
if (expertConfig?.custom !== void 0 && Object.keys(expertConfig.custom).length > 0) {
|
|
18078
|
-
const customResult = createCustomExperts(expertConfig.custom,
|
|
17996
|
+
const customResult = createCustomExperts(expertConfig.custom, logger18, createOptions);
|
|
18079
17997
|
customCount = customResult.count;
|
|
18080
17998
|
registeredIds.push(...customResult.ids);
|
|
18081
17999
|
}
|
|
18082
18000
|
const totalCount = builtInCount + customCount;
|
|
18083
|
-
|
|
18001
|
+
logger18.info("Expert initialization complete", {
|
|
18084
18002
|
builtInCount,
|
|
18085
18003
|
customCount,
|
|
18086
18004
|
totalCount,
|
|
@@ -18095,33 +18013,33 @@ function initializeExperts(options) {
|
|
|
18095
18013
|
}
|
|
18096
18014
|
|
|
18097
18015
|
// src/cli-server-gateway.ts
|
|
18098
|
-
async function tryWireGatewayAdapter(
|
|
18016
|
+
async function tryWireGatewayAdapter(logger18) {
|
|
18099
18017
|
const sandboxActive = detectSandbox().active;
|
|
18100
18018
|
const env2 = readOpenAICompatEnv();
|
|
18101
18019
|
if (env2 === null) {
|
|
18102
|
-
handleMissingEnv(
|
|
18020
|
+
handleMissingEnv(logger18, sandboxActive);
|
|
18103
18021
|
return void 0;
|
|
18104
18022
|
}
|
|
18105
18023
|
const result = await buildOpenAICompatAdapters();
|
|
18106
18024
|
if (result === null) return void 0;
|
|
18107
18025
|
if (!result.ok) {
|
|
18108
|
-
handleProbeFailure(
|
|
18026
|
+
handleProbeFailure(logger18, sandboxActive, result.error.message);
|
|
18109
18027
|
return void 0;
|
|
18110
18028
|
}
|
|
18111
18029
|
if (result.value.length === 0) {
|
|
18112
|
-
handleZeroModels(
|
|
18030
|
+
handleZeroModels(logger18, sandboxActive);
|
|
18113
18031
|
return void 0;
|
|
18114
18032
|
}
|
|
18115
|
-
|
|
18033
|
+
logger18.info("OpenAI-compatible gateway wired", {
|
|
18116
18034
|
baseUrl: env2.baseUrl,
|
|
18117
18035
|
modelCount: result.value.length,
|
|
18118
18036
|
models: result.value.map((a) => a.modelId)
|
|
18119
18037
|
});
|
|
18120
18038
|
return result.value[0];
|
|
18121
18039
|
}
|
|
18122
|
-
function handleMissingEnv(
|
|
18040
|
+
function handleMissingEnv(logger18, sandboxActive) {
|
|
18123
18041
|
if (sandboxActive) {
|
|
18124
|
-
|
|
18042
|
+
logger18.error(
|
|
18125
18043
|
"Sandbox mode active but NEXUS_OPENAI_COMPAT_URL / NEXUS_OPENAI_COMPAT_KEY are not set. Configure the gateway in your launch env or opencode.json. See docs/guides/SANDBOXED-USAGE.md.",
|
|
18126
18044
|
new Error("Missing gateway configuration in sandbox mode")
|
|
18127
18045
|
);
|
|
@@ -18129,28 +18047,28 @@ function handleMissingEnv(logger17, sandboxActive) {
|
|
|
18129
18047
|
}
|
|
18130
18048
|
return void 0;
|
|
18131
18049
|
}
|
|
18132
|
-
function handleProbeFailure(
|
|
18050
|
+
function handleProbeFailure(logger18, sandboxActive, reason) {
|
|
18133
18051
|
if (sandboxActive) {
|
|
18134
|
-
|
|
18052
|
+
logger18.error(
|
|
18135
18053
|
"Sandbox mode active and OpenAI-compatible gateway probe failed.",
|
|
18136
18054
|
new Error(reason)
|
|
18137
18055
|
);
|
|
18138
18056
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
18139
18057
|
}
|
|
18140
|
-
|
|
18058
|
+
logger18.warn("OpenAI-compatible gateway probe failed; continuing with CLI adapters", {
|
|
18141
18059
|
error: reason
|
|
18142
18060
|
});
|
|
18143
18061
|
return void 0;
|
|
18144
18062
|
}
|
|
18145
|
-
function handleZeroModels(
|
|
18063
|
+
function handleZeroModels(logger18, sandboxActive) {
|
|
18146
18064
|
if (sandboxActive) {
|
|
18147
|
-
|
|
18065
|
+
logger18.error(
|
|
18148
18066
|
"Sandbox mode active and gateway returned 0 models. Check upstream provider quotas / list filters.",
|
|
18149
18067
|
new Error("Gateway discovered 0 models")
|
|
18150
18068
|
);
|
|
18151
18069
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
18152
18070
|
}
|
|
18153
|
-
|
|
18071
|
+
logger18.warn("OpenAI-compatible gateway returned 0 models; ignoring");
|
|
18154
18072
|
return void 0;
|
|
18155
18073
|
}
|
|
18156
18074
|
|
|
@@ -19007,7 +18925,7 @@ var ALL_STANDARDS_SKILLS = [
|
|
|
19007
18925
|
...CODING_SKILLS,
|
|
19008
18926
|
...ARCHITECTURE_SKILLS
|
|
19009
18927
|
];
|
|
19010
|
-
function registerStandardsSkills(library,
|
|
18928
|
+
function registerStandardsSkills(library, logger18) {
|
|
19011
18929
|
let registered = 0;
|
|
19012
18930
|
for (const skillDef of ALL_STANDARDS_SKILLS) {
|
|
19013
18931
|
try {
|
|
@@ -19015,10 +18933,10 @@ function registerStandardsSkills(library, logger17) {
|
|
|
19015
18933
|
registered++;
|
|
19016
18934
|
} catch (error) {
|
|
19017
18935
|
const message = getErrorMessage(error);
|
|
19018
|
-
|
|
18936
|
+
logger18.warn(`Failed to register skill "${skillDef.name}": ${message}`);
|
|
19019
18937
|
}
|
|
19020
18938
|
}
|
|
19021
|
-
|
|
18939
|
+
logger18.info(
|
|
19022
18940
|
`Registered ${String(registered)}/${String(ALL_STANDARDS_SKILLS.length)} standards skills`,
|
|
19023
18941
|
{
|
|
19024
18942
|
domains: {
|
|
@@ -19048,7 +18966,7 @@ function adaptConfigToLibrary(config) {
|
|
|
19048
18966
|
}
|
|
19049
18967
|
function createBeliefPromoter() {
|
|
19050
18968
|
return async (event) => {
|
|
19051
|
-
const { getToolMemory } = await import("./tool-memory-
|
|
18969
|
+
const { getToolMemory } = await import("./tool-memory-LUXUOE6Q.js");
|
|
19052
18970
|
const tm = getToolMemory();
|
|
19053
18971
|
await tm.recordBelief(
|
|
19054
18972
|
`skill:${event.name}`,
|
|
@@ -19059,40 +18977,40 @@ function createBeliefPromoter() {
|
|
|
19059
18977
|
};
|
|
19060
18978
|
}
|
|
19061
18979
|
async function initializeSkillLibrary(options) {
|
|
19062
|
-
const { skillsConfig, logger:
|
|
18980
|
+
const { skillsConfig, logger: logger18 } = options;
|
|
19063
18981
|
if (globalSkillLibrary !== void 0) {
|
|
19064
|
-
|
|
18982
|
+
logger18.debug("Skill library already initialized");
|
|
19065
18983
|
return { initialized: true, library: globalSkillLibrary };
|
|
19066
18984
|
}
|
|
19067
18985
|
if (skillsConfig?.enabled === false) {
|
|
19068
|
-
|
|
18986
|
+
logger18.info("Skill library disabled by configuration");
|
|
19069
18987
|
return { initialized: false, reason: "disabled in config" };
|
|
19070
18988
|
}
|
|
19071
18989
|
const libraryConfig = skillsConfig !== void 0 ? adaptConfigToLibrary(skillsConfig) : void 0;
|
|
19072
|
-
globalSkillLibrary = createSkillLibrary(libraryConfig,
|
|
19073
|
-
registerStandardsSkills(globalSkillLibrary,
|
|
19074
|
-
await loadExternalSkillPacks(skillsConfig, globalSkillLibrary,
|
|
19075
|
-
|
|
18990
|
+
globalSkillLibrary = createSkillLibrary(libraryConfig, logger18);
|
|
18991
|
+
registerStandardsSkills(globalSkillLibrary, logger18);
|
|
18992
|
+
await loadExternalSkillPacks(skillsConfig, globalSkillLibrary, logger18);
|
|
18993
|
+
logger18.info("Skill library initialized", {
|
|
19076
18994
|
maxSkills: globalSkillLibrary.getConfig().maxSkills,
|
|
19077
18995
|
enablePruning: globalSkillLibrary.getConfig().enablePruning,
|
|
19078
18996
|
trackHistory: globalSkillLibrary.getConfig().trackExecutionHistory
|
|
19079
18997
|
});
|
|
19080
18998
|
return { initialized: true, library: globalSkillLibrary };
|
|
19081
18999
|
}
|
|
19082
|
-
async function loadExternalSkillPacks(skillsConfig, library,
|
|
19000
|
+
async function loadExternalSkillPacks(skillsConfig, library, logger18) {
|
|
19083
19001
|
const externalPacks = skillsConfig?.externalPacks;
|
|
19084
19002
|
if (!externalPacks || externalPacks.length === 0) {
|
|
19085
19003
|
return;
|
|
19086
19004
|
}
|
|
19087
|
-
|
|
19088
|
-
const { loaded, errors } = await loadAllExternalPacks(externalPacks,
|
|
19005
|
+
logger18.info("Loading external skill packs", { count: externalPacks.length });
|
|
19006
|
+
const { loaded, errors } = await loadAllExternalPacks(externalPacks, logger18);
|
|
19089
19007
|
for (const packResult of loaded) {
|
|
19090
19008
|
for (const skill of packResult.skills) {
|
|
19091
19009
|
library.addSkill(skill);
|
|
19092
19010
|
}
|
|
19093
19011
|
}
|
|
19094
19012
|
if (errors.length > 0) {
|
|
19095
|
-
|
|
19013
|
+
logger18.warn("Some external packs failed to load", {
|
|
19096
19014
|
failedCount: errors.length,
|
|
19097
19015
|
failedPacks: errors.map((e) => e.packName)
|
|
19098
19016
|
});
|
|
@@ -19102,19 +19020,19 @@ async function loadExternalSkillPacks(skillsConfig, library, logger17) {
|
|
|
19102
19020
|
// src/cli-server-feedback.ts
|
|
19103
19021
|
var globalFeedbackIntegration;
|
|
19104
19022
|
function initializeFeedbackIntegration(options) {
|
|
19105
|
-
const { logger:
|
|
19023
|
+
const { logger: logger18, config, router } = options;
|
|
19106
19024
|
try {
|
|
19107
19025
|
globalFeedbackIntegration = createFeedbackIntegration({
|
|
19108
19026
|
enableAutoFeedback: true,
|
|
19109
19027
|
// Enable automatic feedback collection
|
|
19110
19028
|
...config,
|
|
19111
|
-
logger:
|
|
19029
|
+
logger: logger18
|
|
19112
19030
|
});
|
|
19113
19031
|
if (router !== void 0 && globalFeedbackIntegration instanceof FeedbackIntegration) {
|
|
19114
19032
|
globalFeedbackIntegration.registerCompositeRouter(router);
|
|
19115
|
-
|
|
19033
|
+
logger18.debug("FeedbackIntegration attached to CompositeRouter");
|
|
19116
19034
|
}
|
|
19117
|
-
|
|
19035
|
+
logger18.info("FeedbackIntegration initialized", {
|
|
19118
19036
|
enableAutoFeedback: config?.enableAutoFeedback ?? true,
|
|
19119
19037
|
hasRouter: router !== void 0
|
|
19120
19038
|
});
|
|
@@ -19125,7 +19043,7 @@ function initializeFeedbackIntegration(options) {
|
|
|
19125
19043
|
};
|
|
19126
19044
|
} catch (error) {
|
|
19127
19045
|
const message = getErrorMessage(error);
|
|
19128
|
-
|
|
19046
|
+
logger18.warn("FeedbackIntegration initialization failed", { error: message });
|
|
19129
19047
|
return {
|
|
19130
19048
|
initialized: false,
|
|
19131
19049
|
reason: `Initialization failed: ${message}`
|
|
@@ -19151,8 +19069,8 @@ function buildAuthConfig(config) {
|
|
|
19151
19069
|
tokenFile: configAuth?.tokenFile ?? getDefaultTokenPath()
|
|
19152
19070
|
};
|
|
19153
19071
|
}
|
|
19154
|
-
function initializeAuth(config,
|
|
19155
|
-
const log =
|
|
19072
|
+
function initializeAuth(config, logger18) {
|
|
19073
|
+
const log = logger18 ?? createLogger({ component: "auth" });
|
|
19156
19074
|
const authConfig = buildAuthConfig(config);
|
|
19157
19075
|
const handler = new AuthHandler(authConfig, log);
|
|
19158
19076
|
const tokenFile = authConfig.tokenFile ?? getDefaultTokenPath();
|
|
@@ -19178,9 +19096,9 @@ function initializeAuth(config, logger17) {
|
|
|
19178
19096
|
|
|
19179
19097
|
// src/cli-server-audit.ts
|
|
19180
19098
|
var DEFAULT_AUDIT_DIR = nexusDataPath("audit");
|
|
19181
|
-
function initializeAuditLogger(securityConfig,
|
|
19099
|
+
function initializeAuditLogger(securityConfig, logger18) {
|
|
19182
19100
|
if (securityConfig?.audit?.enabled !== true) {
|
|
19183
|
-
|
|
19101
|
+
logger18.debug("Audit logging disabled (set security.audit.enabled: true to enable)");
|
|
19184
19102
|
return null;
|
|
19185
19103
|
}
|
|
19186
19104
|
const auditConfig = securityConfig.audit;
|
|
@@ -19197,20 +19115,20 @@ function initializeAuditLogger(securityConfig, logger17) {
|
|
|
19197
19115
|
flushIntervalMs: 1e3
|
|
19198
19116
|
},
|
|
19199
19117
|
void 0,
|
|
19200
|
-
|
|
19118
|
+
logger18
|
|
19201
19119
|
);
|
|
19202
19120
|
auditLogger.logSystemStartup({ auditLogDir: logDir });
|
|
19203
|
-
|
|
19121
|
+
logger18.info("Audit logging enabled", { logDir });
|
|
19204
19122
|
return auditLogger;
|
|
19205
19123
|
}
|
|
19206
|
-
async function shutdownAuditLogger(auditLogger,
|
|
19124
|
+
async function shutdownAuditLogger(auditLogger, logger18) {
|
|
19207
19125
|
if (auditLogger === null) return;
|
|
19208
19126
|
try {
|
|
19209
19127
|
auditLogger.logSystemShutdown();
|
|
19210
19128
|
await auditLogger.close();
|
|
19211
|
-
|
|
19129
|
+
logger18.info("Audit logger shutdown complete");
|
|
19212
19130
|
} catch (error) {
|
|
19213
|
-
|
|
19131
|
+
logger18.error(
|
|
19214
19132
|
"Error shutting down audit logger",
|
|
19215
19133
|
error instanceof Error ? error : new Error(String(error))
|
|
19216
19134
|
);
|
|
@@ -19224,9 +19142,9 @@ function getRateLimitValues(config) {
|
|
|
19224
19142
|
const rl = config?.security?.rateLimit;
|
|
19225
19143
|
return { enabled: rl?.enabled ?? true, rpm: rl?.requestsPerMinute ?? 60 };
|
|
19226
19144
|
}
|
|
19227
|
-
function createConfiguredPolicyFirewall(
|
|
19145
|
+
function createConfiguredPolicyFirewall(logger18, config) {
|
|
19228
19146
|
const policyVals = getPolicyValues(config);
|
|
19229
|
-
return createDefaultPolicyFirewall({ mode: policyVals.mode, logger:
|
|
19147
|
+
return createDefaultPolicyFirewall({ mode: policyVals.mode, logger: logger18 });
|
|
19230
19148
|
}
|
|
19231
19149
|
function getAuthValues(config) {
|
|
19232
19150
|
const envAuth = process.env["NEXUS_AUTH_ENABLED"];
|
|
@@ -19235,12 +19153,12 @@ function getAuthValues(config) {
|
|
|
19235
19153
|
const method = configAuth?.method ?? process.env["NEXUS_AUTH_METHOD"] ?? "none";
|
|
19236
19154
|
return { enabled, method };
|
|
19237
19155
|
}
|
|
19238
|
-
function logSecurityConfig(
|
|
19239
|
-
const policyFirewall = createConfiguredPolicyFirewall(
|
|
19156
|
+
function logSecurityConfig(logger18, config) {
|
|
19157
|
+
const policyFirewall = createConfiguredPolicyFirewall(logger18, config);
|
|
19240
19158
|
const authVals = getAuthValues(config);
|
|
19241
19159
|
const policyVals = getPolicyValues(config);
|
|
19242
19160
|
const rateLimitVals = getRateLimitValues(config);
|
|
19243
|
-
|
|
19161
|
+
logger18.info("Security configuration", {
|
|
19244
19162
|
policyMode: policyVals.mode,
|
|
19245
19163
|
defaultExecutionMode: policyVals.defaultExec,
|
|
19246
19164
|
policyRuleCount: policyFirewall.getRules().length,
|
|
@@ -19251,32 +19169,32 @@ function logSecurityConfig(logger17, config) {
|
|
|
19251
19169
|
allowedPaths: config?.security?.allowedPaths ?? ["./"]
|
|
19252
19170
|
});
|
|
19253
19171
|
if (!authVals.enabled) {
|
|
19254
|
-
|
|
19172
|
+
logger18.warn(
|
|
19255
19173
|
"Authentication explicitly disabled \u2014 network-exposed endpoints are unprotected. Remove NEXUS_AUTH_ENABLED=false to re-enable."
|
|
19256
19174
|
);
|
|
19257
19175
|
}
|
|
19258
|
-
|
|
19176
|
+
logger18.debug("Policy firewall rules", {
|
|
19259
19177
|
rules: policyFirewall.getRules().map((r) => ({ name: r.name, description: r.description }))
|
|
19260
19178
|
});
|
|
19261
19179
|
return policyFirewall;
|
|
19262
19180
|
}
|
|
19263
19181
|
|
|
19264
19182
|
// src/cli-server.ts
|
|
19265
|
-
function setupShutdownHandlers(cleanup,
|
|
19183
|
+
function setupShutdownHandlers(cleanup, logger18) {
|
|
19266
19184
|
let isShuttingDown = false;
|
|
19267
19185
|
const handleShutdown = async (signal) => {
|
|
19268
19186
|
if (isShuttingDown) {
|
|
19269
|
-
|
|
19187
|
+
logger18.debug("Shutdown already in progress, ignoring signal", { signal });
|
|
19270
19188
|
return;
|
|
19271
19189
|
}
|
|
19272
19190
|
isShuttingDown = true;
|
|
19273
|
-
|
|
19191
|
+
logger18.info("Received shutdown signal", { signal });
|
|
19274
19192
|
try {
|
|
19275
19193
|
await cleanup();
|
|
19276
|
-
|
|
19194
|
+
logger18.info("Shutdown complete");
|
|
19277
19195
|
process.exit(EXIT_CODES.SUCCESS);
|
|
19278
19196
|
} catch (error) {
|
|
19279
|
-
|
|
19197
|
+
logger18.error(
|
|
19280
19198
|
"Error during shutdown",
|
|
19281
19199
|
error instanceof Error ? error : new Error(String(error))
|
|
19282
19200
|
);
|
|
@@ -19285,24 +19203,24 @@ function setupShutdownHandlers(cleanup, logger17) {
|
|
|
19285
19203
|
};
|
|
19286
19204
|
const onSignal = (signal) => () => {
|
|
19287
19205
|
handleShutdown(signal).catch((err2) => {
|
|
19288
|
-
|
|
19206
|
+
logger18.error("Shutdown handler crashed", err2 instanceof Error ? err2 : new Error(String(err2)));
|
|
19289
19207
|
process.exit(EXIT_CODES.SHUTDOWN_ERROR);
|
|
19290
19208
|
});
|
|
19291
19209
|
};
|
|
19292
19210
|
process.on("SIGINT", onSignal("SIGINT"));
|
|
19293
19211
|
process.on("SIGTERM", onSignal("SIGTERM"));
|
|
19294
19212
|
process.on("uncaughtException", (error) => {
|
|
19295
|
-
|
|
19213
|
+
logger18.error("Uncaught exception", error);
|
|
19296
19214
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
19297
19215
|
});
|
|
19298
19216
|
process.on("unhandledRejection", (reason) => {
|
|
19299
19217
|
const error = reason instanceof Error ? reason : new Error(String(reason));
|
|
19300
|
-
|
|
19218
|
+
logger18.error("Unhandled rejection", error);
|
|
19301
19219
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
19302
19220
|
});
|
|
19303
19221
|
}
|
|
19304
|
-
function logStartupInfo(
|
|
19305
|
-
|
|
19222
|
+
function logStartupInfo(logger18, detectionResult, verbose) {
|
|
19223
|
+
logger18.info("Starting Nexus Agents", {
|
|
19306
19224
|
version: VERSION,
|
|
19307
19225
|
mode: detectionResult.mode,
|
|
19308
19226
|
modeSource: detectionResult.source,
|
|
@@ -19312,7 +19230,7 @@ function logStartupInfo(logger17, detectionResult, verbose) {
|
|
|
19312
19230
|
platform: process.platform
|
|
19313
19231
|
});
|
|
19314
19232
|
if (verbose) {
|
|
19315
|
-
|
|
19233
|
+
logger18.debug("Mode detection signals", {
|
|
19316
19234
|
stdinIsTty: detectionResult.signals.stdinIsTty,
|
|
19317
19235
|
stdoutIsTty: detectionResult.signals.stdoutIsTty,
|
|
19318
19236
|
mcpClientName: detectionResult.signals.mcpClientName,
|
|
@@ -19322,20 +19240,20 @@ function logStartupInfo(logger17, detectionResult, verbose) {
|
|
|
19322
19240
|
});
|
|
19323
19241
|
}
|
|
19324
19242
|
}
|
|
19325
|
-
function validateModeOrExit(
|
|
19243
|
+
function validateModeOrExit(logger18, mode) {
|
|
19326
19244
|
if (mode === "mesh") {
|
|
19327
|
-
|
|
19245
|
+
logger18.error("Mesh mode is not yet implemented. Use --mode=server or --mode=orchestrator.");
|
|
19328
19246
|
process.exit(EXIT_CODES.INVALID_ARGS);
|
|
19329
19247
|
}
|
|
19330
19248
|
}
|
|
19331
|
-
function loadAndLogConfig(
|
|
19332
|
-
const result = loadConfig({ logger:
|
|
19249
|
+
function loadAndLogConfig(logger18) {
|
|
19250
|
+
const result = loadConfig({ logger: logger18 });
|
|
19333
19251
|
if (!result.ok) {
|
|
19334
|
-
|
|
19252
|
+
logger18.error("Failed to load configuration", new Error(result.error.message));
|
|
19335
19253
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
19336
19254
|
}
|
|
19337
19255
|
const configResult = result.value;
|
|
19338
|
-
|
|
19256
|
+
logger18.info("Configuration loaded", {
|
|
19339
19257
|
configPath: configResult.configPath ?? "(defaults)",
|
|
19340
19258
|
usingDefaults: configResult.usingDefaults,
|
|
19341
19259
|
warningCount: configResult.warnings.length,
|
|
@@ -19344,20 +19262,20 @@ function loadAndLogConfig(logger17) {
|
|
|
19344
19262
|
hasSecurity: configResult.config.security !== void 0
|
|
19345
19263
|
});
|
|
19346
19264
|
for (const warning of configResult.warnings) {
|
|
19347
|
-
|
|
19265
|
+
logger18.warn(warning);
|
|
19348
19266
|
}
|
|
19349
19267
|
return configResult;
|
|
19350
19268
|
}
|
|
19351
19269
|
function createShutdownCleanup(options) {
|
|
19352
|
-
const { eventBusBridge, observer, eventContext, server, serverLogger, logger:
|
|
19270
|
+
const { eventBusBridge, observer, eventContext, server, serverLogger, logger: logger18, auditLogger } = options;
|
|
19353
19271
|
return async () => {
|
|
19354
|
-
await shutdownAuditLogger(auditLogger,
|
|
19272
|
+
await shutdownAuditLogger(auditLogger, logger18);
|
|
19355
19273
|
if (eventBusBridge.initialized) {
|
|
19356
|
-
logFinalEventBusStats(
|
|
19274
|
+
logFinalEventBusStats(logger18);
|
|
19357
19275
|
eventBusBridge.cleanup();
|
|
19358
19276
|
}
|
|
19359
19277
|
recordServerShutdown(observer, eventContext);
|
|
19360
|
-
logFinalHealthMetrics(observer,
|
|
19278
|
+
logFinalHealthMetrics(observer, logger18);
|
|
19361
19279
|
shutdownToolMemory();
|
|
19362
19280
|
const closeResult = await closeServer(server, serverLogger);
|
|
19363
19281
|
if (!closeResult.ok) {
|
|
@@ -19365,61 +19283,61 @@ function createShutdownCleanup(options) {
|
|
|
19365
19283
|
}
|
|
19366
19284
|
};
|
|
19367
19285
|
}
|
|
19368
|
-
function createAndValidateMcpServer(
|
|
19286
|
+
function createAndValidateMcpServer(logger18) {
|
|
19369
19287
|
const serverResult = createServer({
|
|
19370
19288
|
name: "nexus-agents",
|
|
19371
19289
|
version: VERSION,
|
|
19372
|
-
logger:
|
|
19290
|
+
logger: logger18
|
|
19373
19291
|
});
|
|
19374
19292
|
if (!serverResult.ok) {
|
|
19375
|
-
|
|
19293
|
+
logger18.error("Failed to create MCP server", new Error(serverResult.error.message));
|
|
19376
19294
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
19377
19295
|
}
|
|
19378
19296
|
return serverResult.value;
|
|
19379
19297
|
}
|
|
19380
|
-
async function initializeAndLogSandbox(
|
|
19298
|
+
async function initializeAndLogSandbox(logger18, sandboxConfig) {
|
|
19381
19299
|
const sandboxResult = await initializeSandbox(sandboxConfig);
|
|
19382
|
-
|
|
19300
|
+
logger18.info("Sandbox initialized", {
|
|
19383
19301
|
mode: getSandboxMode(),
|
|
19384
19302
|
executor: sandboxResult.executor.name,
|
|
19385
19303
|
usedFallback: sandboxResult.usedFallback,
|
|
19386
19304
|
configuredMode: sandboxConfig?.mode ?? "default"
|
|
19387
19305
|
});
|
|
19388
19306
|
}
|
|
19389
|
-
async function connectToStdioTransport(server,
|
|
19390
|
-
|
|
19307
|
+
async function connectToStdioTransport(server, logger18, serverLogger) {
|
|
19308
|
+
logger18.setDestination?.("stderr");
|
|
19391
19309
|
serverLogger.setDestination?.("stderr");
|
|
19392
|
-
|
|
19310
|
+
logger18.info("Connecting to stdio transport");
|
|
19393
19311
|
const transport = new StdioServerTransport();
|
|
19394
19312
|
const connectResult = await connectTransport(server, transport, serverLogger);
|
|
19395
19313
|
if (!connectResult.ok) {
|
|
19396
|
-
|
|
19314
|
+
logger18.error("Failed to connect MCP server", new Error(connectResult.error.message));
|
|
19397
19315
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
19398
19316
|
}
|
|
19399
|
-
|
|
19317
|
+
logger18.info("MCP server started successfully");
|
|
19400
19318
|
}
|
|
19401
|
-
function createAdapterRegistry(
|
|
19319
|
+
function createAdapterRegistry(logger18) {
|
|
19402
19320
|
return createUnifiedRegistry({
|
|
19403
|
-
logger:
|
|
19321
|
+
logger: logger18,
|
|
19404
19322
|
defaultCliTimeoutMs: MCP_TIMEOUTS.perTool["orchestrate"] ?? MCP_TIMEOUTS.defaultMs
|
|
19405
19323
|
});
|
|
19406
19324
|
}
|
|
19407
|
-
function buildGatewayConfig(config,
|
|
19325
|
+
function buildGatewayConfig(config, logger18) {
|
|
19408
19326
|
const gatewaySection = config.gateway;
|
|
19409
19327
|
const enabled = gatewaySection?.enabled !== false;
|
|
19410
19328
|
const tierOverrides = parseTierOverrides(gatewaySection?.tierOverrides);
|
|
19411
19329
|
return {
|
|
19412
19330
|
enabled,
|
|
19413
|
-
logger:
|
|
19331
|
+
logger: logger18,
|
|
19414
19332
|
...tierOverrides !== void 0 && { tierOverrides }
|
|
19415
19333
|
};
|
|
19416
19334
|
}
|
|
19417
|
-
async function initializeAndRegisterTools(server,
|
|
19418
|
-
|
|
19335
|
+
async function initializeAndRegisterTools(server, logger18, policyFirewall, config, feedbackIntegration) {
|
|
19336
|
+
logger18.info("Loading built-in workflow templates");
|
|
19419
19337
|
const builtInTemplates = await initializeBuiltInTemplates();
|
|
19420
|
-
|
|
19421
|
-
const adapterRegistry = createAdapterRegistry(
|
|
19422
|
-
const gatewayAdapter = await tryWireGatewayAdapter(
|
|
19338
|
+
logger18.info("Loaded built-in templates", { count: builtInTemplates.size });
|
|
19339
|
+
const adapterRegistry = createAdapterRegistry(logger18);
|
|
19340
|
+
const gatewayAdapter = await tryWireGatewayAdapter(logger18);
|
|
19423
19341
|
const modelAdapter = gatewayAdapter ?? adapterRegistry.getDefault();
|
|
19424
19342
|
const policyVals = getPolicyValues(config);
|
|
19425
19343
|
const allowedPaths = config.security?.allowedPaths;
|
|
@@ -19427,13 +19345,13 @@ async function initializeAndRegisterTools(server, logger17, policyFirewall, conf
|
|
|
19427
19345
|
const workflowConfig = config.workflows;
|
|
19428
19346
|
const toolsOptions = {
|
|
19429
19347
|
server,
|
|
19430
|
-
logger:
|
|
19348
|
+
logger: logger18,
|
|
19431
19349
|
builtInTemplates,
|
|
19432
19350
|
policyFirewall,
|
|
19433
19351
|
executionMode: policyVals.defaultExec,
|
|
19434
19352
|
modelAdapter,
|
|
19435
19353
|
// Gateway middleware for tier-aware dispatch logging (Issue #896, #897)
|
|
19436
|
-
gatewayConfig: buildGatewayConfig(config,
|
|
19354
|
+
gatewayConfig: buildGatewayConfig(config, logger18),
|
|
19437
19355
|
...allowedPaths !== void 0 && { allowedPaths },
|
|
19438
19356
|
...securityConfig !== void 0 && { securityConfig },
|
|
19439
19357
|
...workflowConfig !== void 0 && { workflowConfig },
|
|
@@ -19441,45 +19359,45 @@ async function initializeAndRegisterTools(server, logger17, policyFirewall, conf
|
|
|
19441
19359
|
};
|
|
19442
19360
|
registerMcpTools(toolsOptions);
|
|
19443
19361
|
}
|
|
19444
|
-
function applyLoggingConfig(
|
|
19362
|
+
function applyLoggingConfig(logger18, verbose, config) {
|
|
19445
19363
|
if (!verbose && config.logging?.level !== void 0) {
|
|
19446
|
-
|
|
19447
|
-
|
|
19364
|
+
logger18.setLevel(config.logging.level);
|
|
19365
|
+
logger18.debug("Log level set from configuration", { level: config.logging.level });
|
|
19448
19366
|
}
|
|
19449
|
-
if (config.logging?.format !== void 0 &&
|
|
19450
|
-
|
|
19451
|
-
|
|
19367
|
+
if (config.logging?.format !== void 0 && logger18.setFormat !== void 0) {
|
|
19368
|
+
logger18.setFormat(config.logging.format);
|
|
19369
|
+
logger18.debug("Log format set from configuration", { format: config.logging.format });
|
|
19452
19370
|
}
|
|
19453
|
-
if (config.logging?.destination !== void 0 &&
|
|
19454
|
-
|
|
19455
|
-
|
|
19371
|
+
if (config.logging?.destination !== void 0 && logger18.setDestination !== void 0) {
|
|
19372
|
+
logger18.setDestination(config.logging.destination, config.logging.filePath);
|
|
19373
|
+
logger18.debug("Log destination set from configuration", {
|
|
19456
19374
|
destination: config.logging.destination,
|
|
19457
19375
|
filePath: config.logging.filePath
|
|
19458
19376
|
});
|
|
19459
19377
|
}
|
|
19460
19378
|
}
|
|
19461
|
-
async function initializeSubsystems(config,
|
|
19462
|
-
const expertResult = initializeExperts({ expertConfig: config.experts, logger:
|
|
19463
|
-
|
|
19379
|
+
async function initializeSubsystems(config, logger18) {
|
|
19380
|
+
const expertResult = initializeExperts({ expertConfig: config.experts, logger: logger18 });
|
|
19381
|
+
logger18.debug("Expert system initialized", {
|
|
19464
19382
|
builtIn: expertResult.builtInCount,
|
|
19465
19383
|
custom: expertResult.customCount
|
|
19466
19384
|
});
|
|
19467
|
-
const skillsResult = await initializeSkillLibrary({ skillsConfig: config.skills, logger:
|
|
19468
|
-
|
|
19385
|
+
const skillsResult = await initializeSkillLibrary({ skillsConfig: config.skills, logger: logger18 });
|
|
19386
|
+
logger18.debug("Skill library initialization", {
|
|
19469
19387
|
initialized: skillsResult.initialized,
|
|
19470
19388
|
reason: skillsResult.reason
|
|
19471
19389
|
});
|
|
19472
|
-
const sicaResult = initializeSica({ sicaConfig: config.sica, logger:
|
|
19473
|
-
|
|
19390
|
+
const sicaResult = initializeSica({ sicaConfig: config.sica, logger: logger18 });
|
|
19391
|
+
logger18.debug("SICA initialization", {
|
|
19474
19392
|
enabled: sicaResult.enabled,
|
|
19475
19393
|
reason: sicaResult.reason
|
|
19476
19394
|
});
|
|
19477
|
-
const feedbackResult = initializeFeedbackIntegration({ logger:
|
|
19478
|
-
|
|
19395
|
+
const feedbackResult = initializeFeedbackIntegration({ logger: logger18 });
|
|
19396
|
+
logger18.debug("FeedbackIntegration initialization", {
|
|
19479
19397
|
initialized: feedbackResult.initialized,
|
|
19480
19398
|
reason: feedbackResult.reason
|
|
19481
19399
|
});
|
|
19482
|
-
const { server, logger: serverLogger } = createAndValidateMcpServer(
|
|
19400
|
+
const { server, logger: serverLogger } = createAndValidateMcpServer(logger18);
|
|
19483
19401
|
const observer = initializeSwarmObserver(serverLogger, {
|
|
19484
19402
|
maxEvents: config.observability?.swarmObserverMaxEvents
|
|
19485
19403
|
});
|
|
@@ -19499,32 +19417,32 @@ async function initializeSubsystems(config, logger17) {
|
|
|
19499
19417
|
}
|
|
19500
19418
|
var SERVER_STARTUP_TIMEOUT_MS = 3e4;
|
|
19501
19419
|
async function startServer(verbose, mode, modeWasExplicit = false, orchestratorOptions) {
|
|
19502
|
-
const
|
|
19503
|
-
if (verbose)
|
|
19504
|
-
validateModeOrExit(
|
|
19420
|
+
const logger18 = createLogger({ component: "cli" });
|
|
19421
|
+
if (verbose) logger18.setLevel("debug");
|
|
19422
|
+
validateModeOrExit(logger18, mode);
|
|
19505
19423
|
if (mode === "orchestrator") {
|
|
19506
19424
|
await startOrchestratorMode(orchestratorOptions ?? { verbose });
|
|
19507
19425
|
return;
|
|
19508
19426
|
}
|
|
19509
19427
|
const startupWatchdog = setTimeout(() => {
|
|
19510
|
-
|
|
19428
|
+
logger18.error(
|
|
19511
19429
|
`Server startup exceeded ${String(SERVER_STARTUP_TIMEOUT_MS)}ms \u2014 aborting. Common causes: hung config load, blocked subsystem init, stdio transport stall.`
|
|
19512
19430
|
);
|
|
19513
19431
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
19514
19432
|
}, SERVER_STARTUP_TIMEOUT_MS);
|
|
19515
19433
|
startupWatchdog.unref();
|
|
19516
19434
|
const detectionResult = detectMode({ explicitMode: modeWasExplicit ? mode : void 0 });
|
|
19517
|
-
logStartupInfo(
|
|
19518
|
-
const configResult = loadAndLogConfig(
|
|
19519
|
-
applyLoggingConfig(
|
|
19520
|
-
validateNexusEnv(
|
|
19521
|
-
const { server, serverLogger, observer, eventBusBridge, auditLogger } = await initializeSubsystems(configResult.config,
|
|
19522
|
-
await connectToStdioTransport(server,
|
|
19435
|
+
logStartupInfo(logger18, detectionResult, verbose);
|
|
19436
|
+
const configResult = loadAndLogConfig(logger18);
|
|
19437
|
+
applyLoggingConfig(logger18, verbose, configResult.config);
|
|
19438
|
+
validateNexusEnv(logger18);
|
|
19439
|
+
const { server, serverLogger, observer, eventBusBridge, auditLogger } = await initializeSubsystems(configResult.config, logger18);
|
|
19440
|
+
await connectToStdioTransport(server, logger18, serverLogger);
|
|
19523
19441
|
const eventContext = recordServerStartup(observer);
|
|
19524
19442
|
const stdinMonitor = getStdinLifecycleMonitor();
|
|
19525
19443
|
stdinMonitor.start();
|
|
19526
19444
|
stdinMonitor.onClose(() => {
|
|
19527
|
-
|
|
19445
|
+
logger18.warn("Parent process closed stdin, shutting down");
|
|
19528
19446
|
process.exit(0);
|
|
19529
19447
|
});
|
|
19530
19448
|
const cleanup = createShutdownCleanup({
|
|
@@ -19533,12 +19451,12 @@ async function startServer(verbose, mode, modeWasExplicit = false, orchestratorO
|
|
|
19533
19451
|
eventContext,
|
|
19534
19452
|
server,
|
|
19535
19453
|
serverLogger,
|
|
19536
|
-
logger:
|
|
19454
|
+
logger: logger18,
|
|
19537
19455
|
auditLogger
|
|
19538
19456
|
});
|
|
19539
|
-
setupShutdownHandlers(cleanup,
|
|
19457
|
+
setupShutdownHandlers(cleanup, logger18);
|
|
19540
19458
|
clearTimeout(startupWatchdog);
|
|
19541
|
-
|
|
19459
|
+
logger18.debug("Server running, waiting for requests...");
|
|
19542
19460
|
}
|
|
19543
19461
|
|
|
19544
19462
|
// src/cli-commands-validators.ts
|
|
@@ -19792,8 +19710,8 @@ function printFirstRunHint() {
|
|
|
19792
19710
|
const isTTY = process.stderr.isTTY;
|
|
19793
19711
|
if (!isTTY) return;
|
|
19794
19712
|
const dataDir = getNexusDataDir();
|
|
19795
|
-
const hasConfig =
|
|
19796
|
-
if (
|
|
19713
|
+
const hasConfig = existsSync20("./.nexus-agents/nexus-agents.yaml") || existsSync20("./.nexus-agents/nexus-agents.yml") || existsSync20("./nexus-agents.yaml") || existsSync20("./nexus-agents.yml");
|
|
19714
|
+
if (existsSync20(dataDir) || hasConfig) return;
|
|
19797
19715
|
process.stderr.write(
|
|
19798
19716
|
"\n\x1B[36mnexus-agents\x1B[0m: First time? Run \x1B[1mnexus-agents setup\x1B[0m to configure.\n\n"
|
|
19799
19717
|
);
|
|
@@ -19908,7 +19826,7 @@ async function handleResearchCommand(args) {
|
|
|
19908
19826
|
}
|
|
19909
19827
|
}
|
|
19910
19828
|
async function handleRegistryCommand(args) {
|
|
19911
|
-
const { registryCommand, isValidRegistrySubcommand, formatRegistryUsage } = await import("./registry-command-
|
|
19829
|
+
const { registryCommand, isValidRegistrySubcommand, formatRegistryUsage } = await import("./registry-command-YMZPSW7S.js");
|
|
19912
19830
|
const subcommand = args.subcommand;
|
|
19913
19831
|
if (!isValidRegistrySubcommand(subcommand)) {
|
|
19914
19832
|
process.stdout.write(`${formatRegistryUsage()}
|
|
@@ -19956,7 +19874,7 @@ async function handleVerifyCommand(args) {
|
|
|
19956
19874
|
async function handleDoctorCommand(args) {
|
|
19957
19875
|
const exitCode = await doctorCommand({ fix: args.options.fix });
|
|
19958
19876
|
if (args.options.deep) {
|
|
19959
|
-
const { runDeepDiagnostics: runDeepDiagnostics2, formatDeepDiagnostics: formatDeepDiagnostics2 } = await import("./doctor-deep-
|
|
19877
|
+
const { runDeepDiagnostics: runDeepDiagnostics2, formatDeepDiagnostics: formatDeepDiagnostics2 } = await import("./doctor-deep-ZMBSG2DF.js");
|
|
19960
19878
|
const diag = runDeepDiagnostics2();
|
|
19961
19879
|
process.stdout.write(formatDeepDiagnostics2(diag) + "\n");
|
|
19962
19880
|
}
|
|
@@ -20000,7 +19918,7 @@ async function handleInitCommand(args) {
|
|
|
20000
19918
|
process.exit(result.success ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
|
|
20001
19919
|
}
|
|
20002
19920
|
async function runInitOpencodeFlow(args) {
|
|
20003
|
-
const { runInitOpencode } = await import("./init-opencode-
|
|
19921
|
+
const { runInitOpencode } = await import("./init-opencode-WFL4OXMB.js");
|
|
20004
19922
|
const opencodePath = args.options.opencode;
|
|
20005
19923
|
if (opencodePath === void 0 || opencodePath === "") {
|
|
20006
19924
|
process.stderr.write("Error: --opencode requires a path argument.\n");
|
|
@@ -20027,7 +19945,7 @@ async function runInitOpencodeFlow(args) {
|
|
|
20027
19945
|
process.exit(EXIT_CODES.SUCCESS);
|
|
20028
19946
|
}
|
|
20029
19947
|
async function renderOpencodeValidate(opencodePath) {
|
|
20030
|
-
const { runOpencodeValidate } = await import("./init-opencode-
|
|
19948
|
+
const { runOpencodeValidate } = await import("./init-opencode-WFL4OXMB.js");
|
|
20031
19949
|
const result = await runOpencodeValidate(opencodePath);
|
|
20032
19950
|
if (!result.ok) {
|
|
20033
19951
|
process.stderr.write(`init --opencode --validate: ${result.reason ?? "failed"}
|
|
@@ -20067,7 +19985,7 @@ async function handleSetupCommandAsync(args) {
|
|
|
20067
19985
|
process.exit(exitCode === 0 ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
|
|
20068
19986
|
}
|
|
20069
19987
|
async function runCustomApiSetup(args) {
|
|
20070
|
-
const { configureCustomApi } = await import("./setup-custom-api-
|
|
19988
|
+
const { configureCustomApi } = await import("./setup-custom-api-4EYRKCHB.js");
|
|
20071
19989
|
const baseUrl = args.options.customApi;
|
|
20072
19990
|
if (baseUrl === void 0) return EXIT_CODES.SERVER_START_FAILED;
|
|
20073
19991
|
const input = {
|
|
@@ -20964,7 +20882,7 @@ function handleCapabilitiesCommand(args) {
|
|
|
20964
20882
|
}
|
|
20965
20883
|
|
|
20966
20884
|
// src/testing/memory-benchmark-phase3.ts
|
|
20967
|
-
async function measurePromotionEffectiveness(backend,
|
|
20885
|
+
async function measurePromotionEffectiveness(backend, logger18) {
|
|
20968
20886
|
const promotedEntries = [];
|
|
20969
20887
|
const metadata = { importance: "high", tags: ["promoted", "benchmark"] };
|
|
20970
20888
|
for (let i = 0; i < 10; i++) {
|
|
@@ -20984,7 +20902,7 @@ async function measurePromotionEffectiveness(backend, logger17) {
|
|
|
20984
20902
|
if (result.ok) retained++;
|
|
20985
20903
|
}
|
|
20986
20904
|
const retentionRate = promotedEntries.length > 0 ? retained / promotedEntries.length : 1;
|
|
20987
|
-
|
|
20905
|
+
logger18?.debug("Promotion effectiveness measured", {
|
|
20988
20906
|
promoted: promotedEntries.length,
|
|
20989
20907
|
retained,
|
|
20990
20908
|
retentionRate
|
|
@@ -21010,7 +20928,7 @@ async function countDecayed(backend, keys) {
|
|
|
21010
20928
|
}
|
|
21011
20929
|
return decayed;
|
|
21012
20930
|
}
|
|
21013
|
-
async function measureDecayAppropriateness(backend,
|
|
20931
|
+
async function measureDecayAppropriateness(backend, logger18) {
|
|
21014
20932
|
const lowKeys = await storeTestEntries(backend, "low", 5);
|
|
21015
20933
|
const highKeys = await storeTestEntries(backend, "high", 5);
|
|
21016
20934
|
const cutoffDate = new Date(Date.now() + 1e3);
|
|
@@ -21019,7 +20937,7 @@ async function measureDecayAppropriateness(backend, logger17) {
|
|
|
21019
20937
|
const lowDecayed = await countDecayed(backend, lowKeys);
|
|
21020
20938
|
const totalDecayed = highDecayed + lowDecayed;
|
|
21021
20939
|
const regret = totalDecayed > 0 ? highDecayed / totalDecayed : 0;
|
|
21022
|
-
|
|
20940
|
+
logger18?.debug("Decay appropriateness measured", {
|
|
21023
20941
|
highImportanceDecayed: highDecayed,
|
|
21024
20942
|
lowImportanceDecayed: lowDecayed,
|
|
21025
20943
|
regretScore: regret
|
|
@@ -21215,13 +21133,13 @@ function averageMetrics(acc, kValues, numCases) {
|
|
|
21215
21133
|
}
|
|
21216
21134
|
return { recallAtK, precisionAtK, mrr: acc.mrrSum / numCases };
|
|
21217
21135
|
}
|
|
21218
|
-
async function measureRetrievalQuality(backend, testCases, kValues,
|
|
21136
|
+
async function measureRetrievalQuality(backend, testCases, kValues, logger18) {
|
|
21219
21137
|
const acc = createAccumulators(kValues);
|
|
21220
21138
|
const maxK = Math.max(...kValues);
|
|
21221
21139
|
for (const testCase of testCases) {
|
|
21222
21140
|
const searchResult = await backend.search(testCase.query, maxK);
|
|
21223
21141
|
if (!searchResult.ok) {
|
|
21224
|
-
|
|
21142
|
+
logger18.warn("Search failed during benchmark", { query: testCase.query });
|
|
21225
21143
|
continue;
|
|
21226
21144
|
}
|
|
21227
21145
|
const retrievedKeys = searchResult.value.map((e) => e.key);
|
|
@@ -21275,21 +21193,21 @@ async function measureSelfConsistency(backend) {
|
|
|
21275
21193
|
}
|
|
21276
21194
|
return buildCoherenceResult(validCount, allEntries.value.length);
|
|
21277
21195
|
}
|
|
21278
|
-
async function validateCrossRefs(refs, targetBackend,
|
|
21196
|
+
async function validateCrossRefs(refs, targetBackend, logger18) {
|
|
21279
21197
|
let validCount = 0;
|
|
21280
21198
|
for (const ref of refs) {
|
|
21281
21199
|
const result = await targetBackend.retrieve(ref.targetKey);
|
|
21282
21200
|
if (result.ok) validCount++;
|
|
21283
|
-
else
|
|
21201
|
+
else logger18?.debug("Orphaned reference", { source: ref.sourceKey, target: ref.targetKey });
|
|
21284
21202
|
}
|
|
21285
21203
|
return buildCoherenceResult(validCount, refs.length);
|
|
21286
21204
|
}
|
|
21287
|
-
async function measureCoherence(backend, config,
|
|
21205
|
+
async function measureCoherence(backend, config, logger18) {
|
|
21288
21206
|
const refs = config?.crossReferences ?? [];
|
|
21289
21207
|
if (refs.length === 0) return measureSelfConsistency(backend);
|
|
21290
|
-
return validateCrossRefs(refs, config?.targetBackend ?? backend,
|
|
21208
|
+
return validateCrossRefs(refs, config?.targetBackend ?? backend, logger18);
|
|
21291
21209
|
}
|
|
21292
|
-
async function measureGrowthRate(backend, operationCount = 50,
|
|
21210
|
+
async function measureGrowthRate(backend, operationCount = 50, logger18) {
|
|
21293
21211
|
const initialEntries = await backend.search("", 1e4);
|
|
21294
21212
|
let initialBytes = 0;
|
|
21295
21213
|
if (initialEntries.ok) {
|
|
@@ -21307,13 +21225,13 @@ async function measureGrowthRate(backend, operationCount = 50, logger17) {
|
|
|
21307
21225
|
finalBytes = finalEntries.value.reduce((sum, e) => sum + estimateStorageBytes(e), 0);
|
|
21308
21226
|
}
|
|
21309
21227
|
const bytesPerOp = operationCount > 0 ? (finalBytes - initialBytes) / operationCount : 0;
|
|
21310
|
-
|
|
21228
|
+
logger18?.debug("Growth rate measured", { initialBytes, finalBytes, bytesPerOp });
|
|
21311
21229
|
return { bytesPerOperation: bytesPerOp, operationsExecuted: operationCount };
|
|
21312
21230
|
}
|
|
21313
|
-
async function measureDecayConsistency(backend,
|
|
21231
|
+
async function measureDecayConsistency(backend, logger18) {
|
|
21314
21232
|
const beforePrune = await backend.search("", 1e4);
|
|
21315
21233
|
if (!beforePrune.ok) {
|
|
21316
|
-
|
|
21234
|
+
logger18?.debug("Cannot measure decay consistency - search failed");
|
|
21317
21235
|
return { consistencyScore: 1, itemsChecked: 0 };
|
|
21318
21236
|
}
|
|
21319
21237
|
const beforeCount = beforePrune.value.length;
|
|
@@ -21328,7 +21246,7 @@ async function measureDecayConsistency(backend, logger17) {
|
|
|
21328
21246
|
if (result.ok) retrievable++;
|
|
21329
21247
|
}
|
|
21330
21248
|
const score = sampleSize > 0 ? retrievable / sampleSize : 1;
|
|
21331
|
-
|
|
21249
|
+
logger18?.debug("Decay consistency measured", { sampleSize, retrievable, score });
|
|
21332
21250
|
return { consistencyScore: score, itemsChecked: sampleSize };
|
|
21333
21251
|
}
|
|
21334
21252
|
function buildBenchmarkResult(m) {
|
|
@@ -21354,20 +21272,20 @@ function buildBenchmarkResult(m) {
|
|
|
21354
21272
|
};
|
|
21355
21273
|
}
|
|
21356
21274
|
async function runMemoryBenchmark(backend, testCases, config) {
|
|
21357
|
-
const { logger:
|
|
21275
|
+
const { logger: logger18, kValues, iterations } = parseConfig(config);
|
|
21358
21276
|
const startTime = getTimeProvider().now();
|
|
21359
|
-
|
|
21360
|
-
const quality = await measureRetrievalQuality(backend, testCases, kValues,
|
|
21277
|
+
logger18.info("Starting memory benchmark", { testCases: testCases.length, iterations });
|
|
21278
|
+
const quality = await measureRetrievalQuality(backend, testCases, kValues, logger18);
|
|
21361
21279
|
const latency = await measureLatency(backend, iterations);
|
|
21362
21280
|
const storage = await measureStorage(backend);
|
|
21363
|
-
const coherence = await measureCoherence(backend, config?.coherenceConfig,
|
|
21281
|
+
const coherence = await measureCoherence(backend, config?.coherenceConfig, logger18);
|
|
21364
21282
|
const growthIterations = config?.quickMode === true ? 10 : 50;
|
|
21365
|
-
const growth = await measureGrowthRate(backend, growthIterations,
|
|
21366
|
-
const decay = await measureDecayConsistency(backend,
|
|
21367
|
-
const promotion = await measurePromotionEffectiveness(backend,
|
|
21368
|
-
const appropriateness = await measureDecayAppropriateness(backend,
|
|
21283
|
+
const growth = await measureGrowthRate(backend, growthIterations, logger18);
|
|
21284
|
+
const decay = await measureDecayConsistency(backend, logger18);
|
|
21285
|
+
const promotion = await measurePromotionEffectiveness(backend, logger18);
|
|
21286
|
+
const appropriateness = await measureDecayAppropriateness(backend, logger18);
|
|
21369
21287
|
const durationMs = getTimeProvider().now() - startTime;
|
|
21370
|
-
|
|
21288
|
+
logger18.info("Memory benchmark complete", { mrr: quality.mrr, durationMs });
|
|
21371
21289
|
return buildBenchmarkResult({
|
|
21372
21290
|
quality,
|
|
21373
21291
|
latency,
|
|
@@ -21561,8 +21479,8 @@ function determineStrategy(cliTools, adapters) {
|
|
|
21561
21479
|
return "none (no adapters available)";
|
|
21562
21480
|
}
|
|
21563
21481
|
function collectStatus() {
|
|
21564
|
-
const
|
|
21565
|
-
const calculator = createFitnessScoreCalculator(
|
|
21482
|
+
const logger18 = createLogger({ component: "status", level: "error" });
|
|
21483
|
+
const calculator = createFitnessScoreCalculator(logger18);
|
|
21566
21484
|
const audit = calculator.audit(VERSION);
|
|
21567
21485
|
const adapters = checkApiAdapters();
|
|
21568
21486
|
const cliTools = detectCliTools();
|
|
@@ -21626,7 +21544,7 @@ function handleStatusCommand2(args) {
|
|
|
21626
21544
|
|
|
21627
21545
|
// src/cli/scenario-command.ts
|
|
21628
21546
|
import { readdir as readdir4 } from "fs/promises";
|
|
21629
|
-
import { join as
|
|
21547
|
+
import { join as join17, resolve as resolve13 } from "path";
|
|
21630
21548
|
|
|
21631
21549
|
// src/testing/e2e/scenario-runner.ts
|
|
21632
21550
|
import { readFile as readFile7 } from "fs/promises";
|
|
@@ -21786,7 +21704,7 @@ function checkCircularDependencies(workflow) {
|
|
|
21786
21704
|
var defaultStubFactory = {
|
|
21787
21705
|
createAgentStub(agentType, action) {
|
|
21788
21706
|
return async (inputs) => {
|
|
21789
|
-
await new Promise((
|
|
21707
|
+
await new Promise((resolve14) => setTimeout(resolve14, 10));
|
|
21790
21708
|
return {
|
|
21791
21709
|
stepId: `${agentType}-${action}`,
|
|
21792
21710
|
status: "success",
|
|
@@ -21945,7 +21863,7 @@ function createScenarioRunner(stubFactory) {
|
|
|
21945
21863
|
}
|
|
21946
21864
|
|
|
21947
21865
|
// src/cli/scenario-command.ts
|
|
21948
|
-
var FIXTURES_DIR =
|
|
21866
|
+
var FIXTURES_DIR = resolve13(import.meta.dirname, "../testing/e2e/fixtures");
|
|
21949
21867
|
var SCENARIO_SUFFIX = ".scenario.yaml";
|
|
21950
21868
|
async function listScenarios() {
|
|
21951
21869
|
try {
|
|
@@ -21996,7 +21914,7 @@ async function handleRun(args) {
|
|
|
21996
21914
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
21997
21915
|
}
|
|
21998
21916
|
const runner = createScenarioRunner();
|
|
21999
|
-
const fixturePath =
|
|
21917
|
+
const fixturePath = join17(FIXTURES_DIR, `${name}${SCENARIO_SUFFIX}`);
|
|
22000
21918
|
try {
|
|
22001
21919
|
const fixture = await runner.loadFixture(fixturePath);
|
|
22002
21920
|
const result = await runner.run(fixture);
|
|
@@ -22386,6 +22304,137 @@ function printSignal(signal) {
|
|
|
22386
22304
|
console.log("");
|
|
22387
22305
|
}
|
|
22388
22306
|
|
|
22307
|
+
// src/cli/migrate-command.ts
|
|
22308
|
+
import { cpSync, existsSync as existsSync22, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
|
|
22309
|
+
import { homedir } from "os";
|
|
22310
|
+
import { join as join18 } from "path";
|
|
22311
|
+
var logger17 = createLogger({ component: "migrate-command" });
|
|
22312
|
+
var HOMEDIR_DEFAULT_BASE = join18(homedir(), ".nexus-agents");
|
|
22313
|
+
function countItems(dir) {
|
|
22314
|
+
if (!existsSync22(dir)) return 0;
|
|
22315
|
+
try {
|
|
22316
|
+
const entries = readdirSync3(dir, { withFileTypes: true });
|
|
22317
|
+
let n = 0;
|
|
22318
|
+
for (const e of entries) {
|
|
22319
|
+
const p = join18(dir, e.name);
|
|
22320
|
+
if (e.isDirectory()) {
|
|
22321
|
+
n += countItems(p);
|
|
22322
|
+
} else {
|
|
22323
|
+
n += 1;
|
|
22324
|
+
}
|
|
22325
|
+
}
|
|
22326
|
+
return n;
|
|
22327
|
+
} catch {
|
|
22328
|
+
return 0;
|
|
22329
|
+
}
|
|
22330
|
+
}
|
|
22331
|
+
function runMigrate(options = {}) {
|
|
22332
|
+
const fromBase = options.from ?? HOMEDIR_DEFAULT_BASE;
|
|
22333
|
+
const cwd = options.cwd ?? process.cwd();
|
|
22334
|
+
const dryRun = options.dryRun ?? false;
|
|
22335
|
+
const toBase = options.to ?? resolveDefaultTarget(cwd);
|
|
22336
|
+
const earlyExit = checkEarlyExits(fromBase, toBase, dryRun);
|
|
22337
|
+
if (earlyExit !== null) return earlyExit;
|
|
22338
|
+
const perRepoSet = getPerRepoSubdirs();
|
|
22339
|
+
const sourceEntries = readdirSync3(fromBase, { withFileTypes: true });
|
|
22340
|
+
const subdirs = [];
|
|
22341
|
+
for (const entry of sourceEntries) {
|
|
22342
|
+
if (!entry.isDirectory()) continue;
|
|
22343
|
+
subdirs.push(planAndExecuteEntry(entry.name, fromBase, toBase, perRepoSet, dryRun));
|
|
22344
|
+
}
|
|
22345
|
+
const copied = subdirs.filter((s) => s.status === "copied").length;
|
|
22346
|
+
const summary = dryRun ? `Dry run: would copy ${String(copied)} per-repo subdir(s) from ${fromBase} \u2192 ${String(toBase)}.` : `Copied ${String(copied)} per-repo subdir(s) from ${fromBase} \u2192 ${String(toBase)}.`;
|
|
22347
|
+
logger17.info("Migration complete", { dryRun, copied, fromBase, toBase });
|
|
22348
|
+
return { fromBase, toBase, dryRun, subdirs, success: true, summary };
|
|
22349
|
+
}
|
|
22350
|
+
function checkEarlyExits(fromBase, toBase, dryRun) {
|
|
22351
|
+
if (toBase === null) {
|
|
22352
|
+
return {
|
|
22353
|
+
fromBase,
|
|
22354
|
+
toBase: "",
|
|
22355
|
+
dryRun,
|
|
22356
|
+
subdirs: [],
|
|
22357
|
+
success: false,
|
|
22358
|
+
summary: "No git repo detected from cwd. Run from inside a repo or pass --to <path> to choose an explicit destination."
|
|
22359
|
+
};
|
|
22360
|
+
}
|
|
22361
|
+
if (!existsSync22(fromBase)) {
|
|
22362
|
+
return {
|
|
22363
|
+
fromBase,
|
|
22364
|
+
toBase,
|
|
22365
|
+
dryRun,
|
|
22366
|
+
subdirs: [],
|
|
22367
|
+
success: true,
|
|
22368
|
+
summary: `No source state at ${fromBase}. Nothing to migrate.`
|
|
22369
|
+
};
|
|
22370
|
+
}
|
|
22371
|
+
return null;
|
|
22372
|
+
}
|
|
22373
|
+
function planAndExecuteEntry(name, fromBase, toBase, perRepoSet, dryRun) {
|
|
22374
|
+
const source = join18(fromBase, name);
|
|
22375
|
+
const target = join18(toBase, name);
|
|
22376
|
+
if (!perRepoSet.has(name)) {
|
|
22377
|
+
return { subdir: name, status: "skipped-not-per-repo", source, target: "", itemsCopied: 0 };
|
|
22378
|
+
}
|
|
22379
|
+
const items = countItems(source);
|
|
22380
|
+
if (items === 0) {
|
|
22381
|
+
return { subdir: name, status: "skipped-empty", source, target, itemsCopied: 0 };
|
|
22382
|
+
}
|
|
22383
|
+
if (existsSync22(target) && readdirSync3(target).length > 0) {
|
|
22384
|
+
return { subdir: name, status: "skipped-exists", source, target, itemsCopied: 0 };
|
|
22385
|
+
}
|
|
22386
|
+
if (!dryRun) {
|
|
22387
|
+
mkdirSync6(toBase, { recursive: true });
|
|
22388
|
+
cpSync(source, target, { recursive: true, errorOnExist: false });
|
|
22389
|
+
}
|
|
22390
|
+
return { subdir: name, status: "copied", source, target, itemsCopied: items };
|
|
22391
|
+
}
|
|
22392
|
+
function resolveDefaultTarget(cwd) {
|
|
22393
|
+
const repoRoot = findRepoRoot(cwd);
|
|
22394
|
+
if (repoRoot === null) return null;
|
|
22395
|
+
return join18(repoRoot, ".nexus-agents");
|
|
22396
|
+
}
|
|
22397
|
+
function formatMigrationResult(result) {
|
|
22398
|
+
if (!result.success) {
|
|
22399
|
+
return `migrate: ${result.summary}
|
|
22400
|
+
`;
|
|
22401
|
+
}
|
|
22402
|
+
const lines = [];
|
|
22403
|
+
lines.push(result.summary);
|
|
22404
|
+
if (result.subdirs.length === 0) {
|
|
22405
|
+
return `${lines.join("\n")}
|
|
22406
|
+
`;
|
|
22407
|
+
}
|
|
22408
|
+
lines.push("");
|
|
22409
|
+
for (const s of result.subdirs) {
|
|
22410
|
+
const tag = s.status === "copied" ? "\u2713" : "\xB7";
|
|
22411
|
+
const detail = s.status === "copied" ? `(${String(s.itemsCopied)} item(s))` : s.status === "skipped-not-per-repo" ? "(cross-repo \u2014 kept in homedir)" : s.status === "skipped-exists" ? "(destination already has state \u2014 skipped)" : "(empty source \u2014 skipped)";
|
|
22412
|
+
lines.push(` ${tag} ${s.subdir} ${detail}`);
|
|
22413
|
+
}
|
|
22414
|
+
if (!result.dryRun && result.subdirs.some((s) => s.status === "copied")) {
|
|
22415
|
+
lines.push("");
|
|
22416
|
+
lines.push("Next: export NEXUS_REPO_PREFERRED=1 to start using the per-repo data dir.");
|
|
22417
|
+
lines.push(
|
|
22418
|
+
"See: https://github.com/nexus-substrate/nexus-agents/issues/2872 for the full epic."
|
|
22419
|
+
);
|
|
22420
|
+
}
|
|
22421
|
+
return `${lines.join("\n")}
|
|
22422
|
+
`;
|
|
22423
|
+
}
|
|
22424
|
+
async function handleMigrateCommand(args) {
|
|
22425
|
+
const opts = {
|
|
22426
|
+
...args.options.input !== void 0 ? { from: args.options.input } : {},
|
|
22427
|
+
...args.options.output !== void 0 ? { to: args.options.output } : {},
|
|
22428
|
+
...args.options.dryRun !== void 0 ? { dryRun: args.options.dryRun } : {}
|
|
22429
|
+
};
|
|
22430
|
+
const result = runMigrate(opts);
|
|
22431
|
+
process.stderr.write(formatMigrationResult(result));
|
|
22432
|
+
await Promise.resolve();
|
|
22433
|
+
if (!result.success) {
|
|
22434
|
+
process.exit(1);
|
|
22435
|
+
}
|
|
22436
|
+
}
|
|
22437
|
+
|
|
22389
22438
|
// src/cli-commands.ts
|
|
22390
22439
|
function printHelp(args) {
|
|
22391
22440
|
const all = args?.options.all ?? false;
|
|
@@ -22464,6 +22513,8 @@ var ASYNC_COMMAND_HANDLERS = {
|
|
|
22464
22513
|
usage: handleUsageCommand,
|
|
22465
22514
|
// Issue #2444: improvement-review command (observability-driven improvement loop)
|
|
22466
22515
|
"improvement-review": handleImprovementReviewCommand,
|
|
22516
|
+
// Issue #2879 / epic #2872: migrate command (relocate homedir state per-repo)
|
|
22517
|
+
migrate: handleMigrateCommand,
|
|
22467
22518
|
// #2305 / #2308 / #2311: Init Portable Command (async because --install spawns npm)
|
|
22468
22519
|
init: handleInitCommand,
|
|
22469
22520
|
demo: handleDemoCommand,
|
|
@@ -22948,8 +22999,8 @@ var isDirectRun = () => {
|
|
|
22948
22999
|
};
|
|
22949
23000
|
if (isDirectRun()) {
|
|
22950
23001
|
main().catch((error) => {
|
|
22951
|
-
const
|
|
22952
|
-
|
|
23002
|
+
const logger18 = createLogger({ component: "cli" });
|
|
23003
|
+
logger18.error(
|
|
22953
23004
|
"Fatal error during startup",
|
|
22954
23005
|
error instanceof Error ? error : new Error(String(error))
|
|
22955
23006
|
);
|