@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
@@ -0,0 +1,336 @@
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 { buildOpenAIError, convertClaudeToOpenAIResponse, convertOpenAIToClaudeRequest, createClaudeToOpenAIStreamTransform, parseOpenAIRequest, } from "../../proxy/openaiFormat.js";
15
+ import { ProxyTracer } from "../../proxy/proxyTracer.js";
16
+ import { buildModelsListResponse, handleTranslatedJsonRequest, handleTranslatedStreamRequest, } from "../../proxy/proxyTranslationEngine.js";
17
+ import { logRequest } from "../../proxy/requestLogger.js";
18
+ import { buildProxyTranslationPlan } from "../../proxy/routingPolicy.js";
19
+ import { withTimeout } from "../../utils/async/withTimeout.js";
20
+ import { sanitizeForLog } from "../../utils/logSanitize.js";
21
+ import { logger } from "../../utils/logger.js";
22
+ // Maximum time the internal loopback fetch is allowed to take before we
23
+ // give up — keeps a stuck inner /v1/messages handler from hanging the outer
24
+ // /v1/chat/completions request indefinitely.
25
+ const LOOPBACK_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes — long enough for slow Claude streams
26
+ // Default loopback port — matches the CLI proxy default. Overridden via
27
+ // `createOpenAIProxyRoutes`'s third argument when the actual listener port is
28
+ // known (e.g. when started from the CLI handler).
29
+ const DEFAULT_LOOPBACK_PORT = 55669;
30
+ /**
31
+ * Build an OpenAI-shaped error as a typed Response with the intended status.
32
+ *
33
+ * Without the explicit Response wrapper, the CLI proxy runtime maps plain
34
+ * objects to HTTP 200, so error returns would silently arrive as 200s with
35
+ * an error payload. Wrapping in Response forces the runtime to honor the
36
+ * status code we computed.
37
+ */
38
+ function buildOpenAIErrorResponse(status, message) {
39
+ return new Response(JSON.stringify(buildOpenAIError(status, message)), {
40
+ status,
41
+ headers: { "content-type": "application/json" },
42
+ });
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // Adapt ParsedOpenAIRequest to the shape buildProxyTranslationPlan expects
46
+ // ---------------------------------------------------------------------------
47
+ /**
48
+ * buildProxyTranslationPlan's classifier expects ParsedClaudeRequest.
49
+ * The shapes are nearly identical; we just fill in the extra fields it inspects
50
+ * (thinkingConfig, topK) with safe defaults.
51
+ */
52
+ function adaptForTranslationPlan(parsed) {
53
+ return {
54
+ model: parsed.model,
55
+ maxTokens: parsed.maxTokens ?? 4096,
56
+ temperature: parsed.temperature,
57
+ topP: parsed.topP,
58
+ systemPrompt: typeof parsed.systemPrompt === "string" ? parsed.systemPrompt : undefined,
59
+ stream: parsed.stream,
60
+ prompt: parsed.prompt,
61
+ images: parsed.images,
62
+ conversationMessages: parsed.conversationMessages,
63
+ tools: parsed.tools,
64
+ toolChoice: parsed.toolChoice,
65
+ toolChoiceName: parsed.toolChoiceName,
66
+ stopSequences: parsed.stopSequences,
67
+ };
68
+ }
69
+ // ---------------------------------------------------------------------------
70
+ // OpenAI -> Anthropic loopback bridge
71
+ // ---------------------------------------------------------------------------
72
+ /**
73
+ * Forward an OpenAI-format request targeting a Claude model through the
74
+ * proxy's own /v1/messages endpoint via a loopback fetch().
75
+ *
76
+ * This reuses the full Claude passthrough path (OAuth account rotation, retry,
77
+ * SSE interception, etc.) and only adds format conversion at the edges.
78
+ *
79
+ * The loopback target is ALWAYS `127.0.0.1:<loopbackPort>` (never derived
80
+ * from the client-controlled `Host` header — that would be an SSRF vector).
81
+ * `loopbackPort` is provided at route-build time from the listener's actual
82
+ * port via `createOpenAIProxyRoutes(modelRouter, basePath, loopbackPort)`.
83
+ */
84
+ async function handleOpenAIToAnthropicBridge(args) {
85
+ const { ctx, body, targetModel, requestStartTime, loopbackPort } = args;
86
+ const stream = body.stream === true;
87
+ const toolCount = body.tools?.length ?? 0;
88
+ const writeLifecycle = (responseStatus, extra = {}) => logRequest({
89
+ timestamp: new Date().toISOString(),
90
+ requestId: ctx.requestId,
91
+ method: ctx.method,
92
+ path: ctx.path,
93
+ model: body.model,
94
+ stream,
95
+ toolCount,
96
+ account: "",
97
+ accountType: "openai-bridge",
98
+ responseStatus,
99
+ responseTimeMs: Date.now() - requestStartTime,
100
+ ...extra,
101
+ });
102
+ // Convert to Claude format and remap the model to the router's choice.
103
+ const claudeBody = convertOpenAIToClaudeRequest(body);
104
+ claudeBody.model = targetModel;
105
+ // SECURITY: Never derive the loopback target from the client-controlled
106
+ // `Host` header. The bridge always fetches from 127.0.0.1 on the listener's
107
+ // configured port — anything else would be an SSRF vector.
108
+ const internalUrl = `http://127.0.0.1:${loopbackPort}/v1/messages`;
109
+ // Forward a minimal set of headers. The proxy's own /v1/messages handler
110
+ // will attach OAuth credentials from its account pool.
111
+ const forwardHeaders = {
112
+ "content-type": "application/json",
113
+ accept: stream ? "text/event-stream" : "application/json",
114
+ };
115
+ for (const [k, v] of Object.entries(ctx.headers)) {
116
+ if (typeof v !== "string") {
117
+ continue;
118
+ }
119
+ const lower = k.toLowerCase();
120
+ if (lower.startsWith("anthropic-") || lower === "x-api-key") {
121
+ forwardHeaders[lower] = v;
122
+ }
123
+ }
124
+ // Bound the self-call with a timeout so a stuck inner handler can't hang
125
+ // the outer /v1/chat/completions request indefinitely.
126
+ const upstream = await withTimeout(fetch(internalUrl, {
127
+ method: "POST",
128
+ headers: forwardHeaders,
129
+ body: JSON.stringify({ ...claudeBody, stream }),
130
+ }), LOOPBACK_TIMEOUT_MS, `Anthropic loopback timed out after ${LOOPBACK_TIMEOUT_MS}ms`);
131
+ if (!upstream.ok) {
132
+ const errText = await upstream.text().catch(() => "");
133
+ const safeErrText = sanitizeForLog(errText);
134
+ logger.always(`[proxy:openai] anthropic loopback error ${upstream.status}: ${safeErrText}`);
135
+ await writeLifecycle(upstream.status, {
136
+ errorType: "loopback_upstream_error",
137
+ errorMessage: safeErrText,
138
+ });
139
+ return buildOpenAIErrorResponse(upstream.status, safeErrText || `Anthropic loopback failed with status ${upstream.status}`);
140
+ }
141
+ if (stream) {
142
+ if (!upstream.body) {
143
+ await writeLifecycle(502, {
144
+ errorType: "loopback_empty_stream",
145
+ errorMessage: "Anthropic loopback returned empty stream body",
146
+ });
147
+ return buildOpenAIErrorResponse(502, "Anthropic loopback returned empty stream body");
148
+ }
149
+ // Streaming success: log now since the response body is consumed by the
150
+ // client. Token counts are not visible at this layer (the inner /v1/messages
151
+ // handler accounts them), so we omit them here.
152
+ await writeLifecycle(200);
153
+ const transformed = upstream.body.pipeThrough(createClaudeToOpenAIStreamTransform(body.model));
154
+ return new Response(transformed, {
155
+ status: 200,
156
+ headers: {
157
+ "content-type": "text/event-stream",
158
+ "cache-control": "no-cache",
159
+ connection: "keep-alive",
160
+ },
161
+ });
162
+ }
163
+ const claudeJson = (await upstream.json());
164
+ await writeLifecycle(200, {
165
+ inputTokens: claudeJson.usage?.input_tokens,
166
+ outputTokens: claudeJson.usage?.output_tokens,
167
+ cacheCreationTokens: claudeJson.usage?.cache_creation_input_tokens,
168
+ cacheReadTokens: claudeJson.usage?.cache_read_input_tokens,
169
+ });
170
+ return convertClaudeToOpenAIResponse(claudeJson, body.model);
171
+ }
172
+ // ---------------------------------------------------------------------------
173
+ // Route factory
174
+ // ---------------------------------------------------------------------------
175
+ /**
176
+ * Create OpenAI-compatible proxy routes.
177
+ *
178
+ * Every request flows through ctx.neurolink.stream() — no direct HTTP calls
179
+ * to any upstream provider.
180
+ *
181
+ * @param modelRouter - Optional model router for remapping model names.
182
+ * @param basePath - Base path prefix (default: "").
183
+ * @param loopbackPort - Listener port used by the Anthropic loopback bridge.
184
+ * Defaults to the CLI proxy default (55669). MUST be the
185
+ * actual listener port — never derived from request
186
+ * headers — to avoid SSRF.
187
+ * @returns RouteGroup with OpenAI-compatible endpoints.
188
+ */
189
+ export function createOpenAIProxyRoutes(modelRouter, basePath = "", loopbackPort = DEFAULT_LOOPBACK_PORT) {
190
+ return {
191
+ prefix: `${basePath}/v1`,
192
+ routes: [
193
+ // =================================================================
194
+ // POST /v1/chat/completions — Main chat completions endpoint
195
+ // =================================================================
196
+ {
197
+ method: "POST",
198
+ path: `${basePath}/v1/chat/completions`,
199
+ description: "OpenAI-compatible chat completions (translation mode)",
200
+ handler: async (ctx) => {
201
+ const requestStartTime = Date.now();
202
+ const body = ctx.body;
203
+ // --- Validation ---
204
+ if (!body || !body.model || !body.messages?.length) {
205
+ return buildOpenAIErrorResponse(400, "Request must include 'model' and 'messages' fields");
206
+ }
207
+ // --- Resolve target provider/model ---
208
+ const route = modelRouter
209
+ ? modelRouter.resolve(body.model)
210
+ : { provider: null, model: body.model };
211
+ const targetProvider = route.provider ?? undefined;
212
+ const targetModel = route.model ?? body.model;
213
+ logger.debug(`[proxy:openai] ${body.model} → ${targetProvider ?? "auto"}/${targetModel}`);
214
+ // --- Anthropic loopback bridge ---
215
+ // When the resolved target is Anthropic, the proxy has no
216
+ // ANTHROPIC_API_KEY (it uses OAuth passthrough). Instead of trying
217
+ // to stream through the SDK, forward the request to our own
218
+ // /v1/messages endpoint via loopback so it goes through the full
219
+ // Claude passthrough path (OAuth, retry, rotation, SSE intercept).
220
+ if (route.provider === "anthropic") {
221
+ try {
222
+ return await handleOpenAIToAnthropicBridge({
223
+ ctx,
224
+ body,
225
+ targetModel,
226
+ requestStartTime,
227
+ loopbackPort,
228
+ });
229
+ }
230
+ catch (err) {
231
+ // Internal exception text (.message + any stack-trace remnants)
232
+ // is kept ONLY in server-side logs + tracer. The client receives
233
+ // a fixed generic message so internal paths/frames don't leak
234
+ // back through the response body. (CodeQL: information exposure
235
+ // through a stack trace.)
236
+ const rawMessage = err instanceof Error ? err.message : String(err);
237
+ const internalDetail = sanitizeForLog(rawMessage);
238
+ logger.always(`[proxy:openai] anthropic loopback failed: ${internalDetail}`);
239
+ await logRequest({
240
+ timestamp: new Date().toISOString(),
241
+ requestId: ctx.requestId,
242
+ method: ctx.method,
243
+ path: ctx.path,
244
+ model: body.model,
245
+ stream: body.stream === true,
246
+ toolCount: body.tools?.length ?? 0,
247
+ account: "",
248
+ accountType: "openai-bridge",
249
+ responseStatus: 502,
250
+ responseTimeMs: Date.now() - requestStartTime,
251
+ errorType: "loopback_exception",
252
+ errorMessage: internalDetail,
253
+ });
254
+ return buildOpenAIErrorResponse(502, "Anthropic loopback failed");
255
+ }
256
+ }
257
+ // --- Parse request ---
258
+ const parsed = parseOpenAIRequest(body);
259
+ // --- Build translation plan ---
260
+ const adapted = adaptForTranslationPlan(parsed);
261
+ const plan = buildProxyTranslationPlan({
262
+ provider: targetProvider ?? "auto",
263
+ model: targetModel,
264
+ }, modelRouter?.getFallbackChain() ?? [], body.model,
265
+ // The classifier only reads fields present on both types.
266
+ adapted);
267
+ const attempts = plan.attempts;
268
+ // --- Optional tracing ---
269
+ let tracer;
270
+ try {
271
+ tracer = ProxyTracer.startRequest({
272
+ requestId: ctx.requestId,
273
+ method: ctx.method,
274
+ path: ctx.path,
275
+ model: body.model,
276
+ stream: body.stream === true,
277
+ toolCount: Object.keys(parsed.tools).length,
278
+ clientApp: "openai-compat",
279
+ userAgent: ctx.headers["user-agent"] ?? "",
280
+ }, ctx.headers);
281
+ tracer.setMode("full");
282
+ }
283
+ catch {
284
+ // Tracing is best-effort; continue without it.
285
+ }
286
+ // --- Dispatch via shared translation engine ---
287
+ try {
288
+ if (body.stream) {
289
+ return handleTranslatedStreamRequest({
290
+ ctx,
291
+ format: "openai",
292
+ requestModel: body.model,
293
+ parsed,
294
+ attempts,
295
+ tracer,
296
+ requestStartTime,
297
+ });
298
+ }
299
+ return await handleTranslatedJsonRequest({
300
+ ctx,
301
+ format: "openai",
302
+ requestModel: body.model,
303
+ parsed,
304
+ attempts,
305
+ tracer,
306
+ requestStartTime,
307
+ });
308
+ }
309
+ catch (err) {
310
+ // Internal exception text is kept ONLY in server-side logs +
311
+ // tracer. The client receives a fixed generic message so internal
312
+ // paths/frames don't leak back through the response body.
313
+ // (CodeQL: information exposure through a stack trace.)
314
+ const rawMessage = err instanceof Error ? err.message : String(err);
315
+ const internalDetail = sanitizeForLog(rawMessage);
316
+ logger.always(`[proxy:openai] request failed: ${internalDetail}`);
317
+ tracer?.setError("generation_error", internalDetail);
318
+ tracer?.end(500, Date.now() - requestStartTime);
319
+ return buildOpenAIErrorResponse(500, "Internal proxy error");
320
+ }
321
+ },
322
+ },
323
+ // =================================================================
324
+ // GET /v1/models — List available models (OpenAI list format)
325
+ // =================================================================
326
+ {
327
+ method: "GET",
328
+ path: `${basePath}/v1/models`,
329
+ description: "List available models in OpenAI format",
330
+ handler: async () => {
331
+ return buildModelsListResponse(modelRouter);
332
+ },
333
+ },
334
+ ],
335
+ };
336
+ }
@@ -1,14 +1,5 @@
1
- /**
2
- * Built-in agent tools for TaskManager.
3
- *
4
- * These tools allow the AI to self-schedule, manage, and inspect tasks
5
- * during conversations. Created per-instance via `createTaskTools()` factory,
6
- * following the same pattern as `createFileTools()` in files/fileTools.ts.
7
- *
8
- * @module tasks/tools/taskTools
9
- */
10
1
  import type { TaskManager } from "../taskManager.js";
11
- import type { TaskSchedule } from "../../types/index.js";
2
+ import type { Tool } from "../../types/index.js";
12
3
  /**
13
4
  * Create task management tools bound to a TaskManager instance.
14
5
  *
@@ -26,110 +17,4 @@ import type { TaskSchedule } from "../../types/index.js";
26
17
  * // tools.createTask, tools.listTasks, tools.getTaskRuns, etc.
27
18
  * ```
28
19
  */
29
- export declare function createTaskTools(manager: TaskManager): {
30
- createTask: import("ai").Tool<{
31
- name: string;
32
- prompt: string;
33
- schedule: {
34
- type: "once" | "cron" | "interval";
35
- expression?: string | undefined;
36
- timezone?: string | undefined;
37
- every?: number | undefined;
38
- at?: string | undefined;
39
- };
40
- mode?: "isolated" | "continuation" | undefined;
41
- }, {
42
- success: boolean;
43
- taskId: string;
44
- name: string;
45
- status: import("../../index.js").TaskStatus;
46
- mode: import("../../index.js").TaskExecutionMode;
47
- nextRunAt: string | undefined;
48
- schedule: TaskSchedule;
49
- error?: undefined;
50
- } | {
51
- success: boolean;
52
- error: string;
53
- taskId?: undefined;
54
- name?: undefined;
55
- status?: undefined;
56
- mode?: undefined;
57
- nextRunAt?: undefined;
58
- schedule?: undefined;
59
- }>;
60
- listTasks: import("ai").Tool<{
61
- status?: "failed" | "pending" | "completed" | "cancelled" | "active" | "paused" | undefined;
62
- }, {
63
- success: boolean;
64
- count: number;
65
- tasks: {
66
- taskId: string;
67
- name: string;
68
- status: import("../../index.js").TaskStatus;
69
- mode: import("../../index.js").TaskExecutionMode;
70
- schedule: TaskSchedule;
71
- runCount: number;
72
- lastRunAt: string | undefined;
73
- nextRunAt: string | undefined;
74
- }[];
75
- error?: undefined;
76
- } | {
77
- success: boolean;
78
- error: string;
79
- count?: undefined;
80
- tasks?: undefined;
81
- }>;
82
- getTaskRuns: import("ai").Tool<{
83
- taskId: string;
84
- limit?: number | undefined;
85
- }, {
86
- success: boolean;
87
- taskId: string;
88
- count: number;
89
- runs: {
90
- runId: string;
91
- status: "error" | "success";
92
- output: string | undefined;
93
- durationMs: number;
94
- timestamp: string;
95
- error: string | undefined;
96
- }[];
97
- error?: undefined;
98
- } | {
99
- success: boolean;
100
- error: string;
101
- taskId?: undefined;
102
- count?: undefined;
103
- runs?: undefined;
104
- }>;
105
- deleteTask: import("ai").Tool<{
106
- taskId: string;
107
- }, {
108
- success: boolean;
109
- error: string;
110
- deletedTask?: undefined;
111
- taskId?: undefined;
112
- } | {
113
- success: boolean;
114
- deletedTask: string;
115
- taskId: string;
116
- error?: undefined;
117
- }>;
118
- runTaskNow: import("ai").Tool<{
119
- taskId: string;
120
- }, {
121
- success: boolean;
122
- runId: string;
123
- status: "error" | "success";
124
- output: string | undefined;
125
- durationMs: number;
126
- error: string | undefined;
127
- } | {
128
- success: boolean;
129
- error: string;
130
- runId?: undefined;
131
- status?: undefined;
132
- output?: undefined;
133
- durationMs?: undefined;
134
- }>;
135
- };
20
+ export declare function createTaskTools(manager: TaskManager): Record<string, Tool>;
@@ -1,16 +1,7 @@
1
- /**
2
- * Built-in agent tools for TaskManager.
3
- *
4
- * These tools allow the AI to self-schedule, manage, and inspect tasks
5
- * during conversations. Created per-instance via `createTaskTools()` factory,
6
- * following the same pattern as `createFileTools()` in files/fileTools.ts.
7
- *
8
- * @module tasks/tools/taskTools
9
- */
10
- import { tool } from "ai";
11
1
  import { z } from "zod";
12
2
  import { logger } from "../../utils/logger.js";
13
3
  import { TaskError } from "../errors.js";
4
+ import { tool } from "../../utils/tool.js";
14
5
  /**
15
6
  * Parse a schedule object from tool input.
16
7
  * Accepts: { type: "cron", expression } | { type: "interval", every } | { type: "once", at }
@@ -3,9 +3,9 @@
3
3
  * Centralizes commonly used complex types to improve readability and maintainability
4
4
  */
5
5
  import type { ZodTypeAny } from "zod";
6
- import type { Schema } from "ai";
7
6
  import type { JsonValue, Result, AsyncFunction } from "./common.js";
8
7
  import { zodToJsonSchema } from "zod-to-json-schema";
8
+ import type { Schema } from "./tools.js";
9
9
  /**
10
10
  * Type alias for complex Zod schema type to improve readability
11
11
  * Used across providers and validation systems
@@ -34,6 +34,7 @@
34
34
  */
35
35
  import type { HippocampusMemory, HippocampusStorageConfig } from "./memory.js";
36
36
  import type { ObservabilityConfig } from "./observability.js";
37
+ export type { ModelMessage, SystemModelMessage, UserModelMessage, AssistantModelMessage, ToolModelMessage, TextPart, ImagePart, FilePart, ToolCallPart, ToolResultPart, AssistantContent, UserContent, ToolContent, DataContent, } from "ai";
37
38
  /**
38
39
  * Legacy public alias for the Hippocampus storage configuration.
39
40
  * The structural definition lives in `./memory.ts`; this re-export keeps
@@ -1,13 +1,9 @@
1
- /**
2
- * Evaluation type definitions for NeuroLink
3
- * Provider performance tracking, evaluation configurations, and provider optimization types
4
- */
5
- import type { LanguageModelV3CallOptions } from "@ai-sdk/provider";
6
1
  import type { TokenUsage } from "./analytics.js";
7
2
  import type { GenerateResult } from "./generate.js";
8
3
  import type { ToolExecution } from "./tools.js";
9
4
  import type { JsonObject } from "./common.js";
10
5
  import type { AggregatedScores, EvaluationTraceContext, PipelineConfig, ReportConfig, ReportFormat, ScoreResult, ScorerInput } from "./scorer.js";
6
+ import type { LanguageModelV3CallOptions } from "./middleware.js";
11
7
  /**
12
8
  * Evaluation provider type as specified in core module refactoring
13
9
  */
@@ -1,5 +1 @@
1
- /**
2
- * Evaluation type definitions for NeuroLink
3
- * Provider performance tracking, evaluation configurations, and provider optimization types
4
- */
5
1
  export {};
@@ -1,4 +1,3 @@
1
- import type { Schema, Tool, ToolChoice, StepResult, LanguageModel } from "ai";
2
1
  import type { AIProviderName } from "../constants/enums.js";
3
2
  import type { RAGConfig } from "./rag.js";
4
3
  import type { AnalyticsData, TokenUsage } from "./analytics.js";
@@ -17,6 +16,8 @@ import type { StandardRecord, ValidationSchema, ZodUnknownSchema } from "./alias
17
16
  import type { NeurolinkCredentials } from "./providers.js";
18
17
  import type { FileWithMetadata } from "./file.js";
19
18
  import type { WorkflowConfig } from "./workflow.js";
19
+ import type { Schema, Tool, ToolChoice } from "./tools.js";
20
+ import type { StepResult, LanguageModel } from "./providers.js";
20
21
  /**
21
22
  * Generate function options type - Primary method for content generation
22
23
  * Supports multimodal content while maintaining backward compatibility
@@ -467,17 +468,6 @@ export type GenerateOptions = {
467
468
  * callers can correlate generation traces back to their own request lifecycle.
468
469
  */
469
470
  requestId?: string;
470
- /**
471
- * File reference registry for on-demand file processing.
472
- *
473
- * When set, files above the "tiny" size tier (>10KB) will be registered
474
- * as lightweight references instead of being fully loaded into the prompt.
475
- * The LLM can then access file content on-demand via file tools
476
- * (list_attached_files, read_file_section, search_in_file).
477
- *
478
- * @internal Set by NeuroLink SDK — not typically used directly by consumers.
479
- */
480
- fileRegistry?: unknown;
481
471
  /** Per-call middleware configuration. */
482
472
  middleware?: MiddlewareFactoryOptions;
483
473
  /** Callback invoked when generation completes successfully. */
@@ -988,16 +978,6 @@ export type TextGenerationOptions = {
988
978
  includeHeaders?: boolean;
989
979
  };
990
980
  enableSummarization?: boolean;
991
- /**
992
- * File reference registry for on-demand file processing (internal).
993
- *
994
- * When set, files above the "tiny" size tier (>10KB) will be registered
995
- * as lightweight references instead of being fully loaded into the prompt.
996
- * The LLM can then access file content on-demand via file tools.
997
- *
998
- * @internal Set by NeuroLink SDK — not typically used directly by consumers.
999
- */
1000
- fileRegistry?: unknown;
1001
981
  /**
1002
982
  * Skip injecting tool schemas into the system prompt.
1003
983
  * When true, tools are ONLY passed natively via the provider's `tools` parameter,
@@ -1,4 +1,4 @@
1
- import type { LanguageModel } from "ai";
1
+ import type { LanguageModel } from "./providers.js";
2
2
  /**
3
3
  * Result from precall evaluation of user input
4
4
  */
@@ -1,7 +1,12 @@
1
- import type { LanguageModelMiddleware } from "ai";
2
1
  import type { JsonValue } from "../types/common.js";
3
2
  import type { EvaluationData, GetPromptFunction } from "./evaluation.js";
4
3
  import type { AuthenticatedUser, RouteDefinition, ServerContext } from "./server.js";
4
+ import type { LanguageModelMiddleware as BaseLanguageModelMiddleware } from "ai";
5
+ export type { LanguageModelMiddleware } from "ai";
6
+ export type { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3Message, LanguageModelV3StreamPart, LanguageModelV3ToolCall, LanguageModelV3ToolChoice, LanguageModelV3Source, LanguageModelV3Middleware, JSONSchema7, } from "@ai-sdk/provider";
7
+ import type { LanguageModelV3 } from "@ai-sdk/provider";
8
+ export type LanguageModelV3GenerateResult = Awaited<ReturnType<LanguageModelV3["doGenerate"]>>;
9
+ export type LanguageModelV3StreamResult = Awaited<ReturnType<LanguageModelV3["doStream"]>>;
5
10
  /**
6
11
  * Metadata type for NeuroLink middleware
7
12
  * Provides additional information about middleware without affecting execution
@@ -24,7 +29,7 @@ export type NeuroLinkMiddlewareMetadata = {
24
29
  * NeuroLink middleware with metadata
25
30
  * Combines standard AI SDK middleware with NeuroLink-specific metadata
26
31
  */
27
- export type NeuroLinkMiddleware = LanguageModelMiddleware & {
32
+ export type NeuroLinkMiddleware = BaseLanguageModelMiddleware & {
28
33
  /** Middleware metadata */
29
34
  readonly metadata: NeuroLinkMiddlewareMetadata;
30
35
  };
@@ -192,7 +197,7 @@ export type MiddlewareRegistryEntry = {
192
197
  /**
193
198
  * Middleware factory function type
194
199
  */
195
- export type MiddlewareFactory = (config: Record<string, unknown>) => LanguageModelMiddleware;
200
+ export type MiddlewareFactory = (config: Record<string, unknown>) => BaseLanguageModelMiddleware;
196
201
  /**
197
202
  * Middleware validation result
198
203
  */
@@ -4,12 +4,13 @@
4
4
  import type { UnknownRecord, JsonValue, StreamingCapability } from "./common.js";
5
5
  import type { ProviderError } from "./errors.js";
6
6
  import { AIProviderName, AnthropicModels, BedrockModels, DeepSeekModels, GoogleAIModels, LlamaCppModels, LMStudioModels, NvidiaNimModels, OpenAIModels, VertexModels } from "../constants/enums.js";
7
- import type { Tool } from "ai";
8
7
  import type { ValidationSchema } from "./aliases.js";
9
8
  import type { EnhancedGenerateResult, GenerateResult, TextGenerationOptions } from "./generate.js";
10
9
  import type { StreamOptions, StreamResult } from "./stream.js";
11
10
  import type { ExternalMCPToolInfo } from "./externalMcp.js";
12
11
  import type { ClaudeSubscriptionTier, AnthropicAuthMethod, AnthropicAuthConfig, SubscriptionInfo, OAuthToken } from "./subscription.js";
12
+ import type { Tool } from "./tools.js";
13
+ export type { LanguageModel, EmbeddingModel, ImageModel, GenerateTextResult, StepResult, ToolCallRepairFunction, PrepareStepFunction, PrepareStepResult, FinishReason, LanguageModelUsage, LanguageModelRequestMetadata, LanguageModelResponseMetadata, } from "ai";
13
14
  export type { ClaudeSubscriptionTier, AnthropicAuthMethod, AnthropicAuthConfig, SubscriptionInfo, } from "./subscription.js";
14
15
  /**
15
16
  * Generic AI SDK model interface