nexus-agents 2.55.1 → 2.56.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.
@@ -0,0 +1,2520 @@
1
+ import {
2
+ resolveInsideRoot
3
+ } from "./chunk-NUBSJGQZ.js";
4
+ import {
5
+ capitalize
6
+ } from "./chunk-633WH2ML.js";
7
+ import {
8
+ createAllAdapters
9
+ } from "./chunk-RSUCXOQM.js";
10
+ import {
11
+ API_TIMEOUTS,
12
+ CLI_TIMEOUTS,
13
+ CliNameSchema,
14
+ DEFAULT_CAPABILITIES,
15
+ DEFAULT_COMPOSITE_CONFIG,
16
+ DEFAULT_MODEL_CAPABILITIES,
17
+ DEFAULT_MODEL_PER_CLI,
18
+ DEFAULT_ZERO_ROUTER_CONFIG,
19
+ INTERNAL_TIMEOUTS,
20
+ MCP_TIMEOUTS,
21
+ TEST_TIMEOUTS,
22
+ WORKFLOW_TIMEOUTS,
23
+ colors,
24
+ createLogger,
25
+ err,
26
+ formatZodIssuesAsArray,
27
+ getErrorMessage,
28
+ getTimeProvider,
29
+ ok,
30
+ symbols,
31
+ writeLine
32
+ } from "./chunk-UOUJZIKH.js";
33
+ import {
34
+ LEARNING_DIR,
35
+ OUTCOMES_FILE,
36
+ RULES_FILE,
37
+ isPersistenceEnabled
38
+ } from "./chunk-CLYZ7FWP.js";
39
+
40
+ // src/version.ts
41
+ var VERSION = true ? "2.56.0" : "dev";
42
+
43
+ // src/config/schemas-core.ts
44
+ import { z } from "zod";
45
+ var LoggingConfigSchema = z.object({
46
+ level: z.enum(["debug", "info", "warn", "error"]).default("info"),
47
+ format: z.enum(["json", "pretty"]).default("json"),
48
+ // Default to stderr: MCP stdio transport reserves stdout for JSON-RPC frames.
49
+ destination: z.enum(["stdout", "stderr", "file"]).default("stderr"),
50
+ filePath: z.string().optional()
51
+ });
52
+ var ProviderConfigSchema = z.object({
53
+ apiKey: z.string().optional(),
54
+ baseUrl: z.url().optional(),
55
+ timeout: z.number().positive().default(3e4),
56
+ maxRetries: z.number().nonnegative().default(3)
57
+ });
58
+ var ModelTiersSchema = z.object({
59
+ fast: z.array(z.string()).min(1),
60
+ balanced: z.array(z.string()).min(1),
61
+ powerful: z.array(z.string()).min(1)
62
+ });
63
+ var ModelConfigSchema = z.object({
64
+ default: z.string(),
65
+ tiers: ModelTiersSchema,
66
+ providers: z.record(z.string(), ProviderConfigSchema).optional()
67
+ });
68
+ var WorkflowConfigSchema = z.object({
69
+ templatesDir: z.string().default("./workflows"),
70
+ timeout: z.number().positive().default(3e5),
71
+ maxParallel: z.number().positive().default(5)
72
+ });
73
+
74
+ // src/config/schemas-expert.ts
75
+ import { z as z2 } from "zod";
76
+ var VALID_EXPERT_TIERS = ["fast", "balanced", "powerful"];
77
+ var VALID_EXPERT_DOMAINS = [
78
+ "code",
79
+ "security",
80
+ "architecture",
81
+ "documentation",
82
+ "testing",
83
+ "general"
84
+ ];
85
+ var MAX_SYSTEM_PROMPT_LENGTH = 4e3;
86
+ var CustomExpertDefinitionSchema = z2.object({
87
+ /** System prompt defining the expert's persona (max 4000 characters) */
88
+ systemPrompt: z2.string().min(1, "System prompt is required").max(
89
+ MAX_SYSTEM_PROMPT_LENGTH,
90
+ `System prompt must be at most ${String(MAX_SYSTEM_PROMPT_LENGTH)} characters`
91
+ ),
92
+ /** Model tier for routing */
93
+ tier: z2.enum(VALID_EXPERT_TIERS, {
94
+ error: `Invalid tier. Valid options: ${VALID_EXPERT_TIERS.join(", ")}`
95
+ }).default("balanced"),
96
+ /** Primary domain of expertise */
97
+ domain: z2.enum(VALID_EXPERT_DOMAINS, {
98
+ error: `Invalid domain. Valid options: ${VALID_EXPERT_DOMAINS.join(", ")}`
99
+ }).default("general"),
100
+ /** Secondary domains (optional) */
101
+ secondaryDomains: z2.array(z2.enum(VALID_EXPERT_DOMAINS)).optional(),
102
+ /** Expert capabilities */
103
+ capabilities: z2.array(z2.string().min(1)).min(1, "At least one capability is required").default(["task_execution"]),
104
+ /** Model temperature (0-1) */
105
+ temperature: z2.number().min(0).max(1).default(0.3),
106
+ /** Allowed tools (optional, unrestricted if not specified) */
107
+ tools: z2.array(z2.string()).optional(),
108
+ /** Human-readable description */
109
+ description: z2.string().optional(),
110
+ /** Weight for expert selection scoring (0-1) */
111
+ weight: z2.number().min(0).max(1).default(1),
112
+ /** Whether this expert is currently available */
113
+ available: z2.boolean().default(true)
114
+ });
115
+ var ExpertDefinitionSchema = z2.object({
116
+ prompt: z2.string().min(1),
117
+ tier: z2.enum(["fast", "balanced", "powerful"]).default("balanced"),
118
+ temperature: z2.number().min(0).max(1).default(0.3),
119
+ tools: z2.array(z2.string()).optional()
120
+ });
121
+ var ExpertConfigSchema = z2.object({
122
+ /** Enable built-in experts */
123
+ builtin: z2.boolean().default(true),
124
+ /** Custom expert definitions keyed by expert ID */
125
+ custom: z2.record(
126
+ z2.string().regex(/^[a-z][a-z0-9_]*$/, {
127
+ message: "Expert ID must start with a letter and contain only lowercase letters, numbers, and underscores"
128
+ }),
129
+ CustomExpertDefinitionSchema
130
+ ).optional()
131
+ });
132
+
133
+ // src/config/schemas-security.ts
134
+ import { z as z3 } from "zod";
135
+ var PolicyConfigSchema = z3.object({
136
+ /** Default execution mode for tool operations (default: 'read-only') */
137
+ defaultMode: z3.enum(["read-only", "read-write"]).default("read-only"),
138
+ /** Policy enforcement mode (default: 'enforce') */
139
+ policyMode: z3.enum(["enforce", "warn"]).default("enforce")
140
+ });
141
+ var SandboxConfigSchema = z3.object({
142
+ /** Sandbox execution mode (default: 'policy') */
143
+ mode: z3.enum(["none", "policy", "container"]).default("policy"),
144
+ /** Fall back to policy mode if container mode unavailable (default: true) */
145
+ fallbackToPolicy: z3.boolean().default(true),
146
+ /** Docker image to use in container mode (default: 'node:22-alpine') */
147
+ dockerImage: z3.string().optional(),
148
+ /** Enable network access in container mode (default: false) */
149
+ networkEnabled: z3.boolean().default(false)
150
+ });
151
+ var TimeoutConfigSchema = z3.object({
152
+ /** Default timeout in milliseconds (default: 30000) */
153
+ defaultTimeoutMs: z3.number().positive().default(3e4),
154
+ /** Maximum timeout in milliseconds (default: 300000) */
155
+ maxTimeoutMs: z3.number().positive().default(3e5),
156
+ /** Whether to log timeout events (default: true) */
157
+ enableLogging: z3.boolean().default(true),
158
+ /** Enable URI validation to prevent ReDoS (default: true) */
159
+ uriValidation: z3.boolean().default(true),
160
+ /** Per-tool timeout overrides in milliseconds (Issue #657) */
161
+ perToolTimeout: z3.record(z3.string(), z3.number().positive().max(6e5)).optional()
162
+ });
163
+ var ToolRateLimitSchema = z3.object({
164
+ /** Maximum tokens (burst capacity) */
165
+ capacity: z3.number().positive().default(10),
166
+ /** Tokens refilled per interval */
167
+ refillRate: z3.number().positive().default(10),
168
+ /** Refill interval in milliseconds (default: 60000 = 1 minute) */
169
+ refillIntervalMs: z3.number().positive().default(6e4)
170
+ });
171
+ var DEFAULT_TOOL_RATE_LIMITS = {
172
+ orchestrate: { capacity: 10, refillRate: 10, refillIntervalMs: 6e4 },
173
+ delegate: { capacity: 20, refillRate: 20, refillIntervalMs: 6e4 },
174
+ workflow: { capacity: 5, refillRate: 5, refillIntervalMs: 6e4 },
175
+ expert: { capacity: 30, refillRate: 30, refillIntervalMs: 6e4 }
176
+ };
177
+ var SecurityConfigSchema = z3.object({
178
+ allowedPaths: z3.array(z3.string()).default(["./"]),
179
+ blockedPatterns: z3.array(z3.string()).default([]),
180
+ rateLimit: z3.object({
181
+ enabled: z3.boolean().default(true),
182
+ requestsPerMinute: z3.number().positive().default(60),
183
+ /** Per-tool rate limits (Issue #274 Phase 2) */
184
+ perTool: z3.record(z3.string(), ToolRateLimitSchema).optional()
185
+ }).default(() => ({ enabled: true, requestsPerMinute: 60 })),
186
+ secretsFile: z3.string().optional(),
187
+ /** Policy firewall configuration */
188
+ policy: PolicyConfigSchema.optional(),
189
+ /** Sandbox execution configuration (Issue #175) */
190
+ sandbox: SandboxConfigSchema.optional(),
191
+ /** Timeout configuration (Issue #271, CVE-2026-0621) */
192
+ timeout: TimeoutConfigSchema.optional(),
193
+ /** Tool allowlist — when set, only listed tools are registered (Issue #740) */
194
+ toolAllowlist: z3.array(z3.string()).optional(),
195
+ /** Audit logging configuration (Issue #740 Phase 2) */
196
+ audit: z3.object({
197
+ /** Enable audit logging (default: true) */
198
+ enabled: z3.boolean().default(true),
199
+ /** Log directory (default: ~/.nexus-agents/audit) */
200
+ logDir: z3.string().optional(),
201
+ /** Minimum severity to log (default: 'info') */
202
+ minSeverity: z3.enum(["info", "warning", "critical"]).default("info"),
203
+ /** Enable tamper-evident hash chain (default: true) */
204
+ enableHashChain: z3.boolean().default(true),
205
+ /** Maximum log file size in bytes (default: 10MB) */
206
+ maxFileSizeBytes: z3.number().positive().default(10 * 1024 * 1024),
207
+ /** Maximum number of log files to retain (default: 10) */
208
+ maxFiles: z3.number().positive().default(10)
209
+ }).optional(),
210
+ /** Authentication configuration (Issue #739) */
211
+ auth: z3.object({
212
+ /** Enable authentication for network-exposed transports (default: true) */
213
+ enabled: z3.boolean().default(true),
214
+ /** Authentication method (default: 'token') */
215
+ method: z3.enum(["token", "oauth2"]).default("token"),
216
+ /** Header name for bearer token (default: 'Authorization') */
217
+ tokenHeader: z3.string().default("Authorization"),
218
+ /** Token file path (default: ~/.nexus-agents/auth/server-token) */
219
+ tokenFile: z3.string().optional()
220
+ }).optional()
221
+ });
222
+
223
+ // src/config/schemas.ts
224
+ import { z as z9 } from "zod";
225
+
226
+ // src/config/schemas-observability.ts
227
+ import { z as z4 } from "zod";
228
+ var EventBusConfigSchema = z4.object({
229
+ /** Enable EventBus integration (default: true) */
230
+ enabled: z4.boolean().default(true),
231
+ /** Maximum events to retain in history (default: 1000) */
232
+ maxHistorySize: z4.number().positive().default(1e3),
233
+ /** Event patterns to subscribe to (default: all major patterns) */
234
+ subscriptions: z4.object({
235
+ /** Subscribe to consensus events (consensus.*) */
236
+ consensus: z4.boolean().default(true),
237
+ /** Subscribe to agent events (agent.*) */
238
+ agent: z4.boolean().default(true),
239
+ /** Subscribe to protocol events (protocol.*) */
240
+ protocol: z4.boolean().default(true),
241
+ /** Subscribe to session events (session.*) */
242
+ session: z4.boolean().default(true),
243
+ /** Subscribe to message events (message.*) */
244
+ message: z4.boolean().default(false),
245
+ // Off by default (high volume)
246
+ /** Subscribe to byzantine detection events (byzantine.*) */
247
+ byzantine: z4.boolean().default(true)
248
+ }).default(() => ({
249
+ consensus: true,
250
+ agent: true,
251
+ protocol: true,
252
+ session: true,
253
+ message: false,
254
+ byzantine: true
255
+ })),
256
+ /** Logging configuration for events */
257
+ logging: z4.object({
258
+ /** Log level for frequent events (default: debug) */
259
+ frequentEventLevel: z4.enum(["debug", "info"]).default("debug"),
260
+ /** Log level for important events (default: info) */
261
+ importantEventLevel: z4.enum(["debug", "info"]).default("info")
262
+ }).default(() => ({
263
+ frequentEventLevel: "debug",
264
+ importantEventLevel: "info"
265
+ }))
266
+ });
267
+ var ObservabilityConfigSchema = z4.object({
268
+ /** EventBus configuration */
269
+ eventBus: EventBusConfigSchema.optional(),
270
+ /** SwarmObserver maximum events (default: 10000) */
271
+ swarmObserverMaxEvents: z4.number().positive().default(1e4)
272
+ });
273
+
274
+ // src/config/schemas-skills.ts
275
+ import { z as z5 } from "zod";
276
+ var ExternalPackSourceSchema = z5.object({
277
+ /** Pack name for identification */
278
+ name: z5.string().min(1),
279
+ /** Source: npm package name or local file path */
280
+ source: z5.string().min(1),
281
+ /** Whether the pack is enabled (default: true) */
282
+ enabled: z5.boolean().default(true)
283
+ });
284
+ var SkillLibraryConfigSchema = z5.object({
285
+ /** Whether skill library is enabled (default: true) */
286
+ enabled: z5.boolean().default(true),
287
+ /** Maximum skills to store (default: 1000) */
288
+ maxSkills: z5.number().int().positive().default(1e3),
289
+ /** Minimum success rate to keep skill (0-1, default: 0.3) */
290
+ minSuccessRateForRetention: z5.number().min(0).max(1).default(0.3),
291
+ /** Number of executions before evaluating retention (default: 5) */
292
+ executionsBeforeEvaluation: z5.number().int().nonnegative().default(5),
293
+ /** Enable automatic skill pruning (default: true) */
294
+ enablePruning: z5.boolean().default(true),
295
+ /** Whether to track detailed execution history (default: true) */
296
+ trackExecutionHistory: z5.boolean().default(true),
297
+ /** Maximum execution history entries per skill (default: 100) */
298
+ maxHistoryPerSkill: z5.number().int().positive().default(100),
299
+ /** External skill pack sources (Issue #654) */
300
+ externalPacks: z5.array(ExternalPackSourceSchema).optional()
301
+ });
302
+
303
+ // src/config/schemas-sica.ts
304
+ import { z as z6 } from "zod";
305
+ var SicaConfigSchema = z6.object({
306
+ /** Whether SICA wrapping is enabled (default: false) */
307
+ enabled: z6.boolean().default(false),
308
+ /** Minimum executions before considering improvement (default: 10) */
309
+ minExecutionsForImprovement: z6.number().int().positive().default(10),
310
+ /** Success rate threshold to trigger improvement (0-1, default: 0.7) */
311
+ improvementThreshold: z6.number().min(0).max(1).default(0.7),
312
+ /** Maximum concurrent versions to evaluate (default: 3) */
313
+ maxActiveVersions: z6.number().int().positive().max(10).default(3),
314
+ /** Whether to auto-select best version (default: true) */
315
+ autoSelectBest: z6.boolean().default(true),
316
+ /** Improvement cooldown in milliseconds (default: 60000) */
317
+ improvementCooldownMs: z6.number().int().nonnegative().default(6e4),
318
+ /** Enable observability logging for SICA events (default: true) */
319
+ enableObservability: z6.boolean().default(true)
320
+ });
321
+
322
+ // src/config/schemas-gateway.ts
323
+ import { z as z7 } from "zod";
324
+ var TierNameSchema = z7.enum(["DIRECT", "ANALYZED", "ORCHESTRATED"]);
325
+ var ALLOWED_COMMANDS = ["node", "npx", "python", "python3", "uvx", "docker"];
326
+ var UpstreamServerSchema = z7.object({
327
+ /** Unique name for this upstream server (used as tool prefix). */
328
+ name: z7.string().min(1).max(50).regex(/^[a-z0-9_-]+$/),
329
+ /** Command to spawn the server. Must be in allowlist. */
330
+ command: z7.enum(ALLOWED_COMMANDS),
331
+ /** Arguments to pass to the command. */
332
+ args: z7.array(z7.string().max(500)).default([]),
333
+ /** Environment variables (use {env:VAR} references, not plaintext secrets). */
334
+ env: z7.record(z7.string(), z7.string()).optional(),
335
+ /** Whether to connect lazily on first tool call (default: true). */
336
+ lazy: z7.boolean().default(true),
337
+ /** Connection timeout in ms (default: 10000). */
338
+ timeoutMs: z7.number().int().min(1e3).max(6e4).default(1e4)
339
+ });
340
+ var MAX_UPSTREAM_SERVERS = 5;
341
+ var GatewayConfigSchema = z7.object({
342
+ /** Enable gateway tier dispatch logging (default: true). */
343
+ enabled: z7.boolean().default(true),
344
+ /**
345
+ * Per-tool tier overrides.
346
+ * Keys are tool names (e.g., 'delegate_to_model'), values are tier names.
347
+ * Overrides the default tier from TOOL_TIER_MAP in tier-classifier.ts.
348
+ */
349
+ tierOverrides: z7.record(z7.string(), TierNameSchema).optional(),
350
+ /**
351
+ * Upstream MCP servers to compose with (#1498).
352
+ * Tools from upstream servers are available as prefixed tools (e.g., tavily.search).
353
+ */
354
+ upstreamServers: z7.array(UpstreamServerSchema).max(MAX_UPSTREAM_SERVERS).optional()
355
+ });
356
+
357
+ // src/config/schemas-routing.ts
358
+ import { z as z8 } from "zod";
359
+ var BudgetConstraintsSchema = z8.object({
360
+ /** Maximum tokens per request */
361
+ maxTokens: z8.number().positive().optional(),
362
+ /** Maximum cost per request in USD */
363
+ maxCostUsd: z8.number().positive().optional(),
364
+ /** Maximum latency per request in milliseconds */
365
+ maxLatencyMs: z8.number().positive().optional()
366
+ }).optional();
367
+ var TopsisCriterionSchema = z8.object({
368
+ /** Criterion name (e.g., 'quality', 'cost', 'latency') */
369
+ name: z8.string().min(1),
370
+ /** Weight for this criterion (0-1, should sum to 1 across all criteria) */
371
+ weight: z8.number().min(0).max(1),
372
+ /** Whether higher values are better (true) or lower is better (false) */
373
+ beneficial: z8.boolean()
374
+ });
375
+ var TopsisConfigSchema = z8.object({
376
+ /** Criteria with weights (must sum to 1.0) */
377
+ criteria: z8.array(TopsisCriterionSchema).optional(),
378
+ /** Minimum acceptable quality score (0-10) */
379
+ minQualityThreshold: z8.number().min(0).max(10).default(5),
380
+ /** Maximum acceptable latency in milliseconds (optional) */
381
+ maxLatencyMs: z8.number().positive().optional(),
382
+ /** Maximum acceptable cost per request in USD (optional) */
383
+ maxCostPerRequest: z8.number().positive().optional(),
384
+ /** Whether to log detailed scoring info */
385
+ verbose: z8.boolean().default(false)
386
+ }).optional();
387
+ var DifficultyWeightsConfigSchema = z8.object({
388
+ /** Weight for reasoning difficulty (0-1) */
389
+ reasoning: z8.number().min(0).max(1).default(0.3),
390
+ /** Weight for knowledge difficulty (0-1) */
391
+ knowledge: z8.number().min(0).max(1).default(0.15),
392
+ /** Weight for creativity difficulty (0-1) */
393
+ creativity: z8.number().min(0).max(1).default(0.15),
394
+ /** Weight for precision difficulty (0-1) */
395
+ precision: z8.number().min(0).max(1).default(0.25),
396
+ /** Weight for context length difficulty (0-1) */
397
+ context_length: z8.number().min(0).max(1).default(0.15)
398
+ });
399
+ var DifficultyThresholdsSchema = z8.object({
400
+ /** Upper bound for 'easy' classification (0-1) */
401
+ easyUpperBound: z8.number().min(0).max(1).default(0.3),
402
+ /** Lower bound for 'hard' classification (0-1) */
403
+ hardLowerBound: z8.number().min(0).max(1).default(0.7)
404
+ });
405
+ var DifficultyLevelSchema = z8.enum(["easy", "medium", "hard"]);
406
+ var ModelTierSchema = z8.enum(["fast", "balanced", "powerful"]);
407
+ var ZeroRouterConfigSchema = z8.object({
408
+ /** Difficulty thresholds for level classification */
409
+ thresholds: DifficultyThresholdsSchema.optional(),
410
+ /** Weights for difficulty aggregation */
411
+ weights: DifficultyWeightsConfigSchema.optional(),
412
+ /** Mapping from difficulty level to model tier */
413
+ difficultyToTier: z8.record(DifficultyLevelSchema, ModelTierSchema).optional(),
414
+ /** Mapping from model tier to CLI preference order */
415
+ tierToClis: z8.record(ModelTierSchema, z8.array(CliNameSchema)).optional(),
416
+ /** Enable adaptive calibration from outcomes */
417
+ enableCalibration: z8.boolean().default(true),
418
+ /** Maximum outcomes to store for calibration */
419
+ maxCalibrationOutcomes: z8.number().int().positive().default(1e3),
420
+ /** Minimum outcomes before applying calibration adjustments */
421
+ minCalibrationOutcomes: z8.number().int().positive().default(50),
422
+ /** Verbose logging */
423
+ verbose: z8.boolean().default(false)
424
+ }).optional();
425
+ var LatencyTrackerConfigSchema = z8.object({
426
+ /** Maximum number of samples to keep per CLI */
427
+ windowSize: z8.number().int().positive().default(100),
428
+ /** Time-weighted decay factor (0-1, higher = more weight to recent) */
429
+ decayFactor: z8.number().min(0).max(1).default(0.95),
430
+ /** Maximum age of samples in milliseconds before forced eviction */
431
+ maxSampleAgeMs: z8.number().int().positive().default(36e5),
432
+ /** Percentiles to calculate */
433
+ percentiles: z8.array(z8.number().min(0).max(100)).max(20).default([50, 95, 99])
434
+ }).optional();
435
+ var RoutingMemoryConfigSchema = z8.object({
436
+ /** Minimum observations before using learned routing */
437
+ minObservations: z8.number().int().positive().default(5),
438
+ /** Confidence threshold for using cached decisions */
439
+ confidenceThreshold: z8.number().min(0).max(1).default(0.6),
440
+ /** Success rate threshold for trusting a routing pattern */
441
+ successRateThreshold: z8.number().min(0).max(1).default(0.7),
442
+ /** Maximum age of cached actions in milliseconds */
443
+ actionCacheMaxAgeMs: z8.number().int().positive().default(36e5)
444
+ }).optional();
445
+ var RoutingConfigSchema = z8.object({
446
+ /**
447
+ * Pipeline stage toggles.
448
+ * Enable or disable individual routing stages.
449
+ */
450
+ stages: z8.object({
451
+ /** Enable budget filtering stage */
452
+ budgetFilter: z8.boolean().default(true),
453
+ /** Enable ZeroRouter difficulty-based routing */
454
+ zeroRouter: z8.boolean().default(true),
455
+ /** Enable preference-trained routing */
456
+ preferenceRouting: z8.boolean().default(false),
457
+ /** Enable TOPSIS ranking */
458
+ topsisRanking: z8.boolean().default(true),
459
+ /** Enable LinUCB selection */
460
+ linucbSelection: z8.boolean().default(true),
461
+ /** Enable latency tracking */
462
+ latencyTracking: z8.boolean().default(true),
463
+ /** Enable routing memory for learned routing */
464
+ routingMemory: z8.boolean().default(false),
465
+ /** Enable confidence cascade stage (Issue #755, ADR-0005) */
466
+ confidenceCascade: z8.boolean().default(false),
467
+ /** Enable capability match stage (Issue #755, ADR-0005) */
468
+ capabilityMatch: z8.boolean().default(false),
469
+ /** Enable quality constraint stage (Issue #755, ADR-0005) */
470
+ qualityConstraint: z8.boolean().default(false),
471
+ /** Enable resource strategy stage for budget-aware oscillation (Issue #998) */
472
+ resourceStrategy: z8.boolean().default(true),
473
+ /** Enable strategy distillation for learned routing rules (Issue #999) */
474
+ strategyDistillation: z8.boolean().default(false)
475
+ }).optional(),
476
+ /**
477
+ * Budget constraints for routing decisions.
478
+ */
479
+ budget: BudgetConstraintsSchema,
480
+ /**
481
+ * TOPSIS multi-criteria decision making configuration.
482
+ */
483
+ topsis: TopsisConfigSchema,
484
+ /**
485
+ * ZeroRouter difficulty-based routing configuration.
486
+ */
487
+ zeroRouter: ZeroRouterConfigSchema,
488
+ /**
489
+ * Latency tracker configuration.
490
+ */
491
+ latencyTracker: LatencyTrackerConfigSchema,
492
+ /**
493
+ * Routing memory configuration.
494
+ */
495
+ routingMemory: RoutingMemoryConfigSchema,
496
+ /**
497
+ * LinUCB bandit parameters.
498
+ */
499
+ linucb: z8.object({
500
+ /** Exploration parameter (higher = more exploration) */
501
+ alpha: z8.number().positive().default(1),
502
+ /** Maximum routing decision time in milliseconds */
503
+ maxDecisionTimeMs: z8.number().positive().default(50)
504
+ }).optional(),
505
+ /**
506
+ * Preference router parameters.
507
+ */
508
+ preference: z8.object({
509
+ /** Minimum data points before using learned preferences */
510
+ minDataPoints: z8.number().int().positive().default(10)
511
+ }).optional(),
512
+ /**
513
+ * Weight for latency score in final routing (0-1).
514
+ */
515
+ latencyScoreWeight: z8.number().min(0).max(1).default(0.2)
516
+ });
517
+
518
+ // src/config/schemas.ts
519
+ var AppConfigSchema = z9.object({
520
+ models: ModelConfigSchema,
521
+ experts: ExpertConfigSchema.optional(),
522
+ workflows: WorkflowConfigSchema.optional(),
523
+ security: SecurityConfigSchema.optional(),
524
+ logging: LoggingConfigSchema.optional(),
525
+ /** Observability configuration (Issue #307) */
526
+ observability: ObservabilityConfigSchema.optional(),
527
+ /** Routing configuration (Issue #475) - used in orchestrator mode */
528
+ routing: RoutingConfigSchema.optional(),
529
+ /** Skill library configuration (Issue #491) */
530
+ skills: SkillLibraryConfigSchema.optional(),
531
+ /** SICA self-improvement configuration (Issue #492) */
532
+ sica: SicaConfigSchema.optional(),
533
+ /** Gateway middleware configuration (Issue #897) */
534
+ gateway: GatewayConfigSchema.optional()
535
+ });
536
+ var defaultConfig = {
537
+ models: {
538
+ default: "claude-sonnet",
539
+ tiers: {
540
+ fast: ["claude-haiku", "gemini-flash"],
541
+ balanced: ["claude-sonnet", "gemini-pro"],
542
+ powerful: ["claude-opus", "codex-5.3"]
543
+ }
544
+ },
545
+ logging: {
546
+ level: "info",
547
+ format: "json",
548
+ // stderr is the safe default: MCP stdio transport reserves stdout for
549
+ // JSON-RPC frames. Any log written to stdout corrupts the transport.
550
+ destination: "stderr"
551
+ },
552
+ security: {
553
+ allowedPaths: ["./"],
554
+ blockedPatterns: [],
555
+ rateLimit: {
556
+ enabled: true,
557
+ requestsPerMinute: 60
558
+ },
559
+ policy: {
560
+ defaultMode: "read-only",
561
+ policyMode: "enforce"
562
+ },
563
+ timeout: {
564
+ defaultTimeoutMs: 3e4,
565
+ maxTimeoutMs: 3e5,
566
+ enableLogging: true,
567
+ uriValidation: true
568
+ }
569
+ }
570
+ };
571
+
572
+ // src/config/env-schema.ts
573
+ import { z as z10 } from "zod";
574
+ var positiveIntStr = z10.string().regex(/^\d+$/, "Must be a positive integer string");
575
+ var boolStr = z10.enum(["true", "false"]);
576
+ var floatStr = z10.string().regex(/^\d+(\.\d+)?$/, "Must be a non-negative number string");
577
+ var NexusEnvSchema = z10.object({
578
+ // --- Timeouts ---
579
+ NEXUS_TIMEOUT_CLI: positiveIntStr.optional(),
580
+ NEXUS_TIMEOUT_CLISIMPLE: positiveIntStr.optional(),
581
+ NEXUS_TIMEOUT_CLICOMPLEX: positiveIntStr.optional(),
582
+ NEXUS_TIMEOUT_API: positiveIntStr.optional(),
583
+ NEXUS_TIMEOUT_WORKFLOW: positiveIntStr.optional(),
584
+ NEXUS_TIMEOUT_MCP: positiveIntStr.optional(),
585
+ NEXUS_VOTE_TIMEOUT_MS: positiveIntStr.optional(),
586
+ NEXUS_MCP_TIMEOUT_MS: positiveIntStr.optional(),
587
+ NEXUS_WORKFLOW_TIMEOUT_MS: positiveIntStr.optional(),
588
+ NEXUS_GRAPH_TIMEOUT_MS: positiveIntStr.optional(),
589
+ NEXUS_TEST_TIMEOUT_MS: positiveIntStr.optional(),
590
+ NEXUS_EXPERT_TIMEOUT_MS: positiveIntStr.optional(),
591
+ NEXUS_WORKER_TIMEOUT_MS: positiveIntStr.optional(),
592
+ // --- Retry ---
593
+ NEXUS_RETRY_MAX_RETRIES: positiveIntStr.optional(),
594
+ NEXUS_RETRY_BASE_DELAY: positiveIntStr.optional(),
595
+ NEXUS_RETRY_MAX_DELAY: positiveIntStr.optional(),
596
+ NEXUS_RETRY_JITTER: floatStr.optional(),
597
+ // --- Rate Limit ---
598
+ NEXUS_RATE_LIMIT_ENABLED: boolStr.optional(),
599
+ NEXUS_RATE_LIMIT_RPM: positiveIntStr.optional(),
600
+ NEXUS_RATE_LIMIT_MAX_CONCURRENT: positiveIntStr.optional(),
601
+ NEXUS_RATE_LIMIT_CAPACITY: positiveIntStr.optional(),
602
+ NEXUS_RATE_LIMIT_REFILL_RATE: positiveIntStr.optional(),
603
+ NEXUS_RATE_LIMIT_REFILL_INTERVAL: positiveIntStr.optional(),
604
+ // --- Workers & Concurrency ---
605
+ NEXUS_MAX_CONCURRENT_EXPERTS: positiveIntStr.optional(),
606
+ NEXUS_WORKERS_MAX: positiveIntStr.optional(),
607
+ NEXUS_WORKERS_POOL_SIZE: positiveIntStr.optional(),
608
+ NEXUS_WORKERS_IDLE_TIMEOUT: positiveIntStr.optional(),
609
+ NEXUS_WORKFLOW_MAX_PARALLEL: positiveIntStr.optional(),
610
+ NEXUS_TEST_PARALLELISM: positiveIntStr.optional(),
611
+ NEXUS_EVALUATION_MAX_WORKERS: positiveIntStr.optional(),
612
+ NEXUS_SWARM_OBSERVER_MAX_EVENTS: positiveIntStr.optional(),
613
+ // --- Circuit Breaker ---
614
+ NEXUS_CIRCUIT_BREAKER_THRESHOLD: positiveIntStr.optional(),
615
+ NEXUS_CIRCUIT_BREAKER_RESET_TIMEOUT: positiveIntStr.optional(),
616
+ // --- V2 Pipeline ---
617
+ NEXUS_V2_MODE: z10.enum(["off", "partial", "full"]).optional(),
618
+ NEXUS_V2_DELEGATE: boolStr.optional(),
619
+ NEXUS_V2_ORCHESTRATE: boolStr.optional(),
620
+ NEXUS_V2_POLICY_MODE: z10.enum(["off", "warn", "block"]).optional(),
621
+ NEXUS_AORCHESTRA: boolStr.optional(),
622
+ NEXUS_AORCHESTRA_DISPATCH: boolStr.optional(),
623
+ NEXUS_WORKER_MAX_CALLS: positiveIntStr.optional(),
624
+ // --- Server ---
625
+ NEXUS_AUTH_ENABLED: boolStr.optional(),
626
+ NEXUS_AUTH_METHOD: z10.string().optional(),
627
+ // --- Logging ---
628
+ NEXUS_LOG_LEVEL: z10.enum(["trace", "debug", "info", "warn", "error", "fatal", "silent"]).optional(),
629
+ // --- Features ---
630
+ NEXUS_PERSIST_LEARNING: boolStr.optional(),
631
+ NEXUS_REFLECTIVE_MEMORY: z10.enum(["true", "false", "shadow"]).optional(),
632
+ NEXUS_EVENTBUS_ENABLED: boolStr.optional(),
633
+ NEXUS_EVENTBUS_MAX_HISTORY: positiveIntStr.optional(),
634
+ NEXUS_BILLING_MODE: z10.enum(["plan", "api"]).optional(),
635
+ NEXUS_CONFIG_PATH: z10.string().optional(),
636
+ NEXUS_ALLOW_MOCK_ORCHESTRATION: boolStr.optional(),
637
+ // --- Hooks & Sessions ---
638
+ NEXUS_HOOK_VERBOSE: boolStr.optional(),
639
+ NEXUS_SESSIONS_DB: z10.string().optional(),
640
+ NEXUS_DISABLE_SESSIONS: boolStr.optional(),
641
+ NEXUS_DISABLE_METRICS: boolStr.optional()
642
+ });
643
+ var KNOWN_NAMES = Object.keys(NexusEnvSchema.shape);
644
+ function at(arr, i) {
645
+ return arr[i] ?? 0;
646
+ }
647
+ function levenshtein(a, b) {
648
+ const m = a.length;
649
+ const n = b.length;
650
+ let prev = Array.from({ length: n + 1 }, (_, j) => j);
651
+ let curr = new Array(n + 1).fill(0);
652
+ for (let i = 1; i <= m; i++) {
653
+ curr[0] = i;
654
+ for (let j = 1; j <= n; j++) {
655
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
656
+ curr[j] = Math.min(at(prev, j) + 1, at(curr, j - 1) + 1, at(prev, j - 1) + cost);
657
+ }
658
+ [prev, curr] = [curr, prev];
659
+ }
660
+ return at(prev, n);
661
+ }
662
+ function suggestSimilar(name, known) {
663
+ let best = null;
664
+ let bestDist = 4;
665
+ for (const candidate of known) {
666
+ const dist = levenshtein(name, candidate);
667
+ if (dist < bestDist) {
668
+ bestDist = dist;
669
+ best = candidate;
670
+ }
671
+ }
672
+ return best;
673
+ }
674
+ function classifyEnvKeys(nexusKeys, env) {
675
+ const knownRecord = {};
676
+ const unknownVars = [];
677
+ for (const key of nexusKeys) {
678
+ if (KNOWN_NAMES.includes(key)) {
679
+ const value = env[key];
680
+ if (value !== void 0) {
681
+ knownRecord[key] = value;
682
+ }
683
+ } else {
684
+ unknownVars.push({
685
+ name: key,
686
+ suggestion: suggestSimilar(key, KNOWN_NAMES)
687
+ });
688
+ }
689
+ }
690
+ return { knownRecord, unknownVars };
691
+ }
692
+ function logValidationWarnings(logger2, unknownVars, invalidVars) {
693
+ for (const u of unknownVars) {
694
+ const hint = u.suggestion !== null ? ` (did you mean ${u.suggestion}?)` : "";
695
+ logger2.warn(`Unknown environment variable: ${u.name}${hint}`);
696
+ }
697
+ for (const inv of invalidVars) {
698
+ logger2.warn(`Invalid environment variable ${inv.name}="${inv.value}": ${inv.error}`);
699
+ }
700
+ }
701
+ function validateNexusEnv(logger2) {
702
+ const nexusKeys = Object.keys(process.env).filter((k) => k.startsWith("NEXUS_"));
703
+ const { knownRecord, unknownVars } = classifyEnvKeys(nexusKeys, process.env);
704
+ const invalidVars = [];
705
+ const result = NexusEnvSchema.safeParse(knownRecord);
706
+ if (!result.success) {
707
+ for (const issue of result.error.issues) {
708
+ const varName = String(issue.path[0]);
709
+ invalidVars.push({
710
+ name: varName,
711
+ value: knownRecord[varName] ?? "",
712
+ error: issue.message
713
+ });
714
+ }
715
+ }
716
+ if (logger2 !== void 0) {
717
+ logValidationWarnings(logger2, unknownVars, invalidVars);
718
+ }
719
+ return { unknownVars, invalidVars };
720
+ }
721
+ function getKnownNexusVarNames() {
722
+ return KNOWN_NAMES;
723
+ }
724
+
725
+ // src/config/model-availability.ts
726
+ var DEFAULT_TTL_MS = 6e4;
727
+ var DEFAULT_MAX_ENTRIES = 50;
728
+ var AvailabilityCache = class {
729
+ cache = /* @__PURE__ */ new Map();
730
+ ttlMs;
731
+ maxEntries;
732
+ constructor(config = {}) {
733
+ this.ttlMs = config.ttlMs ?? DEFAULT_TTL_MS;
734
+ this.maxEntries = config.maxEntries ?? DEFAULT_MAX_ENTRIES;
735
+ }
736
+ /** Get a cached probe result, or undefined if expired/missing. */
737
+ get(modelId) {
738
+ const entry = this.cache.get(modelId);
739
+ if (entry === void 0) return void 0;
740
+ if (getTimeProvider().now() - entry.checkedAt > this.ttlMs) {
741
+ this.cache.delete(modelId);
742
+ return void 0;
743
+ }
744
+ return entry;
745
+ }
746
+ /** Store a probe result, evicting oldest if at capacity. */
747
+ set(result) {
748
+ if (this.cache.size >= this.maxEntries && !this.cache.has(result.modelId)) {
749
+ const oldest = this.cache.keys().next();
750
+ if (oldest.done !== true) {
751
+ this.cache.delete(oldest.value);
752
+ }
753
+ }
754
+ this.cache.set(result.modelId, result);
755
+ }
756
+ /** Mark a model as unavailable without a full probe. */
757
+ markUnavailable(modelId, error) {
758
+ this.set({
759
+ modelId,
760
+ available: false,
761
+ latencyMs: 0,
762
+ checkedAt: getTimeProvider().now(),
763
+ error
764
+ });
765
+ }
766
+ /** Mark a model as available. */
767
+ markAvailable(modelId, latencyMs) {
768
+ this.set({
769
+ modelId,
770
+ available: true,
771
+ latencyMs,
772
+ checkedAt: getTimeProvider().now()
773
+ });
774
+ }
775
+ /** Check if a model is known-unavailable (cached and not expired). */
776
+ isKnownUnavailable(modelId) {
777
+ const entry = this.get(modelId);
778
+ return entry !== void 0 && !entry.available;
779
+ }
780
+ /** Get all cached entries (for diagnostics). */
781
+ entries() {
782
+ return [...this.cache.values()];
783
+ }
784
+ /** Number of cached entries. */
785
+ get size() {
786
+ return this.cache.size;
787
+ }
788
+ /** Clear all cached entries. */
789
+ clear() {
790
+ this.cache.clear();
791
+ }
792
+ };
793
+ var FALLBACK_CHAINS = {
794
+ claude: ["claude-opus", "claude-sonnet", "claude-haiku"],
795
+ gemini: ["gemini-3-pro", "gemini-pro", "gemini-3-flash", "gemini-flash"],
796
+ codex: ["codex-5.3", "codex-5.2", "codex-5.1-mini"],
797
+ opencode: ["opencode-custom-opus", "opencode-custom-sonnet", "opencode-default"]
798
+ };
799
+ function resolveFallback(modelId, cache) {
800
+ const cli = getCliForModelId(modelId);
801
+ if (cli === void 0) return null;
802
+ const chain = FALLBACK_CHAINS[cli];
803
+ for (const candidate of chain) {
804
+ if (candidate === modelId) continue;
805
+ if (!cache.isKnownUnavailable(candidate)) {
806
+ return {
807
+ modelId: candidate,
808
+ reason: `Fallback from ${modelId} (unavailable) to ${candidate}`
809
+ };
810
+ }
811
+ }
812
+ return null;
813
+ }
814
+ function getFallbackChain(cli) {
815
+ return FALLBACK_CHAINS[cli];
816
+ }
817
+ function getCliForModelId(modelId) {
818
+ for (const [cli, defaultModel] of Object.entries(DEFAULT_MODEL_PER_CLI)) {
819
+ const chain = FALLBACK_CHAINS[cli];
820
+ if (chain.includes(modelId)) return cli;
821
+ if (defaultModel === modelId) return cli;
822
+ }
823
+ return void 0;
824
+ }
825
+ var globalCache;
826
+ function getAvailabilityCache() {
827
+ globalCache ??= new AvailabilityCache();
828
+ return globalCache;
829
+ }
830
+ function resetAvailabilityCache() {
831
+ globalCache = void 0;
832
+ }
833
+ function filterAvailableModels(modelIds, cache) {
834
+ const available = [];
835
+ const removed = [];
836
+ for (const id of modelIds) {
837
+ if (cache.isKnownUnavailable(id)) {
838
+ removed.push(id);
839
+ } else {
840
+ available.push(id);
841
+ }
842
+ }
843
+ return { available, removed };
844
+ }
845
+
846
+ // src/config/routing-config-adapter.ts
847
+ var ADAPTER_DEFAULTS = {
848
+ latencyScoreWeight: 0.2
849
+ };
850
+ function adaptZeroRouterConfig(yaml2) {
851
+ if (yaml2 === void 0) return {};
852
+ return {
853
+ thresholds: yaml2.thresholds ?? DEFAULT_ZERO_ROUTER_CONFIG.thresholds,
854
+ weights: yaml2.weights ?? DEFAULT_ZERO_ROUTER_CONFIG.weights,
855
+ difficultyToTier: yaml2.difficultyToTier ?? DEFAULT_ZERO_ROUTER_CONFIG.difficultyToTier,
856
+ tierToClis: yaml2.tierToClis ?? DEFAULT_ZERO_ROUTER_CONFIG.tierToClis,
857
+ enableCalibration: yaml2.enableCalibration,
858
+ maxCalibrationOutcomes: yaml2.maxCalibrationOutcomes,
859
+ minCalibrationOutcomes: yaml2.minCalibrationOutcomes,
860
+ verbose: yaml2.verbose
861
+ };
862
+ }
863
+ function adaptLatencyTrackerConfig(yaml2) {
864
+ if (yaml2 === void 0) return {};
865
+ return {
866
+ windowSize: yaml2.windowSize,
867
+ decayFactor: yaml2.decayFactor,
868
+ maxSampleAgeMs: yaml2.maxSampleAgeMs,
869
+ percentiles: yaml2.percentiles
870
+ };
871
+ }
872
+ function adaptRoutingMemoryConfig(yaml2) {
873
+ if (yaml2 === void 0) return {};
874
+ return {
875
+ minObservations: yaml2.minObservations,
876
+ confidenceThreshold: yaml2.confidenceThreshold,
877
+ successRateThreshold: yaml2.successRateThreshold,
878
+ actionCacheMaxAgeMs: yaml2.actionCacheMaxAgeMs
879
+ };
880
+ }
881
+ function adaptStagesConfig(yaml2) {
882
+ if (yaml2 === void 0) return {};
883
+ return {
884
+ enableBudgetFilter: yaml2.budgetFilter,
885
+ enableZeroRouter: yaml2.zeroRouter,
886
+ enablePreferenceRouting: yaml2.preferenceRouting,
887
+ enableTopsisRanking: yaml2.topsisRanking,
888
+ enableLinUCBSelection: yaml2.linucbSelection,
889
+ enableLatencyTracking: yaml2.latencyTracking,
890
+ enableRoutingMemory: yaml2.routingMemory,
891
+ // Issue #755: New replacement stages
892
+ enableConfidenceCascade: yaml2.confidenceCascade,
893
+ enableCapabilityMatch: yaml2.capabilityMatch,
894
+ enableQualityConstraint: yaml2.qualityConstraint,
895
+ // Issue #998: Resource strategy
896
+ enableResourceStrategy: yaml2.resourceStrategy,
897
+ // Issue #999: Strategy distillation
898
+ enableStrategyDistillation: yaml2.strategyDistillation
899
+ };
900
+ }
901
+ var STAGE_FLAG_KEYS = [
902
+ "enableBudgetFilter",
903
+ "enableZeroRouter",
904
+ "enablePreferenceRouting",
905
+ "enableTopsisRanking",
906
+ "enableLinUCBSelection",
907
+ "enableLatencyTracking",
908
+ "enableRoutingMemory",
909
+ "enableConfidenceCascade",
910
+ "enableCapabilityMatch",
911
+ "enableQualityConstraint",
912
+ "enableResourceStrategy",
913
+ "enableStrategyDistillation",
914
+ "enableKnnRouting",
915
+ "enableCapacityBalancing"
916
+ ];
917
+ var PERSISTENCE_AWARE_FLAGS = /* @__PURE__ */ new Set([
918
+ "enableRoutingMemory",
919
+ "enableStrategyDistillation",
920
+ "enablePreferenceRouting"
921
+ ]);
922
+ function resolveStageFlags(stagesConfig) {
923
+ const persistenceOn = isPersistenceEnabled();
924
+ const result = {};
925
+ for (const key of STAGE_FLAG_KEYS) {
926
+ const explicit = stagesConfig[key];
927
+ if (explicit !== void 0) {
928
+ result[key] = explicit;
929
+ } else if (PERSISTENCE_AWARE_FLAGS.has(key) && persistenceOn) {
930
+ result[key] = true;
931
+ } else {
932
+ result[key] = DEFAULT_COMPOSITE_CONFIG[key];
933
+ }
934
+ }
935
+ return result;
936
+ }
937
+ function buildBaseConfig(config, stagesConfig) {
938
+ const stageFlags = resolveStageFlags(stagesConfig);
939
+ return {
940
+ ...stageFlags,
941
+ billingMode: DEFAULT_COMPOSITE_CONFIG.billingMode,
942
+ latencyScoreWeight: config.latencyScoreWeight,
943
+ budgetConstraints: config.budget,
944
+ linucbAlpha: config.linucb?.alpha ?? DEFAULT_COMPOSITE_CONFIG.linucbAlpha,
945
+ maxDecisionTimeMs: config.linucb?.maxDecisionTimeMs ?? DEFAULT_COMPOSITE_CONFIG.maxDecisionTimeMs,
946
+ preferenceMinDataPoints: config.preference?.minDataPoints ?? DEFAULT_COMPOSITE_CONFIG.preferenceMinDataPoints
947
+ };
948
+ }
949
+ function adaptRoutingConfig(yamlConfig) {
950
+ const config = yamlConfig ?? ADAPTER_DEFAULTS;
951
+ const stagesConfig = adaptStagesConfig(config.stages);
952
+ const baseConfig = buildBaseConfig(config, stagesConfig);
953
+ return {
954
+ ...baseConfig,
955
+ zeroRouterConfig: adaptZeroRouterConfig(config.zeroRouter),
956
+ latencyTrackerConfig: adaptLatencyTrackerConfig(config.latencyTracker),
957
+ routingMemoryConfig: adaptRoutingMemoryConfig(config.routingMemory)
958
+ };
959
+ }
960
+
961
+ // src/config/defaults-env.ts
962
+ function parseIntEnv(envKey, fallback) {
963
+ const envValue = process.env[envKey];
964
+ if (envValue === void 0) {
965
+ return fallback;
966
+ }
967
+ const parsed = parseInt(envValue, 10);
968
+ return isNaN(parsed) || parsed <= 0 ? fallback : parsed;
969
+ }
970
+ function parseFloatEnv(envKey, fallback) {
971
+ const envValue = process.env[envKey];
972
+ if (envValue === void 0) {
973
+ return fallback;
974
+ }
975
+ const parsed = parseFloat(envValue);
976
+ return isNaN(parsed) || !isFinite(parsed) ? fallback : parsed;
977
+ }
978
+ function parseBoolEnv(envKey, fallback) {
979
+ const envValue = process.env[envKey]?.toLowerCase();
980
+ if (envValue === void 0) {
981
+ return fallback;
982
+ }
983
+ if (envValue === "true" || envValue === "1") return true;
984
+ if (envValue === "false" || envValue === "0") return false;
985
+ return fallback;
986
+ }
987
+ function createGetTimeout(timeoutDefaults) {
988
+ return (key) => {
989
+ const envKey = `NEXUS_TIMEOUT_${key.replace(/Ms$/, "").toUpperCase()}`;
990
+ return parseIntEnv(envKey, timeoutDefaults[key]);
991
+ };
992
+ }
993
+ function createGetRetryConfig(retryDefaults) {
994
+ return () => {
995
+ return {
996
+ maxRetries: parseIntEnv("NEXUS_RETRY_MAX_RETRIES", retryDefaults.maxRetries),
997
+ baseDelayMs: parseIntEnv("NEXUS_RETRY_BASE_DELAY", retryDefaults.baseDelayMs),
998
+ maxDelayMs: parseIntEnv("NEXUS_RETRY_MAX_DELAY", retryDefaults.maxDelayMs),
999
+ jitterFactor: parseFloatEnv("NEXUS_RETRY_JITTER", retryDefaults.jitterFactor)
1000
+ };
1001
+ };
1002
+ }
1003
+ function createGetRateLimitConfig(rateLimitDefaults) {
1004
+ return () => {
1005
+ return {
1006
+ requestsPerMinute: parseIntEnv("NEXUS_RATE_LIMIT_RPM", rateLimitDefaults.requestsPerMinute),
1007
+ enabled: parseBoolEnv("NEXUS_RATE_LIMIT_ENABLED", rateLimitDefaults.enabled),
1008
+ maxConcurrent: parseIntEnv(
1009
+ "NEXUS_RATE_LIMIT_MAX_CONCURRENT",
1010
+ rateLimitDefaults.maxConcurrent
1011
+ ),
1012
+ capacity: parseIntEnv("NEXUS_RATE_LIMIT_CAPACITY", rateLimitDefaults.capacity),
1013
+ refillRate: parseIntEnv("NEXUS_RATE_LIMIT_REFILL_RATE", rateLimitDefaults.refillRate),
1014
+ refillIntervalMs: parseIntEnv(
1015
+ "NEXUS_RATE_LIMIT_REFILL_INTERVAL",
1016
+ rateLimitDefaults.refillIntervalMs
1017
+ )
1018
+ };
1019
+ };
1020
+ }
1021
+ function createGetWorkerConfig(workerDefaults) {
1022
+ return () => {
1023
+ return {
1024
+ maxWorkers: parseIntEnv("NEXUS_WORKERS_MAX", workerDefaults.maxWorkers),
1025
+ poolSize: parseIntEnv("NEXUS_WORKERS_POOL_SIZE", workerDefaults.poolSize),
1026
+ idleTimeoutMs: parseIntEnv("NEXUS_WORKERS_IDLE_TIMEOUT", workerDefaults.idleTimeoutMs),
1027
+ workflowMaxParallel: parseIntEnv(
1028
+ "NEXUS_WORKFLOW_MAX_PARALLEL",
1029
+ workerDefaults.workflowMaxParallel
1030
+ ),
1031
+ testParallelism: parseIntEnv("NEXUS_TEST_PARALLELISM", workerDefaults.testParallelism),
1032
+ evaluationMaxWorkers: parseIntEnv(
1033
+ "NEXUS_EVALUATION_MAX_WORKERS",
1034
+ workerDefaults.evaluationMaxWorkers
1035
+ ),
1036
+ eventBusMaxHistory: parseIntEnv(
1037
+ "NEXUS_EVENTBUS_MAX_HISTORY",
1038
+ workerDefaults.eventBusMaxHistory
1039
+ ),
1040
+ swarmObserverMaxEvents: parseIntEnv(
1041
+ "NEXUS_SWARM_OBSERVER_MAX_EVENTS",
1042
+ workerDefaults.swarmObserverMaxEvents
1043
+ )
1044
+ };
1045
+ };
1046
+ }
1047
+ function createGetCircuitBreakerConfig(cbDefaults) {
1048
+ return () => {
1049
+ return {
1050
+ failureThreshold: parseIntEnv("NEXUS_CIRCUIT_BREAKER_THRESHOLD", cbDefaults.failureThreshold),
1051
+ resetTimeoutMs: parseIntEnv("NEXUS_CIRCUIT_BREAKER_RESET_TIMEOUT", cbDefaults.resetTimeoutMs),
1052
+ halfOpenSuccessThreshold: cbDefaults.halfOpenSuccessThreshold,
1053
+ countTimeoutsAsFailures: cbDefaults.countTimeoutsAsFailures,
1054
+ countAuthFailuresAsFailures: cbDefaults.countAuthFailuresAsFailures,
1055
+ countRateLimitsAsFailures: cbDefaults.countRateLimitsAsFailures,
1056
+ halfOpenMaxRequests: cbDefaults.halfOpenMaxRequests
1057
+ };
1058
+ };
1059
+ }
1060
+ function createGetToolRateLimit(toolRateLimits) {
1061
+ return (tool) => {
1062
+ return toolRateLimits[tool];
1063
+ };
1064
+ }
1065
+ function createGetEnvVarDocumentation(defaults) {
1066
+ return () => {
1067
+ const t = defaults.TIMEOUT_DEFAULTS;
1068
+ const r = defaults.RATE_LIMIT_DEFAULTS;
1069
+ const rt = defaults.RETRY_DEFAULTS;
1070
+ const w = defaults.WORKER_DEFAULTS;
1071
+ const cb = defaults.CIRCUIT_BREAKER_DEFAULTS;
1072
+ return `# Environment Variable Overrides
1073
+
1074
+ All defaults can be overridden via environment variables using the NEXUS_ prefix.
1075
+
1076
+ ## Timeouts
1077
+
1078
+ | Variable | Default | Description |
1079
+ | -------- | ------- | ----------- |
1080
+ | NEXUS_TIMEOUT_CLI | ${String(t.cliMs)} | CLI execution timeout (ms) |
1081
+ | NEXUS_TIMEOUT_API | ${String(t.apiMs)} | API request timeout (ms) |
1082
+ | NEXUS_TIMEOUT_WORKFLOW | ${String(t.workflowMs)} | Workflow timeout (ms) |
1083
+ | NEXUS_TIMEOUT_MCP | ${String(t.mcpMs)} | MCP operation timeout (ms) |
1084
+
1085
+ ## Rate Limits
1086
+
1087
+ | Variable | Default | Description |
1088
+ | -------- | ------- | ----------- |
1089
+ | NEXUS_RATE_LIMIT_RPM | ${String(r.requestsPerMinute)} | Requests per minute |
1090
+ | NEXUS_RATE_LIMIT_ENABLED | ${String(r.enabled)} | Enable rate limiting |
1091
+ | NEXUS_RATE_LIMIT_CAPACITY | ${String(r.capacity)} | Token bucket capacity |
1092
+
1093
+ ## Retries
1094
+
1095
+ | Variable | Default | Description |
1096
+ | -------- | ------- | ----------- |
1097
+ | NEXUS_RETRY_MAX_RETRIES | ${String(rt.maxRetries)} | Maximum retry attempts |
1098
+ | NEXUS_RETRY_BASE_DELAY | ${String(rt.baseDelayMs)} | Base delay (ms) |
1099
+ | NEXUS_RETRY_MAX_DELAY | ${String(rt.maxDelayMs)} | Maximum delay (ms) |
1100
+ | NEXUS_RETRY_JITTER | ${String(rt.jitterFactor)} | Jitter factor (0-1) |
1101
+
1102
+ ## Workers
1103
+
1104
+ | Variable | Default | Description |
1105
+ | -------- | ------- | ----------- |
1106
+ | NEXUS_WORKERS_MAX | ${String(w.maxWorkers)} | Maximum workers |
1107
+ | NEXUS_WORKERS_POOL_SIZE | ${String(w.poolSize)} | Worker pool size |
1108
+ | NEXUS_WORKFLOW_MAX_PARALLEL | ${String(w.workflowMaxParallel)} | Max parallel workflow steps |
1109
+ | NEXUS_TEST_PARALLELISM | ${String(w.testParallelism)} | Test parallelism |
1110
+
1111
+ ## Circuit Breaker
1112
+
1113
+ | Variable | Default | Description |
1114
+ | -------- | ------- | ----------- |
1115
+ | NEXUS_CIRCUIT_BREAKER_THRESHOLD | ${String(cb.failureThreshold)} | Failure threshold |
1116
+ | NEXUS_CIRCUIT_BREAKER_RESET_TIMEOUT | ${String(cb.resetTimeoutMs)} | Reset timeout (ms) |
1117
+ `;
1118
+ };
1119
+ }
1120
+
1121
+ // src/config/defaults.ts
1122
+ var DEFAULTS = {
1123
+ /**
1124
+ * Default timeout settings in milliseconds.
1125
+ * Values sourced from config/timeouts.ts (Issue #984).
1126
+ */
1127
+ TIMEOUT_DEFAULTS: {
1128
+ /** CLI tool execution timeout in milliseconds. */
1129
+ cliMs: CLI_TIMEOUTS.default.standard,
1130
+ /** Simple CLI task timeout (single function, quick query). */
1131
+ cliSimpleMs: CLI_TIMEOUTS.default.simple,
1132
+ /** Complex CLI task timeout (codebase-wide, deep analysis). */
1133
+ cliComplexMs: CLI_TIMEOUTS.default.complex,
1134
+ /** API request timeout in milliseconds. */
1135
+ apiMs: API_TIMEOUTS.defaultMs,
1136
+ /** Maximum API timeout in milliseconds. */
1137
+ apiMaxMs: API_TIMEOUTS.maxMs,
1138
+ /** Workflow-level timeout in milliseconds (5 minutes). */
1139
+ workflowMs: WORKFLOW_TIMEOUTS.workflowMs,
1140
+ /** Maximum workflow timeout in milliseconds (30 minutes). */
1141
+ workflowMaxMs: WORKFLOW_TIMEOUTS.workflowMaxMs,
1142
+ /** Step-level timeout in milliseconds. */
1143
+ stepMs: INTERNAL_TIMEOUTS.selfEvalMs,
1144
+ /** MCP operation default timeout in milliseconds (generic, not per-tool). */
1145
+ mcpMs: API_TIMEOUTS.defaultMs,
1146
+ /** MCP operation maximum timeout in milliseconds. */
1147
+ mcpMaxMs: MCP_TIMEOUTS.maxMs,
1148
+ /** Health check timeout in milliseconds. */
1149
+ healthCheckMs: INTERNAL_TIMEOUTS.healthCheckMs,
1150
+ /** Global test run timeout in milliseconds (10 minutes). */
1151
+ testGlobalMs: TEST_TIMEOUTS.globalMs,
1152
+ /** Per-task test timeout in milliseconds. */
1153
+ testTaskMs: TEST_TIMEOUTS.taskMs,
1154
+ /** Circuit breaker reset timeout in milliseconds. */
1155
+ circuitBreakerResetMs: INTERNAL_TIMEOUTS.circuitBreakerResetMs
1156
+ },
1157
+ /**
1158
+ * Default rate limit settings for outbound operations.
1159
+ */
1160
+ RATE_LIMIT_DEFAULTS: {
1161
+ /** Global requests per minute. */
1162
+ requestsPerMinute: 60,
1163
+ /** Whether rate limiting is enabled by default. */
1164
+ enabled: true,
1165
+ /** Maximum number of concurrent requests. */
1166
+ maxConcurrent: 4,
1167
+ /** Token bucket capacity. */
1168
+ capacity: 100,
1169
+ /** Token bucket refill rate per second. */
1170
+ refillRate: 10,
1171
+ /** Refill interval in milliseconds. */
1172
+ refillIntervalMs: 100
1173
+ },
1174
+ /**
1175
+ * Per-tool rate limit defaults for MCP tools.
1176
+ * (Source: Issue #274 Phase 2 - per-tool rate limits)
1177
+ */
1178
+ TOOL_RATE_LIMITS: {
1179
+ orchestrate: { capacity: 10, refillRate: 10, refillIntervalMs: 6e4 },
1180
+ delegate: { capacity: 20, refillRate: 20, refillIntervalMs: 6e4 },
1181
+ workflow: { capacity: 5, refillRate: 5, refillIntervalMs: 6e4 },
1182
+ expert: { capacity: 30, refillRate: 30, refillIntervalMs: 6e4 }
1183
+ },
1184
+ /**
1185
+ * Default retry strategy settings for transient failures.
1186
+ */
1187
+ RETRY_DEFAULTS: {
1188
+ /** Maximum retry attempts before failing. */
1189
+ maxRetries: 3,
1190
+ /** Base delay between retries in milliseconds. */
1191
+ baseDelayMs: 1e3,
1192
+ /** Maximum delay between retries in milliseconds. */
1193
+ maxDelayMs: 3e4,
1194
+ /** Jitter factor (0-1) to randomize retry delays. */
1195
+ jitterFactor: 0.1
1196
+ },
1197
+ /**
1198
+ * Workflow-specific retry defaults.
1199
+ */
1200
+ WORKFLOW_RETRY_DEFAULTS: {
1201
+ /** Maximum retry attempts for workflow steps. */
1202
+ maxRetries: 2,
1203
+ /** Base delay for workflow retries in milliseconds. */
1204
+ baseDelayMs: 2e3,
1205
+ /** Maximum delay for workflow retries in milliseconds. */
1206
+ maxDelayMs: 6e4,
1207
+ /** Jitter factor for workflow retries. */
1208
+ jitterFactor: 0.15
1209
+ },
1210
+ /**
1211
+ * CLI-specific retry defaults.
1212
+ */
1213
+ CLI_RETRY_DEFAULTS: {
1214
+ /** Maximum retry attempts for CLI operations. */
1215
+ maxRetries: 2,
1216
+ /** Base delay for CLI retries in milliseconds. */
1217
+ baseDelayMs: 5e3,
1218
+ /** Maximum delay for CLI retries in milliseconds. */
1219
+ maxDelayMs: 6e4,
1220
+ /** Jitter factor for CLI retries. */
1221
+ jitterFactor: 0.2
1222
+ },
1223
+ /**
1224
+ * Test framework retry defaults.
1225
+ */
1226
+ TEST_RETRY_DEFAULTS: {
1227
+ /** Maximum retries per test task. */
1228
+ maxRetries: 2,
1229
+ /** Whether to retry failed tasks by default. */
1230
+ retryFailedTasks: true
1231
+ },
1232
+ /**
1233
+ * Default buffer sizing for batching and chunked processing.
1234
+ */
1235
+ BUFFER_DEFAULTS: {
1236
+ /** Preferred batch size for bulk operations. */
1237
+ batchSize: 100,
1238
+ /** Chunk size for streaming or segmented processing. */
1239
+ chunkSize: 256,
1240
+ /** Maximum items allowed in a buffer. */
1241
+ maxItems: 1e3,
1242
+ /** Maximum memory size in bytes (10 MB). */
1243
+ maxMemoryBytes: 10 * 1024 * 1024,
1244
+ /** Log buffer flush interval in milliseconds. */
1245
+ logFlushIntervalMs: 5e3
1246
+ },
1247
+ /**
1248
+ * Default worker pool sizing.
1249
+ */
1250
+ WORKER_DEFAULTS: {
1251
+ /** Maximum number of workers. */
1252
+ maxWorkers: 8,
1253
+ /** Default worker pool size. */
1254
+ poolSize: 4,
1255
+ /** Worker idle timeout in milliseconds (5 minutes). */
1256
+ idleTimeoutMs: 5 * 6e4,
1257
+ /** Maximum parallel workflow steps. */
1258
+ workflowMaxParallel: 5,
1259
+ /** Test framework parallelism. */
1260
+ testParallelism: 3,
1261
+ /** Evaluation harness max workers. */
1262
+ evaluationMaxWorkers: 8,
1263
+ /** EventBus max history size. */
1264
+ eventBusMaxHistory: 1e3,
1265
+ /** Swarm observer max events. */
1266
+ swarmObserverMaxEvents: 1e4
1267
+ },
1268
+ /**
1269
+ * Default circuit breaker settings.
1270
+ * (Source: Issue #81 - Circuit breaker for CLI failures)
1271
+ */
1272
+ CIRCUIT_BREAKER_DEFAULTS: {
1273
+ /** Failure threshold to open circuit. */
1274
+ failureThreshold: 5,
1275
+ /** Reset timeout in milliseconds. */
1276
+ resetTimeoutMs: 3e4,
1277
+ /** Success threshold to close circuit in half-open state. */
1278
+ halfOpenSuccessThreshold: 2,
1279
+ /** Whether to count timeouts as failures. */
1280
+ countTimeoutsAsFailures: true,
1281
+ /** Whether to count auth failures as failures. */
1282
+ countAuthFailuresAsFailures: false,
1283
+ /** Whether to count rate limit errors as failures (#1529). */
1284
+ countRateLimitsAsFailures: true,
1285
+ /** Maximum requests allowed in half-open state. */
1286
+ halfOpenMaxRequests: 3
1287
+ },
1288
+ /**
1289
+ * Default context/memory settings.
1290
+ */
1291
+ CONTEXT_DEFAULTS: {
1292
+ /** Maximum context tokens. */
1293
+ maxTokens: 1e5,
1294
+ /** Token budget warning threshold (80%). */
1295
+ warningThreshold: 0.8,
1296
+ /** Token budget critical threshold (95%). */
1297
+ criticalThreshold: 0.95,
1298
+ /** Maximum history entries to retain. */
1299
+ maxHistoryEntries: 1e3
1300
+ },
1301
+ /**
1302
+ * Default provider/model settings.
1303
+ */
1304
+ PROVIDER_DEFAULTS: {
1305
+ /** Default timeout for provider API calls in ms. */
1306
+ timeout: 3e4,
1307
+ /** Maximum retries for provider requests. */
1308
+ maxRetries: 3,
1309
+ /** Default model tier. */
1310
+ defaultTier: "balanced",
1311
+ /** Default temperature. */
1312
+ temperatureDefault: 0.3,
1313
+ /** Minimum temperature. */
1314
+ temperatureMin: 0,
1315
+ /** Maximum temperature. */
1316
+ temperatureMax: 1,
1317
+ /** Billing mode: 'plan' (monthly subscription) or 'api' (pay-per-token). Env: NEXUS_BILLING_MODE */
1318
+ billingMode: "plan"
1319
+ },
1320
+ /**
1321
+ * Security-related defaults.
1322
+ */
1323
+ SECURITY_DEFAULTS: {
1324
+ /** Maximum system prompt length in characters. */
1325
+ maxSystemPromptLength: 4e3,
1326
+ /** Default policy execution mode. */
1327
+ policyDefaultMode: "read-only",
1328
+ /** Default policy mode. */
1329
+ policyMode: "enforce",
1330
+ /** Default sandbox mode. */
1331
+ sandboxMode: "policy",
1332
+ /** Whether to fall back to policy mode if container unavailable. */
1333
+ sandboxFallbackToPolicy: true,
1334
+ /** Whether network is enabled in container mode. */
1335
+ sandboxNetworkEnabled: false
1336
+ }
1337
+ };
1338
+ var getTimeout = createGetTimeout(DEFAULTS.TIMEOUT_DEFAULTS);
1339
+ var getRetryConfig = createGetRetryConfig(DEFAULTS.RETRY_DEFAULTS);
1340
+ var getRateLimitConfig = createGetRateLimitConfig(DEFAULTS.RATE_LIMIT_DEFAULTS);
1341
+ var getWorkerConfig = createGetWorkerConfig(DEFAULTS.WORKER_DEFAULTS);
1342
+ var getCircuitBreakerConfig = createGetCircuitBreakerConfig(
1343
+ DEFAULTS.CIRCUIT_BREAKER_DEFAULTS
1344
+ );
1345
+ var getToolRateLimit = createGetToolRateLimit(DEFAULTS.TOOL_RATE_LIMITS);
1346
+ var getEnvVarDocumentation = createGetEnvVarDocumentation(DEFAULTS);
1347
+
1348
+ // src/config/config-manager.ts
1349
+ import { z as z11 } from "zod";
1350
+ var NumericValueSchema = z11.number();
1351
+ var BooleanValueSchema = z11.boolean();
1352
+ var StringValueSchema = z11.string();
1353
+ function validateValue(value, expectedType) {
1354
+ if (typeof expectedType === "number") return NumericValueSchema.safeParse(value).success;
1355
+ if (typeof expectedType === "boolean") return BooleanValueSchema.safeParse(value).success;
1356
+ if (typeof expectedType === "string") return StringValueSchema.safeParse(value).success;
1357
+ return false;
1358
+ }
1359
+ var ENV_VAR_MAP = {
1360
+ "TIMEOUT_DEFAULTS.cliMs": "NEXUS_TIMEOUT_CLI",
1361
+ "TIMEOUT_DEFAULTS.apiMs": "NEXUS_TIMEOUT_API",
1362
+ "TIMEOUT_DEFAULTS.workflowMs": "NEXUS_TIMEOUT_WORKFLOW",
1363
+ "TIMEOUT_DEFAULTS.mcpMs": "NEXUS_TIMEOUT_MCP",
1364
+ "RATE_LIMIT_DEFAULTS.requestsPerMinute": "NEXUS_RATE_LIMIT_RPM",
1365
+ "RATE_LIMIT_DEFAULTS.enabled": "NEXUS_RATE_LIMIT_ENABLED",
1366
+ "RATE_LIMIT_DEFAULTS.maxConcurrent": "NEXUS_RATE_LIMIT_MAX_CONCURRENT",
1367
+ "RATE_LIMIT_DEFAULTS.capacity": "NEXUS_RATE_LIMIT_CAPACITY",
1368
+ "RATE_LIMIT_DEFAULTS.refillRate": "NEXUS_RATE_LIMIT_REFILL_RATE",
1369
+ "RATE_LIMIT_DEFAULTS.refillIntervalMs": "NEXUS_RATE_LIMIT_REFILL_INTERVAL",
1370
+ "RETRY_DEFAULTS.maxRetries": "NEXUS_RETRY_MAX_RETRIES",
1371
+ "RETRY_DEFAULTS.baseDelayMs": "NEXUS_RETRY_BASE_DELAY",
1372
+ "RETRY_DEFAULTS.maxDelayMs": "NEXUS_RETRY_MAX_DELAY",
1373
+ "RETRY_DEFAULTS.jitterFactor": "NEXUS_RETRY_JITTER",
1374
+ "WORKER_DEFAULTS.maxWorkers": "NEXUS_WORKERS_MAX",
1375
+ "WORKER_DEFAULTS.poolSize": "NEXUS_WORKERS_POOL_SIZE",
1376
+ "WORKER_DEFAULTS.idleTimeoutMs": "NEXUS_WORKERS_IDLE_TIMEOUT",
1377
+ "WORKER_DEFAULTS.workflowMaxParallel": "NEXUS_WORKFLOW_MAX_PARALLEL",
1378
+ "WORKER_DEFAULTS.testParallelism": "NEXUS_TEST_PARALLELISM",
1379
+ "WORKER_DEFAULTS.evaluationMaxWorkers": "NEXUS_EVALUATION_MAX_WORKERS",
1380
+ "WORKER_DEFAULTS.eventBusMaxHistory": "NEXUS_EVENTBUS_MAX_HISTORY",
1381
+ "WORKER_DEFAULTS.swarmObserverMaxEvents": "NEXUS_SWARM_OBSERVER_MAX_EVENTS",
1382
+ "CIRCUIT_BREAKER_DEFAULTS.failureThreshold": "NEXUS_CIRCUIT_BREAKER_THRESHOLD",
1383
+ "CIRCUIT_BREAKER_DEFAULTS.resetTimeoutMs": "NEXUS_CIRCUIT_BREAKER_RESET_TIMEOUT"
1384
+ };
1385
+ function parseEnvValue(envValue, defaultValue) {
1386
+ if (typeof defaultValue === "number") {
1387
+ const parsed = Number(envValue);
1388
+ return !isNaN(parsed) && isFinite(parsed) ? parsed : void 0;
1389
+ }
1390
+ if (typeof defaultValue === "boolean") {
1391
+ const lower = envValue.toLowerCase();
1392
+ if (lower === "true" || lower === "1") return true;
1393
+ if (lower === "false" || lower === "0") return false;
1394
+ return void 0;
1395
+ }
1396
+ if (typeof defaultValue === "string") return envValue;
1397
+ return void 0;
1398
+ }
1399
+ var ConfigManager = class _ConfigManager {
1400
+ static instance = null;
1401
+ overrides = /* @__PURE__ */ new Map();
1402
+ constructor() {
1403
+ }
1404
+ /** Gets the singleton instance. */
1405
+ static getInstance() {
1406
+ _ConfigManager.instance ??= new _ConfigManager();
1407
+ return _ConfigManager.instance;
1408
+ }
1409
+ /** Resets the singleton instance (for testing). */
1410
+ static resetInstance() {
1411
+ _ConfigManager.instance = null;
1412
+ }
1413
+ /** Gets the effective value for a configuration key. */
1414
+ get(category, key) {
1415
+ return this.getWithMeta(category, key).value;
1416
+ }
1417
+ /** Gets the effective value with source metadata. */
1418
+ getWithMeta(category, key) {
1419
+ const fullKey = `${category}.${String(key)}`;
1420
+ const defaultValue = DEFAULTS[category][key];
1421
+ const override = this.overrides.get(fullKey);
1422
+ if (override) {
1423
+ return {
1424
+ value: override.value,
1425
+ source: override.source,
1426
+ key: fullKey,
1427
+ isOverride: true,
1428
+ defaultValue
1429
+ };
1430
+ }
1431
+ const envVar = ENV_VAR_MAP[fullKey];
1432
+ if (envVar !== void 0 && envVar.length > 0) {
1433
+ const envValue = process.env[envVar];
1434
+ if (envValue !== void 0) {
1435
+ const parsed = parseEnvValue(envValue, defaultValue);
1436
+ if (parsed !== void 0) {
1437
+ return { value: parsed, source: "env", key: fullKey, isOverride: true, defaultValue };
1438
+ }
1439
+ }
1440
+ }
1441
+ return {
1442
+ value: defaultValue,
1443
+ source: "package",
1444
+ key: fullKey,
1445
+ isOverride: false,
1446
+ defaultValue
1447
+ };
1448
+ }
1449
+ /**
1450
+ * Sets an override for a configuration key.
1451
+ * @throws {Error} If value fails type validation
1452
+ */
1453
+ setOverride(category, key, value, source) {
1454
+ const fullKey = `${category}.${String(key)}`;
1455
+ const defaultValue = DEFAULTS[category][key];
1456
+ if (!validateValue(value, defaultValue)) {
1457
+ throw new Error(
1458
+ `Invalid value type for ${fullKey}: expected ${typeof defaultValue}, got ${typeof value}`
1459
+ );
1460
+ }
1461
+ this.overrides.set(fullKey, { value, source, setAt: new Date(getTimeProvider().now()) });
1462
+ }
1463
+ /** Clears an override. Returns true if it existed. */
1464
+ clearOverride(category, key) {
1465
+ return this.overrides.delete(`${category}.${String(key)}`);
1466
+ }
1467
+ /** Clears all overrides. */
1468
+ clearAllOverrides() {
1469
+ this.overrides.clear();
1470
+ }
1471
+ /** Lists all active overrides. */
1472
+ listOverrides() {
1473
+ return Array.from(this.overrides.entries()).map(([key, override]) => ({
1474
+ key,
1475
+ value: override.value,
1476
+ source: override.source,
1477
+ setAt: override.setAt
1478
+ }));
1479
+ }
1480
+ /** Lists all configuration keys with their effective values. */
1481
+ listAll(categoryFilter) {
1482
+ const categories = categoryFilter ? [categoryFilter] : Object.keys(DEFAULTS);
1483
+ const result = [];
1484
+ for (const category of categories) {
1485
+ for (const key of Object.keys(DEFAULTS[category])) {
1486
+ const fullKey = `${category}.${key}`;
1487
+ const meta = this.getWithMeta(category, key);
1488
+ result.push({
1489
+ category,
1490
+ key,
1491
+ value: meta.value,
1492
+ source: meta.source,
1493
+ envVar: ENV_VAR_MAP[fullKey]
1494
+ });
1495
+ }
1496
+ }
1497
+ return result;
1498
+ }
1499
+ /** Gets the environment variable name for a config key. */
1500
+ getEnvVarName(category, key) {
1501
+ return ENV_VAR_MAP[`${category}.${String(key)}`];
1502
+ }
1503
+ /** Checks if a key has an active override. */
1504
+ hasOverride(category, key) {
1505
+ return this.overrides.has(`${category}.${String(key)}`);
1506
+ }
1507
+ };
1508
+ function getConfigManager() {
1509
+ return ConfigManager.getInstance();
1510
+ }
1511
+
1512
+ // src/config/config-loader.ts
1513
+ import { readFileSync, existsSync } from "fs";
1514
+ import { resolve, join } from "path";
1515
+ import { homedir } from "os";
1516
+ import * as yaml from "yaml";
1517
+ var DEFAULT_CONFIG_FILE = "nexus-agents.yaml";
1518
+ var ALTERNATE_CONFIG_FILE = "nexus-agents.yml";
1519
+ var ConfigLoadError = class extends Error {
1520
+ code;
1521
+ constructor(message, code, cause) {
1522
+ super(message, { cause });
1523
+ this.name = "ConfigLoadError";
1524
+ this.code = code;
1525
+ }
1526
+ };
1527
+ function validatePath(userPath, root) {
1528
+ const resolved = resolveInsideRoot(userPath, root);
1529
+ if (resolved === null) {
1530
+ return err(
1531
+ new ConfigLoadError(
1532
+ `Config path traversal detected: ${userPath} escapes ${root}`,
1533
+ "PATH_TRAVERSAL"
1534
+ )
1535
+ );
1536
+ }
1537
+ return ok(resolved);
1538
+ }
1539
+ function findConfigPath(cwd) {
1540
+ const envPath = process.env["NEXUS_CONFIG_PATH"];
1541
+ if (envPath !== void 0 && envPath !== "") {
1542
+ const validation = validatePath(envPath, cwd);
1543
+ if (validation.ok && existsSync(validation.value)) {
1544
+ return validation.value;
1545
+ }
1546
+ }
1547
+ const yamlPath = resolve(cwd, DEFAULT_CONFIG_FILE);
1548
+ if (existsSync(yamlPath)) {
1549
+ return yamlPath;
1550
+ }
1551
+ const ymlPath = resolve(cwd, ALTERNATE_CONFIG_FILE);
1552
+ if (existsSync(ymlPath)) {
1553
+ return ymlPath;
1554
+ }
1555
+ const globalDir = join(homedir(), ".nexus-agents");
1556
+ const globalYamlPath = join(globalDir, DEFAULT_CONFIG_FILE);
1557
+ if (existsSync(globalYamlPath)) {
1558
+ return globalYamlPath;
1559
+ }
1560
+ const globalYmlPath = join(globalDir, ALTERNATE_CONFIG_FILE);
1561
+ if (existsSync(globalYmlPath)) {
1562
+ return globalYmlPath;
1563
+ }
1564
+ return void 0;
1565
+ }
1566
+ function parseYaml(content) {
1567
+ try {
1568
+ const parsed = yaml.parse(content);
1569
+ return ok(parsed);
1570
+ } catch (error) {
1571
+ const message = error instanceof Error ? error.message : "Unknown YAML parse error";
1572
+ return err(
1573
+ new ConfigLoadError(`YAML parse error: ${message}`, "YAML_PARSE_ERROR", error)
1574
+ );
1575
+ }
1576
+ }
1577
+ function deepMerge(target, source) {
1578
+ const result = { ...target };
1579
+ for (const key of Object.keys(source)) {
1580
+ const sourceValue = source[key];
1581
+ const targetValue = target[key];
1582
+ if (sourceValue !== void 0 && typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) {
1583
+ result[key] = deepMerge(
1584
+ targetValue,
1585
+ sourceValue
1586
+ );
1587
+ } else if (sourceValue !== void 0) {
1588
+ result[key] = sourceValue;
1589
+ }
1590
+ }
1591
+ return result;
1592
+ }
1593
+ function loadDefaultConfig(logger2) {
1594
+ logger2.debug("No config file found, using defaults");
1595
+ const validated = AppConfigSchema.safeParse(defaultConfig);
1596
+ if (!validated.success) {
1597
+ return err(
1598
+ new ConfigLoadError(
1599
+ `Default config validation failed: ${validated.error.message}`,
1600
+ "VALIDATION_ERROR"
1601
+ )
1602
+ );
1603
+ }
1604
+ return ok({
1605
+ config: validated.data,
1606
+ usingDefaults: true,
1607
+ warnings: ["No config file found, using default configuration"]
1608
+ });
1609
+ }
1610
+ function readAndParseConfig(configPath, mergeDefaults, logger2) {
1611
+ let content;
1612
+ try {
1613
+ content = readFileSync(configPath, "utf-8");
1614
+ } catch (error) {
1615
+ const message = error instanceof Error ? error.message : "Unknown error";
1616
+ return err(
1617
+ new ConfigLoadError(
1618
+ `Failed to read config file: ${message}`,
1619
+ "FILE_READ_ERROR",
1620
+ error
1621
+ )
1622
+ );
1623
+ }
1624
+ const parseResult = parseYaml(content);
1625
+ if (!parseResult.ok) return err(parseResult.error);
1626
+ if (mergeDefaults && typeof parseResult.value === "object" && parseResult.value !== null) {
1627
+ logger2.debug("Merged config with defaults");
1628
+ return ok(
1629
+ deepMerge(
1630
+ defaultConfig,
1631
+ parseResult.value
1632
+ )
1633
+ );
1634
+ }
1635
+ return ok(parseResult.value);
1636
+ }
1637
+ function validateConfig(configData, configPath, logger2) {
1638
+ const validation = AppConfigSchema.safeParse(configData);
1639
+ if (!validation.success) {
1640
+ const issues = formatZodIssuesAsArray(validation.error);
1641
+ return err(
1642
+ new ConfigLoadError(`Config validation failed:
1643
+ ${issues.join("\n")}`, "VALIDATION_ERROR")
1644
+ );
1645
+ }
1646
+ logger2.info("Configuration loaded successfully", { configPath });
1647
+ return ok({ config: validation.data, configPath, usingDefaults: false, warnings: [] });
1648
+ }
1649
+ function loadConfig(options = {}) {
1650
+ const { configPath: explicitPath, cwd = process.cwd(), mergeDefaults = true } = options;
1651
+ const logger2 = options.logger ?? createLogger({ component: "ConfigLoader" });
1652
+ let configPath;
1653
+ if (explicitPath !== void 0) {
1654
+ const validation = validatePath(explicitPath, cwd);
1655
+ if (!validation.ok) return err(validation.error);
1656
+ configPath = validation.value;
1657
+ } else {
1658
+ configPath = findConfigPath(cwd);
1659
+ }
1660
+ if (configPath === void 0) return loadDefaultConfig(logger2);
1661
+ const parseResult = readAndParseConfig(configPath, mergeDefaults, logger2);
1662
+ if (!parseResult.ok) return err(parseResult.error);
1663
+ return validateConfig(parseResult.value, configPath, logger2);
1664
+ }
1665
+ var loadedConfig;
1666
+ function getConfig(options) {
1667
+ if (loadedConfig !== void 0) {
1668
+ return loadedConfig;
1669
+ }
1670
+ const result = loadConfig(options);
1671
+ if (!result.ok) {
1672
+ throw result.error;
1673
+ }
1674
+ loadedConfig = result.value;
1675
+ return loadedConfig;
1676
+ }
1677
+
1678
+ // src/cli/setup-data-dir.ts
1679
+ import { mkdirSync, existsSync as existsSync3 } from "fs";
1680
+ import { homedir as homedir3 } from "os";
1681
+ import { join as join3 } from "path";
1682
+
1683
+ // src/cli/doctor.ts
1684
+ import { existsSync as existsSync2, readFileSync as readFileSync2, accessSync, constants as fsConstants } from "fs";
1685
+ import { homedir as homedir2 } from "os";
1686
+ import { join as join2 } from "path";
1687
+
1688
+ // src/mcp/server.ts
1689
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1690
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1691
+
1692
+ // src/mcp/task-store.ts
1693
+ import { InMemoryTaskStore } from "@modelcontextprotocol/sdk/experimental/tasks";
1694
+ var MAX_TASK_TTL_MS = 6e5;
1695
+ var DEFAULT_TASK_TTL_MS = 3e5;
1696
+ var MAX_TASK_CAPACITY = 50;
1697
+ var CLEANUP_INTERVAL_MS = 6e4;
1698
+ var logger = createLogger({ component: "task-store" });
1699
+ var singletonStore;
1700
+ var cleanupTimer;
1701
+ function getTaskStore() {
1702
+ if (singletonStore === void 0) {
1703
+ singletonStore = new InMemoryTaskStore();
1704
+ logger.info("Task store created", { maxCapacity: MAX_TASK_CAPACITY });
1705
+ cleanupTimer = setInterval(() => {
1706
+ evictExcessTasks();
1707
+ }, CLEANUP_INTERVAL_MS);
1708
+ if (typeof cleanupTimer === "object" && "unref" in cleanupTimer) {
1709
+ cleanupTimer.unref();
1710
+ }
1711
+ }
1712
+ return singletonStore;
1713
+ }
1714
+ function clampTaskTtl(requestedTtl) {
1715
+ if (requestedTtl === void 0 || requestedTtl === null) {
1716
+ return DEFAULT_TASK_TTL_MS;
1717
+ }
1718
+ if (requestedTtl > MAX_TASK_TTL_MS) {
1719
+ logger.warn("Task TTL clamped to maximum", {
1720
+ requested: requestedTtl,
1721
+ max: MAX_TASK_TTL_MS
1722
+ });
1723
+ return MAX_TASK_TTL_MS;
1724
+ }
1725
+ return requestedTtl;
1726
+ }
1727
+ function evictExcessTasks() {
1728
+ if (singletonStore === void 0) return;
1729
+ const allTasks = singletonStore.getAllTasks();
1730
+ if (allTasks.length <= MAX_TASK_CAPACITY) return;
1731
+ const sorted = [...allTasks].sort(
1732
+ (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
1733
+ );
1734
+ const evictCount = sorted.length - MAX_TASK_CAPACITY;
1735
+ for (let i = 0; i < evictCount; i++) {
1736
+ const task = sorted[i];
1737
+ if (task === void 0) continue;
1738
+ singletonStore.updateTaskStatus(task.taskId, "cancelled", "Evicted: capacity exceeded").catch((err2) => {
1739
+ logger.debug("Failed to evict task", {
1740
+ taskId: task.taskId,
1741
+ error: String(err2)
1742
+ });
1743
+ });
1744
+ }
1745
+ logger.info("Evicted excess tasks", { evicted: evictCount, total: sorted.length });
1746
+ }
1747
+
1748
+ // src/mcp/server.ts
1749
+ var DEFAULT_SERVER_NAME = "nexus-agents";
1750
+ function createServerError(code, message, error) {
1751
+ const serverError = { code, message };
1752
+ if (error instanceof Error) {
1753
+ serverError.cause = error;
1754
+ }
1755
+ return serverError;
1756
+ }
1757
+ function createServer(config) {
1758
+ const serverName = config?.name ?? DEFAULT_SERVER_NAME;
1759
+ const serverVersion = config?.version ?? VERSION;
1760
+ const logger2 = config?.logger ?? createLogger({ component: "mcp-server" });
1761
+ try {
1762
+ initDataDirectories();
1763
+ logger2.info("Creating MCP server", {
1764
+ name: serverName,
1765
+ version: serverVersion
1766
+ });
1767
+ const server = new McpServer(
1768
+ {
1769
+ name: serverName,
1770
+ version: serverVersion
1771
+ },
1772
+ {
1773
+ capabilities: {
1774
+ logging: {},
1775
+ prompts: {},
1776
+ resources: {},
1777
+ tasks: {}
1778
+ },
1779
+ taskStore: getTaskStore()
1780
+ }
1781
+ );
1782
+ logger2.debug("MCP server created successfully");
1783
+ return ok({ server, logger: logger2 });
1784
+ } catch (error) {
1785
+ const errorMessage = getErrorMessage(error);
1786
+ logger2.error("Failed to create MCP server", error instanceof Error ? error : void 0);
1787
+ return err(
1788
+ createServerError(
1789
+ "SERVER_CREATION_FAILED",
1790
+ `Failed to create MCP server: ${errorMessage}`,
1791
+ error
1792
+ )
1793
+ );
1794
+ }
1795
+ }
1796
+ async function connectTransport(server, transport, logger2) {
1797
+ const log = logger2 ?? createLogger({ component: "mcp-server" });
1798
+ try {
1799
+ log.info("Connecting server to transport");
1800
+ await server.connect(transport);
1801
+ log.debug("Server connected to transport successfully");
1802
+ return ok(void 0);
1803
+ } catch (error) {
1804
+ const errorMessage = getErrorMessage(error);
1805
+ log.error("Failed to connect to transport", error instanceof Error ? error : void 0);
1806
+ return err(
1807
+ createServerError(
1808
+ "SERVER_START_FAILED",
1809
+ `Failed to connect to transport: ${errorMessage}`,
1810
+ error
1811
+ )
1812
+ );
1813
+ }
1814
+ }
1815
+ async function startStdioServer(config) {
1816
+ const serverResult = createServer(config);
1817
+ if (!serverResult.ok) {
1818
+ return serverResult;
1819
+ }
1820
+ const { server, logger: logger2 } = serverResult.value;
1821
+ try {
1822
+ logger2.setDestination?.("stderr");
1823
+ logger2.info("Starting stdio transport");
1824
+ const transport = new StdioServerTransport();
1825
+ const connectResult = await connectTransport(server, transport, logger2);
1826
+ if (!connectResult.ok) {
1827
+ return connectResult;
1828
+ }
1829
+ logger2.info("MCP server running with stdio transport");
1830
+ return ok({ server, logger: logger2 });
1831
+ } catch (error) {
1832
+ const errorMessage = getErrorMessage(error);
1833
+ logger2.error("Failed to start stdio server", error instanceof Error ? error : void 0);
1834
+ return err(
1835
+ createServerError(
1836
+ "SERVER_START_FAILED",
1837
+ `Failed to start stdio server: ${errorMessage}`,
1838
+ error
1839
+ )
1840
+ );
1841
+ }
1842
+ }
1843
+ async function closeServer(server, logger2) {
1844
+ const log = logger2 ?? createLogger({ component: "mcp-server" });
1845
+ try {
1846
+ log.info("Closing MCP server");
1847
+ await server.close();
1848
+ log.info("MCP server closed successfully");
1849
+ return ok(void 0);
1850
+ } catch (error) {
1851
+ const errorMessage = getErrorMessage(error);
1852
+ log.error("Failed to close server", error instanceof Error ? error : void 0);
1853
+ return err(
1854
+ createServerError("SERVER_STOP_FAILED", `Failed to close server: ${errorMessage}`, error)
1855
+ );
1856
+ }
1857
+ }
1858
+
1859
+ // src/cli/doctor-formatting.ts
1860
+ var REQUIRED_NODE_MAJOR = 22;
1861
+ function formatStatus(healthy, warn = false) {
1862
+ if (healthy) return `${colors.green}${symbols.check}${colors.reset}`;
1863
+ if (warn) return `${colors.yellow}${symbols.warn}${colors.reset}`;
1864
+ return `${colors.red}${symbols.cross}${colors.reset}`;
1865
+ }
1866
+ function formatVersionStatus(status) {
1867
+ switch (status) {
1868
+ case "supported":
1869
+ return `${colors.green}supported${colors.reset}`;
1870
+ case "outdated":
1871
+ return `${colors.yellow}outdated${colors.reset}`;
1872
+ case "unsupported":
1873
+ case "breaking":
1874
+ return `${colors.red}${status}${colors.reset}`;
1875
+ default:
1876
+ return status;
1877
+ }
1878
+ }
1879
+ function formatCapacity(capacity) {
1880
+ if (capacity === void 0) return "Unknown";
1881
+ const remaining = 100 - capacity.utilizationPercent;
1882
+ const remainingStr = String(remaining);
1883
+ if (remaining > 80) return `${colors.green}${remainingStr}% remaining${colors.reset}`;
1884
+ if (remaining > 20) return `${colors.yellow}${remainingStr}% remaining${colors.reset}`;
1885
+ return `${colors.red}${remainingStr}% remaining${colors.reset}`;
1886
+ }
1887
+ function printInstalledCliDetails(cli) {
1888
+ writeLine(` Version: ${cli.version} (${formatVersionStatus(cli.versionStatus)})`);
1889
+ const authText = cli.authenticated ? `${colors.green}${cli.authMethod ?? "Authenticated"}${colors.reset}` : `${colors.red}Not authenticated${colors.reset}`;
1890
+ writeLine(` Auth: ${authText}`);
1891
+ if (cli.capacity !== void 0) {
1892
+ writeLine(` Capacity: ${formatCapacity(cli.capacity)}`);
1893
+ }
1894
+ }
1895
+ function printCliResult(cli) {
1896
+ const status = cli.installed && cli.authenticated;
1897
+ const warn = cli.installed && (!cli.authenticated || cli.versionStatus === "outdated");
1898
+ writeLine(
1899
+ `${formatStatus(status, warn)} ${colors.bold}${capitalize(cli.name)} CLI${colors.reset}`
1900
+ );
1901
+ if (cli.installed) {
1902
+ printInstalledCliDetails(cli);
1903
+ } else {
1904
+ const errorText = cli.error ?? "Not installed";
1905
+ writeLine(` ${colors.red}Error: ${errorText}${colors.reset}`);
1906
+ }
1907
+ if (cli.fix !== void 0 && cli.fix !== "") {
1908
+ writeLine(` ${colors.dim}Fix: ${cli.fix}${colors.reset}`);
1909
+ }
1910
+ writeLine("");
1911
+ }
1912
+ function printCapabilities(clis) {
1913
+ const installedClis = clis.filter((c) => c.installed);
1914
+ if (installedClis.length === 0) {
1915
+ writeLine(`${formatStatus(false)} No CLIs installed`);
1916
+ return;
1917
+ }
1918
+ const caps = DEFAULT_CAPABILITIES;
1919
+ const bestReasoning = installedClis.reduce(
1920
+ (best, c) => caps[c.name].reasoning > caps[best.name].reasoning ? c : best
1921
+ );
1922
+ const bestContext = installedClis.reduce(
1923
+ (best, c) => caps[c.name].contextWindow > caps[best.name].contextWindow ? c : best
1924
+ );
1925
+ const bestSpeed = installedClis.reduce(
1926
+ (best, c) => caps[c.name].speed > caps[best.name].speed ? c : best
1927
+ );
1928
+ const contextTokensK = (caps[bestContext.name].contextWindow / 1e3).toFixed(0);
1929
+ writeLine(
1930
+ `${formatStatus(true)} Complex reasoning: ${colors.bold}${capitalize(bestReasoning.name)}${colors.reset}`
1931
+ );
1932
+ writeLine(
1933
+ `${formatStatus(true)} Large context: ${colors.bold}${capitalize(bestContext.name)}${colors.reset} (${contextTokensK}K tokens)`
1934
+ );
1935
+ writeLine(
1936
+ `${formatStatus(true)} Fast execution: ${colors.bold}${capitalize(bestSpeed.name)}${colors.reset}`
1937
+ );
1938
+ }
1939
+ function printNodeVersionCheck(check) {
1940
+ const versionText = check.supported ? `${colors.green}${check.version}${colors.reset}` : `${colors.yellow}${check.version}${colors.reset}`;
1941
+ writeLine(`${formatStatus(check.supported, !check.supported)} Node.js version: ${versionText}`);
1942
+ if (!check.supported) {
1943
+ writeLine(
1944
+ ` ${colors.dim}Warning: Node.js ${String(REQUIRED_NODE_MAJOR)}.x LTS required${colors.reset}`
1945
+ );
1946
+ }
1947
+ }
1948
+ function printApiKeysCheck(keys) {
1949
+ const configuredCount = keys.filter((k) => k.configured).length;
1950
+ const configuredNames = keys.filter((k) => k.configured).map((k) => k.name);
1951
+ const hasAny = configuredCount > 0;
1952
+ writeLine(
1953
+ `${formatStatus(hasAny, !hasAny)} API keys configured: ${String(configuredCount)} of ${String(keys.length)}`
1954
+ );
1955
+ if (hasAny) {
1956
+ writeLine(` ${colors.dim}Keys: ${configuredNames.join(", ")}${colors.reset}`);
1957
+ } else {
1958
+ writeLine(
1959
+ ` ${colors.dim}Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY${colors.reset}`
1960
+ );
1961
+ }
1962
+ }
1963
+ function printConfigFileCheck(check) {
1964
+ if (check.found && check.path !== null) {
1965
+ writeLine(`${formatStatus(true)} Configuration loaded: ${check.path}`);
1966
+ } else {
1967
+ writeLine(`${formatStatus(false, true)} Configuration file: Not found`);
1968
+ writeLine(` ${colors.dim}Run: nexus-agents config init${colors.reset}`);
1969
+ }
1970
+ }
1971
+ function printRegistryAdvisory(advisory) {
1972
+ const allAvailable = advisory.unavailableModels === 0;
1973
+ const countText = `${String(advisory.availableModels)} of ${String(advisory.totalModels)}`;
1974
+ writeLine(`${formatStatus(allAvailable, !allAvailable)} Models available: ${countText}`);
1975
+ if (advisory.unavailableModels > 0) {
1976
+ const missing = advisory.models.filter((m) => !m.available);
1977
+ for (const m of missing) {
1978
+ writeLine(` ${colors.dim}${m.displayName} \u2014 ${m.reason}${colors.reset}`);
1979
+ }
1980
+ }
1981
+ const ageText = `${String(advisory.registryAgeDays)} days old`;
1982
+ if (advisory.registryStale) {
1983
+ writeLine(
1984
+ `${colors.yellow}${symbols.warn}${colors.reset} Model registry is ${ageText} \u2014 may have stale model data`
1985
+ );
1986
+ writeLine(` ${colors.dim}Run: npx tsx scripts/probe-models.ts${colors.reset}`);
1987
+ } else {
1988
+ writeLine(`${formatStatus(true)} Model registry: ${ageText}`);
1989
+ }
1990
+ }
1991
+ function printLearningPersistence(check) {
1992
+ if (!check.enabled) {
1993
+ writeLine(`${formatStatus(true)} Learning persistence: ${colors.dim}Disabled${colors.reset}`);
1994
+ writeLine(` ${colors.dim}Set NEXUS_PERSIST_LEARNING=true to enable${colors.reset}`);
1995
+ return;
1996
+ }
1997
+ const healthy = check.dirExists && check.dirWritable && check.error === null;
1998
+ writeLine(`${formatStatus(healthy, !healthy)} Learning persistence: Enabled`);
1999
+ if (check.error !== null) {
2000
+ writeLine(` ${colors.red}Error: ${check.error}${colors.reset}`);
2001
+ return;
2002
+ }
2003
+ const dirStatus = check.dirExists ? check.dirWritable ? `${colors.green}writable${colors.reset}` : `${colors.red}not writable${colors.reset}` : `${colors.yellow}not created yet${colors.reset}`;
2004
+ writeLine(` Data directory: ${dirStatus}`);
2005
+ writeLine(` Outcomes: ${String(check.outcomeCount)} recorded`);
2006
+ writeLine(` Distilled rules: ${String(check.ruleCount)} active`);
2007
+ if (check.rulesLastSaved !== null) {
2008
+ writeLine(` Rules last saved: ${check.rulesLastSaved}`);
2009
+ }
2010
+ }
2011
+ function printSqliteCheck(check) {
2012
+ if (check.available) {
2013
+ writeLine(
2014
+ `${formatStatus(true)} SQLite (better-sqlite3): ${colors.green}Available${colors.reset}`
2015
+ );
2016
+ } else {
2017
+ writeLine(
2018
+ `${formatStatus(false, true)} SQLite (better-sqlite3): ${colors.yellow}Not available${colors.reset}`
2019
+ );
2020
+ writeLine(
2021
+ ` ${colors.dim}Memory backends (agentic, adaptive, typed) require it${colors.reset}`
2022
+ );
2023
+ writeLine(` ${colors.dim}Fix: npm install -g better-sqlite3${colors.reset}`);
2024
+ }
2025
+ }
2026
+ function printDataDirectory(check) {
2027
+ if (check.rootExists) {
2028
+ const existCount = check.subdirectories.filter((d) => d.exists).length;
2029
+ const totalCount = check.subdirectories.length;
2030
+ const allExist = existCount === totalCount;
2031
+ const allWritable = check.subdirectories.every((d) => !d.exists || d.writable);
2032
+ const healthy = allExist && allWritable;
2033
+ writeLine(
2034
+ `${formatStatus(healthy, !healthy)} Data directory: ${check.rootPath} (${String(existCount)}/${String(totalCount)} subdirs)`
2035
+ );
2036
+ if (!allExist) {
2037
+ const missing = check.subdirectories.filter((d) => !d.exists);
2038
+ for (const dir of missing) {
2039
+ writeLine(` ${colors.dim}Missing: ${dir.name}/${colors.reset}`);
2040
+ }
2041
+ writeLine(` ${colors.dim}Fix: nexus-agents setup${colors.reset}`);
2042
+ }
2043
+ if (!allWritable) {
2044
+ const readonly_ = check.subdirectories.filter((d) => d.exists && !d.writable);
2045
+ for (const dir of readonly_) {
2046
+ writeLine(` ${colors.yellow}Not writable: ${dir.name}/${colors.reset}`);
2047
+ }
2048
+ }
2049
+ } else {
2050
+ writeLine(
2051
+ `${formatStatus(false, true)} Data directory: ${colors.yellow}Not created${colors.reset}`
2052
+ );
2053
+ writeLine(` ${colors.dim}Run: nexus-agents setup${colors.reset}`);
2054
+ }
2055
+ }
2056
+ function printDoctorSummary(result) {
2057
+ const unhealthyCount = result.clis.filter((c) => !c.installed || !c.authenticated).length;
2058
+ const nodeIssue = result.nodeVersion.supported ? 0 : 1;
2059
+ const totalIssues = unhealthyCount + nodeIssue + (result.mcpServerReady ? 0 : 1);
2060
+ const summary = result.allHealthy ? `${colors.green}${colors.bold}Status: Ready${colors.reset}` : `${colors.yellow}${colors.bold}Summary: ${String(totalIssues)} issue(s) found${colors.reset}`;
2061
+ writeLine(summary);
2062
+ writeLine("");
2063
+ }
2064
+ function printDoctorResults(result) {
2065
+ writeLine("");
2066
+ writeLine(`${colors.bold}Nexus Agents Doctor${colors.reset}`);
2067
+ writeLine("===================");
2068
+ writeLine("");
2069
+ writeLine(`${colors.cyan}Checking environment...${colors.reset}`);
2070
+ writeLine("");
2071
+ printNodeVersionCheck(result.nodeVersion);
2072
+ printApiKeysCheck(result.apiKeys);
2073
+ printConfigFileCheck(result.configFile);
2074
+ writeLine("");
2075
+ writeLine(`${colors.cyan}Checking CLI installations...${colors.reset}`);
2076
+ writeLine("");
2077
+ for (const cli of result.clis) {
2078
+ printCliResult(cli);
2079
+ }
2080
+ writeLine(`${colors.cyan}Checking MCP configuration...${colors.reset}`);
2081
+ writeLine("");
2082
+ writeLine(
2083
+ `${formatStatus(result.mcpServerReady)} MCP Server mode: ${result.mcpServerReady ? "Ready" : "Not ready"}`
2084
+ );
2085
+ writeLine(
2086
+ `${formatStatus(result.mcpClientReady)} MCP Client mode: ${result.mcpClientReady ? "Ready (Codex mcp-server)" : "Not ready (Codex not installed)"}`
2087
+ );
2088
+ writeLine("");
2089
+ writeLine(`${colors.cyan}Checking capabilities...${colors.reset}`);
2090
+ writeLine("");
2091
+ printCapabilities(result.clis);
2092
+ writeLine("");
2093
+ writeLine(`${colors.cyan}Checking model registry...${colors.reset}`);
2094
+ writeLine("");
2095
+ printRegistryAdvisory(result.registryAdvisory);
2096
+ writeLine("");
2097
+ writeLine(`${colors.cyan}Checking learning subsystem...${colors.reset}`);
2098
+ writeLine("");
2099
+ printLearningPersistence(result.learningPersistence);
2100
+ writeLine("");
2101
+ writeLine(`${colors.cyan}Checking data storage...${colors.reset}`);
2102
+ writeLine("");
2103
+ printSqliteCheck(result.sqliteCheck);
2104
+ printDataDirectory(result.dataDirectory);
2105
+ writeLine("");
2106
+ printDoctorSummary(result);
2107
+ }
2108
+
2109
+ // src/cli/doctor.ts
2110
+ var REQUIRED_NODE_MAJOR2 = 22;
2111
+ var API_KEY_VARS = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GOOGLE_AI_API_KEY"];
2112
+ var CONFIG_FILE_PATHS = ["./nexus-agents.yaml", "./nexus-agents.yml"];
2113
+ var DATA_SUBDIRECTORIES = [
2114
+ "memory",
2115
+ "memory/beliefs",
2116
+ "learning",
2117
+ "sessions",
2118
+ "audit",
2119
+ "voting",
2120
+ "auth",
2121
+ "research",
2122
+ "checkpoints"
2123
+ ];
2124
+ function getFixCommand(name, issue) {
2125
+ const commands = {
2126
+ claude: {
2127
+ install: "npm install -g @anthropic-ai/claude-code",
2128
+ upgrade: "npm update -g @anthropic-ai/claude-code",
2129
+ auth: "claude auth login"
2130
+ },
2131
+ gemini: {
2132
+ install: "npm install -g @google/gemini-cli",
2133
+ upgrade: "npm update -g @google/gemini-cli",
2134
+ auth: "gemini auth login"
2135
+ },
2136
+ codex: {
2137
+ install: "npm install -g @openai/codex",
2138
+ upgrade: "npm update -g @openai/codex",
2139
+ auth: "codex auth login"
2140
+ },
2141
+ opencode: {
2142
+ install: "npm install -g opencode-ai",
2143
+ upgrade: "npm update -g opencode-ai",
2144
+ auth: "opencode auth login"
2145
+ }
2146
+ };
2147
+ return commands[name][issue] ?? "";
2148
+ }
2149
+ function createNotFoundResult(name, errorMsg) {
2150
+ return {
2151
+ name,
2152
+ installed: false,
2153
+ version: "N/A",
2154
+ versionStatus: "unsupported",
2155
+ authenticated: false,
2156
+ error: errorMsg,
2157
+ fix: getFixCommand(name, "install")
2158
+ };
2159
+ }
2160
+ function detectAuthMethod(name) {
2161
+ const authMethods = {
2162
+ claude: "CLI auth",
2163
+ gemini: "ADC/CLI auth",
2164
+ codex: "CLI auth",
2165
+ opencode: "CLI auth"
2166
+ };
2167
+ return authMethods[name];
2168
+ }
2169
+ function createHealthyResult(name, health, capacity) {
2170
+ const authenticated = health.healthy;
2171
+ const result = {
2172
+ name,
2173
+ installed: true,
2174
+ version: health.version,
2175
+ versionStatus: health.versionStatus,
2176
+ authenticated,
2177
+ ...authenticated && { authMethod: detectAuthMethod(name) },
2178
+ ...capacity !== void 0 && { capacity }
2179
+ };
2180
+ if (health.message !== void 0 && health.message !== "") {
2181
+ return { ...result, error: health.message };
2182
+ }
2183
+ if (!authenticated) {
2184
+ return { ...result, fix: getFixCommand(name, "auth") };
2185
+ }
2186
+ if (health.versionStatus === "outdated") {
2187
+ return { ...result, fix: getFixCommand(name, "upgrade") };
2188
+ }
2189
+ return result;
2190
+ }
2191
+ async function checkCli(name) {
2192
+ const adapters = createAllAdapters();
2193
+ const adapter = adapters.get(name);
2194
+ if (!adapter) {
2195
+ return createNotFoundResult(name, "Adapter not available");
2196
+ }
2197
+ try {
2198
+ const health = await adapter.healthCheck();
2199
+ let capacity;
2200
+ try {
2201
+ capacity = await adapter.getCapacity();
2202
+ } catch (capErr) {
2203
+ void capErr;
2204
+ }
2205
+ return createHealthyResult(name, health, capacity);
2206
+ } catch (error) {
2207
+ const message = getErrorMessage(error);
2208
+ const isNotFound = message.includes("ENOENT") || message.includes("not found");
2209
+ return createNotFoundResult(name, isNotFound ? "Not found in PATH" : message);
2210
+ }
2211
+ }
2212
+ function checkNodeVersion() {
2213
+ const version = process.version;
2214
+ const major = Number(version.slice(1).split(".")[0]);
2215
+ return {
2216
+ version,
2217
+ major,
2218
+ supported: major >= REQUIRED_NODE_MAJOR2
2219
+ };
2220
+ }
2221
+ function checkApiKeys() {
2222
+ return API_KEY_VARS.map((name) => ({
2223
+ name,
2224
+ configured: typeof process.env[name] === "string" && process.env[name] !== ""
2225
+ }));
2226
+ }
2227
+ function checkConfigFile() {
2228
+ for (const configPath of CONFIG_FILE_PATHS) {
2229
+ if (existsSync2(configPath)) {
2230
+ return { found: true, path: configPath };
2231
+ }
2232
+ }
2233
+ return { found: false, path: null };
2234
+ }
2235
+ function checkMcpServerReady() {
2236
+ try {
2237
+ const result = createServer({ name: "nexus-agents-doctor-check" });
2238
+ return result.ok;
2239
+ } catch {
2240
+ return false;
2241
+ }
2242
+ }
2243
+ function buildRegistryAdvisory(cliResults) {
2244
+ const installedClis = new Set(cliResults.filter((c) => c.installed).map((c) => c.name));
2245
+ const models = DEFAULT_MODEL_CAPABILITIES.models.filter((m) => m.cliName !== void 0).map((m) => {
2246
+ const cliName = m.cliName ?? "";
2247
+ const available = cliName.length > 0 && installedClis.has(cliName);
2248
+ const reason = available ? `${cliName} CLI is installed` : `${cliName} CLI is not installed`;
2249
+ return { modelId: m.id, displayName: m.displayName, cliName, available, reason };
2250
+ });
2251
+ const STALE_THRESHOLD_DAYS = 30;
2252
+ const updatedAt = new Date(DEFAULT_MODEL_CAPABILITIES.updatedAt);
2253
+ const nowMs = getTimeProvider().now();
2254
+ const ageDays = Math.floor((nowMs - updatedAt.getTime()) / (1e3 * 60 * 60 * 24));
2255
+ return {
2256
+ totalModels: models.length,
2257
+ availableModels: models.filter((m) => m.available).length,
2258
+ unavailableModels: models.filter((m) => !m.available).length,
2259
+ models,
2260
+ registryAgeDays: ageDays,
2261
+ registryStale: ageDays > STALE_THRESHOLD_DAYS
2262
+ };
2263
+ }
2264
+ function countJsonlLines(filePath) {
2265
+ if (!existsSync2(filePath)) return 0;
2266
+ return readFileSync2(filePath, "utf-8").split("\n").filter((l) => l.trim().length > 0).length;
2267
+ }
2268
+ function readRulesMetadata(filePath) {
2269
+ if (!existsSync2(filePath)) return { count: 0, savedAt: null };
2270
+ try {
2271
+ const raw = JSON.parse(readFileSync2(filePath, "utf-8"));
2272
+ const rules = raw["rules"];
2273
+ const saved = raw["savedAt"];
2274
+ return {
2275
+ count: Array.isArray(rules) ? rules.length : 0,
2276
+ savedAt: typeof saved === "string" ? saved : null
2277
+ };
2278
+ } catch {
2279
+ return { count: 0, savedAt: null };
2280
+ }
2281
+ }
2282
+ function checkDirAccess(dir) {
2283
+ const exists = existsSync2(dir);
2284
+ if (!exists) return { exists: false, writable: false };
2285
+ try {
2286
+ accessSync(dir, fsConstants.W_OK);
2287
+ return { exists: true, writable: true };
2288
+ } catch {
2289
+ return { exists: true, writable: false };
2290
+ }
2291
+ }
2292
+ var DISABLED_CHECK = {
2293
+ enabled: false,
2294
+ dirExists: false,
2295
+ dirWritable: false,
2296
+ outcomeCount: 0,
2297
+ ruleCount: 0,
2298
+ rulesLastSaved: null,
2299
+ error: null
2300
+ };
2301
+ function checkLearningPersistence() {
2302
+ if (!isPersistenceEnabled()) return DISABLED_CHECK;
2303
+ try {
2304
+ const { exists: dirExists, writable: dirWritable } = checkDirAccess(LEARNING_DIR);
2305
+ const outcomeCount = countJsonlLines(OUTCOMES_FILE);
2306
+ const { count: ruleCount, savedAt: rulesLastSaved } = readRulesMetadata(RULES_FILE);
2307
+ return {
2308
+ enabled: true,
2309
+ dirExists,
2310
+ dirWritable,
2311
+ outcomeCount,
2312
+ ruleCount,
2313
+ rulesLastSaved,
2314
+ error: null
2315
+ };
2316
+ } catch (error) {
2317
+ return {
2318
+ enabled: true,
2319
+ dirExists: false,
2320
+ dirWritable: false,
2321
+ outcomeCount: 0,
2322
+ ruleCount: 0,
2323
+ rulesLastSaved: null,
2324
+ error: getErrorMessage(error)
2325
+ };
2326
+ }
2327
+ }
2328
+ async function checkSqlite() {
2329
+ try {
2330
+ await import("better-sqlite3");
2331
+ return { available: true, error: null };
2332
+ } catch (error) {
2333
+ const msg = getErrorMessage(error);
2334
+ const isNotFound = msg.includes("Cannot find") || msg.includes("MODULE_NOT_FOUND");
2335
+ return {
2336
+ available: false,
2337
+ error: isNotFound ? "better-sqlite3 not installed \u2014 5 memory backends unavailable" : `better-sqlite3 load error: ${msg}`
2338
+ };
2339
+ }
2340
+ }
2341
+ function checkDataDirectory() {
2342
+ const rootPath = join2(homedir2(), ".nexus-agents");
2343
+ const rootExists = existsSync2(rootPath);
2344
+ const subdirectories = DATA_SUBDIRECTORIES.map((name) => {
2345
+ const fullPath = join2(rootPath, name);
2346
+ const exists = existsSync2(fullPath);
2347
+ return { name, path: fullPath, exists, writable: exists && isWritable(fullPath) };
2348
+ });
2349
+ return { rootExists, rootPath, subdirectories };
2350
+ }
2351
+ function isWritable(dirPath) {
2352
+ try {
2353
+ accessSync(dirPath, fsConstants.W_OK);
2354
+ return true;
2355
+ } catch {
2356
+ return false;
2357
+ }
2358
+ }
2359
+ async function runDoctor() {
2360
+ const clis = await Promise.all([
2361
+ checkCli("claude"),
2362
+ checkCli("gemini"),
2363
+ checkCli("codex"),
2364
+ checkCli("opencode")
2365
+ ]);
2366
+ const nodeVersion = checkNodeVersion();
2367
+ const apiKeys = checkApiKeys();
2368
+ const configFile = checkConfigFile();
2369
+ const mcpServerReady = checkMcpServerReady();
2370
+ const codexCheck = clis.find((c) => c.name === "codex");
2371
+ const mcpClientReady = codexCheck?.installed ?? false;
2372
+ const registryAdvisory = buildRegistryAdvisory(clis);
2373
+ const learningPersistence = checkLearningPersistence();
2374
+ const sqliteCheck = await checkSqlite();
2375
+ const dataDirectory = checkDataDirectory();
2376
+ const hasAuthMethod = apiKeys.some((k) => k.configured) || clis.some((c) => c.installed && c.authenticated);
2377
+ const allHealthy = nodeVersion.supported && hasAuthMethod && mcpServerReady && clis.every((c) => c.installed && c.authenticated && c.versionStatus !== "unsupported");
2378
+ return {
2379
+ clis,
2380
+ nodeVersion,
2381
+ apiKeys,
2382
+ configFile,
2383
+ mcpServerReady,
2384
+ mcpClientReady,
2385
+ registryAdvisory,
2386
+ learningPersistence,
2387
+ sqliteCheck,
2388
+ dataDirectory,
2389
+ allHealthy,
2390
+ timestamp: new Date(getTimeProvider().now())
2391
+ };
2392
+ }
2393
+ async function doctorCommand(options = {}) {
2394
+ const result = await runDoctor();
2395
+ printDoctorResults(result);
2396
+ if (options.fix === true) {
2397
+ await runDoctorFix(result);
2398
+ }
2399
+ return result.allHealthy ? 0 : 1;
2400
+ }
2401
+ async function runDoctorFix(result) {
2402
+ const writeLine2 = (text) => {
2403
+ process.stdout.write(text + "\n");
2404
+ };
2405
+ writeLine2("");
2406
+ writeLine2("\x1B[1mAuto-fix\x1B[0m");
2407
+ writeLine2("\u2500".repeat(40));
2408
+ let fixCount = 0;
2409
+ if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
2410
+ const { runSetup } = await import("./setup-command-AV4MODEL.js");
2411
+ const setupResult = runSetup({
2412
+ skipMcp: true,
2413
+ skipRules: true,
2414
+ skipHooks: true,
2415
+ skipConfig: true,
2416
+ skipOpencode: true
2417
+ });
2418
+ if (setupResult.success) {
2419
+ writeLine2("\u2713 Created missing data directories");
2420
+ fixCount++;
2421
+ }
2422
+ }
2423
+ if (!result.configFile.found) {
2424
+ const { runConfigInitSync } = await import("./setup-config-PWK6WHMG.js");
2425
+ const configResult = runConfigInitSync(process.cwd(), false, false);
2426
+ if (configResult.success && configResult.created) {
2427
+ writeLine2(`\u2713 Generated config: ${configResult.path}`);
2428
+ fixCount++;
2429
+ }
2430
+ }
2431
+ if (!result.sqliteCheck.available) {
2432
+ writeLine2("");
2433
+ writeLine2("\u26A0 better-sqlite3 not installed (manual step required):");
2434
+ writeLine2(" npm install -g better-sqlite3");
2435
+ }
2436
+ if (fixCount > 0) {
2437
+ writeLine2("");
2438
+ writeLine2(
2439
+ `\x1B[32m${String(fixCount)} issue(s) fixed.\x1B[0m Re-run \x1B[1mnexus-agents doctor\x1B[0m to verify.`
2440
+ );
2441
+ } else {
2442
+ writeLine2("No auto-fixable issues found.");
2443
+ }
2444
+ writeLine2("");
2445
+ }
2446
+
2447
+ // src/cli/setup-data-dir.ts
2448
+ var NEXUS_DATA_DIR = join3(homedir3(), ".nexus-agents");
2449
+ var RESTRICTED_DIRS = /* @__PURE__ */ new Set(["auth"]);
2450
+ function initDataDirectories(dryRun = false) {
2451
+ const created = [];
2452
+ const alreadyExisted = [];
2453
+ try {
2454
+ ensureDir(NEXUS_DATA_DIR, dryRun, created, alreadyExisted);
2455
+ for (const subdir of DATA_SUBDIRECTORIES) {
2456
+ const mode = RESTRICTED_DIRS.has(subdir) ? 448 : void 0;
2457
+ ensureDir(join3(NEXUS_DATA_DIR, subdir), dryRun, created, alreadyExisted, mode);
2458
+ }
2459
+ return { success: true, rootPath: NEXUS_DATA_DIR, created, alreadyExisted, error: null };
2460
+ } catch (error) {
2461
+ const msg = error instanceof Error ? error.message : String(error);
2462
+ return { success: false, rootPath: NEXUS_DATA_DIR, created, alreadyExisted, error: msg };
2463
+ }
2464
+ }
2465
+ function ensureDir(dirPath, dryRun, created, alreadyExisted, mode) {
2466
+ if (existsSync3(dirPath)) {
2467
+ alreadyExisted.push(dirPath);
2468
+ return;
2469
+ }
2470
+ if (!dryRun) {
2471
+ mkdirSync(dirPath, { recursive: true, ...mode !== void 0 ? { mode } : {} });
2472
+ }
2473
+ created.push(dirPath);
2474
+ }
2475
+
2476
+ export {
2477
+ VERSION,
2478
+ LoggingConfigSchema,
2479
+ ProviderConfigSchema,
2480
+ ModelTiersSchema,
2481
+ ModelConfigSchema,
2482
+ WorkflowConfigSchema,
2483
+ VALID_EXPERT_TIERS,
2484
+ VALID_EXPERT_DOMAINS,
2485
+ MAX_SYSTEM_PROMPT_LENGTH,
2486
+ CustomExpertDefinitionSchema,
2487
+ ExpertDefinitionSchema,
2488
+ ExpertConfigSchema,
2489
+ DEFAULT_TOOL_RATE_LIMITS,
2490
+ SecurityConfigSchema,
2491
+ AppConfigSchema,
2492
+ defaultConfig,
2493
+ adaptRoutingConfig,
2494
+ DEFAULTS,
2495
+ getConfigManager,
2496
+ loadConfig,
2497
+ getConfig,
2498
+ validateNexusEnv,
2499
+ getKnownNexusVarNames,
2500
+ AvailabilityCache,
2501
+ resolveFallback,
2502
+ getFallbackChain,
2503
+ getCliForModelId,
2504
+ getAvailabilityCache,
2505
+ resetAvailabilityCache,
2506
+ filterAvailableModels,
2507
+ DEFAULT_TASK_TTL_MS,
2508
+ clampTaskTtl,
2509
+ checkApiKeys,
2510
+ checkSqlite,
2511
+ checkDataDirectory,
2512
+ runDoctor,
2513
+ doctorCommand,
2514
+ initDataDirectories,
2515
+ createServer,
2516
+ connectTransport,
2517
+ startStdioServer,
2518
+ closeServer
2519
+ };
2520
+ //# sourceMappingURL=chunk-C3FGEDD7.js.map