@juspay/neurolink 9.65.1 → 9.66.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 (287) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/adapters/video/videoAnalyzer.d.ts +1 -1
  3. package/dist/agent/directTools.d.ts +9 -17
  4. package/dist/agent/directTools.js +1 -5
  5. package/dist/autoresearch/tools.d.ts +2 -214
  6. package/dist/autoresearch/tools.js +1 -1
  7. package/dist/browser/neurolink.min.js +388 -386
  8. package/dist/cli/commands/proxy.js +154 -5
  9. package/dist/client/reactHooks.js +16 -8
  10. package/dist/client/reactHooks.tsx +24 -9
  11. package/dist/core/baseProvider.d.ts +1 -6
  12. package/dist/core/baseProvider.js +1 -1
  13. package/dist/core/modules/GenerationHandler.d.ts +2 -2
  14. package/dist/core/modules/GenerationHandler.js +3 -1
  15. package/dist/core/modules/MessageBuilder.d.ts +1 -15
  16. package/dist/core/modules/MessageBuilder.js +0 -14
  17. package/dist/core/modules/StreamHandler.js +1 -1
  18. package/dist/core/modules/ToolsManager.d.ts +1 -17
  19. package/dist/core/modules/ToolsManager.js +1 -17
  20. package/dist/core/streamAnalytics.js +1 -1
  21. package/dist/evaluation/contextBuilder.d.ts +1 -4
  22. package/dist/evaluation/contextBuilder.js +0 -3
  23. package/dist/evaluation/index.d.ts +1 -4
  24. package/dist/evaluation/index.js +0 -3
  25. package/dist/files/fileTools.d.ts +2 -18
  26. package/dist/files/fileTools.js +3 -19
  27. package/dist/lib/adapters/video/videoAnalyzer.d.ts +1 -1
  28. package/dist/lib/agent/directTools.d.ts +9 -17
  29. package/dist/lib/agent/directTools.js +1 -5
  30. package/dist/lib/autoresearch/tools.d.ts +2 -214
  31. package/dist/lib/autoresearch/tools.js +1 -1
  32. package/dist/lib/client/reactHooks.js +16 -8
  33. package/dist/lib/core/baseProvider.d.ts +1 -6
  34. package/dist/lib/core/baseProvider.js +1 -1
  35. package/dist/lib/core/modules/GenerationHandler.d.ts +2 -2
  36. package/dist/lib/core/modules/GenerationHandler.js +3 -1
  37. package/dist/lib/core/modules/MessageBuilder.d.ts +1 -15
  38. package/dist/lib/core/modules/MessageBuilder.js +0 -14
  39. package/dist/lib/core/modules/StreamHandler.js +1 -1
  40. package/dist/lib/core/modules/ToolsManager.d.ts +1 -17
  41. package/dist/lib/core/modules/ToolsManager.js +1 -17
  42. package/dist/lib/core/streamAnalytics.js +1 -1
  43. package/dist/lib/evaluation/contextBuilder.d.ts +1 -4
  44. package/dist/lib/evaluation/contextBuilder.js +0 -3
  45. package/dist/lib/evaluation/index.d.ts +1 -4
  46. package/dist/lib/evaluation/index.js +0 -3
  47. package/dist/lib/files/fileTools.d.ts +2 -18
  48. package/dist/lib/files/fileTools.js +3 -19
  49. package/dist/lib/memory/memoryRetrievalTools.d.ts +2 -126
  50. package/dist/lib/memory/memoryRetrievalTools.js +1 -9
  51. package/dist/lib/middleware/builtin/autoEvaluation.d.ts +0 -3
  52. package/dist/lib/middleware/builtin/autoEvaluation.js +0 -3
  53. package/dist/lib/middleware/builtin/guardrails.js +1 -1
  54. package/dist/lib/middleware/builtin/lifecycle.d.ts +0 -9
  55. package/dist/lib/middleware/builtin/lifecycle.js +0 -9
  56. package/dist/lib/middleware/factory.d.ts +1 -1
  57. package/dist/lib/middleware/factory.js +1 -1
  58. package/dist/lib/middleware/registry.d.ts +1 -1
  59. package/dist/lib/neurolink.d.ts +14 -2
  60. package/dist/lib/neurolink.js +46 -18
  61. package/dist/lib/processors/media/AudioProcessor.js +8 -3
  62. package/dist/lib/providers/amazonBedrock.js +1 -2
  63. package/dist/lib/providers/amazonSagemaker.d.ts +1 -7
  64. package/dist/lib/providers/amazonSagemaker.js +0 -6
  65. package/dist/lib/providers/anthropic.d.ts +1 -1
  66. package/dist/lib/providers/anthropic.js +2 -1
  67. package/dist/lib/providers/anthropicBaseProvider.d.ts +1 -1
  68. package/dist/lib/providers/anthropicBaseProvider.js +2 -1
  69. package/dist/lib/providers/azureOpenai.d.ts +1 -1
  70. package/dist/lib/providers/azureOpenai.js +2 -1
  71. package/dist/lib/providers/cloudflare.d.ts +1 -1
  72. package/dist/lib/providers/cloudflare.js +2 -1
  73. package/dist/lib/providers/cohere.d.ts +1 -1
  74. package/dist/lib/providers/cohere.js +2 -1
  75. package/dist/lib/providers/deepseek.d.ts +1 -1
  76. package/dist/lib/providers/deepseek.js +2 -1
  77. package/dist/lib/providers/fireworks.d.ts +1 -1
  78. package/dist/lib/providers/fireworks.js +2 -1
  79. package/dist/lib/providers/googleAiStudio.d.ts +1 -1
  80. package/dist/lib/providers/googleAiStudio.js +0 -1
  81. package/dist/lib/providers/googleNativeGemini3.d.ts +1 -1
  82. package/dist/lib/providers/googleNativeGemini3.js +1 -1
  83. package/dist/lib/providers/googleVertex.d.ts +1 -1
  84. package/dist/lib/providers/googleVertex.js +0 -1
  85. package/dist/lib/providers/groq.d.ts +1 -1
  86. package/dist/lib/providers/groq.js +2 -1
  87. package/dist/lib/providers/huggingFace.d.ts +1 -1
  88. package/dist/lib/providers/huggingFace.js +3 -1
  89. package/dist/lib/providers/ideogram.d.ts +1 -1
  90. package/dist/lib/providers/jina.d.ts +1 -1
  91. package/dist/lib/providers/litellm.d.ts +1 -1
  92. package/dist/lib/providers/litellm.js +12 -6
  93. package/dist/lib/providers/llamaCpp.d.ts +1 -1
  94. package/dist/lib/providers/llamaCpp.js +2 -1
  95. package/dist/lib/providers/lmStudio.d.ts +1 -1
  96. package/dist/lib/providers/lmStudio.js +2 -1
  97. package/dist/lib/providers/mistral.d.ts +1 -1
  98. package/dist/lib/providers/mistral.js +2 -1
  99. package/dist/lib/providers/nvidiaNim.d.ts +1 -1
  100. package/dist/lib/providers/nvidiaNim.js +2 -1
  101. package/dist/lib/providers/ollama.d.ts +1 -1
  102. package/dist/lib/providers/ollama.js +1 -2
  103. package/dist/lib/providers/openAI.d.ts +1 -1
  104. package/dist/lib/providers/openAI.js +3 -1
  105. package/dist/lib/providers/openRouter.d.ts +1 -1
  106. package/dist/lib/providers/openRouter.js +3 -1
  107. package/dist/lib/providers/openaiCompatible.d.ts +1 -1
  108. package/dist/lib/providers/openaiCompatible.js +3 -1
  109. package/dist/lib/providers/perplexity.d.ts +1 -1
  110. package/dist/lib/providers/perplexity.js +2 -1
  111. package/dist/lib/providers/providerTypeUtils.d.ts +2 -7
  112. package/dist/lib/providers/providerTypeUtils.js +0 -6
  113. package/dist/lib/providers/recraft.d.ts +1 -1
  114. package/dist/lib/providers/replicate.d.ts +1 -1
  115. package/dist/lib/providers/stability.d.ts +1 -1
  116. package/dist/lib/providers/togetherAi.d.ts +1 -1
  117. package/dist/lib/providers/togetherAi.js +2 -1
  118. package/dist/lib/providers/voyage.d.ts +1 -1
  119. package/dist/lib/providers/xai.d.ts +1 -1
  120. package/dist/lib/providers/xai.js +2 -1
  121. package/dist/lib/proxy/claudeFormat.d.ts +0 -15
  122. package/dist/lib/proxy/claudeFormat.js +1 -11
  123. package/dist/lib/proxy/modelRouter.d.ts +5 -1
  124. package/dist/lib/proxy/modelRouter.js +8 -0
  125. package/dist/lib/proxy/openaiFormat.d.ts +137 -0
  126. package/dist/lib/proxy/openaiFormat.js +801 -0
  127. package/dist/lib/proxy/proxyTranslationEngine.d.ts +124 -0
  128. package/dist/lib/proxy/proxyTranslationEngine.js +679 -0
  129. package/dist/lib/rag/ragIntegration.d.ts +1 -12
  130. package/dist/lib/rag/ragIntegration.js +0 -8
  131. package/dist/lib/server/routes/claudeProxyRoutes.d.ts +6 -5
  132. package/dist/lib/server/routes/claudeProxyRoutes.js +22 -355
  133. package/dist/lib/server/routes/index.d.ts +1 -0
  134. package/dist/lib/server/routes/index.js +10 -2
  135. package/dist/lib/server/routes/openaiProxyRoutes.d.ts +30 -0
  136. package/dist/lib/server/routes/openaiProxyRoutes.js +337 -0
  137. package/dist/lib/tasks/tools/taskTools.d.ts +2 -117
  138. package/dist/lib/tasks/tools/taskTools.js +1 -10
  139. package/dist/lib/types/aliases.d.ts +1 -1
  140. package/dist/lib/types/conversation.d.ts +1 -0
  141. package/dist/lib/types/evaluation.d.ts +1 -5
  142. package/dist/lib/types/evaluation.js +0 -4
  143. package/dist/lib/types/generate.d.ts +2 -22
  144. package/dist/lib/types/guardrails.d.ts +1 -1
  145. package/dist/lib/types/middleware.d.ts +8 -3
  146. package/dist/lib/types/providers.d.ts +2 -1
  147. package/dist/lib/types/proxy.d.ts +179 -0
  148. package/dist/lib/types/rag.d.ts +1 -1
  149. package/dist/lib/types/rag.js +0 -6
  150. package/dist/lib/types/server.d.ts +3 -0
  151. package/dist/lib/types/stream.d.ts +2 -11
  152. package/dist/lib/types/tools.d.ts +2 -1
  153. package/dist/lib/utils/generation.d.ts +8 -0
  154. package/dist/lib/utils/generation.js +9 -0
  155. package/dist/lib/utils/generationErrors.d.ts +10 -0
  156. package/dist/lib/utils/generationErrors.js +11 -0
  157. package/dist/lib/utils/messageBuilder.d.ts +1 -6
  158. package/dist/lib/utils/messageBuilder.js +0 -5
  159. package/dist/lib/utils/noOutputSentinel.d.ts +0 -13
  160. package/dist/lib/utils/noOutputSentinel.js +1 -14
  161. package/dist/lib/utils/providerRetry.js +1 -1
  162. package/dist/lib/utils/tool.d.ts +8 -0
  163. package/dist/lib/utils/tool.js +9 -0
  164. package/dist/lib/utils/toolCallRepair.d.ts +1 -16
  165. package/dist/lib/utils/toolCallRepair.js +1 -16
  166. package/dist/lib/utils/toolChoice.d.ts +1 -1
  167. package/dist/lib/utils/videoAnalysisProcessor.d.ts +1 -8
  168. package/dist/lib/utils/videoAnalysisProcessor.js +0 -7
  169. package/dist/memory/memoryRetrievalTools.d.ts +2 -126
  170. package/dist/memory/memoryRetrievalTools.js +1 -9
  171. package/dist/middleware/builtin/autoEvaluation.d.ts +0 -3
  172. package/dist/middleware/builtin/autoEvaluation.js +0 -3
  173. package/dist/middleware/builtin/guardrails.js +1 -1
  174. package/dist/middleware/builtin/lifecycle.d.ts +0 -9
  175. package/dist/middleware/builtin/lifecycle.js +0 -9
  176. package/dist/middleware/factory.d.ts +1 -1
  177. package/dist/middleware/factory.js +1 -1
  178. package/dist/middleware/registry.d.ts +1 -1
  179. package/dist/neurolink.d.ts +14 -2
  180. package/dist/neurolink.js +46 -18
  181. package/dist/processors/media/AudioProcessor.js +8 -3
  182. package/dist/providers/amazonBedrock.js +1 -2
  183. package/dist/providers/amazonSagemaker.d.ts +1 -7
  184. package/dist/providers/amazonSagemaker.js +0 -6
  185. package/dist/providers/anthropic.d.ts +1 -1
  186. package/dist/providers/anthropic.js +2 -1
  187. package/dist/providers/anthropicBaseProvider.d.ts +1 -1
  188. package/dist/providers/anthropicBaseProvider.js +2 -1
  189. package/dist/providers/azureOpenai.d.ts +1 -1
  190. package/dist/providers/azureOpenai.js +2 -1
  191. package/dist/providers/cloudflare.d.ts +1 -1
  192. package/dist/providers/cloudflare.js +2 -1
  193. package/dist/providers/cohere.d.ts +1 -1
  194. package/dist/providers/cohere.js +2 -1
  195. package/dist/providers/deepseek.d.ts +1 -1
  196. package/dist/providers/deepseek.js +2 -1
  197. package/dist/providers/fireworks.d.ts +1 -1
  198. package/dist/providers/fireworks.js +2 -1
  199. package/dist/providers/googleAiStudio.d.ts +1 -1
  200. package/dist/providers/googleNativeGemini3.d.ts +1 -1
  201. package/dist/providers/googleNativeGemini3.js +1 -1
  202. package/dist/providers/googleVertex.d.ts +1 -1
  203. package/dist/providers/groq.d.ts +1 -1
  204. package/dist/providers/groq.js +2 -1
  205. package/dist/providers/huggingFace.d.ts +1 -1
  206. package/dist/providers/huggingFace.js +3 -1
  207. package/dist/providers/ideogram.d.ts +1 -1
  208. package/dist/providers/jina.d.ts +1 -1
  209. package/dist/providers/litellm.d.ts +1 -1
  210. package/dist/providers/litellm.js +12 -6
  211. package/dist/providers/llamaCpp.d.ts +1 -1
  212. package/dist/providers/llamaCpp.js +2 -1
  213. package/dist/providers/lmStudio.d.ts +1 -1
  214. package/dist/providers/lmStudio.js +2 -1
  215. package/dist/providers/mistral.d.ts +1 -1
  216. package/dist/providers/mistral.js +2 -1
  217. package/dist/providers/nvidiaNim.d.ts +1 -1
  218. package/dist/providers/nvidiaNim.js +2 -1
  219. package/dist/providers/ollama.d.ts +1 -1
  220. package/dist/providers/ollama.js +1 -2
  221. package/dist/providers/openAI.d.ts +1 -1
  222. package/dist/providers/openAI.js +3 -1
  223. package/dist/providers/openRouter.d.ts +1 -1
  224. package/dist/providers/openRouter.js +3 -1
  225. package/dist/providers/openaiCompatible.d.ts +1 -1
  226. package/dist/providers/openaiCompatible.js +3 -1
  227. package/dist/providers/perplexity.d.ts +1 -1
  228. package/dist/providers/perplexity.js +2 -1
  229. package/dist/providers/providerTypeUtils.d.ts +2 -7
  230. package/dist/providers/providerTypeUtils.js +0 -6
  231. package/dist/providers/recraft.d.ts +1 -1
  232. package/dist/providers/replicate.d.ts +1 -1
  233. package/dist/providers/stability.d.ts +1 -1
  234. package/dist/providers/togetherAi.d.ts +1 -1
  235. package/dist/providers/togetherAi.js +2 -1
  236. package/dist/providers/voyage.d.ts +1 -1
  237. package/dist/providers/xai.d.ts +1 -1
  238. package/dist/providers/xai.js +2 -1
  239. package/dist/proxy/claudeFormat.d.ts +0 -15
  240. package/dist/proxy/claudeFormat.js +1 -11
  241. package/dist/proxy/modelRouter.d.ts +5 -1
  242. package/dist/proxy/modelRouter.js +8 -0
  243. package/dist/proxy/openaiFormat.d.ts +137 -0
  244. package/dist/proxy/openaiFormat.js +800 -0
  245. package/dist/proxy/proxyTranslationEngine.d.ts +124 -0
  246. package/dist/proxy/proxyTranslationEngine.js +678 -0
  247. package/dist/rag/ragIntegration.d.ts +1 -12
  248. package/dist/rag/ragIntegration.js +0 -8
  249. package/dist/server/routes/claudeProxyRoutes.d.ts +6 -5
  250. package/dist/server/routes/claudeProxyRoutes.js +22 -355
  251. package/dist/server/routes/index.d.ts +1 -0
  252. package/dist/server/routes/index.js +10 -2
  253. package/dist/server/routes/openaiProxyRoutes.d.ts +30 -0
  254. package/dist/server/routes/openaiProxyRoutes.js +336 -0
  255. package/dist/tasks/tools/taskTools.d.ts +2 -117
  256. package/dist/tasks/tools/taskTools.js +1 -10
  257. package/dist/types/aliases.d.ts +1 -1
  258. package/dist/types/conversation.d.ts +1 -0
  259. package/dist/types/evaluation.d.ts +1 -5
  260. package/dist/types/evaluation.js +0 -4
  261. package/dist/types/generate.d.ts +2 -22
  262. package/dist/types/guardrails.d.ts +1 -1
  263. package/dist/types/middleware.d.ts +8 -3
  264. package/dist/types/providers.d.ts +2 -1
  265. package/dist/types/proxy.d.ts +179 -0
  266. package/dist/types/rag.d.ts +1 -1
  267. package/dist/types/rag.js +0 -6
  268. package/dist/types/server.d.ts +3 -0
  269. package/dist/types/stream.d.ts +2 -11
  270. package/dist/types/tools.d.ts +2 -1
  271. package/dist/utils/generation.d.ts +8 -0
  272. package/dist/utils/generation.js +8 -0
  273. package/dist/utils/generationErrors.d.ts +10 -0
  274. package/dist/utils/generationErrors.js +10 -0
  275. package/dist/utils/messageBuilder.d.ts +1 -6
  276. package/dist/utils/messageBuilder.js +0 -5
  277. package/dist/utils/noOutputSentinel.d.ts +0 -13
  278. package/dist/utils/noOutputSentinel.js +1 -14
  279. package/dist/utils/providerRetry.js +1 -1
  280. package/dist/utils/tool.d.ts +8 -0
  281. package/dist/utils/tool.js +8 -0
  282. package/dist/utils/toolCallRepair.d.ts +1 -16
  283. package/dist/utils/toolCallRepair.js +1 -16
  284. package/dist/utils/toolChoice.d.ts +1 -1
  285. package/dist/utils/videoAnalysisProcessor.d.ts +1 -8
  286. package/dist/utils/videoAnalysisProcessor.js +0 -7
  287. package/package.json +2 -3
