@juspay/neurolink 9.68.0 → 9.68.2

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.
@@ -1,135 +1,59 @@
1
- import { createOpenAI } from "@ai-sdk/openai";
2
1
  import { XaiModels } from "../constants/enums.js";
3
- import { BaseProvider } from "../core/baseProvider.js";
4
- import { DEFAULT_MAX_STEPS } from "../core/constants.js";
5
- import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
6
- import { isNeuroLink } from "../neurolink.js";
7
- import { createLoggingFetch } from "../utils/loggingFetch.js";
8
- import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
9
2
  import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
10
3
  import { logger } from "../utils/logger.js";
11
4
  import { createXaiConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
12
- import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
13
- import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
14
- import { resolveToolChoice } from "../utils/toolChoice.js";
15
- import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
16
- import { stepCountIs } from "../utils/tool.js";
17
- import { streamText } from "../utils/generation.js";
18
- /**
19
- * Logging fetch wrapper — masks the proxy URL on non-2xx responses so
20
- * stack traces and log lines don't leak the upstream's internal token /
21
- * tenant id (mirrors the deepseek/groq/etc. providers).
22
- */
5
+ import { TimeoutError } from "../utils/timeout.js";
6
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
23
7
  const XAI_DEFAULT_BASE_URL = "https://api.x.ai/v1";
24
8
  const getXaiApiKey = () => validateApiKey(createXaiConfig());
25
9
  const getDefaultXaiModel = () => getProviderModel("XAI_MODEL", XaiModels.GROK_3);
26
10
  /**
27
- * xAI Grok Provider
11
+ * xAI Grok Provider — direct HTTP, no AI SDK.
28
12
  *
29
- * OpenAI-compatible chat completions at api.x.ai/v1. Supports the Grok
30
- * family: grok-2, grok-3, grok-3-mini, grok-2-vision-latest (multimodal),
31
- * and grok-beta. Streaming and tool calling supported.
13
+ * OpenAI-compatible chat completions at api.x.ai/v1 (Grok family:
14
+ * grok-3, grok-3-mini, grok-2-latest, grok-2-vision-latest, grok-beta).
15
+ * All request/stream/tool-loop orchestration lives in
16
+ * `OpenAIChatCompletionsProvider`; this class only declares configuration
17
+ * and provider-specific error mapping.
32
18
  *
33
19
  * @see https://docs.x.ai/api
34
20
  */
35
- export class XaiProvider extends BaseProvider {
36
- model;
37
- apiKey;
38
- baseURL;
21
+ export class XaiProvider extends OpenAIChatCompletionsProvider {
39
22
  constructor(modelName, sdk, _region, credentials) {
40
- const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
41
- super(modelName, "xai", validatedNeurolink);
23
+ // Trim the override before applying precedence. A blank/whitespace
24
+ // `credentials.apiKey` must NOT bypass the env key — that would build a
25
+ // client with an unusable bearer token and fail at request time.
42
26
  const overrideApiKey = credentials?.apiKey?.trim();
43
- this.apiKey =
44
- overrideApiKey && overrideApiKey.length > 0
45
- ? overrideApiKey
46
- : getXaiApiKey();
47
- this.baseURL =
48
- credentials?.baseURL ?? process.env.XAI_BASE_URL ?? XAI_DEFAULT_BASE_URL;
49
- const xai = createOpenAI({
50
- apiKey: this.apiKey,
51
- baseURL: this.baseURL,
52
- fetch: createLoggingFetch("xai"),
53
- });
54
- this.model = xai.chat(this.modelName);
27
+ const apiKey = overrideApiKey && overrideApiKey.length > 0
28
+ ? overrideApiKey
29
+ : getXaiApiKey();
30
+ const baseURL = credentials?.baseURL?.trim() ||
31
+ process.env.XAI_BASE_URL?.trim() ||
32
+ XAI_DEFAULT_BASE_URL;
33
+ super("xai", modelName, sdk, { baseURL, apiKey });
55
34
  logger.debug("xAI Provider initialized", {
56
35
  modelName: this.modelName,
57
36
  providerName: this.providerName,
58
- baseURL: this.baseURL,
37
+ baseURL: this.config.baseURL,
59
38
  });
60
39
  }
61
- async executeStream(options, _analysisSchema) {
62
- return withClientStreamSpan({
63
- name: "neurolink.provider.stream",
64
- tracer: tracers.provider,
65
- attributes: {
66
- [ATTR.GEN_AI_SYSTEM]: "xai",
67
- [ATTR.GEN_AI_MODEL]: this.modelName,
68
- [ATTR.GEN_AI_OPERATION]: "stream",
69
- [ATTR.NL_STREAM_MODE]: true,
70
- },
71
- }, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
72
- }
73
- async executeStreamInner(options) {
74
- this.validateStreamOptions(options);
75
- const startTime = Date.now();
76
- const timeout = this.getTimeout(options);
77
- const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
78
- try {
79
- const shouldUseTools = !options.disableTools && this.supportsTools();
80
- const tools = shouldUseTools
81
- ? options.tools || (await this.getAllTools())
82
- : {};
83
- const messages = await this.buildMessagesForStream(options);
84
- const model = await this.getAISDKModelWithMiddleware(options);
85
- const result = await streamText({
86
- model,
87
- messages,
88
- temperature: options.temperature,
89
- maxOutputTokens: options.maxTokens,
90
- tools,
91
- stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
92
- toolChoice: resolveToolChoice(options, tools, shouldUseTools),
93
- abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
94
- experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
95
- experimental_repairToolCall: this.getToolCallRepairFn(options),
96
- onStepFinish: ({ toolCalls, toolResults }) => {
97
- emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
98
- this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
99
- logger.warn("[XaiProvider] Failed to store tool executions", {
100
- provider: this.providerName,
101
- error: error instanceof Error ? error.message : String(error),
102
- });
103
- });
104
- },
105
- });
106
- timeoutController?.cleanup();
107
- const transformedStream = this.createTextStream(result);
108
- const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
109
- requestId: `xai-stream-${Date.now()}`,
110
- streamingMode: true,
111
- });
112
- return {
113
- stream: transformedStream,
114
- provider: this.providerName,
115
- model: this.modelName,
116
- analytics: analyticsPromise,
117
- metadata: { startTime, streamId: `xai-${Date.now()}` },
118
- };
119
- }
120
- catch (error) {
121
- timeoutController?.cleanup();
122
- throw this.handleProviderError(error);
123
- }
124
- }
125
40
  getProviderName() {
126
- return this.providerName;
41
+ return "xai";
127
42
  }
