@juspay/neurolink 9.41.0 → 9.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +7 -1
- package/dist/auth/anthropicOAuth.d.ts +18 -3
- package/dist/auth/anthropicOAuth.js +137 -4
- package/dist/auth/providers/firebase.js +5 -1
- package/dist/auth/providers/jwt.js +5 -1
- package/dist/auth/providers/workos.js +5 -1
- package/dist/auth/sessionManager.d.ts +1 -1
- package/dist/auth/sessionManager.js +58 -27
- package/dist/browser/neurolink.min.js +337 -318
- package/dist/cli/commands/mcp.js +3 -0
- package/dist/cli/commands/proxy.d.ts +2 -1
- package/dist/cli/commands/proxy.js +279 -16
- package/dist/cli/commands/task.js +3 -0
- package/dist/cli/factories/commandFactory.d.ts +2 -0
- package/dist/cli/factories/commandFactory.js +38 -0
- package/dist/cli/parser.js +4 -3
- package/dist/client/aiSdkAdapter.js +3 -0
- package/dist/client/streamingClient.js +30 -10
- package/dist/core/modules/GenerationHandler.js +3 -2
- package/dist/core/redisConversationMemoryManager.js +7 -3
- package/dist/evaluation/BatchEvaluator.js +4 -1
- package/dist/evaluation/hooks/observabilityHooks.js +5 -3
- package/dist/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
- package/dist/evaluation/pipeline/evaluationPipeline.js +20 -8
- package/dist/evaluation/pipeline/strategies/batchStrategy.js +6 -3
- package/dist/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
- package/dist/lib/auth/anthropicOAuth.d.ts +18 -3
- package/dist/lib/auth/anthropicOAuth.js +137 -4
- package/dist/lib/auth/providers/firebase.js +5 -1
- package/dist/lib/auth/providers/jwt.js +5 -1
- package/dist/lib/auth/providers/workos.js +5 -1
- package/dist/lib/auth/sessionManager.d.ts +1 -1
- package/dist/lib/auth/sessionManager.js +58 -27
- package/dist/lib/client/aiSdkAdapter.js +3 -0
- package/dist/lib/client/streamingClient.js +30 -10
- package/dist/lib/core/modules/GenerationHandler.js +3 -2
- package/dist/lib/core/redisConversationMemoryManager.js +7 -3
- package/dist/lib/evaluation/BatchEvaluator.js +4 -1
- package/dist/lib/evaluation/hooks/observabilityHooks.js +5 -3
- package/dist/lib/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
- package/dist/lib/evaluation/pipeline/evaluationPipeline.js +20 -8
- package/dist/lib/evaluation/pipeline/strategies/batchStrategy.js +6 -3
- package/dist/lib/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
- package/dist/lib/neurolink.d.ts +3 -2
- package/dist/lib/neurolink.js +260 -494
- package/dist/lib/observability/otelBridge.d.ts +2 -2
- package/dist/lib/observability/otelBridge.js +12 -3
- package/dist/lib/providers/amazonBedrock.js +2 -4
- package/dist/lib/providers/anthropic.d.ts +9 -5
- package/dist/lib/providers/anthropic.js +19 -14
- package/dist/lib/providers/anthropicBaseProvider.d.ts +3 -3
- package/dist/lib/providers/anthropicBaseProvider.js +5 -4
- package/dist/lib/providers/azureOpenai.d.ts +1 -1
- package/dist/lib/providers/azureOpenai.js +5 -4
- package/dist/lib/providers/googleAiStudio.js +30 -1
- package/dist/lib/providers/googleVertex.js +28 -6
- package/dist/lib/providers/huggingFace.d.ts +3 -3
- package/dist/lib/providers/huggingFace.js +6 -8
- package/dist/lib/providers/litellm.js +41 -29
- package/dist/lib/providers/mistral.js +2 -1
- package/dist/lib/providers/ollama.js +80 -23
- package/dist/lib/providers/openAI.js +3 -2
- package/dist/lib/providers/openRouter.js +2 -1
- package/dist/lib/providers/openaiCompatible.d.ts +4 -4
- package/dist/lib/providers/openaiCompatible.js +4 -4
- package/dist/lib/proxy/claudeFormat.d.ts +3 -2
- package/dist/lib/proxy/claudeFormat.js +25 -20
- package/dist/lib/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
- package/dist/lib/proxy/cloaking/plugins/sessionIdentity.js +9 -33
- package/dist/lib/proxy/modelRouter.js +3 -0
- package/dist/lib/proxy/oauthFetch.d.ts +1 -1
- package/dist/lib/proxy/oauthFetch.js +65 -72
- package/dist/lib/proxy/proxyConfig.js +44 -24
- package/dist/lib/proxy/proxyEnv.d.ts +19 -0
- package/dist/lib/proxy/proxyEnv.js +73 -0
- package/dist/lib/proxy/proxyFetch.js +50 -4
- package/dist/lib/proxy/proxyTracer.d.ts +133 -0
- package/dist/lib/proxy/proxyTracer.js +645 -0
- package/dist/lib/proxy/rawStreamCapture.d.ts +10 -0
- package/dist/lib/proxy/rawStreamCapture.js +83 -0
- package/dist/lib/proxy/requestLogger.d.ts +32 -5
- package/dist/lib/proxy/requestLogger.js +406 -37
- package/dist/lib/proxy/sseInterceptor.d.ts +97 -0
- package/dist/lib/proxy/sseInterceptor.js +402 -0
- package/dist/lib/proxy/usageStats.d.ts +4 -3
- package/dist/lib/proxy/usageStats.js +25 -12
- package/dist/lib/rag/chunkers/MarkdownChunker.js +13 -5
- package/dist/lib/rag/chunking/markdownChunker.js +15 -6
- package/dist/lib/server/routes/claudeProxyRoutes.d.ts +7 -2
- package/dist/lib/server/routes/claudeProxyRoutes.js +1737 -508
- package/dist/lib/services/server/ai/observability/instrumentation.d.ts +7 -1
- package/dist/lib/services/server/ai/observability/instrumentation.js +240 -40
- package/dist/lib/tasks/backends/bullmqBackend.d.ts +1 -0
- package/dist/lib/tasks/backends/bullmqBackend.js +14 -7
- package/dist/lib/tasks/store/redisTaskStore.d.ts +1 -0
- package/dist/lib/tasks/store/redisTaskStore.js +34 -26
- package/dist/lib/tasks/taskManager.d.ts +3 -0
- package/dist/lib/tasks/taskManager.js +63 -30
- package/dist/lib/telemetry/index.d.ts +2 -1
- package/dist/lib/telemetry/index.js +2 -1
- package/dist/lib/telemetry/telemetryService.d.ts +3 -0
- package/dist/lib/telemetry/telemetryService.js +65 -5
- package/dist/lib/types/cli.d.ts +10 -0
- package/dist/lib/types/proxyTypes.d.ts +37 -5
- package/dist/lib/types/streamTypes.d.ts +25 -3
- package/dist/lib/utils/messageBuilder.js +3 -2
- package/dist/lib/utils/providerHealth.d.ts +18 -0
- package/dist/lib/utils/providerHealth.js +240 -9
- package/dist/lib/utils/providerUtils.js +14 -8
- package/dist/lib/utils/toolChoice.d.ts +4 -0
- package/dist/lib/utils/toolChoice.js +7 -0
- package/dist/neurolink.d.ts +3 -2
- package/dist/neurolink.js +260 -494
- package/dist/observability/otelBridge.d.ts +2 -2
- package/dist/observability/otelBridge.js +12 -3
- package/dist/providers/amazonBedrock.js +2 -4
- package/dist/providers/anthropic.d.ts +9 -5
- package/dist/providers/anthropic.js +19 -14
- package/dist/providers/anthropicBaseProvider.d.ts +3 -3
- package/dist/providers/anthropicBaseProvider.js +5 -4
- package/dist/providers/azureOpenai.d.ts +1 -1
- package/dist/providers/azureOpenai.js +5 -4
- package/dist/providers/googleAiStudio.js +30 -1
- package/dist/providers/googleVertex.js +28 -6
- package/dist/providers/huggingFace.d.ts +3 -3
- package/dist/providers/huggingFace.js +6 -7
- package/dist/providers/litellm.js +41 -29
- package/dist/providers/mistral.js +2 -1
- package/dist/providers/ollama.js +80 -23
- package/dist/providers/openAI.js +3 -2
- package/dist/providers/openRouter.js +2 -1
- package/dist/providers/openaiCompatible.d.ts +4 -4
- package/dist/providers/openaiCompatible.js +4 -3
- package/dist/proxy/claudeFormat.d.ts +3 -2
- package/dist/proxy/claudeFormat.js +25 -20
- package/dist/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
- package/dist/proxy/cloaking/plugins/sessionIdentity.js +9 -33
- package/dist/proxy/modelRouter.js +3 -0
- package/dist/proxy/oauthFetch.d.ts +1 -1
- package/dist/proxy/oauthFetch.js +65 -72
- package/dist/proxy/proxyConfig.js +44 -24
- package/dist/proxy/proxyEnv.d.ts +19 -0
- package/dist/proxy/proxyEnv.js +72 -0
- package/dist/proxy/proxyFetch.js +50 -4
- package/dist/proxy/proxyTracer.d.ts +133 -0
- package/dist/proxy/proxyTracer.js +644 -0
- package/dist/proxy/rawStreamCapture.d.ts +10 -0
- package/dist/proxy/rawStreamCapture.js +82 -0
- package/dist/proxy/requestLogger.d.ts +32 -5
- package/dist/proxy/requestLogger.js +406 -37
- package/dist/proxy/sseInterceptor.d.ts +97 -0
- package/dist/proxy/sseInterceptor.js +401 -0
- package/dist/proxy/usageStats.d.ts +4 -3
- package/dist/proxy/usageStats.js +25 -12
- package/dist/rag/chunkers/MarkdownChunker.js +13 -5
- package/dist/rag/chunking/markdownChunker.js +15 -6
- package/dist/server/routes/claudeProxyRoutes.d.ts +7 -2
- package/dist/server/routes/claudeProxyRoutes.js +1737 -508
- package/dist/services/server/ai/observability/instrumentation.d.ts +7 -1
- package/dist/services/server/ai/observability/instrumentation.js +240 -40
- package/dist/tasks/backends/bullmqBackend.d.ts +1 -0
- package/dist/tasks/backends/bullmqBackend.js +14 -7
- package/dist/tasks/store/redisTaskStore.d.ts +1 -0
- package/dist/tasks/store/redisTaskStore.js +34 -26
- package/dist/tasks/taskManager.d.ts +3 -0
- package/dist/tasks/taskManager.js +63 -30
- package/dist/telemetry/index.d.ts +2 -1
- package/dist/telemetry/index.js +2 -1
- package/dist/telemetry/telemetryService.d.ts +3 -0
- package/dist/telemetry/telemetryService.js +65 -5
- package/dist/types/cli.d.ts +10 -0
- package/dist/types/proxyTypes.d.ts +37 -5
- package/dist/types/streamTypes.d.ts +25 -3
- package/dist/utils/messageBuilder.js +3 -2
- package/dist/utils/providerHealth.d.ts +18 -0
- package/dist/utils/providerHealth.js +240 -9
- package/dist/utils/providerUtils.js +14 -8
- package/dist/utils/toolChoice.d.ts +4 -0
- package/dist/utils/toolChoice.js +6 -0
- package/docs/assets/dashboards/neurolink-proxy-observability-dashboard.json +6609 -0
- package/docs/changelog.md +252 -0
- package/package.json +17 -1
- package/scripts/observability/check-proxy-telemetry.mjs +235 -0
- package/scripts/observability/docker-compose.proxy-observability.yaml +55 -0
- package/scripts/observability/import-openobserve-dashboard.mjs +240 -0
- package/scripts/observability/manage-local-openobserve.sh +184 -0
- package/scripts/observability/otel-collector.proxy-observability.yaml +78 -0
- package/scripts/observability/proxy-observability.env.example +23 -0
package/dist/cli/commands/mcp.js
CHANGED
|
@@ -565,6 +565,7 @@ export class MCPCommandFactory {
|
|
|
565
565
|
? null
|
|
566
566
|
: ora("Testing MCP server connections...").start();
|
|
567
567
|
const sdk = new NeuroLink();
|
|
568
|
+
await sdk.getMCPStatus();
|
|
568
569
|
let serversToTest = await sdk.listMCPServers();
|
|
569
570
|
if (targetServer) {
|
|
570
571
|
serversToTest = serversToTest.filter((s) => s.name === targetServer);
|
|
@@ -654,6 +655,7 @@ export class MCPCommandFactory {
|
|
|
654
655
|
}
|
|
655
656
|
}
|
|
656
657
|
const sdk = new NeuroLink();
|
|
658
|
+
await sdk.getMCPStatus();
|
|
657
659
|
// Check if server exists and is connected
|
|
658
660
|
const allServers = await sdk.listMCPServers();
|
|
659
661
|
const server = allServers.find((s) => s.name === serverName);
|
|
@@ -762,6 +764,7 @@ export class MCPCommandFactory {
|
|
|
762
764
|
process.exit(1);
|
|
763
765
|
}
|
|
764
766
|
const sdk = new NeuroLink();
|
|
767
|
+
await sdk.getMCPStatus();
|
|
765
768
|
const allServers = await sdk.listMCPServers();
|
|
766
769
|
const server = allServers.find((s) => s.name === serverName);
|
|
767
770
|
if (!server) {
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
* (generate/stream), with an optional ModelRouter for model remapping.
|
|
11
11
|
*/
|
|
12
12
|
import type { CommandModule } from "yargs";
|
|
13
|
-
import type { ProxyStartArgs, ProxyStatusArgs, ProxyGuardArgs } from "../../lib/types/index.js";
|
|
13
|
+
import type { ProxyStartArgs, ProxyStatusArgs, ProxyGuardArgs, ProxyTelemetryArgs } from "../../lib/types/index.js";
|
|
14
14
|
export declare function mapClaudeErrorTypeToStatus(errorType?: string): number;
|
|
15
15
|
export declare const proxyStartCommand: CommandModule<object, ProxyStartArgs>;
|
|
16
16
|
export declare const proxyStatusCommand: CommandModule<object, ProxyStatusArgs>;
|
|
17
|
+
export declare const proxyTelemetryCommand: CommandModule<object, ProxyTelemetryArgs>;
|
|
17
18
|
export declare const proxyGuardCommand: CommandModule<object, ProxyGuardArgs>;
|
|
18
19
|
export declare const proxySetupCommand: CommandModule;
|
|
19
20
|
export declare const proxyInstallCommand: CommandModule;
|
|
@@ -16,9 +16,12 @@ import chalk from "chalk";
|
|
|
16
16
|
import ora from "ora";
|
|
17
17
|
import { logger } from "../../lib/utils/logger.js";
|
|
18
18
|
import { formatUptime, isProcessRunning, StateFileManager, } from "../utils/serverUtils.js";
|
|
19
|
+
import { loadProxyEnvFile, resolveProxyEnvFile, } from "../../lib/proxy/proxyEnv.js";
|
|
19
20
|
import { createRequire } from "node:module";
|
|
21
|
+
import { fileURLToPath } from "node:url";
|
|
20
22
|
const _require = createRequire(import.meta.url);
|
|
21
23
|
const { version: PROXY_VERSION } = _require("../../../package.json");
|
|
24
|
+
const PROXY_TELEMETRY_SCRIPT_PATH = fileURLToPath(new URL("../../../scripts/observability/manage-local-openobserve.sh", import.meta.url));
|
|
22
25
|
// =============================================================================
|
|
23
26
|
// STATE MANAGEMENT
|
|
24
27
|
// =============================================================================
|
|
@@ -220,6 +223,32 @@ function spawnFailOpenGuard(host, port, parentPid) {
|
|
|
220
223
|
return undefined;
|
|
221
224
|
}
|
|
222
225
|
}
|
|
226
|
+
async function runProxyTelemetryManager(command) {
|
|
227
|
+
const { existsSync } = await import("fs");
|
|
228
|
+
if (!existsSync(PROXY_TELEMETRY_SCRIPT_PATH)) {
|
|
229
|
+
throw new Error("Proxy telemetry helper files were not found in this installation. Reinstall NeuroLink with observability assets included.");
|
|
230
|
+
}
|
|
231
|
+
await new Promise((resolve, reject) => {
|
|
232
|
+
const child = spawn("bash", [PROXY_TELEMETRY_SCRIPT_PATH, command], {
|
|
233
|
+
stdio: "inherit",
|
|
234
|
+
env: process.env,
|
|
235
|
+
});
|
|
236
|
+
child.on("error", (error) => {
|
|
237
|
+
reject(error);
|
|
238
|
+
});
|
|
239
|
+
child.on("exit", (code, signal) => {
|
|
240
|
+
if (signal) {
|
|
241
|
+
reject(new Error(`proxy telemetry ${command} terminated by signal ${signal}`));
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (code !== 0) {
|
|
245
|
+
reject(new Error(`proxy telemetry ${command} exited with code ${code ?? 1}`));
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
resolve();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
}
|
|
223
252
|
// =============================================================================
|
|
224
253
|
// STARTUP BANNER
|
|
225
254
|
// =============================================================================
|
|
@@ -313,6 +342,16 @@ export const proxyStartCommand = {
|
|
|
313
342
|
alias: "c",
|
|
314
343
|
description: "Path to proxy config file (YAML/JSON)",
|
|
315
344
|
defaultDescription: "~/.neurolink/proxy-config.yaml",
|
|
345
|
+
})
|
|
346
|
+
.option("env-file", {
|
|
347
|
+
type: "string",
|
|
348
|
+
alias: "envFile",
|
|
349
|
+
description: "Path to proxy provider env file (overrides cwd .env for the proxy process)",
|
|
350
|
+
})
|
|
351
|
+
.option("passthrough", {
|
|
352
|
+
type: "boolean",
|
|
353
|
+
default: false,
|
|
354
|
+
description: "Run in transparent passthrough mode (no retry, no rotation, no polyfill)",
|
|
316
355
|
})
|
|
317
356
|
.example("neurolink proxy start", "Start proxy on default port 55669 with fill-first strategy")
|
|
318
357
|
.example("neurolink proxy start -p 8080 -s fill-first", "Start proxy on port 8080 with fill-first")
|
|
@@ -357,6 +396,22 @@ export const proxyStartCommand = {
|
|
|
357
396
|
// -----------------------------------------------------------------
|
|
358
397
|
// 1. Create NeuroLink instance — reads all env vars automatically
|
|
359
398
|
// -----------------------------------------------------------------
|
|
399
|
+
let loadedEnvFile;
|
|
400
|
+
try {
|
|
401
|
+
const envResult = await loadProxyEnvFile({
|
|
402
|
+
explicitEnvFile: argv.envFile,
|
|
403
|
+
});
|
|
404
|
+
loadedEnvFile = envResult.path;
|
|
405
|
+
if (spinner && loadedEnvFile) {
|
|
406
|
+
spinner.text = `Loaded proxy env from ${loadedEnvFile}`;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
catch (envError) {
|
|
410
|
+
if (spinner) {
|
|
411
|
+
spinner.fail(chalk.red(envError instanceof Error ? envError.message : String(envError)));
|
|
412
|
+
}
|
|
413
|
+
process.exit(1);
|
|
414
|
+
}
|
|
360
415
|
// Skip MCP initialization for proxy — tools come from Claude Code, not MCP servers
|
|
361
416
|
process.env.NEUROLINK_SKIP_MCP = "true";
|
|
362
417
|
const { NeuroLink } = await import("../../lib/neurolink.js");
|
|
@@ -433,15 +488,24 @@ export const proxyStartCommand = {
|
|
|
433
488
|
},
|
|
434
489
|
}, 502);
|
|
435
490
|
});
|
|
436
|
-
const
|
|
491
|
+
const passthrough = argv.passthrough ?? false;
|
|
492
|
+
const routeGroup = createClaudeProxyRoutes(modelRouter, "", strategy, passthrough);
|
|
437
493
|
// Register proxy routes — inject NeuroLink into ServerContext
|
|
438
494
|
for (const route of routeGroup.routes) {
|
|
439
495
|
const method = route.method.toLowerCase();
|
|
440
496
|
app[method](route.path, async (c) => {
|
|
441
497
|
const emptyBody = {};
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
498
|
+
let body;
|
|
499
|
+
let rawBody;
|
|
500
|
+
if (method === "post") {
|
|
501
|
+
rawBody = await c.req.text().catch(() => undefined);
|
|
502
|
+
try {
|
|
503
|
+
body = rawBody ? JSON.parse(rawBody) : emptyBody;
|
|
504
|
+
}
|
|
505
|
+
catch {
|
|
506
|
+
body = emptyBody;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
445
509
|
// Log incoming request
|
|
446
510
|
const model = body?.model ?? "-";
|
|
447
511
|
const stream = body?.stream
|
|
@@ -461,6 +525,7 @@ export const proxyStartCommand = {
|
|
|
461
525
|
query: Object.fromEntries(new URL(c.req.url).searchParams.entries()),
|
|
462
526
|
params: c.req.param(),
|
|
463
527
|
body,
|
|
528
|
+
rawBody, // Preserve original bytes for passthrough mode
|
|
464
529
|
neurolink, // NeuroLink instance for generate/stream
|
|
465
530
|
toolRegistry: neurolink.getToolRegistry(),
|
|
466
531
|
timestamp: Date.now(),
|
|
@@ -564,6 +629,7 @@ export const proxyStartCommand = {
|
|
|
564
629
|
uptime: process.uptime(),
|
|
565
630
|
version: PROXY_VERSION,
|
|
566
631
|
stats: {
|
|
632
|
+
totalAttempts: stats.totalAttempts,
|
|
567
633
|
totalRequests: stats.totalRequests,
|
|
568
634
|
totalSuccess: stats.totalSuccess,
|
|
569
635
|
totalErrors: stats.totalErrors,
|
|
@@ -571,7 +637,8 @@ export const proxyStartCommand = {
|
|
|
571
637
|
accounts: Object.values(stats.accounts).map((a) => ({
|
|
572
638
|
label: a.label,
|
|
573
639
|
type: a.type,
|
|
574
|
-
|
|
640
|
+
attempts: a.attemptCount,
|
|
641
|
+
requests: a.attemptCount,
|
|
575
642
|
success: a.successCount,
|
|
576
643
|
errors: a.errorCount,
|
|
577
644
|
rateLimits: a.rateLimitCount,
|
|
@@ -583,7 +650,55 @@ export const proxyStartCommand = {
|
|
|
583
650
|
});
|
|
584
651
|
});
|
|
585
652
|
// -----------------------------------------------------------------
|
|
586
|
-
// 5.
|
|
653
|
+
// 5. Initialize OpenTelemetry for proxy observability
|
|
654
|
+
// -----------------------------------------------------------------
|
|
655
|
+
try {
|
|
656
|
+
const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
657
|
+
if (!process.env.OTEL_SERVICE_NAME) {
|
|
658
|
+
process.env.OTEL_SERVICE_NAME = "neurolink-proxy";
|
|
659
|
+
}
|
|
660
|
+
// Merge resource attributes (preserving any existing ones)
|
|
661
|
+
process.env.OTEL_RESOURCE_ATTRIBUTES = [
|
|
662
|
+
`service.name=neurolink-proxy`,
|
|
663
|
+
`service.version=${PROXY_VERSION}`,
|
|
664
|
+
`deployment.environment=local`,
|
|
665
|
+
process.env.OTEL_RESOURCE_ATTRIBUTES,
|
|
666
|
+
]
|
|
667
|
+
.filter(Boolean)
|
|
668
|
+
.join(",");
|
|
669
|
+
const { initializeOpenTelemetry, isOpenTelemetryInitialized } = await import("../../lib/services/server/ai/observability/instrumentation.js");
|
|
670
|
+
const { buildObservabilityConfigFromEnv } = await import("../../lib/utils/observabilityHelpers.js");
|
|
671
|
+
if (!isOpenTelemetryInitialized()) {
|
|
672
|
+
const observabilityConfig = buildObservabilityConfigFromEnv();
|
|
673
|
+
const langfuseConfig = observabilityConfig?.langfuse;
|
|
674
|
+
const langfuseEnabled = langfuseConfig?.enabled === true;
|
|
675
|
+
initializeOpenTelemetry({
|
|
676
|
+
enabled: langfuseEnabled,
|
|
677
|
+
publicKey: langfuseConfig?.publicKey || "",
|
|
678
|
+
secretKey: langfuseConfig?.secretKey || "",
|
|
679
|
+
baseUrl: langfuseConfig?.baseUrl,
|
|
680
|
+
environment: "proxy",
|
|
681
|
+
release: PROXY_VERSION,
|
|
682
|
+
userId: "neurolink-proxy",
|
|
683
|
+
autoDetectOperationName: true,
|
|
684
|
+
});
|
|
685
|
+
if (langfuseEnabled) {
|
|
686
|
+
logger.always(`[proxy] Langfuse enabled — exporting to ${langfuseConfig.baseUrl || "https://cloud.langfuse.com"} (environment=proxy)`);
|
|
687
|
+
}
|
|
688
|
+
if (otlpEndpoint) {
|
|
689
|
+
logger.always(`[proxy] OTLP exporter enabled — exporting to ${otlpEndpoint} (service.name=neurolink-proxy)`);
|
|
690
|
+
}
|
|
691
|
+
if (!langfuseEnabled && !otlpEndpoint) {
|
|
692
|
+
logger.always("[proxy] OpenTelemetry exporters disabled — set OTEL_EXPORTER_OTLP_ENDPOINT or Langfuse credentials to enable proxy observability");
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
catch (otelError) {
|
|
697
|
+
// OTel is non-critical — proxy must still work without it
|
|
698
|
+
logger.debug(`[proxy] OpenTelemetry init failed (non-fatal): ${otelError instanceof Error ? otelError.message : String(otelError)}`);
|
|
699
|
+
}
|
|
700
|
+
// -----------------------------------------------------------------
|
|
701
|
+
// 6. Start listening
|
|
587
702
|
// -----------------------------------------------------------------
|
|
588
703
|
const port = argv.port ?? 55669;
|
|
589
704
|
const host = argv.host ?? "127.0.0.1";
|
|
@@ -608,9 +723,13 @@ export const proxyStartCommand = {
|
|
|
608
723
|
host,
|
|
609
724
|
strategy,
|
|
610
725
|
startTime: new Date().toISOString(),
|
|
726
|
+
envFile: loadedEnvFile,
|
|
611
727
|
fallbackChain,
|
|
612
728
|
guardPid,
|
|
613
|
-
managedBy: "
|
|
729
|
+
managedBy: process.platform === "darwin" && process.ppid === 1
|
|
730
|
+
? "launchd"
|
|
731
|
+
: "manual",
|
|
732
|
+
passthrough,
|
|
614
733
|
};
|
|
615
734
|
saveProxyState(state);
|
|
616
735
|
if (spinner) {
|
|
@@ -619,6 +738,10 @@ export const proxyStartCommand = {
|
|
|
619
738
|
const normalizedHost = host === "0.0.0.0" ? "localhost" : host;
|
|
620
739
|
const url = `http://${normalizedHost}:${port}`;
|
|
621
740
|
printProxyBanner(url, strategy);
|
|
741
|
+
logger.always(` ${chalk.bold("Mode:")} ${chalk.cyan(passthrough ? "passthrough" : "full")}`);
|
|
742
|
+
if (loadedEnvFile) {
|
|
743
|
+
logger.always(` ${chalk.bold("Env File:")} ${chalk.cyan(loadedEnvFile)}`);
|
|
744
|
+
}
|
|
622
745
|
// Auto-configure Claude Code — use the normalized URL (localhost, not 0.0.0.0)
|
|
623
746
|
try {
|
|
624
747
|
await setClaudeProxySettings(url);
|
|
@@ -630,7 +753,7 @@ export const proxyStartCommand = {
|
|
|
630
753
|
(e instanceof Error ? e.message : String(e)));
|
|
631
754
|
}
|
|
632
755
|
// -----------------------------------------------------------------
|
|
633
|
-
//
|
|
756
|
+
// 7. Background token refresh (every 30 seconds)
|
|
634
757
|
// -----------------------------------------------------------------
|
|
635
758
|
const { needsRefresh, refreshToken, persistTokens } = await import("../../lib/proxy/tokenRefresh.js");
|
|
636
759
|
const { tokenStore } = await import("../../lib/auth/tokenStore.js");
|
|
@@ -697,12 +820,21 @@ export const proxyStartCommand = {
|
|
|
697
820
|
cleanupLogs(7, 500);
|
|
698
821
|
}, 60 * 60 * 1000);
|
|
699
822
|
// -----------------------------------------------------------------
|
|
700
|
-
//
|
|
823
|
+
// 8. Graceful shutdown
|
|
701
824
|
// -----------------------------------------------------------------
|
|
702
825
|
const shutdown = async (signal) => {
|
|
703
826
|
clearInterval(refreshInterval);
|
|
704
827
|
clearInterval(logCleanupInterval);
|
|
705
828
|
logger.always(`\nShutting down proxy (${signal})...`);
|
|
829
|
+
// Flush and shutdown OpenTelemetry before closing the server
|
|
830
|
+
try {
|
|
831
|
+
const { flushOpenTelemetry, shutdownOpenTelemetry } = await import("../../lib/services/server/ai/observability/instrumentation.js");
|
|
832
|
+
await flushOpenTelemetry();
|
|
833
|
+
await shutdownOpenTelemetry();
|
|
834
|
+
}
|
|
835
|
+
catch {
|
|
836
|
+
/* non-fatal — proxy shutdown must not block on OTel */
|
|
837
|
+
}
|
|
706
838
|
// Only clear Claude settings on user-initiated stop (SIGINT).
|
|
707
839
|
// On SIGTERM (launchd restart cycle), leave settings intact so
|
|
708
840
|
// the restarted proxy picks up seamlessly.
|
|
@@ -746,7 +878,10 @@ export const proxyStartCommand = {
|
|
|
746
878
|
};
|
|
747
879
|
function printStatusStats(stats) {
|
|
748
880
|
console.info(`\n Stats:`);
|
|
749
|
-
|
|
881
|
+
if (stats.totalAttempts !== undefined) {
|
|
882
|
+
console.info(` Attempts: ${stats.totalAttempts}`);
|
|
883
|
+
}
|
|
884
|
+
console.info(` Completed: ${stats.totalRequests} total, ${stats.totalSuccess} success, ${stats.totalErrors} errors`);
|
|
750
885
|
console.info(` Rate limits: ${stats.totalRateLimits}`);
|
|
751
886
|
if (stats.accounts?.length) {
|
|
752
887
|
console.info(`\n Accounts:`);
|
|
@@ -754,7 +889,11 @@ function printStatusStats(stats) {
|
|
|
754
889
|
const acctStatus = a.cooling
|
|
755
890
|
? chalk.red("cooling")
|
|
756
891
|
: chalk.green("active");
|
|
757
|
-
|
|
892
|
+
const attempts = a.attempts ?? a.requests ?? 0;
|
|
893
|
+
const success = a.success ?? 0;
|
|
894
|
+
const errors = a.errors ?? 0;
|
|
895
|
+
const rateLimits = a.rateLimits ?? 0;
|
|
896
|
+
console.info(` ${a.label.padEnd(20)} ${a.type.padEnd(8)} ${String(attempts).padEnd(6)} attempts ${String(success).padEnd(6)} success ${String(errors).padEnd(6)} errors ${String(rateLimits).padEnd(6)} rl ${acctStatus}`);
|
|
758
897
|
}
|
|
759
898
|
}
|
|
760
899
|
}
|
|
@@ -793,6 +932,7 @@ export const proxyStatusCommand = {
|
|
|
793
932
|
uptime: null,
|
|
794
933
|
startTime: null,
|
|
795
934
|
url: null,
|
|
935
|
+
envFile: null,
|
|
796
936
|
fallbackChain: null,
|
|
797
937
|
};
|
|
798
938
|
if (state && isProcessRunning(state.pid)) {
|
|
@@ -804,10 +944,25 @@ export const proxyStatusCommand = {
|
|
|
804
944
|
status.startTime = state.startTime;
|
|
805
945
|
status.uptime = Date.now() - new Date(state.startTime).getTime();
|
|
806
946
|
status.url = `http://${state.host === "0.0.0.0" ? "localhost" : state.host}:${state.port}`;
|
|
947
|
+
status.envFile = state.envFile ?? null;
|
|
807
948
|
status.fallbackChain = state.fallbackChain ?? null;
|
|
808
949
|
}
|
|
950
|
+
// Fetch live stats before rendering (JSON or text)
|
|
951
|
+
let liveStats = null;
|
|
952
|
+
if (status.running && status.url) {
|
|
953
|
+
try {
|
|
954
|
+
const statusResp = await fetch(`${status.url}/status`);
|
|
955
|
+
if (statusResp.ok) {
|
|
956
|
+
const statusData = (await statusResp.json());
|
|
957
|
+
liveStats = statusData.stats;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
catch {
|
|
961
|
+
// Non-fatal — live stats unavailable
|
|
962
|
+
}
|
|
963
|
+
}
|
|
809
964
|
if (argv.format === "json") {
|
|
810
|
-
logger.always(JSON.stringify(status, null, 2));
|
|
965
|
+
logger.always(JSON.stringify({ ...status, stats: liveStats }, null, 2));
|
|
811
966
|
return;
|
|
812
967
|
}
|
|
813
968
|
// Text format
|
|
@@ -822,6 +977,9 @@ export const proxyStatusCommand = {
|
|
|
822
977
|
logger.always(` ${chalk.bold("Strategy:")} ${chalk.cyan(status.strategy)}`);
|
|
823
978
|
logger.always(` ${chalk.bold("Started:")} ${chalk.cyan(status.startTime)}`);
|
|
824
979
|
logger.always(` ${chalk.bold("Uptime:")} ${chalk.cyan(formatUptime(status.uptime ?? 0))}`);
|
|
980
|
+
if (status.envFile) {
|
|
981
|
+
logger.always(` ${chalk.bold("Env File:")} ${chalk.cyan(status.envFile)}`);
|
|
982
|
+
}
|
|
825
983
|
// Display fallback chain if configured
|
|
826
984
|
if (status.fallbackChain && status.fallbackChain.length > 0) {
|
|
827
985
|
logger.always("");
|
|
@@ -875,6 +1033,58 @@ export const proxyStatusCommand = {
|
|
|
875
1033
|
},
|
|
876
1034
|
};
|
|
877
1035
|
// =============================================================================
|
|
1036
|
+
// PROXY TELEMETRY COMMAND
|
|
1037
|
+
// =============================================================================
|
|
1038
|
+
const PROXY_TELEMETRY_ACTIONS = [
|
|
1039
|
+
"setup",
|
|
1040
|
+
"start",
|
|
1041
|
+
"stop",
|
|
1042
|
+
"status",
|
|
1043
|
+
"logs",
|
|
1044
|
+
"import-dashboard",
|
|
1045
|
+
];
|
|
1046
|
+
export const proxyTelemetryCommand = {
|
|
1047
|
+
command: "telemetry <action>",
|
|
1048
|
+
describe: "Manage the local OpenObserve stack and dashboard for proxy observability",
|
|
1049
|
+
builder: (yargs) => yargs
|
|
1050
|
+
.positional("action", {
|
|
1051
|
+
type: "string",
|
|
1052
|
+
choices: [...PROXY_TELEMETRY_ACTIONS],
|
|
1053
|
+
describe: "Telemetry action: setup, start, stop, status, logs, or import-dashboard",
|
|
1054
|
+
})
|
|
1055
|
+
.option("quiet", {
|
|
1056
|
+
type: "boolean",
|
|
1057
|
+
alias: "q",
|
|
1058
|
+
default: false,
|
|
1059
|
+
description: "Suppress the local CLI spinner and delegate directly",
|
|
1060
|
+
})
|
|
1061
|
+
.example("neurolink proxy telemetry setup", "Start OpenObserve, start the OTEL collector, and import the dashboard")
|
|
1062
|
+
.example("neurolink proxy telemetry start", "Start the local proxy telemetry stack without re-importing the dashboard")
|
|
1063
|
+
.example("neurolink proxy telemetry stop", "Stop the local OpenObserve and OTEL collector containers"),
|
|
1064
|
+
handler: async (argv) => {
|
|
1065
|
+
const action = argv.action;
|
|
1066
|
+
const spinner = argv.quiet
|
|
1067
|
+
? null
|
|
1068
|
+
: ora(`Running proxy telemetry ${action}...`).start();
|
|
1069
|
+
try {
|
|
1070
|
+
if (spinner) {
|
|
1071
|
+
spinner.stop();
|
|
1072
|
+
}
|
|
1073
|
+
await runProxyTelemetryManager(action);
|
|
1074
|
+
if (spinner) {
|
|
1075
|
+
spinner.succeed(`proxy telemetry ${action} completed`);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
catch (error) {
|
|
1079
|
+
if (spinner) {
|
|
1080
|
+
spinner.fail(`proxy telemetry ${action} failed`);
|
|
1081
|
+
}
|
|
1082
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
1083
|
+
process.exit(1);
|
|
1084
|
+
}
|
|
1085
|
+
},
|
|
1086
|
+
};
|
|
1087
|
+
// =============================================================================
|
|
878
1088
|
// PROXY FAIL-OPEN GUARD COMMAND (HIDDEN)
|
|
879
1089
|
// =============================================================================
|
|
880
1090
|
export const proxyGuardCommand = {
|
|
@@ -1152,6 +1362,11 @@ export const proxySetupCommand = {
|
|
|
1152
1362
|
type: "boolean",
|
|
1153
1363
|
default: false,
|
|
1154
1364
|
description: "Skip service installation and start proxy in foreground instead",
|
|
1365
|
+
})
|
|
1366
|
+
.option("env-file", {
|
|
1367
|
+
type: "string",
|
|
1368
|
+
alias: "envFile",
|
|
1369
|
+
description: "Path to proxy provider env file to persist for the proxy",
|
|
1155
1370
|
})
|
|
1156
1371
|
.example("neurolink proxy setup", "Full setup with defaults")
|
|
1157
1372
|
.example("neurolink proxy setup -p 9000", "Setup on custom port")
|
|
@@ -1253,9 +1468,27 @@ export const proxySetupCommand = {
|
|
|
1253
1468
|
// =============================================================================
|
|
1254
1469
|
// PROXY INSTALL / UNINSTALL — launchd service (macOS)
|
|
1255
1470
|
// =============================================================================
|
|
1256
|
-
function
|
|
1257
|
-
|
|
1258
|
-
|
|
1471
|
+
function escapeXml(s) {
|
|
1472
|
+
return s
|
|
1473
|
+
.replace(/&/g, "&")
|
|
1474
|
+
.replace(/</g, "<")
|
|
1475
|
+
.replace(/>/g, ">")
|
|
1476
|
+
.replace(/"/g, """)
|
|
1477
|
+
.replace(/'/g, "'");
|
|
1478
|
+
}
|
|
1479
|
+
function buildPlist(port, host, envFile, configFile) {
|
|
1480
|
+
const nodeExec = escapeXml(process.execPath);
|
|
1481
|
+
const entryScript = escapeXml(process.argv[1] ?? join(__dirname, "..", "index.js"));
|
|
1482
|
+
const envFileArgs = envFile
|
|
1483
|
+
? `
|
|
1484
|
+
<string>--env-file</string>
|
|
1485
|
+
<string>${escapeXml(envFile)}</string>`
|
|
1486
|
+
: "";
|
|
1487
|
+
const configArgs = configFile
|
|
1488
|
+
? `
|
|
1489
|
+
<string>--config</string>
|
|
1490
|
+
<string>${escapeXml(configFile)}</string>`
|
|
1491
|
+
: "";
|
|
1259
1492
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
1260
1493
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
1261
1494
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -1274,6 +1507,8 @@ function buildPlist(port, host) {
|
|
|
1274
1507
|
<string>${port}</string>
|
|
1275
1508
|
<string>--host</string>
|
|
1276
1509
|
<string>${host}</string>
|
|
1510
|
+
${envFileArgs}
|
|
1511
|
+
${configArgs}
|
|
1277
1512
|
<string>--quiet</string>
|
|
1278
1513
|
</array>
|
|
1279
1514
|
|
|
@@ -1320,6 +1555,15 @@ export const proxyInstallCommand = {
|
|
|
1320
1555
|
type: "string",
|
|
1321
1556
|
default: "127.0.0.1",
|
|
1322
1557
|
description: "Proxy host",
|
|
1558
|
+
})
|
|
1559
|
+
.option("env-file", {
|
|
1560
|
+
type: "string",
|
|
1561
|
+
alias: "envFile",
|
|
1562
|
+
description: "Path to proxy provider env file to persist for the service",
|
|
1563
|
+
})
|
|
1564
|
+
.option("config", {
|
|
1565
|
+
type: "string",
|
|
1566
|
+
description: "Path to proxy routing config file to persist for the service",
|
|
1323
1567
|
})
|
|
1324
1568
|
.example("neurolink proxy install", "Install with defaults (port 55669)")
|
|
1325
1569
|
.example("neurolink proxy install -p 9000", "Install on custom port");
|
|
@@ -1333,6 +1577,21 @@ export const proxyInstallCommand = {
|
|
|
1333
1577
|
process.exit(1);
|
|
1334
1578
|
}
|
|
1335
1579
|
const { writeFileSync, mkdirSync, existsSync } = await import("fs");
|
|
1580
|
+
const envResolution = resolveProxyEnvFile({
|
|
1581
|
+
explicitEnvFile: argv.envFile,
|
|
1582
|
+
});
|
|
1583
|
+
const envFile = envResolution.path;
|
|
1584
|
+
const explicitConfig = argv.config;
|
|
1585
|
+
const configPath = explicitConfig ?? join(homedir(), ".neurolink", "proxy-config.yaml");
|
|
1586
|
+
if (explicitConfig && !existsSync(configPath)) {
|
|
1587
|
+
console.info(chalk.red(`Proxy config file not found: ${configPath}`));
|
|
1588
|
+
process.exit(1);
|
|
1589
|
+
}
|
|
1590
|
+
const configFile = existsSync(configPath) ? configPath : undefined;
|
|
1591
|
+
if (envFile && !existsSync(envFile)) {
|
|
1592
|
+
console.info(chalk.red(`Proxy env file not found: ${envFile}`));
|
|
1593
|
+
process.exit(1);
|
|
1594
|
+
}
|
|
1336
1595
|
const logsDir = join(homedir(), ".neurolink", "logs");
|
|
1337
1596
|
if (!existsSync(logsDir)) {
|
|
1338
1597
|
mkdirSync(logsDir, { recursive: true });
|
|
@@ -1340,9 +1599,12 @@ export const proxyInstallCommand = {
|
|
|
1340
1599
|
if (!existsSync(PLIST_DIR)) {
|
|
1341
1600
|
mkdirSync(PLIST_DIR, { recursive: true });
|
|
1342
1601
|
}
|
|
1343
|
-
const plist = buildPlist(port, host);
|
|
1602
|
+
const plist = buildPlist(port, host, envFile, configFile);
|
|
1344
1603
|
writeFileSync(PLIST_PATH, plist, "utf-8");
|
|
1345
1604
|
console.info(chalk.green(`✓ Plist written to ${PLIST_PATH}`));
|
|
1605
|
+
if (envFile) {
|
|
1606
|
+
console.info(chalk.green(`✓ Proxy env file: ${envFile}`));
|
|
1607
|
+
}
|
|
1346
1608
|
try {
|
|
1347
1609
|
const { execFileSync } = await import("node:child_process");
|
|
1348
1610
|
execFileSync("launchctl", ["unload", PLIST_PATH], {
|
|
@@ -1375,6 +1637,7 @@ export const proxyInstallCommand = {
|
|
|
1375
1637
|
host,
|
|
1376
1638
|
strategy: "fill-first",
|
|
1377
1639
|
startTime: new Date().toISOString(),
|
|
1640
|
+
envFile,
|
|
1378
1641
|
managedBy: "launchd",
|
|
1379
1642
|
});
|
|
1380
1643
|
}
|
|
@@ -341,6 +341,9 @@ export class TaskCommandFactory {
|
|
|
341
341
|
schedule = { type: "interval", every: parseDuration(argv.every) };
|
|
342
342
|
}
|
|
343
343
|
else {
|
|
344
|
+
if (!argv.at) {
|
|
345
|
+
throw new Error("One-time tasks require --at");
|
|
346
|
+
}
|
|
344
347
|
schedule = { type: "once", at: argv.at };
|
|
345
348
|
}
|
|
346
349
|
const now = new Date().toISOString();
|
|
@@ -10,6 +10,8 @@ export declare class CLICommandFactory {
|
|
|
10
10
|
private static processCliPDFFiles;
|
|
11
11
|
private static processCliFiles;
|
|
12
12
|
private static processCliVideoFiles;
|
|
13
|
+
private static isNonLocalFileReference;
|
|
14
|
+
private static validateCliInputFiles;
|
|
13
15
|
private static processOptions;
|
|
14
16
|
/**
|
|
15
17
|
* Validate Anthropic subscription options
|
|
@@ -480,6 +480,42 @@ export class CLICommandFactory {
|
|
|
480
480
|
// URLs are preserved as-is by resolveFilePaths
|
|
481
481
|
return resolveFilePaths(paths);
|
|
482
482
|
}
|
|
483
|
+
static isNonLocalFileReference(filePath) {
|
|
484
|
+
const lower = filePath.toLowerCase();
|
|
485
|
+
return (lower.startsWith("http://") ||
|
|
486
|
+
lower.startsWith("https://") ||
|
|
487
|
+
lower.startsWith("file://") ||
|
|
488
|
+
lower.startsWith("data:"));
|
|
489
|
+
}
|
|
490
|
+
static validateCliInputFiles(argv) {
|
|
491
|
+
const fileArgs = [
|
|
492
|
+
{ option: "--image", value: argv.image },
|
|
493
|
+
{ option: "--csv", value: argv.csv },
|
|
494
|
+
{ option: "--pdf", value: argv.pdf },
|
|
495
|
+
{ option: "--video", value: argv.video },
|
|
496
|
+
{ option: "--file", value: argv.file },
|
|
497
|
+
];
|
|
498
|
+
const missingPaths = [];
|
|
499
|
+
for (const { option, value } of fileArgs) {
|
|
500
|
+
if (!value) {
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
const rawPaths = Array.isArray(value) ? value : [value];
|
|
504
|
+
const resolvedPaths = resolveFilePaths(rawPaths);
|
|
505
|
+
for (let i = 0; i < resolvedPaths.length; i++) {
|
|
506
|
+
const resolvedPath = resolvedPaths[i];
|
|
507
|
+
if (CLICommandFactory.isNonLocalFileReference(resolvedPath)) {
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
511
|
+
missingPaths.push(`${option} path not found: ${rawPaths[i]} (resolved to ${resolvedPath})`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (missingPaths.length > 0) {
|
|
516
|
+
throw new Error(`One or more input files do not exist:\n${missingPaths.join("\n")}`);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
483
519
|
// Helper method to process common options
|
|
484
520
|
static processOptions(argv) {
|
|
485
521
|
// Handle noColor option by disabling chalk
|
|
@@ -1762,6 +1798,7 @@ export class CLICommandFactory {
|
|
|
1762
1798
|
if (options.delay) {
|
|
1763
1799
|
await new Promise((resolve) => setTimeout(resolve, options.delay));
|
|
1764
1800
|
}
|
|
1801
|
+
CLICommandFactory.validateCliInputFiles(argv);
|
|
1765
1802
|
// Process context
|
|
1766
1803
|
const { inputText, contextMetadata } = CLICommandFactory.processGenerateContext(rawInput, options);
|
|
1767
1804
|
// Handle dry-run mode for testing
|
|
@@ -2355,6 +2392,7 @@ export class CLICommandFactory {
|
|
|
2355
2392
|
if (options.delay) {
|
|
2356
2393
|
await new Promise((resolve) => setTimeout(resolve, options.delay));
|
|
2357
2394
|
}
|
|
2395
|
+
CLICommandFactory.validateCliInputFiles(argv);
|
|
2358
2396
|
const { inputText, contextMetadata } = await CLICommandFactory.processStreamContext(argv, options);
|
|
2359
2397
|
// Handle dry-run mode for testing
|
|
2360
2398
|
if (options.dryRun) {
|
package/dist/cli/parser.js
CHANGED
|
@@ -13,7 +13,7 @@ import { ServeCommandFactory } from "./commands/serve.js";
|
|
|
13
13
|
import { ragCommand } from "./commands/rag.js";
|
|
14
14
|
import { ObservabilityCommandFactory } from "./commands/observability.js";
|
|
15
15
|
import { TelemetryCommandFactory } from "./commands/telemetry.js";
|
|
16
|
-
import { proxyStartCommand, proxyStatusCommand, proxySetupCommand, proxyGuardCommand, proxyInstallCommand, proxyUninstallCommand, } from "./commands/proxy.js";
|
|
16
|
+
import { proxyStartCommand, proxyStatusCommand, proxyTelemetryCommand, proxySetupCommand, proxyGuardCommand, proxyInstallCommand, proxyUninstallCommand, } from "./commands/proxy.js";
|
|
17
17
|
import { EvaluateCommandFactory } from "./commands/evaluate.js";
|
|
18
18
|
import { TaskCommandFactory } from "./commands/task.js";
|
|
19
19
|
// Enhanced CLI with Professional UX
|
|
@@ -187,16 +187,17 @@ export function initializeCliParser() {
|
|
|
187
187
|
.command(AuthCommandFactory.createAuthCommands())
|
|
188
188
|
// Proxy Commands - Claude multi-account proxy
|
|
189
189
|
.command({
|
|
190
|
-
command: "proxy
|
|
190
|
+
command: "proxy",
|
|
191
191
|
describe: "Manage Claude multi-account proxy server",
|
|
192
192
|
builder: (yargs) => yargs
|
|
193
193
|
.command(proxyStartCommand)
|
|
194
194
|
.command(proxyStatusCommand)
|
|
195
|
+
.command(proxyTelemetryCommand)
|
|
195
196
|
.command(proxySetupCommand)
|
|
196
197
|
.command(proxyGuardCommand)
|
|
197
198
|
.command(proxyInstallCommand)
|
|
198
199
|
.command(proxyUninstallCommand)
|
|
199
|
-
.demandCommand(1, "Please specify a proxy subcommand: start, status, setup, guard, install, or uninstall"),
|
|
200
|
+
.demandCommand(1, "Please specify a proxy subcommand: start, status, telemetry <setup|start|stop|status|logs|import-dashboard>, setup, guard, install, or uninstall"),
|
|
200
201
|
handler: () => { },
|
|
201
202
|
})
|
|
202
203
|
// Evaluate Command Group - Using EvaluateCommandFactory
|