@@ -1,11 +1,3 @@
1
- /**
2
- * RAG Integration for generate() and stream()
3
- *
4
- * Provides automatic RAG pipeline setup when `rag` config is provided
5
- * in GenerateOptions or StreamOptions. Handles file loading, chunking,
6
- * embedding generation, vector storage, and tool creation internally
7
- * so developers only need to pass `rag: { files: [...] }`.
8
- */
9
1
  import type { RAGConfig, VectorQueryResult, RAGPreparedTool } from "../types/index.js";
10
2
  /**
11
3
  * Generate deterministic embeddings for chunks.
@@ -35,7 +27,4 @@ declare function diversifyResults(results: VectorQueryResult[], topK: number): V
35
27
  * @returns Prepared RAG tool to inject into the tools record
36
28
  */
37
29
  export declare function prepareRAGTool(ragConfig: RAGConfig, fallbackProvider?: string): Promise<RAGPreparedTool>;
38
- /** @internal Exported for testing only */
39
- export { generateSimpleEmbedding as _generateSimpleEmbedding };
40
- /** @internal Exported for testing only */
41
- export { diversifyResults as _diversifyResults };
30
+ export {};
@@ -1,11 +1,3 @@
1
- /**
2
- * RAG Integration for generate() and stream()
3
- *
4
- * Provides automatic RAG pipeline setup when `rag` config is provided
5
- * in GenerateOptions or StreamOptions. Handles file loading, chunking,
6
- * embedding generation, vector storage, and tool creation internally
7
- * so developers only need to pass `rag: { files: [...] }`.
8
- */
9
1
  import { existsSync, readFileSync } from "fs";
