@juspay/neurolink 9.40.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.
Files changed (224) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +7 -1
  3. package/dist/auth/anthropicOAuth.d.ts +18 -3
  4. package/dist/auth/anthropicOAuth.js +137 -4
  5. package/dist/auth/providers/firebase.js +5 -1
  6. package/dist/auth/providers/jwt.js +5 -1
  7. package/dist/auth/providers/workos.js +5 -1
  8. package/dist/auth/sessionManager.d.ts +1 -1
  9. package/dist/auth/sessionManager.js +58 -27
  10. package/dist/browser/neurolink.min.js +471 -445
  11. package/dist/cli/commands/mcp.js +3 -0
  12. package/dist/cli/commands/proxy.d.ts +2 -1
  13. package/dist/cli/commands/proxy.js +279 -16
  14. package/dist/cli/commands/task.d.ts +56 -0
  15. package/dist/cli/commands/task.js +838 -0
  16. package/dist/cli/factories/commandFactory.d.ts +2 -0
  17. package/dist/cli/factories/commandFactory.js +38 -0
  18. package/dist/cli/parser.js +8 -4
  19. package/dist/client/aiSdkAdapter.js +3 -0
  20. package/dist/client/streamingClient.js +30 -10
  21. package/dist/core/modules/GenerationHandler.js +3 -2
  22. package/dist/core/redisConversationMemoryManager.js +7 -3
  23. package/dist/evaluation/BatchEvaluator.js +4 -1
  24. package/dist/evaluation/hooks/observabilityHooks.js +5 -3
  25. package/dist/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
  26. package/dist/evaluation/pipeline/evaluationPipeline.js +20 -8
  27. package/dist/evaluation/pipeline/strategies/batchStrategy.js +6 -3
  28. package/dist/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
  29. package/dist/lib/auth/anthropicOAuth.d.ts +18 -3
  30. package/dist/lib/auth/anthropicOAuth.js +137 -4
  31. package/dist/lib/auth/providers/firebase.js +5 -1
  32. package/dist/lib/auth/providers/jwt.js +5 -1
  33. package/dist/lib/auth/providers/workos.js +5 -1
  34. package/dist/lib/auth/sessionManager.d.ts +1 -1
  35. package/dist/lib/auth/sessionManager.js +58 -27
  36. package/dist/lib/client/aiSdkAdapter.js +3 -0
  37. package/dist/lib/client/streamingClient.js +30 -10
  38. package/dist/lib/core/modules/GenerationHandler.js +3 -2
  39. package/dist/lib/core/redisConversationMemoryManager.js +7 -3
  40. package/dist/lib/evaluation/BatchEvaluator.js +4 -1
  41. package/dist/lib/evaluation/hooks/observabilityHooks.js +5 -3
  42. package/dist/lib/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
  43. package/dist/lib/evaluation/pipeline/evaluationPipeline.js +20 -8
  44. package/dist/lib/evaluation/pipeline/strategies/batchStrategy.js +6 -3
  45. package/dist/lib/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
  46. package/dist/lib/neurolink.d.ts +18 -1
  47. package/dist/lib/neurolink.js +367 -484
  48. package/dist/lib/observability/otelBridge.d.ts +2 -2
  49. package/dist/lib/observability/otelBridge.js +12 -3
  50. package/dist/lib/providers/amazonBedrock.js +2 -4
  51. package/dist/lib/providers/anthropic.d.ts +9 -5
  52. package/dist/lib/providers/anthropic.js +19 -14
  53. package/dist/lib/providers/anthropicBaseProvider.d.ts +3 -3
  54. package/dist/lib/providers/anthropicBaseProvider.js +5 -4
  55. package/dist/lib/providers/azureOpenai.d.ts +1 -1
  56. package/dist/lib/providers/azureOpenai.js +5 -4
  57. package/dist/lib/providers/googleAiStudio.js +30 -1
  58. package/dist/lib/providers/googleVertex.js +28 -6
  59. package/dist/lib/providers/huggingFace.d.ts +3 -3
  60. package/dist/lib/providers/huggingFace.js +6 -8
  61. package/dist/lib/providers/litellm.js +41 -29
  62. package/dist/lib/providers/mistral.js +2 -1
  63. package/dist/lib/providers/ollama.js +80 -23
  64. package/dist/lib/providers/openAI.js +3 -2
  65. package/dist/lib/providers/openRouter.js +2 -1
  66. package/dist/lib/providers/openaiCompatible.d.ts +4 -4
  67. package/dist/lib/providers/openaiCompatible.js +4 -4
  68. package/dist/lib/proxy/claudeFormat.d.ts +3 -2
  69. package/dist/lib/proxy/claudeFormat.js +25 -20
  70. package/dist/lib/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
  71. package/dist/lib/proxy/cloaking/plugins/sessionIdentity.js +9 -33
  72. package/dist/lib/proxy/modelRouter.js +3 -0
  73. package/dist/lib/proxy/oauthFetch.d.ts +1 -1
  74. package/dist/lib/proxy/oauthFetch.js +65 -72
  75. package/dist/lib/proxy/proxyConfig.js +44 -24
  76. package/dist/lib/proxy/proxyEnv.d.ts +19 -0
  77. package/dist/lib/proxy/proxyEnv.js +73 -0
  78. package/dist/lib/proxy/proxyFetch.js +50 -4
  79. package/dist/lib/proxy/proxyTracer.d.ts +133 -0
  80. package/dist/lib/proxy/proxyTracer.js +645 -0
  81. package/dist/lib/proxy/rawStreamCapture.d.ts +10 -0
  82. package/dist/lib/proxy/rawStreamCapture.js +83 -0
  83. package/dist/lib/proxy/requestLogger.d.ts +32 -5
  84. package/dist/lib/proxy/requestLogger.js +406 -37
  85. package/dist/lib/proxy/sseInterceptor.d.ts +97 -0
  86. package/dist/lib/proxy/sseInterceptor.js +402 -0
  87. package/dist/lib/proxy/usageStats.d.ts +4 -3
  88. package/dist/lib/proxy/usageStats.js +25 -12
  89. package/dist/lib/rag/chunkers/MarkdownChunker.js +13 -5
  90. package/dist/lib/rag/chunking/markdownChunker.js +15 -6
  91. package/dist/lib/server/routes/claudeProxyRoutes.d.ts +7 -2
  92. package/dist/lib/server/routes/claudeProxyRoutes.js +1737 -508
  93. package/dist/lib/services/server/ai/observability/instrumentation.d.ts +7 -1
  94. package/dist/lib/services/server/ai/observability/instrumentation.js +240 -40
  95. package/dist/lib/tasks/backends/bullmqBackend.d.ts +33 -0
  96. package/dist/lib/tasks/backends/bullmqBackend.js +196 -0
  97. package/dist/lib/tasks/backends/nodeTimeoutBackend.d.ts +27 -0
  98. package/dist/lib/tasks/backends/nodeTimeoutBackend.js +141 -0
  99. package/dist/lib/tasks/backends/taskBackendRegistry.d.ts +31 -0
  100. package/dist/lib/tasks/backends/taskBackendRegistry.js +66 -0
  101. package/dist/lib/tasks/errors.d.ts +31 -0
  102. package/dist/lib/tasks/errors.js +18 -0
  103. package/dist/lib/tasks/store/fileTaskStore.d.ts +43 -0
  104. package/dist/lib/tasks/store/fileTaskStore.js +179 -0
  105. package/dist/lib/tasks/store/redisTaskStore.d.ts +43 -0
  106. package/dist/lib/tasks/store/redisTaskStore.js +197 -0
  107. package/dist/lib/tasks/taskExecutor.d.ts +21 -0
  108. package/dist/lib/tasks/taskExecutor.js +166 -0
  109. package/dist/lib/tasks/taskManager.d.ts +63 -0
  110. package/dist/lib/tasks/taskManager.js +426 -0
  111. package/dist/lib/tasks/tools/taskTools.d.ts +135 -0
  112. package/dist/lib/tasks/tools/taskTools.js +274 -0
  113. package/dist/lib/telemetry/index.d.ts +2 -1
  114. package/dist/lib/telemetry/index.js +2 -1
  115. package/dist/lib/telemetry/telemetryService.d.ts +3 -0
  116. package/dist/lib/telemetry/telemetryService.js +65 -5
  117. package/dist/lib/types/cli.d.ts +10 -0
  118. package/dist/lib/types/configTypes.d.ts +3 -0
  119. package/dist/lib/types/generateTypes.d.ts +13 -0
  120. package/dist/lib/types/index.d.ts +1 -0
  121. package/dist/lib/types/proxyTypes.d.ts +37 -5
  122. package/dist/lib/types/streamTypes.d.ts +25 -3
  123. package/dist/lib/types/taskTypes.d.ts +275 -0
  124. package/dist/lib/types/taskTypes.js +37 -0
  125. package/dist/lib/utils/messageBuilder.js +3 -2
  126. package/dist/lib/utils/providerHealth.d.ts +18 -0
  127. package/dist/lib/utils/providerHealth.js +240 -9
  128. package/dist/lib/utils/providerUtils.js +14 -8
  129. package/dist/lib/utils/toolChoice.d.ts +4 -0
  130. package/dist/lib/utils/toolChoice.js +7 -0
  131. package/dist/neurolink.d.ts +18 -1
  132. package/dist/neurolink.js +367 -484
  133. package/dist/observability/otelBridge.d.ts +2 -2
  134. package/dist/observability/otelBridge.js +12 -3
  135. package/dist/providers/amazonBedrock.js +2 -4
  136. package/dist/providers/anthropic.d.ts +9 -5
  137. package/dist/providers/anthropic.js +19 -14
  138. package/dist/providers/anthropicBaseProvider.d.ts +3 -3
  139. package/dist/providers/anthropicBaseProvider.js +5 -4
  140. package/dist/providers/azureOpenai.d.ts +1 -1
  141. package/dist/providers/azureOpenai.js +5 -4
  142. package/dist/providers/googleAiStudio.js +30 -1
  143. package/dist/providers/googleVertex.js +28 -6
  144. package/dist/providers/huggingFace.d.ts +3 -3
  145. package/dist/providers/huggingFace.js +6 -7
  146. package/dist/providers/litellm.js +41 -29
  147. package/dist/providers/mistral.js +2 -1
  148. package/dist/providers/ollama.js +80 -23
  149. package/dist/providers/openAI.js +3 -2
  150. package/dist/providers/openRouter.js +2 -1
  151. package/dist/providers/openaiCompatible.d.ts +4 -4
  152. package/dist/providers/openaiCompatible.js +4 -3
  153. package/dist/proxy/claudeFormat.d.ts +3 -2
  154. package/dist/proxy/claudeFormat.js +25 -20
  155. package/dist/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
  156. package/dist/proxy/cloaking/plugins/sessionIdentity.js +9 -33
  157. package/dist/proxy/modelRouter.js +3 -0
  158. package/dist/proxy/oauthFetch.d.ts +1 -1
  159. package/dist/proxy/oauthFetch.js +65 -72
  160. package/dist/proxy/proxyConfig.js +44 -24
  161. package/dist/proxy/proxyEnv.d.ts +19 -0
  162. package/dist/proxy/proxyEnv.js +72 -0
  163. package/dist/proxy/proxyFetch.js +50 -4
  164. package/dist/proxy/proxyTracer.d.ts +133 -0
  165. package/dist/proxy/proxyTracer.js +644 -0
  166. package/dist/proxy/rawStreamCapture.d.ts +10 -0
  167. package/dist/proxy/rawStreamCapture.js +82 -0
  168. package/dist/proxy/requestLogger.d.ts +32 -5
  169. package/dist/proxy/requestLogger.js +406 -37
  170. package/dist/proxy/sseInterceptor.d.ts +97 -0
  171. package/dist/proxy/sseInterceptor.js +401 -0
  172. package/dist/proxy/usageStats.d.ts +4 -3
  173. package/dist/proxy/usageStats.js +25 -12
  174. package/dist/rag/chunkers/MarkdownChunker.js +13 -5
  175. package/dist/rag/chunking/markdownChunker.js +15 -6
  176. package/dist/server/routes/claudeProxyRoutes.d.ts +7 -2
  177. package/dist/server/routes/claudeProxyRoutes.js +1737 -508
  178. package/dist/services/server/ai/observability/instrumentation.d.ts +7 -1
  179. package/dist/services/server/ai/observability/instrumentation.js +240 -40
  180. package/dist/tasks/backends/bullmqBackend.d.ts +33 -0
  181. package/dist/tasks/backends/bullmqBackend.js +195 -0
  182. package/dist/tasks/backends/nodeTimeoutBackend.d.ts +27 -0
  183. package/dist/tasks/backends/nodeTimeoutBackend.js +140 -0
  184. package/dist/tasks/backends/taskBackendRegistry.d.ts +31 -0
  185. package/dist/tasks/backends/taskBackendRegistry.js +65 -0
  186. package/dist/tasks/errors.d.ts +31 -0
  187. package/dist/tasks/errors.js +17 -0
  188. package/dist/tasks/store/fileTaskStore.d.ts +43 -0
  189. package/dist/tasks/store/fileTaskStore.js +178 -0
  190. package/dist/tasks/store/redisTaskStore.d.ts +43 -0
  191. package/dist/tasks/store/redisTaskStore.js +196 -0
  192. package/dist/tasks/taskExecutor.d.ts +21 -0
  193. package/dist/tasks/taskExecutor.js +165 -0
  194. package/dist/tasks/taskManager.d.ts +63 -0
  195. package/dist/tasks/taskManager.js +425 -0
  196. package/dist/tasks/tools/taskTools.d.ts +135 -0
  197. package/dist/tasks/tools/taskTools.js +273 -0
  198. package/dist/telemetry/index.d.ts +2 -1
  199. package/dist/telemetry/index.js +2 -1
  200. package/dist/telemetry/telemetryService.d.ts +3 -0
  201. package/dist/telemetry/telemetryService.js +65 -5
  202. package/dist/types/cli.d.ts +10 -0
  203. package/dist/types/configTypes.d.ts +3 -0
  204. package/dist/types/generateTypes.d.ts +13 -0
  205. package/dist/types/index.d.ts +1 -0
  206. package/dist/types/proxyTypes.d.ts +37 -5
  207. package/dist/types/streamTypes.d.ts +25 -3
  208. package/dist/types/taskTypes.d.ts +275 -0
  209. package/dist/types/taskTypes.js +36 -0
  210. package/dist/utils/messageBuilder.js +3 -2
  211. package/dist/utils/providerHealth.d.ts +18 -0
  212. package/dist/utils/providerHealth.js +240 -9
  213. package/dist/utils/providerUtils.js +14 -8
  214. package/dist/utils/toolChoice.d.ts +4 -0
  215. package/dist/utils/toolChoice.js +6 -0
  216. package/docs/assets/dashboards/neurolink-proxy-observability-dashboard.json +6609 -0
  217. package/docs/changelog.md +252 -0
  218. package/package.json +19 -1
  219. package/scripts/observability/check-proxy-telemetry.mjs +235 -0
  220. package/scripts/observability/docker-compose.proxy-observability.yaml +55 -0
  221. package/scripts/observability/import-openobserve-dashboard.mjs +240 -0
  222. package/scripts/observability/manage-local-openobserve.sh +184 -0
  223. package/scripts/observability/otel-collector.proxy-observability.yaml +78 -0
  224. package/scripts/observability/proxy-observability.env.example +23 -0