128
43
  getDefaultModel() {
129
44
  return getDefaultXaiModel();
130
45
  }
131
- getAISDKModel() {
132
- return this.model;
46
+ getFallbackModelName() {
47
+ return XaiModels.GROK_3_MINI;
48
+ }
49
+ getFallbackModels() {
50
+ return [
51
+ XaiModels.GROK_3,
52
+ XaiModels.GROK_3_MINI,
53
+ XaiModels.GROK_2_LATEST,
54
+ XaiModels.GROK_2_VISION_LATEST,
55
+ XaiModels.GROK_BETA,
56
+ ];
133
57
  }
134
58
  formatProviderError(error) {
135
59
  if (error instanceof TimeoutError) {
@@ -157,17 +81,5 @@ export class XaiProvider extends BaseProvider {
157
81
  }
158
82
  return new ProviderError(`xAI error: ${message}`, "xai");
159
83
  }
160
- async validateConfiguration() {
161
- return typeof this.apiKey === "string" && this.apiKey.trim().length > 0;
162
- }
163
- getConfiguration() {
164
- return {
165
- provider: this.providerName,
166
- model: this.modelName,
167
- defaultModel: getDefaultXaiModel(),
168
- baseURL: this.baseURL,
169
- };
170
- }
171
84
  }
172
- export default XaiProvider;
173
85
  //# sourceMappingURL=xai.js.map
@@ -125,6 +125,7 @@ export type NeurolinkCredentials = {
125
125
  resourceName?: string;
126
126
  deploymentName?: string;
127
127
  apiVersion?: string;
128
+ useMaxCompletionTokens?: boolean;
128
129
  };
129
130
  mistral?: {
130
131
  apiKey?: string;
@@ -1,24 +1,61 @@
1
1
  import { type AIProviderName } from "../constants/enums.js";
2
- import { BaseProvider } from "../core/baseProvider.js";
3
- import type { StreamOptions, StreamResult, NeurolinkCredentials } from "../types/index.js";
4
- import type { LanguageModel } from "../types/index.js";
5
- export declare class AzureOpenAIProvider extends BaseProvider {
6
- private apiKey;
7
- private resourceName;
8
- private deployment;
9
- private apiVersion;
10
- private azureProvider;
2
+ import type { NeurolinkCredentials, OpenAICompatChatRequest } from "../types/index.js";
3
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
4
+ /**
5
+ * Azure OpenAI Provider direct HTTP, no AI SDK.
6
+ *
7
+ * Supports both classic Azure OpenAI Service endpoints
8
+ * ("*.openai.azure.com", "*.cognitiveservices.azure.com") and the newer
9
+ * Azure AI Foundry endpoints ("*.services.ai.azure.com").
10
+ *
11
+ * All request/stream/tool-loop orchestration lives in
12
+ * `OpenAIChatCompletionsProvider`; this class overrides the URL builder and
13
+ * auth headers to accommodate Azure's deployment-based routing and
14
+ * `api-key` header (rather than Bearer tokens).
15
+ *
16
+ * @see https://learn.microsoft.com/azure/cognitive-services/openai/
17
+ */
18
+ export declare class AzureOpenAIProvider extends OpenAIChatCompletionsProvider {
19
+ protected readonly azureDeployment: string;
20
+ protected readonly azureApiVersion: string;
21
+ protected readonly azureResourceOrigin: string;
22
+ protected readonly azureDeploymentPathPrefix: string;
23
+ protected readonly useMaxCompletionTokensOverride?: boolean;
11
24
  constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["azure"]);
12
- getProviderName(): AIProviderName;
13
- getDefaultModel(): string;
25
+ protected getProviderName(): AIProviderName;
14
26
  /**
15
- * Returns the Vercel AI SDK model instance for Azure OpenAI.
16
- * Uses .chat() explicitly because @ai-sdk/azure v3+ defaults the bare
17
- * provider() call to the Responses API, which many Azure deployments
18
- * do not support yet.
27
+ * The "default model" for Azure is the deployment name — it's the
28
+ * identifier callers pass to select a deployment.
19
29
  */
20
- getAISDKModel(): LanguageModel;
30
+ protected getDefaultModel(): string;
21
31
  protected formatProviderError(error: unknown): Error;
22
- protected executeStream(options: StreamOptions, _analysisSchema?: unknown): Promise<StreamResult>;
32
+ /**
33
+ * Builds the full Azure deployment chat completions URL.
34
+ *
35
+ * Pattern:
36
+ * {resourceOrigin}{deploymentPathPrefix}/deployments/{deployment}/chat/completions?api-version={apiVersion}
37
+ *
38
+ * Examples:
39
+ * Classic: https://myresource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2025-04-01-preview
40
+ * Foundry: https://myhost.services.ai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2025-04-01-preview
41
+ */
42
+ protected getChatCompletionsURL(modelId: string): string;
43
+ /**
44
+ * Azure uses `api-key` rather than the standard `Authorization: Bearer`
45
+ * header expected by OpenAI-compatible endpoints.
46
+ */
47
+ protected getAuthHeaders(): Record<string, string>;
48
+ /**
49
+ * Newer Azure deployments (o-series, gpt-5+) reject `max_tokens` and require
50
+ * `max_completion_tokens`. The `@ai-sdk/openai` path this migration replaced
51
+ * renamed the field automatically; replicate that here.
52
+ *
53
+ * Capability is taken from the explicit `useMaxCompletionTokens` override
54
+ * (credentials / `AZURE_OPENAI_USE_MAX_COMPLETION_TOKENS`) when set — Azure
55
+ * deployment names are user-defined, so a `chat-prod` gpt-5 deployment can't
56
+ * be detected from the name. When unset, fall back to a best-effort
57
+ * model-name heuristic for the common case where the deployment echoes the
58
+ * model (e.g. `gpt-5.4`).
59
+ */
60
+ protected adjustRequestBody(body: OpenAICompatChatRequest, modelId: string): OpenAICompatChatRequest;
23
61
  }
24
- export default AzureOpenAIProvider;