10
2
  import { extname, resolve } from "path";
11
3
  import { z } from "zod";
@@ -9,8 +9,9 @@
9
9
  * provider/model pairs (e.g. "claude-sonnet-4-20250514" -> vertex/gemini-2.5-pro).
10
10
  * Without a router, models are passed through to the Anthropic provider.
11
11
  */
12
+ import { buildTranslationOptions } from "../../proxy/proxyTranslationEngine.js";
12
13
  import type { ModelRouter } from "../../proxy/modelRouter.js";
13
- import type { ParsedClaudeError, ParsedClaudeRequest, ProxyPassthroughAccount, RouteGroup, RuntimeAccountState } from "../../types/index.js";
14
+ import type { ParsedClaudeError, ProxyPassthroughAccount, RouteGroup, RuntimeAccountState } from "../../types/index.js";
14
15
  /** Resolve the configured primary's stable key to its current index in the
15
16
  * request's enabledAccounts list. Returns 0 (insertion-order fallback) when
16
17
  * no key is configured or the key cannot be matched (account disabled/
@@ -42,10 +43,10 @@ export declare function parseClaudeErrorBody(errBody: string): ParsedClaudeError
42
43
  * Detect malformed request errors that should not trigger account/provider failover.
43
44
  */
44
45
  export declare function isInvalidRequestError(status: number, errBody: string): boolean;