@@ -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) {
@@ -13,8 +13,9 @@ 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
+ import { TaskCommandFactory } from "./commands/task.js";
18
19
  // Enhanced CLI with Professional UX
19
20
  export function initializeCliParser() {
20
21
  return (yargs(hideBin(process.argv))
@@ -186,19 +187,22 @@ export function initializeCliParser() {
186
187
  .command(AuthCommandFactory.createAuthCommands())
187
188
  // Proxy Commands - Claude multi-account proxy
188
189
  .command({
189
- command: "proxy <subcommand>",
190
+ command: "proxy",
190
191
  describe: "Manage Claude multi-account proxy server",
191
192
  builder: (yargs) => yargs
192
193
  .command(proxyStartCommand)
193
194
  .command(proxyStatusCommand)
195
+ .command(proxyTelemetryCommand)
194
196
  .command(proxySetupCommand)
195
197
  .command(proxyGuardCommand)
196
198
  .command(proxyInstallCommand)
197
199
  .command(proxyUninstallCommand)
198
- .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"),
199
201
  handler: () => { },
200
202
  })
201
203
  // Evaluate Command Group - Using EvaluateCommandFactory
202
- .command(EvaluateCommandFactory.createEvaluateCommand())); // Close the main return statement
204
+ .command(EvaluateCommandFactory.createEvaluateCommand())
205
+ // Task Command Group - Scheduled and self-running tasks
206
+ .command(TaskCommandFactory.createTaskCommands())); // Close the main return statement
203
207
  }
204
208
  //# sourceMappingURL=parser.js.map
@@ -186,6 +186,9 @@ export class NeuroLinkLanguageModel {
186
186
  // Drain anything already buffered.
187
187
  while (buffer.length > 0) {
188
188
  const chunk = buffer.shift();
189
+ if (!chunk) {
190
+ break;
191
+ }
189
192
  yield chunk;
190
193
  if (chunk.type === "finish") {
191
194
  return;
@@ -251,10 +251,12 @@ export class SSEClient {
251
251
  * Register event handler
252
252
  */
253
253
  on(event, callback) {
254
- if (!this.eventHandlers.has(event)) {
255
- this.eventHandlers.set(event, new Set());
254
+ let handlers = this.eventHandlers.get(event);
255
+ if (!handlers) {
256
+ handlers = new Set();
257
+ this.eventHandlers.set(event, handlers);
256
258
  }
257
- this.eventHandlers.get(event).add(callback);
259
+ handlers.add(callback);
258
260
  }
259
261
  /**
260
262
  * Remove event handler
@@ -315,7 +317,11 @@ export class SSEClient {
315
317
  });
316
318
  while (!done && !error) {
317
319
  if (events.length > 0) {
318
- yield events.shift();
320
+ const nextEvent = events.shift();
321
+ if (!nextEvent) {
322
+ continue;
323
+ }
324
+ yield nextEvent;
319
325
  }
320
326
  else {
321
327
  await new Promise((resolve) => {
@@ -325,7 +331,11 @@ export class SSEClient {
325
331
  }
326
332
  // Yield remaining events
327
333
  while (events.length > 0) {
328
- yield events.shift();
334
+ const nextEvent = events.shift();
335
+ if (!nextEvent) {
336
+ continue;
337
+ }
338
+ yield nextEvent;
329
339
  }
330
340
  if (error) {
331
341
  throw error;
@@ -545,10 +555,12 @@ export class WebSocketStreamingClient {
545
555
  * Register event handler
546
556
  */
547
557
  on(event, callback) {
548
- if (!this.eventHandlers.has(event)) {
549
- this.eventHandlers.set(event, new Set());
558
+ let handlers = this.eventHandlers.get(event);
559
+ if (!handlers) {
560
+ handlers = new Set();
561
+ this.eventHandlers.set(event, handlers);
550
562
  }
551
- this.eventHandlers.get(event).add(callback);
563
+ handlers.add(callback);
552
564
  }
553
565
  /**
554
566
  * Remove event handler
@@ -591,7 +603,11 @@ export class WebSocketStreamingClient {
591
603
  try {
592
604
  while (!disconnected) {
593
605
  if (messageQueue.length > 0) {
594
- yield messageQueue.shift();
606
+ const nextMessage = messageQueue.shift();
607
+ if (nextMessage === undefined) {
608
+ continue;
609
+ }
610
+ yield nextMessage;
595
611
  }
596
612
  else {
597
613
  await new Promise((resolve) => {
@@ -601,7 +617,11 @@ export class WebSocketStreamingClient {
601
617
  }
602
618
  // Yield remaining messages
603
619
  while (messageQueue.length > 0) {
604
- yield messageQueue.shift();
620
+ const nextMessage = messageQueue.shift();
621
+ if (nextMessage === undefined) {
622
+ continue;
623
+ }
624
+ yield nextMessage;
605
625
  }
606
626
  }
607
627
  finally {
@@ -95,6 +95,7 @@ export class GenerationHandler {
95
95
  };
96
96
  }
97
97
  }
98
+ const prepareStep = options.prepareStep;
98
99
  return await generateText({
99
100
  model,
100
101
  messages,
@@ -103,8 +104,8 @@ export class GenerationHandler {
103
104
  stopWhen: stepCountIs(options.maxSteps ?? DEFAULT_MAX_STEPS),
104
105
  ...(shouldUseTools &&
105
106
  options.toolChoice && { toolChoice: options.toolChoice }),
106
- ...(options.prepareStep && {
107
- experimental_prepareStep: ((stepOptions) => options.prepareStep({
107
+ ...(prepareStep && {
108
+ experimental_prepareStep: ((stepOptions) => prepareStep({
108
109
  ...stepOptions,
109
110
  maxSteps: options.maxSteps ?? DEFAULT_MAX_STEPS,
110
111
  })),
@@ -16,6 +16,7 @@ import { runWithCurrentLangfuseContext } from "../services/server/ai/observabili
16
16
  import { logger } from "../utils/logger.js";
17
17
  import { deserializeConversation, getNormalizedConfig, getPooledRedisClient, getSessionKey, getUserSessionsKey, releasePooledRedisClient, scanKeys, serializeConversation, } from "../utils/redis.js";
18
18
  const redisTracer = tracers.redis;
19
+ const REDIS_TIMEOUT_MS = 5000;
19
20
  /**
20
21
  * Redis-based implementation of the ConversationMemoryManager
21
22
  * Uses the same interface but stores data in Redis
@@ -130,13 +131,14 @@ export class RedisConversationMemoryManager {
130
131
  if (!this.redisClient) {
131
132
  return undefined;
132
133
  }
134
+ const redisClient = this.redisClient;
133
135
  return redisTracer.startActiveSpan("neurolink.memory.getSession", { kind: SpanKind.CLIENT, attributes: { "session.id": sessionId } }, async (span) => {
134
136
  if (userId) {
135
137
  span.setAttribute("user.id", userId);
136
138
  }
137
139
  try {
138
140
  const redisKey = getSessionKey(this.redisConfig, sessionId, userId);
139
- const conversationData = await this.redisClient.get(redisKey);
141
+ const conversationData = await withTimeout(redisClient.get(redisKey), REDIS_TIMEOUT_MS);
140
142
  const conversation = deserializeConversation(conversationData || null);
141
143
  if (!conversation) {
142
144
  span.setAttribute("session.found", false);
@@ -630,6 +632,7 @@ export class RedisConversationMemoryManager {
630
632
  logger.warn("[RedisConversationMemoryManager] Redis client not available in buildContextMessages");
631
633
  return [];
632
634
  }
635
+ const redisClient = this.redisClient;
633
636
  // NLK-GAP-012: Add span for buildContext CRUD operation
634
637
  return redisTracer.startActiveSpan("neurolink.memory.buildContext", {
635
638
  kind: SpanKind.CLIENT,
@@ -645,7 +648,7 @@ export class RedisConversationMemoryManager {
645
648
  method: "buildContextMessages",
646
649
  });
647
650
  const redisKey = getSessionKey(this.redisConfig, sessionId, userId);
648
- const conversationData = await this.redisClient.get(redisKey);
651
+ const conversationData = await withTimeout(redisClient.get(redisKey), REDIS_TIMEOUT_MS);
649
652
  const conversation = deserializeConversation(conversationData || null);
650
653
  if (!conversation) {
651
654
  span.setAttribute("session.found", false);
@@ -1080,6 +1083,7 @@ User message: "${userMessage}"`;
1080
1083
  if (!this.redisClient) {
1081
1084
  return false;
1082
1085
  }
1086
+ const redisClient = this.redisClient;
1083
1087
  // NLK-GAP-012: Add span for clearSession CRUD operation
1084
1088
  return redisTracer.startActiveSpan("neurolink.memory.clear", {
1085
1089
  kind: SpanKind.CLIENT,
@@ -1090,7 +1094,7 @@ User message: "${userMessage}"`;
1090
1094
  }, async (span) => {
1091
1095
  try {
1092
1096
  const redisKey = getSessionKey(this.redisConfig, sessionId, userId);
1093
- const result = await this.redisClient.del(redisKey);
1097
+ const result = await withTimeout(redisClient.del(redisKey), REDIS_TIMEOUT_MS);
1094
1098
  if (Number(result) > 0) {
1095
1099
  // Remove session from user's session set
1096
1100
  if (userId) {
@@ -6,6 +6,9 @@ import { Evaluator } from "./index.js";
6
6
  import { createBatchEvaluationError, isRetryableEvaluationError, } from "./errors/EvaluationError.js";
7
7
  import { logger } from "../utils/logger.js";
8
8
  import { NeuroLinkFeatureError } from "../core/infrastructure/index.js";
9
+ function hasEvaluationData(result) {
10
+ return result.success && result.data !== undefined;
11
+ }
9
12
  /**
10
13
  * BatchEvaluator - Performs evaluation on multiple items in parallel.
11
14
  * Supports configurable concurrency, retry logic, and progress tracking.
@@ -201,7 +204,7 @@ export class BatchEvaluator {
201
204
  }
202
205
  }
203
206
  // Calculate summary statistics
204
- const successfulResults = results.filter((r) => r.success && r.data);
207
+ const successfulResults = results.filter(hasEvaluationData);
205
208
  const scores = successfulResults.map((r) => r.data.overall);
206
209
  const passingScores = successfulResults.filter((r) => r.data.overall >=
207
210
  (autoEvalConfig.threshold || this.config.threshold || 7));
@@ -41,10 +41,12 @@ export class ObservabilityHooks {
41
41
  * Register an event handler
42
42
  */
43
43
  on(event, handler) {
44
- if (!this._handlers.has(event)) {
45
- this._handlers.set(event, new Set());
44
+ let handlers = this._handlers.get(event);
45
+ if (!handlers) {
46
+ handlers = new Set();
47
+ this._handlers.set(event, handlers);
46
48
  }
47
- this._handlers.get(event).add(handler);
49
+ handlers.add(handler);
48
50
  // Return unsubscribe function
49
51
  return () => {
50
52
  this._handlers.get(event)?.delete(handler);
@@ -12,9 +12,9 @@ export type PipelineExecutionOptions = {
12
12
  correlationId?: string;
13
13
  /** Custom timeout override */
14
14
  timeout?: number;
15
- /** Skip specific scorers */
15
+ /** Skip specific scorers. Mutually exclusive with onlyScorers. */
16
16
  skipScorers?: string[];
17
- /** Only run specific scorers */
17
+ /** Only run specific scorers. Mutually exclusive with skipScorers. */
18
18
  onlyScorers?: string[];
19
19
  /** Additional metadata to attach */
20
20
  metadata?: JsonObject;
@@ -59,6 +59,7 @@ export declare class EvaluationPipeline {
59
59
  * Execute the pipeline on input
60
60
  */
61
61
  execute(input: ScorerInput, options?: PipelineExecutionOptions): Promise<PipelineResult>;
62
+ private _validateExecutionOptions;
62
63
  /**
63
64
  * Get scorers to run based on options
64
65
  */
@@ -91,6 +91,7 @@ export class EvaluationPipeline {
91
91
  if (!this._initialized) {
92
92
  await this.initialize();
93
93
  }
94
+ this._validateExecutionOptions(options);
94
95
  const startTime = Date.now();
95
96
  const correlationId = options?.correlationId ?? `pipeline-${Date.now()}`;
96
97
  logger.debug(`Executing pipeline: ${this._config.name ?? "unnamed"}`, {
@@ -173,16 +174,25 @@ export class EvaluationPipeline {
173
174
  skippedScorers,
174
175
  };
175
176
  }
177
+ _validateExecutionOptions(options) {
178
+ const hasOnlyScorers = !!options?.onlyScorers && options.onlyScorers.length > 0;
179
+ const hasSkipScorers = !!options?.skipScorers && options.skipScorers.length > 0;
180
+ if (hasOnlyScorers && hasSkipScorers) {
181
+ throw new Error("Cannot specify both 'onlyScorers' and 'skipScorers' options");
182
+ }
183
+ }
176
184
  /**
177
185
  * Get scorers to run based on options
178
186
  */
179
187
  _getScorersToRun(options) {
180
188
  const allScorers = Array.from(this._scorers.entries());
181
- if (options?.onlyScorers && options.onlyScorers.length > 0) {
182
- return allScorers.filter(([id]) => options.onlyScorers.includes(id));
189
+ const onlyScorers = options?.onlyScorers;
190
+ const skipScorers = options?.skipScorers;
191
+ if (onlyScorers && onlyScorers.length > 0) {
192
+ return allScorers.filter(([id]) => onlyScorers.includes(id));
183
193
  }
184
- if (options?.skipScorers && options.skipScorers.length > 0) {
185
- return allScorers.filter(([id]) => !options.skipScorers.includes(id));
194
+ if (skipScorers && skipScorers.length > 0) {
195
+ return allScorers.filter(([id]) => !skipScorers.includes(id));
186
196
  }
187
197
  return allScorers;
188
198
  }
@@ -191,11 +201,13 @@ export class EvaluationPipeline {
191
201
  */
192
202
  _getSkippedScorers(options) {
193
203
  const allIds = Array.from(this._scorers.keys());
194
- if (options?.onlyScorers && options.onlyScorers.length > 0) {
195
- return allIds.filter((id) => !options.onlyScorers.includes(id));
204
+ const onlyScorers = options?.onlyScorers;
205
+ const skipScorers = options?.skipScorers;
206
+ if (onlyScorers && onlyScorers.length > 0) {
207
+ return allIds.filter((id) => !onlyScorers.includes(id));
196
208
  }
197
- if (options?.skipScorers && options.skipScorers.length > 0) {
198
- return options.skipScorers.filter((id) => allIds.includes(id));
209
+ if (skipScorers && skipScorers.length > 0) {
210
+ return skipScorers.filter((id) => allIds.includes(id));
199
211
  }
200
212
  return [];
201
213
  }
@@ -2,6 +2,9 @@
2
2
  * @file Batch Strategy
3
3
  * Batch processing for evaluation pipelines
4
4
  */
5
+ function hasPipelineResult(result) {
6
+ return !result.error && result.result !== undefined;
7
+ }
5
8
  /**
6
9
  * Default batch configuration
7
10
  */
@@ -66,7 +69,7 @@ export class BatchStrategy {
66
69
  }
67
70
  // Calculate summary
68
71
  const totalDuration = Date.now() - startTime;
69
- const successfulResults = results.filter((r) => !r.error && r.result);
72
+ const successfulResults = results.filter(hasPipelineResult);
70
73
  const scores = successfulResults.map((r) => r.result.overallScore);
71
74
  const passed = successfulResults.filter((r) => r.result.passed);
72
75
  return {
@@ -192,7 +195,7 @@ export async function* streamBatchEvaluation(pipeline, inputs, config) {
192
195
  durations.push(result.duration);
193
196
  // If continueOnError is false and this result has an error, abort and return summary
194
197
  if (result.error && batchConfig.continueOnError === false) {
195
- const successfulResults = results.filter((r) => !r.error && r.result);
198
+ const successfulResults = results.filter(hasPipelineResult);
196
199
  const earlyScores = successfulResults.map((r) => r.result.overallScore);
197
200
  const earlyPassed = successfulResults.filter((r) => r.result.passed);
198
201
  return {
@@ -219,7 +222,7 @@ export async function* streamBatchEvaluation(pipeline, inputs, config) {
219
222
  }
220
223
  }
221
224
  // Return summary
222
- const successfulResults = results.filter((r) => !r.error && r.result);
225
+ const successfulResults = results.filter(hasPipelineResult);
223
226
  const scores = successfulResults.map((r) => r.result.overallScore);
224
227
  const passed = successfulResults.filter((r) => r.result.passed);
225
228
  return {
@@ -17,6 +17,12 @@ export const DEFAULT_SAMPLING_CONFIG = {
17
17
  maxRate: 1.0,
18
18
  },
19
19
  };
20
+ const DEFAULT_ADAPTIVE_CONFIG = {
21
+ enabled: false,
22
+ qualityThreshold: 0.7,
23
+ minRate: 0.1,
24
+ maxRate: 1.0,
25
+ };
20
26
  /**
21
27
  * Sampling strategy for evaluation
22
28
  */
@@ -27,9 +33,10 @@ export class SamplingStrategy {
27
33
  _maxRecentScores = 100;
28
34
  constructor(config = {}) {
29
35
  const clamp01 = (v) => Math.max(0, Math.min(1, v));
36
+ const defaultAdaptive = DEFAULT_SAMPLING_CONFIG.adaptive ?? DEFAULT_ADAPTIVE_CONFIG;
30
37
  const rawRate = config.rate ?? DEFAULT_SAMPLING_CONFIG.rate;
31
- const rawMinRate = config.adaptive?.minRate ?? DEFAULT_SAMPLING_CONFIG.adaptive.minRate;
32
- const rawMaxRate = config.adaptive?.maxRate ?? DEFAULT_SAMPLING_CONFIG.adaptive.maxRate;
38
+ const rawMinRate = config.adaptive?.minRate ?? defaultAdaptive.minRate;
39
+ const rawMaxRate = config.adaptive?.maxRate ?? defaultAdaptive.maxRate;
33
40
  const minRate = clamp01(Math.min(rawMinRate, rawMaxRate));
34
41
  const maxRate = clamp01(Math.max(rawMinRate, rawMaxRate));
35
42
  this._config = {
@@ -41,9 +48,8 @@ export class SamplingStrategy {
41
48
  ...(config.alwaysEvaluate ?? {}),
42
49
  },
43
50
  adaptive: {
44
- enabled: config.adaptive?.enabled ?? DEFAULT_SAMPLING_CONFIG.adaptive.enabled,
45
- qualityThreshold: clamp01(config.adaptive?.qualityThreshold ??
46
- DEFAULT_SAMPLING_CONFIG.adaptive.qualityThreshold),
51
+ enabled: config.adaptive?.enabled ?? defaultAdaptive.enabled,
52
+ qualityThreshold: clamp01(config.adaptive?.qualityThreshold ?? defaultAdaptive.qualityThreshold),
47
53
  minRate,
48
54
  maxRate,
49
55
  },
@@ -156,9 +162,12 @@ export class SamplingStrategy {
156
162
  */
157
163
  configure(config) {
158
164
  const clamp01 = (v) => Math.max(0, Math.min(1, v));
165
+ const currentAdaptive = this._config.adaptive ??
166
+ DEFAULT_SAMPLING_CONFIG.adaptive ??
167
+ DEFAULT_ADAPTIVE_CONFIG;
159
168
  const rawRate = config.rate ?? this._config.rate;
160
- const rawMinRate = config.adaptive?.minRate ?? this._config.adaptive.minRate;
161
- const rawMaxRate = config.adaptive?.maxRate ?? this._config.adaptive.maxRate;
169
+ const rawMinRate = config.adaptive?.minRate ?? currentAdaptive.minRate;
170
+ const rawMaxRate = config.adaptive?.maxRate ?? currentAdaptive.maxRate;
162
171
  const minRate = clamp01(Math.min(rawMinRate, rawMaxRate));
163
172
  const maxRate = clamp01(Math.max(rawMinRate, rawMaxRate));
164
173
  this._config = {
@@ -170,9 +179,8 @@ export class SamplingStrategy {
170
179
  ...(config.alwaysEvaluate ?? {}),
171
180
  },
172
181
  adaptive: {
173
- enabled: config.adaptive?.enabled ?? this._config.adaptive.enabled,
174
- qualityThreshold: clamp01(config.adaptive?.qualityThreshold ??
175
- this._config.adaptive.qualityThreshold),
182
+ enabled: config.adaptive?.enabled ?? currentAdaptive.enabled,
183
+ qualityThreshold: clamp01(config.adaptive?.qualityThreshold ?? currentAdaptive.qualityThreshold),
176
184
  minRate,
177
185
  maxRate,
178
186
  },
@@ -43,13 +43,28 @@ export declare const DEFAULT_SCOPES: readonly string[];
43
43
  /**
44
44
  * User-Agent string to spoof Claude CLI
45
45
  */
46
- export declare const CLAUDE_CLI_USER_AGENT = "claude-cli/2.1.2 (external, cli)";
46
+ export declare const CLAUDE_CODE_VERSION = "2.1.87.6d6";
47
+ export declare const CLAUDE_CODE_ENTRYPOINT = "sdk-cli";
48
+ export declare const CLAUDE_CLI_USER_AGENT = "claude-cli/2.1.87 (external, sdk-cli)";
49
+ export type ClaudeCodeIdentity = {
50
+ deviceId: string;
51
+ accountUuid: string;
52
+ sessionId: string;
53
+ metadataUserId: string;
54
+ };
55
+ export declare function parseClaudeCodeUserId(userId: unknown): ClaudeCodeIdentity | null;
56
+ export declare function getOrCreateClaudeCodeIdentity(seed: string, options?: {
57
+ existingUserId?: unknown;
58
+ preferredSessionId?: string;
59
+ }): ClaudeCodeIdentity;
60
+ export declare function purgeExpiredClaudeCodeIdentities(now?: number): number;
61
+ export declare function buildStableClaudeCodeBillingHeader(originalText?: string): string;
47
62
  /**
48
63
  * Required beta headers for OAuth API requests.
49
64
  * The "oauth-2025-04-20" header is CRITICAL for OAuth authentication.
50
- * The "interleaved-thinking-2025-05-14" enables extended thinking.
51
65
  */
52
- export declare const OAUTH_BETA_HEADERS = "oauth-2025-04-20,interleaved-thinking-2025-05-14";
66
+ export declare const OAUTH_BETA_HEADERS = "oauth-2025-04-20";
67
+ export declare const CLAUDE_CODE_OAUTH_BETAS: readonly ["oauth-2025-04-20", "claude-code-20250219", "context-management-2025-06-27", "prompt-caching-scope-2026-01-05", "advanced-tool-use-2025-11-20", "effort-2025-11-24"];
53
68
  /**
54
69
  * Tool name prefix required for OAuth API requests
55
70
  */