nexus-agents 10.0.0 → 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-XTL45OBN.js → chunk-33C22IY4.js} +2 -2
- package/dist/{chunk-TQZSPGAZ.js → chunk-AMK4BTAV.js} +2 -2
- package/dist/{chunk-W2XP4MEN.js → chunk-C6MM6Z65.js} +717 -37
- package/dist/chunk-C6MM6Z65.js.map +1 -0
- package/dist/{chunk-CYROSFMW.js → chunk-HQWQ7MR5.js} +2 -2
- package/dist/{chunk-BDAR2UPN.js → chunk-IYEZVAJT.js} +2457 -3076
- package/dist/chunk-IYEZVAJT.js.map +1 -0
- package/dist/{chunk-HBJ3CVDB.js → chunk-TLITBKMZ.js} +3 -3
- package/dist/cli.js +15 -15
- package/dist/cli.js.map +1 -1
- package/dist/{consensus-vote-IUXJHSSQ.js → consensus-vote-V2JQHILD.js} +4 -4
- package/dist/{improvement-review-KBMTSFYT.js → improvement-review-UIYSAI36.js} +4 -4
- package/dist/index.js +15 -15
- package/dist/{setup-data-dir-JQGH2JCH.js → setup-data-dir-75Z5PSSB.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-BDAR2UPN.js.map +0 -1
- package/dist/chunk-W2XP4MEN.js.map +0 -1
- /package/dist/{chunk-XTL45OBN.js.map → chunk-33C22IY4.js.map} +0 -0
- /package/dist/{chunk-TQZSPGAZ.js.map → chunk-AMK4BTAV.js.map} +0 -0
- /package/dist/{chunk-CYROSFMW.js.map → chunk-HQWQ7MR5.js.map} +0 -0
- /package/dist/{chunk-HBJ3CVDB.js.map → chunk-TLITBKMZ.js.map} +0 -0
- /package/dist/{consensus-vote-IUXJHSSQ.js.map → consensus-vote-V2JQHILD.js.map} +0 -0
- /package/dist/{improvement-review-KBMTSFYT.js.map → improvement-review-UIYSAI36.js.map} +0 -0
- /package/dist/{setup-data-dir-JQGH2JCH.js.map → setup-data-dir-75Z5PSSB.js.map} +0 -0
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
VERSION,
|
|
8
8
|
isNodeVersionSupported,
|
|
9
9
|
recordServerTransport
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AMK4BTAV.js";
|
|
11
11
|
import {
|
|
12
12
|
checkGatewayHealth,
|
|
13
13
|
cliFailsVerdict,
|
|
@@ -33,6 +33,10 @@ import {
|
|
|
33
33
|
createAllAdapters,
|
|
34
34
|
createCliAdapter
|
|
35
35
|
} from "./chunk-O3VPGING.js";
|
|
36
|
+
import {
|
|
37
|
+
DEFAULT_EXECUTION_MODE,
|
|
38
|
+
SecurityConfigSchema
|
|
39
|
+
} from "./chunk-TYLE7Z2S.js";
|
|
36
40
|
import {
|
|
37
41
|
getNexusTmpDir
|
|
38
42
|
} from "./chunk-JPFRRNRR.js";
|
|
@@ -55,6 +59,7 @@ import {
|
|
|
55
59
|
countRoutedOutcomesInFile,
|
|
56
60
|
createLogger,
|
|
57
61
|
err,
|
|
62
|
+
formatZodIssuesAsArray,
|
|
58
63
|
gatewayCostStatus,
|
|
59
64
|
getCliModelName,
|
|
60
65
|
getDefaultModelForCli,
|
|
@@ -68,6 +73,7 @@ import {
|
|
|
68
73
|
ok,
|
|
69
74
|
resolveAuthEvidence,
|
|
70
75
|
resolveGatewayCostDeclaration,
|
|
76
|
+
resolveInsideRoot,
|
|
71
77
|
symbols,
|
|
72
78
|
writeLine
|
|
73
79
|
} from "./chunk-WI73OZAU.js";
|
|
@@ -87,21 +93,683 @@ import {
|
|
|
87
93
|
parseBoolEnv
|
|
88
94
|
} from "./chunk-LWOX65CP.js";
|
|
89
95
|
import {
|
|
96
|
+
CliNameSchema,
|
|
97
|
+
TaskCategorySchema,
|
|
90
98
|
resolveClassGuardMs
|
|
91
99
|
} from "./chunk-4PN3UVZV.js";
|
|
92
100
|
|
|
93
101
|
// src/cli/setup-data-dir.ts
|
|
94
|
-
import { mkdirSync, existsSync as
|
|
102
|
+
import { mkdirSync, existsSync as existsSync4 } from "node:fs";
|
|
95
103
|
|
|
96
104
|
// src/cli/doctor.ts
|
|
97
105
|
import {
|
|
98
|
-
existsSync as
|
|
99
|
-
readFileSync as
|
|
106
|
+
existsSync as existsSync3,
|
|
107
|
+
readFileSync as readFileSync3,
|
|
100
108
|
readdirSync,
|
|
101
109
|
accessSync,
|
|
102
110
|
constants as fsConstants
|
|
103
111
|
} from "node:fs";
|
|
104
112
|
|
|
113
|
+
// src/config/config-loader.ts
|
|
114
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
115
|
+
import { resolve, join } from "node:path";
|
|
116
|
+
import * as yaml from "yaml";
|
|
117
|
+
|
|
118
|
+
// src/config/schemas.ts
|
|
119
|
+
import { z as z9 } from "zod";
|
|
120
|
+
|
|
121
|
+
// src/config/schemas-core.ts
|
|
122
|
+
import { z } from "zod";
|
|
123
|
+
var LoggingConfigSchema = z.object({
|
|
124
|
+
level: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
125
|
+
format: z.enum(["json", "pretty"]).default("json"),
|
|
126
|
+
// Default to stderr: MCP stdio transport reserves stdout for JSON-RPC frames.
|
|
127
|
+
destination: z.enum(["stdout", "stderr", "file"]).default("stderr"),
|
|
128
|
+
filePath: z.string().optional()
|
|
129
|
+
});
|
|
130
|
+
var ProviderConfigSchema = z.object({
|
|
131
|
+
apiKey: z.string().optional(),
|
|
132
|
+
baseUrl: z.url().optional(),
|
|
133
|
+
timeout: z.number().positive().default(3e4),
|
|
134
|
+
maxRetries: z.number().nonnegative().default(3)
|
|
135
|
+
});
|
|
136
|
+
var ModelTiersSchema = z.object({
|
|
137
|
+
fast: z.array(z.string()).min(1),
|
|
138
|
+
balanced: z.array(z.string()).min(1),
|
|
139
|
+
powerful: z.array(z.string()).min(1)
|
|
140
|
+
});
|
|
141
|
+
var ModelConfigSchema = z.object({
|
|
142
|
+
default: z.string(),
|
|
143
|
+
tiers: ModelTiersSchema,
|
|
144
|
+
providers: z.record(z.string(), ProviderConfigSchema).optional()
|
|
145
|
+
});
|
|
146
|
+
var WorkflowConfigSchema = z.object({
|
|
147
|
+
templatesDir: z.string().default("./workflows"),
|
|
148
|
+
timeout: z.number().positive().default(3e5),
|
|
149
|
+
maxParallel: z.number().positive().default(5)
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// src/config/schemas-expert.ts
|
|
153
|
+
import { z as z2 } from "zod";
|
|
154
|
+
var VALID_EXPERT_TIERS = ["fast", "balanced", "powerful"];
|
|
155
|
+
var VALID_EXPERT_DOMAINS = [
|
|
156
|
+
"code",
|
|
157
|
+
"security",
|
|
158
|
+
"architecture",
|
|
159
|
+
"documentation",
|
|
160
|
+
"testing",
|
|
161
|
+
"general"
|
|
162
|
+
];
|
|
163
|
+
var MAX_SYSTEM_PROMPT_LENGTH = 4e3;
|
|
164
|
+
var CustomExpertDefinitionSchema = z2.object({
|
|
165
|
+
/** System prompt defining the expert's persona (max 4000 characters) */
|
|
166
|
+
systemPrompt: z2.string().min(1, "System prompt is required").max(
|
|
167
|
+
MAX_SYSTEM_PROMPT_LENGTH,
|
|
168
|
+
`System prompt must be at most ${String(MAX_SYSTEM_PROMPT_LENGTH)} characters`
|
|
169
|
+
),
|
|
170
|
+
/** Model tier for routing */
|
|
171
|
+
tier: z2.enum(VALID_EXPERT_TIERS, {
|
|
172
|
+
error: `Invalid tier. Valid options: ${VALID_EXPERT_TIERS.join(", ")}`
|
|
173
|
+
}).default("balanced"),
|
|
174
|
+
/** Primary domain of expertise */
|
|
175
|
+
domain: z2.enum(VALID_EXPERT_DOMAINS, {
|
|
176
|
+
error: `Invalid domain. Valid options: ${VALID_EXPERT_DOMAINS.join(", ")}`
|
|
177
|
+
}).default("general"),
|
|
178
|
+
/** Secondary domains (optional) */
|
|
179
|
+
secondaryDomains: z2.array(z2.enum(VALID_EXPERT_DOMAINS)).optional(),
|
|
180
|
+
/** Expert capabilities */
|
|
181
|
+
capabilities: z2.array(z2.string().min(1)).min(1, "At least one capability is required").default(["task_execution"]),
|
|
182
|
+
/** Model temperature (0-1) */
|
|
183
|
+
temperature: z2.number().min(0).max(1).default(0.3),
|
|
184
|
+
/** Allowed tools (optional, unrestricted if not specified) */
|
|
185
|
+
tools: z2.array(z2.string()).optional(),
|
|
186
|
+
/** Human-readable description */
|
|
187
|
+
description: z2.string().optional(),
|
|
188
|
+
/** Weight for expert selection scoring (0-1) */
|
|
189
|
+
weight: z2.number().min(0).max(1).default(1),
|
|
190
|
+
/** Whether this expert is currently available */
|
|
191
|
+
available: z2.boolean().default(true)
|
|
192
|
+
});
|
|
193
|
+
var ExpertDefinitionSchema = z2.object({
|
|
194
|
+
prompt: z2.string().min(1),
|
|
195
|
+
tier: z2.enum(["fast", "balanced", "powerful"]).default("balanced"),
|
|
196
|
+
temperature: z2.number().min(0).max(1).default(0.3),
|
|
197
|
+
tools: z2.array(z2.string()).optional()
|
|
198
|
+
});
|
|
199
|
+
var ExpertConfigSchema = z2.object({
|
|
200
|
+
/** Enable built-in experts */
|
|
201
|
+
builtin: z2.boolean().default(true),
|
|
202
|
+
/** Custom expert definitions keyed by expert ID */
|
|
203
|
+
custom: z2.record(
|
|
204
|
+
z2.string().regex(/^[a-z][a-z0-9_]*$/, {
|
|
205
|
+
message: "Expert ID must start with a letter and contain only lowercase letters, numbers, and underscores"
|
|
206
|
+
}),
|
|
207
|
+
CustomExpertDefinitionSchema
|
|
208
|
+
).optional()
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// src/config/schemas-observability.ts
|
|
212
|
+
import { z as z3 } from "zod";
|
|
213
|
+
var EventBusConfigSchema = z3.object({
|
|
214
|
+
/** Enable EventBus integration (default: true) */
|
|
215
|
+
enabled: z3.boolean().default(true),
|
|
216
|
+
/** Maximum events to retain in history (default: 1000) */
|
|
217
|
+
maxHistorySize: z3.number().positive().default(1e3),
|
|
218
|
+
/** Event patterns to subscribe to (default: all major patterns) */
|
|
219
|
+
subscriptions: z3.object({
|
|
220
|
+
/** Subscribe to consensus events (consensus.*) */
|
|
221
|
+
consensus: z3.boolean().default(true),
|
|
222
|
+
/** Subscribe to agent events (agent.*) */
|
|
223
|
+
agent: z3.boolean().default(true),
|
|
224
|
+
/** Subscribe to protocol events (protocol.*) */
|
|
225
|
+
protocol: z3.boolean().default(true),
|
|
226
|
+
/** Subscribe to session events (session.*) */
|
|
227
|
+
session: z3.boolean().default(true),
|
|
228
|
+
/** Subscribe to message events (message.*) */
|
|
229
|
+
message: z3.boolean().default(false),
|
|
230
|
+
// Off by default (high volume)
|
|
231
|
+
/** Subscribe to byzantine detection events (byzantine.*) */
|
|
232
|
+
byzantine: z3.boolean().default(true)
|
|
233
|
+
}).default(() => ({
|
|
234
|
+
consensus: true,
|
|
235
|
+
agent: true,
|
|
236
|
+
protocol: true,
|
|
237
|
+
session: true,
|
|
238
|
+
message: false,
|
|
239
|
+
byzantine: true
|
|
240
|
+
})),
|
|
241
|
+
/** Logging configuration for events */
|
|
242
|
+
logging: z3.object({
|
|
243
|
+
/** Log level for frequent events (default: debug) */
|
|
244
|
+
frequentEventLevel: z3.enum(["debug", "info"]).default("debug"),
|
|
245
|
+
/** Log level for important events (default: info) */
|
|
246
|
+
importantEventLevel: z3.enum(["debug", "info"]).default("info")
|
|
247
|
+
}).default(() => ({
|
|
248
|
+
frequentEventLevel: "debug",
|
|
249
|
+
importantEventLevel: "info"
|
|
250
|
+
}))
|
|
251
|
+
});
|
|
252
|
+
var ObservabilityConfigSchema = z3.object({
|
|
253
|
+
/** EventBus configuration */
|
|
254
|
+
eventBus: EventBusConfigSchema.optional(),
|
|
255
|
+
/** SwarmObserver maximum events (default: 10000) */
|
|
256
|
+
swarmObserverMaxEvents: z3.number().positive().default(1e4)
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// src/config/schemas-skills.ts
|
|
260
|
+
import { z as z4 } from "zod";
|
|
261
|
+
var ExternalPackSourceSchema = z4.object({
|
|
262
|
+
/** Pack name for identification */
|
|
263
|
+
name: z4.string().min(1),
|
|
264
|
+
/** Source: npm package name or local file path */
|
|
265
|
+
source: z4.string().min(1),
|
|
266
|
+
/** Whether the pack is enabled (default: true) */
|
|
267
|
+
enabled: z4.boolean().default(true)
|
|
268
|
+
});
|
|
269
|
+
var SkillLibraryConfigSchema = z4.object({
|
|
270
|
+
/** Whether skill library is enabled (default: true) */
|
|
271
|
+
enabled: z4.boolean().default(true),
|
|
272
|
+
/** Maximum skills to store (default: 1000) */
|
|
273
|
+
maxSkills: z4.number().int().positive().default(1e3),
|
|
274
|
+
/** Minimum success rate to keep skill (0-1, default: 0.3) */
|
|
275
|
+
minSuccessRateForRetention: z4.number().min(0).max(1).default(0.3),
|
|
276
|
+
/** Number of executions before evaluating retention (default: 5) */
|
|
277
|
+
executionsBeforeEvaluation: z4.number().int().nonnegative().default(5),
|
|
278
|
+
/** Enable automatic skill pruning (default: true) */
|
|
279
|
+
enablePruning: z4.boolean().default(true),
|
|
280
|
+
/** Whether to track detailed execution history (default: true) */
|
|
281
|
+
trackExecutionHistory: z4.boolean().default(true),
|
|
282
|
+
/** Maximum execution history entries per skill (default: 100) */
|
|
283
|
+
maxHistoryPerSkill: z4.number().int().positive().default(100),
|
|
284
|
+
/** External skill pack sources (Issue #654) */
|
|
285
|
+
externalPacks: z4.array(ExternalPackSourceSchema).optional()
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// src/config/schemas-sica.ts
|
|
289
|
+
import { z as z5 } from "zod";
|
|
290
|
+
var SicaConfigSchema = z5.object({
|
|
291
|
+
/** Whether SICA wrapping is enabled (default: false) */
|
|
292
|
+
enabled: z5.boolean().default(false),
|
|
293
|
+
/** Minimum executions before considering improvement (default: 10) */
|
|
294
|
+
minExecutionsForImprovement: z5.number().int().positive().default(10),
|
|
295
|
+
/** Success rate threshold to trigger improvement (0-1, default: 0.7) */
|
|
296
|
+
improvementThreshold: z5.number().min(0).max(1).default(0.7),
|
|
297
|
+
/** Maximum concurrent versions to evaluate (default: 3) */
|
|
298
|
+
maxActiveVersions: z5.number().int().positive().max(10).default(3),
|
|
299
|
+
/** Whether to auto-select best version (default: true) */
|
|
300
|
+
autoSelectBest: z5.boolean().default(true),
|
|
301
|
+
/** Improvement cooldown in milliseconds (default: 60000) */
|
|
302
|
+
improvementCooldownMs: z5.number().int().nonnegative().default(6e4),
|
|
303
|
+
/** Enable observability logging for SICA events (default: true) */
|
|
304
|
+
enableObservability: z5.boolean().default(true)
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// src/config/schemas-gateway.ts
|
|
308
|
+
import { z as z6 } from "zod";
|
|
309
|
+
var TierNameSchema = z6.enum(["DIRECT", "ANALYZED", "ORCHESTRATED"]);
|
|
310
|
+
var ALLOWED_COMMANDS = ["node", "npx", "python", "python3", "uvx", "docker"];
|
|
311
|
+
var UpstreamServerSchema = z6.object({
|
|
312
|
+
/** Unique name for this upstream server (used as tool prefix). */
|
|
313
|
+
name: z6.string().min(1).max(50).regex(/^[a-z0-9_-]+$/),
|
|
314
|
+
/** Command to spawn the server. Must be in allowlist. */
|
|
315
|
+
command: z6.enum(ALLOWED_COMMANDS),
|
|
316
|
+
/** Arguments to pass to the command. */
|
|
317
|
+
args: z6.array(z6.string().max(500)).default([]),
|
|
318
|
+
/** Environment variables (use {env:VAR} references, not plaintext secrets). */
|
|
319
|
+
env: z6.record(z6.string(), z6.string()).optional(),
|
|
320
|
+
/** Whether to connect lazily on first tool call (default: true). */
|
|
321
|
+
lazy: z6.boolean().default(true),
|
|
322
|
+
/** Connection timeout in ms (default: 10000). */
|
|
323
|
+
timeoutMs: z6.number().int().min(1e3).max(6e4).default(1e4)
|
|
324
|
+
});
|
|
325
|
+
var MAX_UPSTREAM_SERVERS = 5;
|
|
326
|
+
var GatewayConfigSchema = z6.object({
|
|
327
|
+
/** Enable gateway tier dispatch logging (default: true). */
|
|
328
|
+
enabled: z6.boolean().default(true),
|
|
329
|
+
/**
|
|
330
|
+
* Per-tool tier overrides.
|
|
331
|
+
* Keys are tool names (e.g., 'delegate_to_model'), values are tier names.
|
|
332
|
+
* Overrides the default tier from TOOL_TIER_MAP in tier-classifier.ts.
|
|
333
|
+
*/
|
|
334
|
+
tierOverrides: z6.record(z6.string(), TierNameSchema).optional(),
|
|
335
|
+
/**
|
|
336
|
+
* Upstream MCP servers to compose with (#1498).
|
|
337
|
+
* Tools from upstream servers are available as prefixed tools (e.g., tavily.search).
|
|
338
|
+
*/
|
|
339
|
+
upstreamServers: z6.array(UpstreamServerSchema).max(MAX_UPSTREAM_SERVERS).optional()
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// src/config/schemas-routing.ts
|
|
343
|
+
import { z as z7 } from "zod";
|
|
344
|
+
var BudgetConstraintsSchema = z7.object({
|
|
345
|
+
/** Maximum tokens per request */
|
|
346
|
+
maxTokens: z7.number().positive().optional(),
|
|
347
|
+
/** Maximum cost per request in USD */
|
|
348
|
+
maxCostUsd: z7.number().positive().optional(),
|
|
349
|
+
/** Maximum latency per request in milliseconds */
|
|
350
|
+
maxLatencyMs: z7.number().positive().optional(),
|
|
351
|
+
/**
|
|
352
|
+
* Per-task-class cost ceilings in USD, keyed by `TaskCategory`
|
|
353
|
+
* (#4196, #4214). Keys are validated against the enum so a typo'd
|
|
354
|
+
* class fails config parsing instead of silently configuring nothing.
|
|
355
|
+
* Absent → no ceiling (OFF/unlimited). Enforced only under
|
|
356
|
+
* `NEXUS_BILLING_MODE=api`; a candidate with missing registry pricing
|
|
357
|
+
* fails a configured ceiling (fail-closed).
|
|
358
|
+
*/
|
|
359
|
+
taskClassMaxCostUsd: z7.partialRecord(TaskCategorySchema, z7.number().positive()).optional()
|
|
360
|
+
}).optional();
|
|
361
|
+
var TopsisCriterionSchema = z7.object({
|
|
362
|
+
/** Criterion name (e.g., 'quality', 'cost', 'latency') */
|
|
363
|
+
name: z7.string().min(1),
|
|
364
|
+
/** Weight for this criterion (0-1, should sum to 1 across all criteria) */
|
|
365
|
+
weight: z7.number().min(0).max(1),
|
|
366
|
+
/** Whether higher values are better (true) or lower is better (false) */
|
|
367
|
+
beneficial: z7.boolean()
|
|
368
|
+
});
|
|
369
|
+
var TopsisConfigSchema = z7.object({
|
|
370
|
+
/** Criteria with weights (must sum to 1.0) */
|
|
371
|
+
criteria: z7.array(TopsisCriterionSchema).optional(),
|
|
372
|
+
/** Minimum acceptable quality score (0-10) */
|
|
373
|
+
minQualityThreshold: z7.number().min(0).max(10).default(5),
|
|
374
|
+
/** Maximum acceptable latency in milliseconds (optional) */
|
|
375
|
+
maxLatencyMs: z7.number().positive().optional(),
|
|
376
|
+
/** Maximum acceptable cost per request in USD (optional) */
|
|
377
|
+
maxCostPerRequest: z7.number().positive().optional(),
|
|
378
|
+
/** Whether to log detailed scoring info */
|
|
379
|
+
verbose: z7.boolean().default(false)
|
|
380
|
+
}).optional();
|
|
381
|
+
var DifficultyWeightsConfigSchema = z7.object({
|
|
382
|
+
/** Weight for reasoning difficulty (0-1) */
|
|
383
|
+
reasoning: z7.number().min(0).max(1).default(0.3),
|
|
384
|
+
/** Weight for knowledge difficulty (0-1) */
|
|
385
|
+
knowledge: z7.number().min(0).max(1).default(0.15),
|
|
386
|
+
/** Weight for creativity difficulty (0-1) */
|
|
387
|
+
creativity: z7.number().min(0).max(1).default(0.15),
|
|
388
|
+
/** Weight for precision difficulty (0-1) */
|
|
389
|
+
precision: z7.number().min(0).max(1).default(0.25),
|
|
390
|
+
/** Weight for context length difficulty (0-1) */
|
|
391
|
+
context_length: z7.number().min(0).max(1).default(0.15)
|
|
392
|
+
});
|
|
393
|
+
var DifficultyThresholdsSchema = z7.object({
|
|
394
|
+
/** Upper bound for 'easy' classification (0-1) */
|
|
395
|
+
easyUpperBound: z7.number().min(0).max(1).default(0.3),
|
|
396
|
+
/** Lower bound for 'hard' classification (0-1) */
|
|
397
|
+
hardLowerBound: z7.number().min(0).max(1).default(0.7)
|
|
398
|
+
});
|
|
399
|
+
var DifficultyLevelSchema = z7.enum(["easy", "medium", "hard"]);
|
|
400
|
+
var ModelTierSchema = z7.enum(["fast", "balanced", "powerful"]);
|
|
401
|
+
var ZeroRouterConfigSchema = z7.object({
|
|
402
|
+
/** Difficulty thresholds for level classification */
|
|
403
|
+
thresholds: DifficultyThresholdsSchema.optional(),
|
|
404
|
+
/** Weights for difficulty aggregation */
|
|
405
|
+
weights: DifficultyWeightsConfigSchema.optional(),
|
|
406
|
+
/** Mapping from difficulty level to model tier */
|
|
407
|
+
difficultyToTier: z7.record(DifficultyLevelSchema, ModelTierSchema).optional(),
|
|
408
|
+
/** Mapping from model tier to CLI preference order */
|
|
409
|
+
tierToClis: z7.record(ModelTierSchema, z7.array(CliNameSchema)).optional(),
|
|
410
|
+
/** Enable adaptive calibration from outcomes */
|
|
411
|
+
enableCalibration: z7.boolean().default(true),
|
|
412
|
+
/** Maximum outcomes to store for calibration */
|
|
413
|
+
maxCalibrationOutcomes: z7.number().int().positive().default(1e3),
|
|
414
|
+
/** Minimum outcomes before applying calibration adjustments */
|
|
415
|
+
minCalibrationOutcomes: z7.number().int().positive().default(50),
|
|
416
|
+
/** Verbose logging */
|
|
417
|
+
verbose: z7.boolean().default(false)
|
|
418
|
+
}).optional();
|
|
419
|
+
var LatencyTrackerConfigSchema = z7.object({
|
|
420
|
+
/** Maximum number of samples to keep per CLI */
|
|
421
|
+
windowSize: z7.number().int().positive().default(100),
|
|
422
|
+
/** Time-weighted decay factor (0-1, higher = more weight to recent) */
|
|
423
|
+
decayFactor: z7.number().min(0).max(1).default(0.95),
|
|
424
|
+
/** Maximum age of samples in milliseconds before forced eviction */
|
|
425
|
+
maxSampleAgeMs: z7.number().int().positive().default(36e5),
|
|
426
|
+
/** Percentiles to calculate */
|
|
427
|
+
percentiles: z7.array(z7.number().min(0).max(100)).max(20).default([50, 95, 99])
|
|
428
|
+
}).optional();
|
|
429
|
+
var RoutingMemoryConfigSchema = z7.object({
|
|
430
|
+
/** Minimum observations before using learned routing */
|
|
431
|
+
minObservations: z7.number().int().positive().default(5),
|
|
432
|
+
/** Confidence threshold for using cached decisions */
|
|
433
|
+
confidenceThreshold: z7.number().min(0).max(1).default(0.6),
|
|
434
|
+
/** Success rate threshold for trusting a routing pattern */
|
|
435
|
+
successRateThreshold: z7.number().min(0).max(1).default(0.7),
|
|
436
|
+
/** Maximum age of cached actions in milliseconds */
|
|
437
|
+
actionCacheMaxAgeMs: z7.number().int().positive().default(36e5)
|
|
438
|
+
}).optional();
|
|
439
|
+
var RoutingConfigSchema = z7.object({
|
|
440
|
+
/**
|
|
441
|
+
* Pipeline stage toggles.
|
|
442
|
+
* Enable or disable individual routing stages.
|
|
443
|
+
*/
|
|
444
|
+
stages: z7.object({
|
|
445
|
+
/** Enable budget filtering stage */
|
|
446
|
+
budgetFilter: z7.boolean().default(true),
|
|
447
|
+
/** Enable ZeroRouter difficulty-based routing */
|
|
448
|
+
zeroRouter: z7.boolean().default(true),
|
|
449
|
+
/** Enable preference-trained routing */
|
|
450
|
+
preferenceRouting: z7.boolean().default(false),
|
|
451
|
+
/** Enable TOPSIS ranking */
|
|
452
|
+
topsisRanking: z7.boolean().default(true),
|
|
453
|
+
/** Enable LinUCB selection */
|
|
454
|
+
linucbSelection: z7.boolean().default(true),
|
|
455
|
+
/** Enable latency tracking */
|
|
456
|
+
latencyTracking: z7.boolean().default(true),
|
|
457
|
+
/** Enable routing memory for learned routing */
|
|
458
|
+
routingMemory: z7.boolean().default(false),
|
|
459
|
+
/** Enable confidence cascade stage (Issue #755, ADR-0005) */
|
|
460
|
+
confidenceCascade: z7.boolean().default(false),
|
|
461
|
+
/** Enable capability match stage (Issue #755, ADR-0005) */
|
|
462
|
+
capabilityMatch: z7.boolean().default(false),
|
|
463
|
+
/** Enable quality constraint stage (Issue #755, ADR-0005) */
|
|
464
|
+
qualityConstraint: z7.boolean().default(false),
|
|
465
|
+
/** Enable resource strategy stage for budget-aware oscillation (Issue #998) */
|
|
466
|
+
resourceStrategy: z7.boolean().default(true),
|
|
467
|
+
/** Enable strategy distillation for learned routing rules (Issue #999) */
|
|
468
|
+
strategyDistillation: z7.boolean().default(false)
|
|
469
|
+
}).optional(),
|
|
470
|
+
/**
|
|
471
|
+
* Budget constraints for routing decisions.
|
|
472
|
+
*/
|
|
473
|
+
budget: BudgetConstraintsSchema,
|
|
474
|
+
/**
|
|
475
|
+
* TOPSIS multi-criteria decision making configuration.
|
|
476
|
+
*/
|
|
477
|
+
topsis: TopsisConfigSchema,
|
|
478
|
+
/**
|
|
479
|
+
* ZeroRouter difficulty-based routing configuration.
|
|
480
|
+
*/
|
|
481
|
+
zeroRouter: ZeroRouterConfigSchema,
|
|
482
|
+
/**
|
|
483
|
+
* Latency tracker configuration.
|
|
484
|
+
*/
|
|
485
|
+
latencyTracker: LatencyTrackerConfigSchema,
|
|
486
|
+
/**
|
|
487
|
+
* Routing memory configuration.
|
|
488
|
+
*/
|
|
489
|
+
routingMemory: RoutingMemoryConfigSchema,
|
|
490
|
+
/**
|
|
491
|
+
* LinUCB bandit parameters.
|
|
492
|
+
*/
|
|
493
|
+
linucb: z7.object({
|
|
494
|
+
/** Exploration parameter (higher = more exploration) */
|
|
495
|
+
alpha: z7.number().positive().default(1)
|
|
496
|
+
}).optional(),
|
|
497
|
+
/**
|
|
498
|
+
* Preference router parameters.
|
|
499
|
+
*/
|
|
500
|
+
preference: z7.object({
|
|
501
|
+
/** Minimum data points before using learned preferences */
|
|
502
|
+
minDataPoints: z7.number().int().positive().default(10)
|
|
503
|
+
}).optional(),
|
|
504
|
+
/**
|
|
505
|
+
* Weight for latency score in final routing (0-1).
|
|
506
|
+
*/
|
|
507
|
+
latencyScoreWeight: z7.number().min(0).max(1).default(0.2)
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
// src/config/schemas-memory.ts
|
|
511
|
+
import { z as z8 } from "zod";
|
|
512
|
+
var unitInterval = z8.number().min(0).max(1);
|
|
513
|
+
var MIN_DECAY_INTERVAL_MS = 1e3;
|
|
514
|
+
var MemoryDecayConfigSchema = z8.object({
|
|
515
|
+
/** Whether decay runs at all (default: true) */
|
|
516
|
+
enabled: z8.boolean().optional(),
|
|
517
|
+
/**
|
|
518
|
+
* Interval between automatic decay runs in ms (default: 1 hour).
|
|
519
|
+
* Floor: {@link MIN_DECAY_INTERVAL_MS}. `runDecay` has no re-entrancy
|
|
520
|
+
* guard, so a sub-second cadence invites overlapping sweeps over the same
|
|
521
|
+
* stores; 1000 ms is the smallest value at which that is implausible.
|
|
522
|
+
*/
|
|
523
|
+
decayIntervalMs: z8.number().int().min(MIN_DECAY_INTERVAL_MS).optional(),
|
|
524
|
+
/** Age in days before superseded beliefs are pruned (default: 30) */
|
|
525
|
+
beliefMaxAgeDays: z8.number().int().positive().optional(),
|
|
526
|
+
/** Agentic entries before importance-based eviction starts (default: 10000) */
|
|
527
|
+
agenticMaxEntries: z8.number().int().positive().optional(),
|
|
528
|
+
/** Importance below which agentic entries are evicted, 0-1 (default: 0.3) */
|
|
529
|
+
agenticImportanceThreshold: unitInterval.optional(),
|
|
530
|
+
/** Priority score below which adaptive entries are evicted, 0-1 (default: 0.2) */
|
|
531
|
+
adaptivePriorityThreshold: unitInterval.optional(),
|
|
532
|
+
/** Run MobiMem TTL eviction on each coordinated decay (default: true) */
|
|
533
|
+
mobimemEvictOnDecay: z8.boolean().optional(),
|
|
534
|
+
/** Check cross-references before evicting (default: true) */
|
|
535
|
+
checkCrossReferences: z8.boolean().optional(),
|
|
536
|
+
/** Grace period in ms before removing cross-referenced items (default: 7 days) */
|
|
537
|
+
crossReferenceGracePeriodMs: z8.number().int().nonnegative().optional()
|
|
538
|
+
});
|
|
539
|
+
var MemoryConfigSchema = z8.object({
|
|
540
|
+
/** Coordinated decay knobs (#5097) */
|
|
541
|
+
decay: MemoryDecayConfigSchema.optional()
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
// src/config/schemas.ts
|
|
545
|
+
var AppConfigSchema = z9.object({
|
|
546
|
+
models: ModelConfigSchema,
|
|
547
|
+
experts: ExpertConfigSchema.optional(),
|
|
548
|
+
workflows: WorkflowConfigSchema.optional(),
|
|
549
|
+
security: SecurityConfigSchema.optional(),
|
|
550
|
+
logging: LoggingConfigSchema.optional(),
|
|
551
|
+
/** Observability configuration (Issue #307) */
|
|
552
|
+
observability: ObservabilityConfigSchema.optional(),
|
|
553
|
+
/** Routing configuration (Issue #475) - used in orchestrator mode */
|
|
554
|
+
routing: RoutingConfigSchema.optional(),
|
|
555
|
+
/** Skill library configuration (Issue #491) */
|
|
556
|
+
skills: SkillLibraryConfigSchema.optional(),
|
|
557
|
+
/** SICA self-improvement configuration (Issue #492) */
|
|
558
|
+
sica: SicaConfigSchema.optional(),
|
|
559
|
+
/** Gateway middleware configuration (Issue #897) */
|
|
560
|
+
gateway: GatewayConfigSchema.optional(),
|
|
561
|
+
/** Memory configuration — today only `decay` reaches runtime (Issue #5097) */
|
|
562
|
+
memory: MemoryConfigSchema.optional()
|
|
563
|
+
});
|
|
564
|
+
var defaultConfig = {
|
|
565
|
+
models: {
|
|
566
|
+
default: "claude-sonnet",
|
|
567
|
+
tiers: {
|
|
568
|
+
fast: ["claude-haiku", "gemini-flash"],
|
|
569
|
+
balanced: ["claude-sonnet", "gemini-pro"],
|
|
570
|
+
powerful: ["claude-opus", "codex-5.3"]
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
logging: {
|
|
574
|
+
level: "info",
|
|
575
|
+
format: "json",
|
|
576
|
+
// stderr is the safe default: MCP stdio transport reserves stdout for
|
|
577
|
+
// JSON-RPC frames. Any log written to stdout corrupts the transport.
|
|
578
|
+
destination: "stderr"
|
|
579
|
+
},
|
|
580
|
+
security: {
|
|
581
|
+
allowedPaths: ["./"],
|
|
582
|
+
blockedPatterns: [],
|
|
583
|
+
rateLimit: {
|
|
584
|
+
enabled: true,
|
|
585
|
+
requestsPerMinute: 60
|
|
586
|
+
},
|
|
587
|
+
policy: {
|
|
588
|
+
defaultMode: DEFAULT_EXECUTION_MODE,
|
|
589
|
+
policyMode: "enforce"
|
|
590
|
+
},
|
|
591
|
+
timeout: {
|
|
592
|
+
defaultTimeoutMs: 3e4,
|
|
593
|
+
maxTimeoutMs: 3e5,
|
|
594
|
+
enableLogging: true,
|
|
595
|
+
uriValidation: true
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
// src/config/config-loader.ts
|
|
601
|
+
var DEFAULT_CONFIG_FILE = "nexus-agents.yaml";
|
|
602
|
+
var ALTERNATE_CONFIG_FILE = "nexus-agents.yml";
|
|
603
|
+
var CONFIG_LOOKUP_PATHS = [
|
|
604
|
+
`.nexus-agents/${DEFAULT_CONFIG_FILE}`,
|
|
605
|
+
`.nexus-agents/${ALTERNATE_CONFIG_FILE}`,
|
|
606
|
+
DEFAULT_CONFIG_FILE,
|
|
607
|
+
ALTERNATE_CONFIG_FILE
|
|
608
|
+
];
|
|
609
|
+
var ConfigLoadError = class extends Error {
|
|
610
|
+
code;
|
|
611
|
+
constructor(message, code, cause) {
|
|
612
|
+
super(message, { cause });
|
|
613
|
+
this.name = "ConfigLoadError";
|
|
614
|
+
this.code = code;
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
function validatePath(userPath, root) {
|
|
618
|
+
const resolved = resolveInsideRoot(userPath, root);
|
|
619
|
+
if (resolved === null) {
|
|
620
|
+
return err(
|
|
621
|
+
new ConfigLoadError(
|
|
622
|
+
`Config path traversal detected: ${userPath} escapes ${root}`,
|
|
623
|
+
"PATH_TRAVERSAL"
|
|
624
|
+
)
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
return ok(resolved);
|
|
628
|
+
}
|
|
629
|
+
function findConfigPath(cwd) {
|
|
630
|
+
const envPath = process.env["NEXUS_CONFIG_PATH"];
|
|
631
|
+
if (envPath !== void 0 && envPath !== "") {
|
|
632
|
+
const validation = validatePath(envPath, cwd);
|
|
633
|
+
if (validation.ok && existsSync(validation.value)) {
|
|
634
|
+
return validation.value;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
for (const rel of CONFIG_LOOKUP_PATHS) {
|
|
638
|
+
const abs = resolve(cwd, rel);
|
|
639
|
+
if (existsSync(abs)) {
|
|
640
|
+
return abs;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
const globalDir = getNexusDataDir();
|
|
644
|
+
const globalYamlPath = join(globalDir, DEFAULT_CONFIG_FILE);
|
|
645
|
+
if (existsSync(globalYamlPath)) {
|
|
646
|
+
return globalYamlPath;
|
|
647
|
+
}
|
|
648
|
+
const globalYmlPath = join(globalDir, ALTERNATE_CONFIG_FILE);
|
|
649
|
+
if (existsSync(globalYmlPath)) {
|
|
650
|
+
return globalYmlPath;
|
|
651
|
+
}
|
|
652
|
+
return void 0;
|
|
653
|
+
}
|
|
654
|
+
function parseYaml(content) {
|
|
655
|
+
try {
|
|
656
|
+
const parsed = yaml.parse(content);
|
|
657
|
+
return ok(parsed);
|
|
658
|
+
} catch (error) {
|
|
659
|
+
const message = error instanceof Error ? error.message : "Unknown YAML parse error";
|
|
660
|
+
return err(
|
|
661
|
+
new ConfigLoadError(`YAML parse error: ${message}`, "YAML_PARSE_ERROR", error)
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set([
|
|
666
|
+
"__proto__",
|
|
667
|
+
"constructor",
|
|
668
|
+
"prototype"
|
|
669
|
+
]);
|
|
670
|
+
function isMergeableObject(value) {
|
|
671
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
672
|
+
}
|
|
673
|
+
function deepMerge(target, source) {
|
|
674
|
+
const result = { ...target };
|
|
675
|
+
for (const key of Object.keys(source)) {
|
|
676
|
+
if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
|
|
677
|
+
const sourceValue = source[key];
|
|
678
|
+
if (sourceValue === void 0) continue;
|
|
679
|
+
const targetValue = target[key];
|
|
680
|
+
if (isMergeableObject(sourceValue) && isMergeableObject(targetValue)) {
|
|
681
|
+
result[key] = deepMerge(targetValue, sourceValue);
|
|
682
|
+
} else {
|
|
683
|
+
result[key] = sourceValue;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return result;
|
|
687
|
+
}
|
|
688
|
+
function loadDefaultConfig(logger2) {
|
|
689
|
+
logger2.debug("No config file found, using defaults");
|
|
690
|
+
const validated = AppConfigSchema.safeParse(defaultConfig);
|
|
691
|
+
if (!validated.success) {
|
|
692
|
+
return err(
|
|
693
|
+
new ConfigLoadError(
|
|
694
|
+
`Default config validation failed: ${validated.error.message}`,
|
|
695
|
+
"VALIDATION_ERROR"
|
|
696
|
+
)
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
return ok({
|
|
700
|
+
config: validated.data,
|
|
701
|
+
usingDefaults: true,
|
|
702
|
+
warnings: ["No config file found, using default configuration"]
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
function readAndParseConfig(configPath, mergeDefaults, logger2) {
|
|
706
|
+
let content;
|
|
707
|
+
try {
|
|
708
|
+
content = readFileSync(configPath, "utf-8");
|
|
709
|
+
} catch (error) {
|
|
710
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
711
|
+
return err(
|
|
712
|
+
new ConfigLoadError(
|
|
713
|
+
`Failed to read config file: ${message}`,
|
|
714
|
+
"FILE_READ_ERROR",
|
|
715
|
+
error
|
|
716
|
+
)
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
const parseResult = parseYaml(content);
|
|
720
|
+
if (!parseResult.ok) return err(parseResult.error);
|
|
721
|
+
if (mergeDefaults && typeof parseResult.value === "object" && parseResult.value !== null) {
|
|
722
|
+
logger2.debug("Merged config with defaults");
|
|
723
|
+
return ok(
|
|
724
|
+
deepMerge(
|
|
725
|
+
defaultConfig,
|
|
726
|
+
parseResult.value
|
|
727
|
+
)
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
return ok(parseResult.value);
|
|
731
|
+
}
|
|
732
|
+
function validateConfig(configData, configPath, logger2) {
|
|
733
|
+
const validation = AppConfigSchema.safeParse(configData);
|
|
734
|
+
if (!validation.success) {
|
|
735
|
+
const issues = formatZodIssuesAsArray(validation.error);
|
|
736
|
+
return err(
|
|
737
|
+
new ConfigLoadError(`Config validation failed:
|
|
738
|
+
${issues.join("\n")}`, "VALIDATION_ERROR")
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
logger2.info("Configuration loaded successfully", { configPath });
|
|
742
|
+
return ok({ config: validation.data, configPath, usingDefaults: false, warnings: [] });
|
|
743
|
+
}
|
|
744
|
+
function loadConfig(options = {}) {
|
|
745
|
+
const { configPath: explicitPath, cwd = process.cwd(), mergeDefaults = true } = options;
|
|
746
|
+
const logger2 = options.logger ?? createLogger({ component: "ConfigLoader" });
|
|
747
|
+
let configPath;
|
|
748
|
+
if (explicitPath !== void 0) {
|
|
749
|
+
const validation = validatePath(explicitPath, cwd);
|
|
750
|
+
if (!validation.ok) return err(validation.error);
|
|
751
|
+
configPath = validation.value;
|
|
752
|
+
} else {
|
|
753
|
+
configPath = findConfigPath(cwd);
|
|
754
|
+
}
|
|
755
|
+
if (configPath === void 0) return loadDefaultConfig(logger2);
|
|
756
|
+
const parseResult = readAndParseConfig(configPath, mergeDefaults, logger2);
|
|
757
|
+
if (!parseResult.ok) return err(parseResult.error);
|
|
758
|
+
return validateConfig(parseResult.value, configPath, logger2);
|
|
759
|
+
}
|
|
760
|
+
var loadedConfig;
|
|
761
|
+
function getConfig(options) {
|
|
762
|
+
if (loadedConfig !== void 0) {
|
|
763
|
+
return loadedConfig;
|
|
764
|
+
}
|
|
765
|
+
const result = loadConfig(options);
|
|
766
|
+
if (!result.ok) {
|
|
767
|
+
throw result.error;
|
|
768
|
+
}
|
|
769
|
+
loadedConfig = result.value;
|
|
770
|
+
return loadedConfig;
|
|
771
|
+
}
|
|
772
|
+
|
|
105
773
|
// src/cli/doctor-scratch-space.ts
|
|
106
774
|
import { statSync, statfsSync } from "node:fs";
|
|
107
775
|
import { tmpdir } from "node:os";
|
|
@@ -593,6 +1261,7 @@ function failingVerdictTerms(result, live) {
|
|
|
593
1261
|
const terms = gatewayTerms(result.gateway, gateway);
|
|
594
1262
|
if (!result.nodeVersion.supported) terms.push("node version");
|
|
595
1263
|
if (!result.mcpServerReady) terms.push("MCP server");
|
|
1264
|
+
if (result.configFile.error !== void 0) terms.push("configuration");
|
|
596
1265
|
if (installFreshnessFailsVerdict(result.installFreshness)) {
|
|
597
1266
|
terms.push("install freshness");
|
|
598
1267
|
}
|
|
@@ -766,7 +1435,9 @@ function printApiKeysCheck(keys) {
|
|
|
766
1435
|
}
|
|
767
1436
|
}
|
|
768
1437
|
function printConfigFileCheck(check) {
|
|
769
|
-
if (check.
|
|
1438
|
+
if (check.error !== void 0) {
|
|
1439
|
+
writeLine(`${formatStatus(false)} Configuration failed: ${check.error}`);
|
|
1440
|
+
} else if (check.found && check.path !== null) {
|
|
770
1441
|
writeLine(`${formatStatus(true)} Configuration loaded: ${check.path}`);
|
|
771
1442
|
} else {
|
|
772
1443
|
writeLine(`${formatStatus(false, true)} Configuration file: Not found`);
|
|
@@ -1012,8 +1683,8 @@ function printHarnessAlignment(check) {
|
|
|
1012
1683
|
}
|
|
1013
1684
|
|
|
1014
1685
|
// src/cli/doctor-harness-alignment.ts
|
|
1015
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
1016
|
-
import { dirname, join, resolve } from "node:path";
|
|
1686
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
1687
|
+
import { dirname, join as join2, resolve as resolve2 } from "node:path";
|
|
1017
1688
|
var HARNESS_FILES = [
|
|
1018
1689
|
{ harness: "Cursor", path: ".cursor/rules/agents.mdc" },
|
|
1019
1690
|
{ harness: "Windsurf", path: ".windsurf/rules/agents.md" },
|
|
@@ -1028,9 +1699,9 @@ function checkHarnessAlignment(cwd = process.cwd()) {
|
|
|
1028
1699
|
const projectRoot = findProjectRoot(cwd);
|
|
1029
1700
|
const inProject = projectRoot !== null;
|
|
1030
1701
|
const base = projectRoot ?? cwd;
|
|
1031
|
-
const agentsMdExists =
|
|
1702
|
+
const agentsMdExists = existsSync2(join2(base, "AGENTS.md"));
|
|
1032
1703
|
const files = HARNESS_FILES.map(
|
|
1033
|
-
({ harness, path }) => inspectFile(harness, path,
|
|
1704
|
+
({ harness, path }) => inspectFile(harness, path, join2(base, path))
|
|
1034
1705
|
);
|
|
1035
1706
|
const alignedCount = files.filter((f) => f.exists && f.redirectsToAgentsMd).length;
|
|
1036
1707
|
const driftCount = files.filter((f) => f.exists && !f.redirectsToAgentsMd).length;
|
|
@@ -1048,16 +1719,16 @@ function findProjectRoot(start) {
|
|
|
1048
1719
|
return findRepoRoot(start) ?? findPackageJsonAncestor(start);
|
|
1049
1720
|
}
|
|
1050
1721
|
function findPackageJsonAncestor(start) {
|
|
1051
|
-
let current =
|
|
1722
|
+
let current = resolve2(start);
|
|
1052
1723
|
for (; ; ) {
|
|
1053
|
-
if (
|
|
1724
|
+
if (existsSync2(join2(current, "package.json"))) return current;
|
|
1054
1725
|
const parent = dirname(current);
|
|
1055
1726
|
if (parent === current) return null;
|
|
1056
1727
|
current = parent;
|
|
1057
1728
|
}
|
|
1058
1729
|
}
|
|
1059
1730
|
function inspectFile(harness, relativePath, absolutePath) {
|
|
1060
|
-
if (!
|
|
1731
|
+
if (!existsSync2(absolutePath)) {
|
|
1061
1732
|
return {
|
|
1062
1733
|
harness,
|
|
1063
1734
|
path: relativePath,
|
|
@@ -1067,7 +1738,7 @@ function inspectFile(harness, relativePath, absolutePath) {
|
|
|
1067
1738
|
};
|
|
1068
1739
|
}
|
|
1069
1740
|
try {
|
|
1070
|
-
const content =
|
|
1741
|
+
const content = readFileSync2(absolutePath, "utf-8");
|
|
1071
1742
|
return {
|
|
1072
1743
|
harness,
|
|
1073
1744
|
path: relativePath,
|
|
@@ -1089,12 +1760,6 @@ function inspectFile(harness, relativePath, absolutePath) {
|
|
|
1089
1760
|
// src/cli/doctor.ts
|
|
1090
1761
|
import { execFileSync } from "node:child_process";
|
|
1091
1762
|
var API_KEY_VARS = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GOOGLE_AI_API_KEY"];
|
|
1092
|
-
var CONFIG_FILE_PATHS = [
|
|
1093
|
-
"./.nexus-agents/nexus-agents.yaml",
|
|
1094
|
-
"./.nexus-agents/nexus-agents.yml",
|
|
1095
|
-
"./nexus-agents.yaml",
|
|
1096
|
-
"./nexus-agents.yml"
|
|
1097
|
-
];
|
|
1098
1763
|
var DATA_SUBDIRECTORIES = [
|
|
1099
1764
|
"memory",
|
|
1100
1765
|
"memory/beliefs",
|
|
@@ -1228,12 +1893,11 @@ function checkApiKeys() {
|
|
|
1228
1893
|
}));
|
|
1229
1894
|
}
|
|
1230
1895
|
function checkConfigFile() {
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
}
|
|
1896
|
+
const result = loadConfig();
|
|
1897
|
+
if (!result.ok) {
|
|
1898
|
+
return { found: true, path: null, error: result.error.message };
|
|
1235
1899
|
}
|
|
1236
|
-
return { found:
|
|
1900
|
+
return { found: !result.value.usingDefaults, path: result.value.configPath ?? null };
|
|
1237
1901
|
}
|
|
1238
1902
|
function checkMcpServerReady() {
|
|
1239
1903
|
try {
|
|
@@ -1271,11 +1935,11 @@ function buildRegistryAdvisory(cliResults, disabledClis, gateway) {
|
|
|
1271
1935
|
function hasPriorUsage() {
|
|
1272
1936
|
try {
|
|
1273
1937
|
const root = getNexusDataDir();
|
|
1274
|
-
if (!
|
|
1938
|
+
if (!existsSync3(root)) return false;
|
|
1275
1939
|
for (const sub of ["audit", "learning", "sessions", "voting"]) {
|
|
1276
1940
|
const p = `${root}/${sub}`;
|
|
1277
1941
|
try {
|
|
1278
|
-
if (
|
|
1942
|
+
if (existsSync3(p) && readdirSync(p).length > 0) return true;
|
|
1279
1943
|
} catch {
|
|
1280
1944
|
}
|
|
1281
1945
|
}
|
|
@@ -1285,17 +1949,17 @@ function hasPriorUsage() {
|
|
|
1285
1949
|
}
|
|
1286
1950
|
}
|
|
1287
1951
|
function countJsonlLines(filePath) {
|
|
1288
|
-
if (!
|
|
1289
|
-
return
|
|
1952
|
+
if (!existsSync3(filePath)) return 0;
|
|
1953
|
+
return readFileSync3(filePath, "utf-8").split("\n").filter((l) => l.trim().length > 0).length;
|
|
1290
1954
|
}
|
|
1291
1955
|
var NO_RULES = { count: 0, activeCount: 0, eligibleOutcomes: null, savedAt: null };
|
|
1292
1956
|
function isActiveRule(rule) {
|
|
1293
1957
|
return typeof rule === "object" && rule !== null && rule["status"] === "active";
|
|
1294
1958
|
}
|
|
1295
1959
|
function readRulesMetadata(filePath) {
|
|
1296
|
-
if (!
|
|
1960
|
+
if (!existsSync3(filePath)) return NO_RULES;
|
|
1297
1961
|
try {
|
|
1298
|
-
const raw = JSON.parse(
|
|
1962
|
+
const raw = JSON.parse(readFileSync3(filePath, "utf-8"));
|
|
1299
1963
|
const rules = Array.isArray(raw["rules"]) ? raw["rules"] : [];
|
|
1300
1964
|
const saved = raw["savedAt"];
|
|
1301
1965
|
const eligible = raw["eligibleOutcomes"];
|
|
@@ -1310,7 +1974,7 @@ function readRulesMetadata(filePath) {
|
|
|
1310
1974
|
}
|
|
1311
1975
|
}
|
|
1312
1976
|
function checkDirAccess(dir) {
|
|
1313
|
-
const exists =
|
|
1977
|
+
const exists = existsSync3(dir);
|
|
1314
1978
|
if (!exists) return { exists: false, writable: false };
|
|
1315
1979
|
try {
|
|
1316
1980
|
accessSync(dir, fsConstants.W_OK);
|
|
@@ -1384,13 +2048,13 @@ async function checkSqlite() {
|
|
|
1384
2048
|
}
|
|
1385
2049
|
function checkDataDirectory() {
|
|
1386
2050
|
const rootPath = getNexusDataDir();
|
|
1387
|
-
const rootExists =
|
|
2051
|
+
const rootExists = existsSync3(rootPath);
|
|
1388
2052
|
const repoRoot = getNexusRepoDir();
|
|
1389
2053
|
const perRepoSet = getPerRepoSubdirs();
|
|
1390
2054
|
const subdirectories = DATA_SUBDIRECTORIES.map((name) => {
|
|
1391
2055
|
const segments = name.split("/");
|
|
1392
2056
|
const fullPath = nexusDataPath(...segments);
|
|
1393
|
-
const exists =
|
|
2057
|
+
const exists = existsSync3(fullPath);
|
|
1394
2058
|
const scope = perRepoSet.has(segments[0] ?? "") ? "per-repo" : "cross-repo";
|
|
1395
2059
|
return { name, path: fullPath, scope, exists, writable: exists && isWritable(fullPath) };
|
|
1396
2060
|
});
|
|
@@ -1457,7 +2121,7 @@ function voterGatewayCostDeclaration(endpoint) {
|
|
|
1457
2121
|
return resolveGatewayCostDeclaration(`api:${endpoint}`) ?? "no-default";
|
|
1458
2122
|
}
|
|
1459
2123
|
function isAllHealthy(input) {
|
|
1460
|
-
return input.gateway !== "fail" && input.nodeSupported && input.hasAuthMethod && input.mcpServerReady && !installFreshnessFailsVerdict(input.installFreshness) && scratchSeverityIsAcceptable(worstSeverity(input.scratchSpace)) && // whenEmpty: zero detected CLIs is not a healthy install (#4581) — unless
|
|
2124
|
+
return input.gateway !== "fail" && input.nodeSupported && input.hasAuthMethod && input.mcpServerReady && input.configFile.error === void 0 && !installFreshnessFailsVerdict(input.installFreshness) && scratchSeverityIsAcceptable(worstSeverity(input.scratchSpace)) && // whenEmpty: zero detected CLIs is not a healthy install (#4581) — unless
|
|
1461
2125
|
// a passing gateway serves the slots (#6609), as on a gateway-only host.
|
|
1462
2126
|
allOf(
|
|
1463
2127
|
input.clis,
|
|
@@ -1515,6 +2179,7 @@ async function runDoctor(deps = {}) {
|
|
|
1515
2179
|
nodeSupported: nodeVersion.supported,
|
|
1516
2180
|
hasAuthMethod: hasAnyAuthMethod(apiKeys, clis, gatewayVerdict(gateway)),
|
|
1517
2181
|
mcpServerReady,
|
|
2182
|
+
configFile,
|
|
1518
2183
|
installFreshness: env.installFreshness,
|
|
1519
2184
|
scratchSpace: env.scratchSpace,
|
|
1520
2185
|
clis,
|
|
@@ -1569,7 +2234,7 @@ async function runDoctorFix(result) {
|
|
|
1569
2234
|
writeLine2("\u2500".repeat(40));
|
|
1570
2235
|
let fixCount = 0;
|
|
1571
2236
|
if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
|
|
1572
|
-
const { initDataDirectories: initDataDirectories2, describeDataDirFix: describeDataDirFix2 } = await import("./setup-data-dir-
|
|
2237
|
+
const { initDataDirectories: initDataDirectories2, describeDataDirFix: describeDataDirFix2 } = await import("./setup-data-dir-75Z5PSSB.js");
|
|
1573
2238
|
const outcome = describeDataDirFix2(initDataDirectories2());
|
|
1574
2239
|
writeLine2(outcome.line);
|
|
1575
2240
|
if (outcome.counted) fixCount++;
|
|
@@ -1626,7 +2291,7 @@ function initDataDirectories(dryRun = false) {
|
|
|
1626
2291
|
return { success: true, rootPath: NEXUS_DATA_DIR, created, alreadyExisted, error: null };
|
|
1627
2292
|
}
|
|
1628
2293
|
function ensureDir(dirPath, dryRun, created, alreadyExisted, mode) {
|
|
1629
|
-
if (
|
|
2294
|
+
if (existsSync4(dirPath)) {
|
|
1630
2295
|
alreadyExisted.push(dirPath);
|
|
1631
2296
|
return;
|
|
1632
2297
|
}
|
|
@@ -1655,6 +2320,21 @@ function describeDataDirFix(result) {
|
|
|
1655
2320
|
}
|
|
1656
2321
|
|
|
1657
2322
|
export {
|
|
2323
|
+
LoggingConfigSchema,
|
|
2324
|
+
ProviderConfigSchema,
|
|
2325
|
+
ModelTiersSchema,
|
|
2326
|
+
ModelConfigSchema,
|
|
2327
|
+
WorkflowConfigSchema,
|
|
2328
|
+
VALID_EXPERT_TIERS,
|
|
2329
|
+
VALID_EXPERT_DOMAINS,
|
|
2330
|
+
MAX_SYSTEM_PROMPT_LENGTH,
|
|
2331
|
+
CustomExpertDefinitionSchema,
|
|
2332
|
+
ExpertDefinitionSchema,
|
|
2333
|
+
ExpertConfigSchema,
|
|
2334
|
+
AppConfigSchema,
|
|
2335
|
+
defaultConfig,
|
|
2336
|
+
loadConfig,
|
|
2337
|
+
getConfig,
|
|
1658
2338
|
DEFAULT_TASK_TTL_MS,
|
|
1659
2339
|
clampTaskTtl,
|
|
1660
2340
|
getCliAdapterDiagnostics,
|
|
@@ -1674,4 +2354,4 @@ export {
|
|
|
1674
2354
|
startStdioServer,
|
|
1675
2355
|
closeServer
|
|
1676
2356
|
};
|
|
1677
|
-
//# sourceMappingURL=chunk-
|
|
2357
|
+
//# sourceMappingURL=chunk-C6MM6Z65.js.map
|