45
- export declare function buildProxyFallbackOptions(parsed: ParsedClaudeRequest, overrides?: {
46
- provider?: string;
47
- model?: string;
48
- }): Record<string, unknown>;
46
+ /**
47
+ * Backward-compatible alias — delegates to the shared translation engine.
48
+ */
49
+ export declare const buildProxyFallbackOptions: typeof buildTranslationOptions;
49
50
  /**
50
51
  * Detect transient upstream failures that should trigger account/provider failover.
51
52
  *
@@ -15,6 +15,7 @@ import { join } from "node:path";
15
15
  import { buildStableClaudeCodeBillingHeader, CLAUDE_CLI_USER_AGENT, CLAUDE_CODE_OAUTH_BETAS, getOrCreateClaudeCodeIdentity, parseClaudeCodeUserId, } from "../../auth/anthropicOAuth.js";
16
16
  import { parseQuotaHeaders, saveAccountQuota, } from "../../proxy/accountQuota.js";
17
17
  import { buildClaudeError, ClaudeStreamSerializer, generateToolUseId, parseClaudeRequest, serializeClaudeResponse, } from "../../proxy/claudeFormat.js";
18
+ import { buildAnthropicModelsListResponse, buildTranslationOptions, extractText, extractToolArgs, extractUsageFromStreamResult, handleTranslatedJsonRequest, handleTranslatedStreamRequest, hasTranslatedOutput, } from "../../proxy/proxyTranslationEngine.js";
18
19
  import { tracers } from "../../telemetry/tracers.js";
19
20
  import { withSpan } from "../../telemetry/withSpan.js";
20
21
  import { ProxyTracer, recordFallbackAttempt } from "../../proxy/proxyTracer.js";
@@ -474,23 +475,24 @@ async function handleTranslatedClaudeRequest(args) {
474
475
  logProxyRoutingPlan(logProxyBody, "translated_request", plan);
475
476
  const attempts = plan.attempts;
476
477
  if (body.stream) {
477
- return handleTranslatedClaudeStreamRequest({
478
+ return handleTranslatedStreamRequest({
478
479
  ctx,
479
- body,
480
- attempts,
480
+ format: "claude",
481
+ requestModel: body.model,
481
482
  parsed,
483
+ attempts,
482
484
  tracer,
483
485
  requestStartTime,
484
486
  });
485
487
  }
486
- return handleTranslatedClaudeJsonRequest({
488
+ return handleTranslatedJsonRequest({
487
489
  ctx,
488
- body,
489
- attempts,
490
+ format: "claude",
491
+ requestModel: body.model,
490
492
  parsed,
493
+ attempts,
491
494
  tracer,
492
495
  requestStartTime,
493
- logProxyBody,
494
496
  });
495
497
  }
496
498
  function logProxyRoutingPlan(logProxyBody, stage, plan) {
@@ -503,215 +505,6 @@ function logProxyRoutingPlan(logProxyBody, stage, plan) {
503
505
  },
504
506
  });
505
507
  }
506
- async function handleTranslatedClaudeStreamRequest(args) {
507
- const { ctx, body, attempts, parsed, tracer, requestStartTime } = args;
508
- const serializer = new ClaudeStreamSerializer(body.model, 0);
509
- const KEEPALIVE_INTERVAL_MS = 15_000;
510
- const encoder = new TextEncoder();
511
- let translationKeepAliveTimer;
512
- let translationCancelled = false;
513
- let translationSucceeded = false;
514
- let translatedModel;
515
- let finalStreamError = "No translation providers succeeded";
516
- let upstreamIterator;
517
- const translationStream = new ReadableStream({
518
- async start(controller) {
519
- for (const frame of serializer.start()) {
520
- controller.enqueue(encoder.encode(frame));
521
- }
522
- translationKeepAliveTimer = setInterval(() => {
523
- try {
524
- controller.enqueue(encoder.encode(": keep-alive\n\n"));
525
- }
526
- catch {
527
- // Controller already closed.
528
- }
529
- }, KEEPALIVE_INTERVAL_MS);
530
- try {
531
- for (let attemptIndex = 0; attemptIndex < attempts.length; attemptIndex++) {
532
- const attempt = attempts[attemptIndex];
533
- if (attemptIndex > 0) {
534
- logger.always(`[proxy] fallback → ${attempt.label}`);
535
- }
536
- let collectedText = "";
537
- try {
538
- const options = buildProxyFallbackOptions(parsed, attempt.provider
539
- ? {
540
- provider: attempt.provider,
541
- model: attempt.model,
542
- }
543
- : {});
544
- const streamResult = await ctx.neurolink.stream(options);
545
- const iterable = streamResult.stream;
546
- upstreamIterator = iterable[Symbol.asyncIterator]();
547
- while (true) {
548
- if (translationCancelled) {
549
- break;
550
- }
551
- const { value: chunk, done } = await upstreamIterator.next();
552
- if (done || translationCancelled) {
553
- break;
554
- }
555
- const text = extractText(chunk);
556
- if (text) {
557
- collectedText += text;
558
- for (const frame of serializer.pushDelta(text)) {
559
- controller.enqueue(encoder.encode(frame));
560
- }
561
- }
562
- }
563
- const toolCalls = streamResult.toolCalls ?? [];
564
- if (!hasTranslatedOutput(collectedText, toolCalls)) {
565
- finalStreamError = `Translated provider ${attempt.label} returned no content or tool calls`;
566
- logger.debug(`[proxy] translation attempt ${attempt.label} returned no content or tool calls`);
567
- continue;
568
- }
569
- if (!translationCancelled && toolCalls.length) {
570
- for (const toolCall of toolCalls) {
571
- const toolName = toolCall.toolName ??
572
- toolCall.name ??
573
- "unknown";
574
- for (const frame of serializer.pushToolUse(generateToolUseId(), toolName, extractToolArgs(toolCall))) {
575
- controller.enqueue(encoder.encode(frame));
576
- }
577
- }
578
- }
579
- if (!translationCancelled) {
580
- const reason = streamResult.finishReason ?? "end_turn";
581
- const resolvedUsage = extractUsageFromStreamResult(streamResult.usage);
582
- for (const frame of serializer.finish(resolvedUsage.output, reason)) {
583
- controller.enqueue(encoder.encode(frame));
584
- }
585
- }
586
- translatedModel = streamResult.model;
587
- translationSucceeded = true;
588
- return;
589
- }
590
- catch (streamErr) {
591
- if (translationCancelled) {
592
- return;
593
- }
594
- finalStreamError =
595
- streamErr instanceof Error
596
- ? streamErr.message
597
- : String(streamErr);
598
- if (collectedText.trim().length > 0) {
599
- logger.always(`[proxy] mid-stream error (translation mode): ${finalStreamError}`);
600
- const errorEvent = `event: error\ndata: ${JSON.stringify({ type: "error", error: { type: "api_error", message: `Upstream stream interrupted: ${finalStreamError}` } })}\n\n`;
601
- controller.enqueue(encoder.encode(errorEvent));
602
- return;
603
- }
604
- logger.debug(`[proxy] translation attempt ${attempt.label} failed: ${finalStreamError}`);
605
- }
606
- }
607
- if (!translationCancelled) {
608
- logger.always(`[proxy] mid-stream error (translation mode): ${finalStreamError}`);
609
- const errorEvent = `event: error\ndata: ${JSON.stringify({ type: "error", error: { type: "api_error", message: `Upstream stream interrupted: ${finalStreamError}` } })}\n\n`;
610
- controller.enqueue(encoder.encode(errorEvent));
611
- }
612
- }
613
- finally {
614
- if (translationKeepAliveTimer) {
615
- clearInterval(translationKeepAliveTimer);
616
- }
617
- if (!translationCancelled) {
618
- controller.close();
619
- }
620
- if (tracer && translatedModel && translatedModel !== body.model) {
621
- tracer.setModelSubstitution(body.model, translatedModel);
622
- }
623
- if (!translationSucceeded) {
624
- tracer?.setError("generation_error", finalStreamError.slice(0, 500));
625
- }
626
- tracer?.end(200, Date.now() - requestStartTime);
627
- }
628
- },
629
- cancel() {
630
- translationCancelled = true;
631
- if (translationKeepAliveTimer) {
632
- clearInterval(translationKeepAliveTimer);
633
- translationKeepAliveTimer = undefined;
634
- }
635
- if (upstreamIterator?.return) {
636
- upstreamIterator.return(undefined).catch((cancelErr) => {
637
- logger.debug(`[proxy] upstream cancel error: ${cancelErr instanceof Error ? cancelErr.message : String(cancelErr)}`);
638
- });
639
- }
640
- },
641
- });
642
- return new Response(translationStream, {
643
- headers: {
644
- "content-type": "text/event-stream",
645
- "cache-control": "no-cache",
646
- connection: "keep-alive",
647
- },
648
- });
649
- }
650
- async function handleTranslatedClaudeJsonRequest(args) {
651
- const { ctx, body, attempts, parsed, tracer, requestStartTime, logProxyBody, } = args;
652
- let lastAttemptError = "No translation providers succeeded";
653
- for (let attemptIndex = 0; attemptIndex < attempts.length; attemptIndex++) {
654
- const attempt = attempts[attemptIndex];
655
- if (attemptIndex > 0) {
656
- logger.always(`[proxy] fallback → ${attempt.label}`);
657
- }
658
- try {
659
- const options = buildProxyFallbackOptions(parsed, attempt.provider
660
- ? {
661
- provider: attempt.provider,
662
- model: attempt.model,
663
- }
664
- : {});
665
- const streamResult = await ctx.neurolink.stream(options);
666
- let collectedText = "";
667
- for await (const chunk of streamResult.stream) {
668
- const text = extractText(chunk);
669
- if (text) {
670
- collectedText += text;
671
- }
672
- }
673
- if (!hasTranslatedOutput(collectedText, streamResult.toolCalls)) {
674
- lastAttemptError = `Translated provider ${attempt.label} returned no content or tool calls`;
675
- logger.debug(`[proxy] translation attempt ${attempt.label} returned no content or tool calls`);
676
- continue;
677
- }
678
- const internal = {
679
- content: collectedText,
680
- model: streamResult.model,
681
- finishReason: streamResult.finishReason ?? "end_turn",
682
- reasoning: undefined,
683
- usage: streamResult.usage
684
- ? extractUsageFromStreamResult(streamResult.usage)
685
- : undefined,
686
- toolCalls: streamResult.toolCalls,
687
- };
688
- if (tracer && streamResult.model && streamResult.model !== body.model) {
689
- tracer.setModelSubstitution(body.model, streamResult.model);
690
- }
691
- tracer?.end(200, Date.now() - requestStartTime);
692
- const clientResponse = serializeClaudeResponse(internal, body.model);
693
- const clientResponseText = JSON.stringify(clientResponse);
694
- logProxyBody({
695
- phase: "client_response",
696
- headers: { "content-type": "application/json" },
697
- body: clientResponseText,
698
- bodySize: Buffer.byteLength(clientResponseText, "utf8"),
699
- contentType: "application/json",
700
- responseStatus: 200,
701
- durationMs: Date.now() - requestStartTime,
702
- });
703
- return clientResponse;
704
- }
705
- catch (attemptError) {
706
- lastAttemptError =
707
- attemptError instanceof Error
708
- ? attemptError.message
709
- : String(attemptError);
710
- logger.debug(`[proxy] translation attempt ${attempt.label} failed: ${lastAttemptError}`);
711
- }
712
- }
713
- throw new Error(lastAttemptError);
714
- }
715
508
  async function handleClaudePassthroughRequest(args) {
716
509
  const { ctx, body, clientRequestBody, tracer, requestStartTime, logProxyBody, } = args;
717
510
  tracer?.setMode("passthrough-cli");
@@ -3351,7 +3144,13 @@ export function createClaudeProxyRoutes(modelRouter, basePath = "", accountStrat
3351
3144
  streaming: { enabled: true, contentType: "text/event-stream" },
3352
3145
  },
3353
3146
  // =====================================================================
3354
- // GET /v1/models -- List available models
3147
+ // GET /v1/models -- List available models (Anthropic schema)
3148
+ //
3149
+ // Returns the Anthropic-shaped list response (`type`, `display_name`,
3150
+ // `created_at`, `first_id`, `last_id`, `has_more`) so Anthropic SDK
3151
+ // consumers calling this Claude-compatible surface get the schema they
3152
+ // expect. The OpenAI route serves the same data in OpenAI list format
3153
+ // via its own builder.
3355
3154
  // =====================================================================
3356
3155
  {
3357
3156
  method: "GET",
@@ -3360,24 +3159,8 @@ export function createClaudeProxyRoutes(modelRouter, basePath = "", accountStrat
3360
3159
  name: "neurolink.http.claudeProxy.listModels",
3361
3160
  tracer: tracers.http,
3362
3161
  attributes: { "http.route": `${basePath}/v1/models` },
3363
- }, async () => {
3364
- const models = [
3365
- "claude-sonnet-4-20250514",
3366
- "claude-sonnet-4-5-20250929",
3367
- "claude-haiku-4-5-20241022",
3368
- "claude-opus-4-20250514",
3369
- ];
3370
- return {
3371
- object: "list",
3372
- data: models.map((id) => ({
3373
- id,
3374
- object: "model",
3375
- created: 1700000000,
3376
- owned_by: "anthropic",
3377
- })),
3378
- };
3379
- }),
3380
- description: "List available Claude models",
3162
+ }, async () => buildAnthropicModelsListResponse(modelRouter)),
3163
+ description: "List available models (Anthropic schema)",
3381
3164
  tags: ["claude-proxy", "models"],
3382
3165
  },
3383
3166
  // =====================================================================
@@ -3418,50 +3201,6 @@ export function createClaudeProxyRoutes(modelRouter, basePath = "", accountStrat
3418
3201
  // ---------------------------------------------------------------------------
3419
3202
  // Helpers
3420
3203
  // ---------------------------------------------------------------------------
3421
- /**
3422
- * Extract token usage from a StreamResult.usage object, handling multiple
3423
- * naming conventions across AI SDK versions and providers:
3424
- * - AI SDK v6: inputTokens / outputTokens
3425
- * - AI SDK v4: promptTokens / completionTokens
3426
- * - NeuroLink internal: input / output
3427
- */
3428
- function extractUsageFromStreamResult(usage) {
3429
- if (!usage || typeof usage !== "object") {
3430
- return { input: 0, output: 0, total: 0 };
3431
- }
3432
- const u = usage;
3433
- const input = (typeof u.inputTokens === "number" ? u.inputTokens : 0) ||
3434
- (typeof u.promptTokens === "number" ? u.promptTokens : 0) ||
3435
- (typeof u.input === "number" ? u.input : 0);
3436
- const output = (typeof u.outputTokens === "number" ? u.outputTokens : 0) ||
3437
- (typeof u.completionTokens === "number" ? u.completionTokens : 0) ||
3438
- (typeof u.output === "number" ? u.output : 0);
3439
- return { input, output, total: input + output };
3440
- }
3441
- /**
3442
- * Extract text content from a stream chunk (handles various chunk formats).
3443
- */
3444
- function extractText(chunk) {
3445
- if (typeof chunk === "string") {
3446
- return chunk;
3447
- }
3448
- if (chunk && typeof chunk === "object") {
3449
- const c = chunk;
3450
- // NeuroLink StreamResult chunk format: { content: string }
3451
- if (typeof c.content === "string") {
3452
- return c.content;
3453
- }
3454
- // Vercel AI SDK text delta format
3455
- if (c.type === "text-delta" && typeof c.textDelta === "string") {
3456
- return c.textDelta;
3457
- }
3458
- // Direct text field
3459
- if (typeof c.text === "string") {
3460
- return c.text;
3461
- }
3462
- }
3463
- return null;
3464
- }
3465
3204
  function getOrCreateRuntimeState(accountKey) {
3466
3205
  const existing = accountRuntimeState.get(accountKey);
3467
3206
  if (existing) {
@@ -3612,82 +3351,10 @@ function normalizeClaudeRequestForAnthropic(body) {
3612
3351
  }),
3613
3352
  };
3614
3353
  }
3615
- export function buildProxyFallbackOptions(parsed, overrides = {}) {
3616
- const historyMessages = parsed.conversationMessages.slice(0, -1);
3617
- const toolNames = Object.keys(parsed.tools);
3618
- const images = shouldOmitImagesForTarget(overrides.provider, overrides.model)
3619
- ? []
3620
- : parsed.images;
3621
- const thinkingConfig = shouldOmitThinkingConfigForTarget(overrides.provider, overrides.model)
3622
- ? undefined
3623
- : parsed.thinkingConfig;
3624
- const toolChoice = parsed.toolChoiceName
3625
- ? { type: "tool", toolName: parsed.toolChoiceName }
3626
- : parsed.toolChoice;
3627
- return {
3628
- input: {
3629
- text: parsed.prompt,
3630
- ...(images.length > 0 ? { images } : {}),
3631
- },
3632
- ...(overrides.provider ? { provider: overrides.provider } : {}),
3633
- ...(overrides.model ? { model: overrides.model } : {}),
3634
- systemPrompt: parsed.systemPrompt,
3635
- maxTokens: parsed.maxTokens,
3636
- ...(parsed.temperature !== undefined
3637
- ? { temperature: parsed.temperature }
3638
- : {}),
3639
- ...(parsed.topP !== undefined ? { topP: parsed.topP } : {}),
3640
- ...(parsed.topK !== undefined ? { topK: parsed.topK } : {}),
3641
- ...(parsed.stopSequences?.length
3642
- ? { stopSequences: parsed.stopSequences }
3643
- : {}),
3644
- ...(thinkingConfig ? { thinkingConfig } : {}),
3645
- ...(toolNames.length === 0 ? { disableTools: true } : {}),
3646
- // Claude-compatible requests already declare the exact tool contract.
3647
- // Filter out NeuroLink's built-in agent tools so translated fallbacks only
3648
- // expose the tools the client actually knows how to handle.
3649
- ...(toolNames.length > 0
3650
- ? {
3651
- tools: parsed.tools,
3652
- toolFilter: toolNames,
3653
- }
3654
- : {}),
3655
- ...(toolChoice ? { toolChoice } : {}),
3656
- ...(historyMessages.length > 0
3657
- ? { conversationMessages: historyMessages }
3658
- : {}),
3659
- disableInternalFallback: true,
3660
- skipToolPromptInjection: true,
3661
- maxSteps: 1,
3662
- };
3663
- }
3664
- function hasTranslatedOutput(collectedText, toolCalls) {
3665
- return collectedText.trim().length > 0 || (toolCalls?.length ?? 0) > 0;
3666
- }
3667
- function shouldOmitImagesForTarget(provider, model) {
3668
- // `open-large` in our LiteLLM setup handles text and tools, but returns an
3669
- // empty completion when binary images are forwarded. Claude Code already
3670
- // includes textual image markers in the prompt, so dropping only the binary
3671
- // image payload keeps the request usable instead of breaking fallback.
3672
- return provider === "litellm" && model === "open-large";
3673
- }
3674
- function shouldOmitThinkingConfigForTarget(provider, model) {
3675
- if (provider === "litellm") {
3676
- return true;
3677
- }
3678
- if (provider !== "vertex") {
3679
- return false;
3680
- }
3681
- // Only Gemini 2.5+ and 3.x support thinking_level on Vertex.
3682
- const m = model?.toLowerCase() ?? "";
3683
- return !/gemini-(2\.5|3)/.test(m);
3684
- }
3685
- function extractToolArgs(toolCall) {
3686
- return (toolCall.args ??
3687
- toolCall.parameters ??
3688
- toolCall.input ??
3689
- {});
3690
- }
3354
+ /**
3355
+ * Backward-compatible alias — delegates to the shared translation engine.
3356
+ */
3357
+ export const buildProxyFallbackOptions = buildTranslationOptions;
3691
3358
  /**
3692
3359
  * Detect transient upstream failures that should trigger account/provider failover.
3693
3360
  *
@@ -6,6 +6,7 @@ import type { CreateRoutesOptions, RouteDefinition, RouteGroup } from "../../typ
6
6
  export { createAgentRoutes } from "./agentRoutes.js";
7
7
  export { createClaudeProxyRoutes } from "./claudeProxyRoutes.js";
8
8
  export { createHealthRoutes } from "./healthRoutes.js";
9
+ export { createOpenAIProxyRoutes } from "./openaiProxyRoutes.js";
9
10
  export { createMCPRoutes } from "./mcpRoutes.js";
10
11
  export { createMemoryRoutes } from "./memoryRoutes.js";
11
12
  export { createOpenApiRoutes } from "./openApiRoutes.js";
@@ -6,6 +6,7 @@ import { createAgentRoutes } from "./agentRoutes.js";
6
6
  import { createClaudeProxyRoutes } from "./claudeProxyRoutes.js";
7
7
  // ClaudeProxyDeps removed
8
8
  import { createHealthRoutes } from "./healthRoutes.js";
9
+ import { createOpenAIProxyRoutes } from "./openaiProxyRoutes.js";
9
10
  import { createMCPRoutes } from "./mcpRoutes.js";
10
11
  import { createMemoryRoutes } from "./memoryRoutes.js";
11
12
  import { createOpenApiRoutes } from "./openApiRoutes.js";
@@ -15,6 +16,7 @@ export { createAgentRoutes } from "./agentRoutes.js";
15
16
  export { createClaudeProxyRoutes } from "./claudeProxyRoutes.js";
16
17
  // ClaudeProxyDeps removed
17
18
  export { createHealthRoutes } from "./healthRoutes.js";
19
+ export { createOpenAIProxyRoutes } from "./openaiProxyRoutes.js";
18
20
  export { createMCPRoutes } from "./mcpRoutes.js";
19
21
  export { createMemoryRoutes } from "./memoryRoutes.js";
20
22
  export { createOpenApiRoutes } from "./openApiRoutes.js";
@@ -35,10 +37,16 @@ export function createAllRoutes(basePath = "/api", options) {
35
37
  if (options?.enableSwagger) {
36
38
  routes.push(createOpenApiRoutes(basePath, options.getRoutes));
37
39
  }
38
- // Conditionally add Claude-compatible proxy routes
39
- if (options?.claudeProxy) {
40
+ // Unified proxy flag enables both Claude and OpenAI endpoints.
41
+ // Legacy per-format flags are still supported for backward compatibility.
42
+ const enableClaudeProxy = options?.proxy || options?.claudeProxy;
43
+ const enableOpenAIProxy = options?.proxy || options?.openaiProxy;
44
+ if (enableClaudeProxy) {
40
45
  routes.push(createClaudeProxyRoutes(undefined, basePath));
41
46
  }
47
+ if (enableOpenAIProxy) {
48
+ routes.push(createOpenAIProxyRoutes(undefined, basePath));
49
+ }
42
50
  return routes;
43
51
  }
44
52
  /**
@@ -0,0 +1,30 @@
1
+ /**
2
+ * OpenAI-Compatible Proxy Routes
3
+ *
4
+ * Exposes OpenAI Chat Completions-compatible /v1/chat/completions endpoint.
5
+ * ALL requests are routed through ctx.neurolink.stream() — no direct
6
+ * HTTP calls to any upstream provider.
7
+ *
8
+ * This is a thin wrapper that parses OpenAI format requests and delegates
9
+ * to the shared proxy translation engine.
10
+ *
11
+ * An optional ModelRouter can remap incoming model names to different
12
+ * provider/model pairs (e.g. "gpt-4o" -> vertex/gemini-2.5-pro).
13
+ */
14
+ import type { ModelRouter } from "../../proxy/modelRouter.js";
15
+ import type { RouteGroup } from "../../types/index.js";
16
+ /**
17
+ * Create OpenAI-compatible proxy routes.
18
+ *
19
+ * Every request flows through ctx.neurolink.stream() — no direct HTTP calls
20
+ * to any upstream provider.
21
+ *
22
+ * @param modelRouter - Optional model router for remapping model names.
23
+ * @param basePath - Base path prefix (default: "").
24
+ * @param loopbackPort - Listener port used by the Anthropic loopback bridge.
25
+ * Defaults to the CLI proxy default (55669). MUST be the
26
+ * actual listener port — never derived from request
27
+ * headers — to avoid SSRF.
28
+ * @returns RouteGroup with OpenAI-compatible endpoints.
29
+ */
30
+ export declare function createOpenAIProxyRoutes(modelRouter?: ModelRouter, basePath?: string, loopbackPort?: number): RouteGroup;