@juspay/neurolink 9.68.0 → 9.68.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/dist/browser/neurolink.min.js +432 -442
- package/dist/lib/providers/azureOpenai.d.ts +55 -18
- package/dist/lib/providers/azureOpenai.js +167 -167
- package/dist/lib/types/providers.d.ts +1 -0
- package/dist/providers/azureOpenai.d.ts +55 -18
- package/dist/providers/azureOpenai.js +167 -167
- package/dist/types/providers.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1,24 +1,61 @@
|
|
|
1
1
|
import { type AIProviderName } from "../constants/enums.js";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
*
|
|
16
|
-
*
|
|
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
|
-
|
|
30
|
+
protected getDefaultModel(): string;
|
|
21
31
|
protected formatProviderError(error: unknown): Error;
|
|
22
|
-
|
|
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;
|
|
@@ -1,30 +1,64 @@
|
|
|
1
|
-
import { createAzure } from "@ai-sdk/azure";
|
|
2
1
|
import { APIVersions } from "../constants/enums.js";
|
|
3
|
-
import { BaseProvider } from "../core/baseProvider.js";
|
|
4
|
-
import { DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
5
|
-
import { createProxyFetch } from "../proxy/proxyFetch.js";
|
|
6
|
-
import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
|
|
7
2
|
import { AuthenticationError, NetworkError, ProviderError, } from "../types/index.js";
|
|
8
3
|
import { logger } from "../utils/logger.js";
|
|
9
4
|
import { createAzureAPIKeyConfig, createAzureEndpointConfig, validateApiKey, } from "../utils/providerConfig.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
import { TimeoutError } from "../utils/timeout.js";
|
|
6
|
+
import { transformParamsForLogging } from "../utils/transformationUtils.js";
|
|
7
|
+
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
8
|
+
import { requiresMaxCompletionTokens } from "./openaiChatCompletionsClient.js";
|
|
9
|
+
/**
|
|
10
|
+
* Azure OpenAI Provider — direct HTTP, no AI SDK.
|
|
11
|
+
*
|
|
12
|
+
* Supports both classic Azure OpenAI Service endpoints
|
|
13
|
+
* ("*.openai.azure.com", "*.cognitiveservices.azure.com") and the newer
|
|
14
|
+
* Azure AI Foundry endpoints ("*.services.ai.azure.com").
|
|
15
|
+
*
|
|
16
|
+
* All request/stream/tool-loop orchestration lives in
|
|
17
|
+
* `OpenAIChatCompletionsProvider`; this class overrides the URL builder and
|
|
18
|
+
* auth headers to accommodate Azure's deployment-based routing and
|
|
19
|
+
* `api-key` header (rather than Bearer tokens).
|
|
20
|
+
*
|
|
21
|
+
* @see https://learn.microsoft.com/azure/cognitive-services/openai/
|
|
22
|
+
*/
|
|
23
|
+
export class AzureOpenAIProvider extends OpenAIChatCompletionsProvider {
|
|
24
|
+
// Azure-specific routing state resolved once in the constructor.
|
|
25
|
+
azureDeployment;
|
|
26
|
+
azureApiVersion;
|
|
27
|
+
// Parsed from the endpoint — mutually exclusive: either resourceName (for
|
|
28
|
+
// classic hosts) or foundryBaseURL (for AI Foundry) is non-empty.
|
|
29
|
+
azureResourceOrigin;
|
|
30
|
+
azureDeploymentPathPrefix;
|
|
31
|
+
// Explicit `max_completion_tokens` capability. `undefined` ⇒ fall back to the
|
|
32
|
+
// deployment-name heuristic in adjustRequestBody().
|
|
33
|
+
useMaxCompletionTokensOverride;
|
|
20
34
|
constructor(modelName, sdk, _region, credentials) {
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
const apiKey = credentials?.apiKey || process.env.AZURE_OPENAI_API_KEY || "";
|
|
36
|
+
// -----------------------------------------------------------------------
|
|
37
|
+
// Parse the AZURE_OPENAI_ENDPOINT environment variable (or credentials)
|
|
38
|
+
// into the pieces needed to build deployment-based chat completions URLs.
|
|
39
|
+
//
|
|
40
|
+
// Two supported endpoint formats:
|
|
41
|
+
//
|
|
42
|
+
// 1. Classic Azure OpenAI / Cognitive Services:
|
|
43
|
+
// https://<resource>.openai.azure.com
|
|
44
|
+
// https://<resource>.cognitiveservices.azure.com
|
|
45
|
+
// The @ai-sdk/azure tradition was to pass the bare resource subdomain
|
|
46
|
+
// and let the SDK reconstruct the full URL. We instead keep the full
|
|
47
|
+
// origin and emit the standard deployment path from it:
|
|
48
|
+
// {origin}/openai/deployments/{deployment}/chat/completions
|
|
49
|
+
//
|
|
50
|
+
// 2. Azure AI Foundry:
|
|
51
|
+
// https://<host>.services.ai.azure.com[/openai]
|
|
52
|
+
// The host has no resource-name subdomain convention. The operator
|
|
53
|
+
// may or may not include the "/openai" path prefix; we normalise that.
|
|
54
|
+
// Final URL pattern:
|
|
55
|
+
// {origin}{normalisedPath}/deployments/{deployment}/chat/completions
|
|
56
|
+
//
|
|
57
|
+
// In both cases we pass the "resource origin" (scheme+host) as `baseURL`
|
|
58
|
+
// to super so that `getAvailableModels()` can still build a models URL
|
|
59
|
+
// from it if needed; `getChatCompletionsURL()` builds the real path.
|
|
60
|
+
// -----------------------------------------------------------------------
|
|
23
61
|
const endpoint = process.env.AZURE_OPENAI_ENDPOINT || "";
|
|
24
|
-
// Use URL parsing instead of string-replace so endpoints that already
|
|
25
|
-
// carry a path segment (e.g. "https://<host>/openai" — a valid Azure AI
|
|
26
|
-
// Foundry shape) don't end up duplicating it as "<host>/openai/openai".
|
|
27
|
-
// Tolerate missing scheme by prefixing https:// before parsing.
|
|
28
62
|
let endpointUrl;
|
|
29
63
|
if (endpoint) {
|
|
30
64
|
try {
|
|
@@ -35,95 +69,85 @@ export class AzureOpenAIProvider extends BaseProvider {
|
|
|
35
69
|
}
|
|
36
70
|
}
|
|
37
71
|
const endpointHost = endpointUrl?.hostname ?? "";
|
|
72
|
+
// Strip trailing slashes from the pathname; treat "/" as empty.
|
|
38
73
|
const endpointPath = endpointUrl?.pathname && endpointUrl.pathname !== "/"
|
|
39
74
|
? endpointUrl.pathname.replace(/\/+$/, "")
|
|
40
75
|
: "";
|
|
41
|
-
// Classic
|
|
42
|
-
// ("*.cognitiveservices.azure.com") endpoints encode the resource name as
|
|
43
|
-
// a subdomain that @ai-sdk/azure expects to receive verbatim. The newer
|
|
44
|
-
// Azure AI Foundry endpoint format ("*.services.ai.azure.com") does not
|
|
45
|
-
// round-trip through that subdomain rewrite, so passing the resource name
|
|
46
|
-
// would yield e.g. "<host>.services.ai.azure.com.openai.azure.com". For
|
|
47
|
-
// those hosts we hand the full URL back via baseURL instead.
|
|
76
|
+
// Classic hosts encode the resource name as a subdomain.
|
|
48
77
|
const isClassicAzureHost = /\.(openai|cognitiveservices)\.azure\.com$/.test(endpointHost);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
// For classic hosts the deployment URL path always starts with "/openai".
|
|
79
|
+
// For Foundry hosts we reuse whatever the operator supplied, appending
|
|
80
|
+
// "/openai" only when the path doesn't already end with it (or a
|
|
81
|
+
// versioned variant like "/openai/v1").
|
|
82
|
+
let deploymentPathPrefix;
|
|
83
|
+
if (isClassicAzureHost) {
|
|
84
|
+
deploymentPathPrefix = "/openai";
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const hasOpenAIPathSuffix = /\/openai(?:\/v\d+)?$/.test(endpointPath);
|
|
88
|
+
deploymentPathPrefix = hasOpenAIPathSuffix
|
|
89
|
+
? endpointPath
|
|
90
|
+
: `${endpointPath}/openai`;
|
|
91
|
+
}
|
|
92
|
+
const resourceOrigin = endpointUrl?.origin ?? "";
|
|
93
|
+
const deployment = credentials?.deploymentName ||
|
|
94
|
+
modelName ||
|
|
95
|
+
process.env.AZURE_OPENAI_MODEL ||
|
|
96
|
+
process.env.AZURE_OPENAI_DEPLOYMENT ||
|
|
97
|
+
process.env.AZURE_OPENAI_DEPLOYMENT_ID ||
|
|
98
|
+
"gpt-4o";
|
|
99
|
+
const apiVersion = credentials?.apiVersion ||
|
|
100
|
+
process.env.AZURE_API_VERSION ||
|
|
101
|
+
APIVersions.AZURE_LATEST;
|
|
102
|
+
// Deployment names are user-defined, so a model-name heuristic can't
|
|
103
|
+
// reliably tell whether the backing model needs max_completion_tokens.
|
|
104
|
+
// Prefer an explicit signal (credentials or env); fall back to the
|
|
105
|
+
// heuristic only when unset.
|
|
106
|
+
const envMaxCompletion = process.env.AZURE_OPENAI_USE_MAX_COMPLETION_TOKENS;
|
|
107
|
+
const maxCompletionOverride = credentials?.useMaxCompletionTokens ??
|
|
108
|
+
(envMaxCompletion === undefined
|
|
109
|
+
? undefined
|
|
110
|
+
: /^(1|true|yes)$/i.test(envMaxCompletion));
|
|
111
|
+
// Validate required credentials before committing.
|
|
112
|
+
if (!apiKey) {
|
|
79
113
|
validateApiKey(createAzureAPIKeyConfig());
|
|
80
114
|
}
|
|
81
|
-
if (!
|
|
115
|
+
if (!resourceOrigin) {
|
|
82
116
|
validateApiKey(createAzureEndpointConfig());
|
|
83
117
|
}
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// useDeploymentBasedUrls is required because @ai-sdk/azure v3+ defaults to
|
|
90
|
-
// the /v1/ URL format, but most Azure deployments still require the legacy
|
|
91
|
-
// /deployments/{deployment}/ URL pattern.
|
|
92
|
-
this.azureProvider = baseURLForFoundry
|
|
93
|
-
? createAzure({
|
|
94
|
-
baseURL: baseURLForFoundry,
|
|
95
|
-
apiKey: this.apiKey,
|
|
96
|
-
apiVersion: this.apiVersion,
|
|
97
|
-
useDeploymentBasedUrls: true,
|
|
98
|
-
fetch: createProxyFetch(),
|
|
99
|
-
})
|
|
100
|
-
: createAzure({
|
|
101
|
-
resourceName: this.resourceName,
|
|
102
|
-
apiKey: this.apiKey,
|
|
103
|
-
apiVersion: this.apiVersion,
|
|
104
|
-
useDeploymentBasedUrls: true,
|
|
105
|
-
fetch: createProxyFetch(),
|
|
106
|
-
});
|
|
107
|
-
logger.debug("Azure Vercel Provider initialized", {
|
|
108
|
-
deployment: this.deployment,
|
|
109
|
-
resourceName: this.resourceName,
|
|
110
|
-
provider: "azure-vercel",
|
|
118
|
+
// Pass the resource origin as baseURL so the base class can construct
|
|
119
|
+
// auxiliary URLs (e.g. /models) from it when needed.
|
|
120
|
+
super("azure", modelName, sdk, {
|
|
121
|
+
baseURL: resourceOrigin,
|
|
122
|
+
apiKey,
|
|
111
123
|
});
|
|
124
|
+
this.azureDeployment = deployment;
|
|
125
|
+
this.azureApiVersion = apiVersion;
|
|
126
|
+
this.azureResourceOrigin = resourceOrigin;
|
|
127
|
+
this.azureDeploymentPathPrefix = deploymentPathPrefix;
|
|
128
|
+
this.useMaxCompletionTokensOverride = maxCompletionOverride;
|
|
129
|
+
if (logger.shouldLog("debug")) {
|
|
130
|
+
logger.debug("Azure OpenAI Provider initialized", transformParamsForLogging({
|
|
131
|
+
deployment: this.azureDeployment,
|
|
132
|
+
resourceOrigin: this.azureResourceOrigin,
|
|
133
|
+
deploymentPathPrefix: this.azureDeploymentPathPrefix,
|
|
134
|
+
apiVersion: this.azureApiVersion,
|
|
135
|
+
provider: "azure",
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
112
138
|
}
|
|
139
|
+
// ===========================================================================
|
|
140
|
+
// Abstract-hook implementations
|
|
141
|
+
// ===========================================================================
|
|
113
142
|
getProviderName() {
|
|
114
143
|
return "azure";
|
|
115
144
|
}
|
|
116
|
-
getDefaultModel() {
|
|
117
|
-
return this.deployment;
|
|
118
|
-
}
|
|
119
145
|
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* provider() call to the Responses API, which many Azure deployments
|
|
123
|
-
* do not support yet.
|
|
146
|
+
* The "default model" for Azure is the deployment name — it's the
|
|
147
|
+
* identifier callers pass to select a deployment.
|
|
124
148
|
*/
|
|
125
|
-
|
|
126
|
-
return this.
|
|
149
|
+
getDefaultModel() {
|
|
150
|
+
return this.azureDeployment;
|
|
127
151
|
}
|
|
128
152
|
formatProviderError(error) {
|
|
129
153
|
if (error instanceof TimeoutError) {
|
|
@@ -140,81 +164,57 @@ export class AzureOpenAIProvider extends BaseProvider {
|
|
|
140
164
|
: "Unknown error";
|
|
141
165
|
return new ProviderError(`Azure OpenAI error: ${message}`, "azure");
|
|
142
166
|
}
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
: String(event.error),
|
|
188
|
-
});
|
|
189
|
-
},
|
|
190
|
-
onStepFinish: (event) => {
|
|
191
|
-
emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), event.toolResults);
|
|
192
|
-
this.handleToolExecutionStorage([...event.toolCalls], [...event.toolResults], options, new Date()).catch((error) => {
|
|
193
|
-
logger.warn("[AzureOpenaiProvider] Failed to store tool executions", {
|
|
194
|
-
provider: this.providerName,
|
|
195
|
-
error: error instanceof Error ? error.message : String(error),
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
},
|
|
199
|
-
});
|
|
200
|
-
timeoutController?.cleanup();
|
|
201
|
-
// Transform string stream to content object stream using BaseProvider method
|
|
202
|
-
const transformedStream = this.createTextStream(stream, () => capturedProviderError);
|
|
167
|
+
// ===========================================================================
|
|
168
|
+
// New overridable hooks (provided by the base-enhancement branch)
|
|
169
|
+
// ===========================================================================
|
|
170
|
+
/**
|
|
171
|
+
* Builds the full Azure deployment chat completions URL.
|
|
172
|
+
*
|
|
173
|
+
* Pattern:
|
|
174
|
+
* {resourceOrigin}{deploymentPathPrefix}/deployments/{deployment}/chat/completions?api-version={apiVersion}
|
|
175
|
+
*
|
|
176
|
+
* Examples:
|
|
177
|
+
* Classic: https://myresource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2025-04-01-preview
|
|
178
|
+
* Foundry: https://myhost.services.ai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2025-04-01-preview
|
|
179
|
+
*/
|
|
180
|
+
getChatCompletionsURL(modelId) {
|
|
181
|
+
// modelId is the deployment name when it has been resolved; fall back to
|
|
182
|
+
// the stored deployment when the base passes a generic placeholder.
|
|
183
|
+
const deployment = modelId || this.azureDeployment;
|
|
184
|
+
const prefix = this.azureDeploymentPathPrefix.replace(/\/+$/, "");
|
|
185
|
+
return (`${this.azureResourceOrigin}${prefix}/deployments/${deployment}` +
|
|
186
|
+
`/chat/completions?api-version=${this.azureApiVersion}`);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Azure uses `api-key` rather than the standard `Authorization: Bearer`
|
|
190
|
+
* header expected by OpenAI-compatible endpoints.
|
|
191
|
+
*/
|
|
192
|
+
getAuthHeaders() {
|
|
193
|
+
return { "api-key": this.config.apiKey };
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Newer Azure deployments (o-series, gpt-5+) reject `max_tokens` and require
|
|
197
|
+
* `max_completion_tokens`. The `@ai-sdk/openai` path this migration replaced
|
|
198
|
+
* renamed the field automatically; replicate that here.
|
|
199
|
+
*
|
|
200
|
+
* Capability is taken from the explicit `useMaxCompletionTokens` override
|
|
201
|
+
* (credentials / `AZURE_OPENAI_USE_MAX_COMPLETION_TOKENS`) when set — Azure
|
|
202
|
+
* deployment names are user-defined, so a `chat-prod` gpt-5 deployment can't
|
|
203
|
+
* be detected from the name. When unset, fall back to a best-effort
|
|
204
|
+
* model-name heuristic for the common case where the deployment echoes the
|
|
205
|
+
* model (e.g. `gpt-5.4`).
|
|
206
|
+
*/
|
|
207
|
+
adjustRequestBody(body, modelId) {
|
|
208
|
+
const needsMaxCompletion = this.useMaxCompletionTokensOverride ??
|
|
209
|
+
requiresMaxCompletionTokens(modelId);
|
|
210
|
+
if (body.max_tokens !== undefined && needsMaxCompletion) {
|
|
203
211
|
return {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
metadata: {
|
|
208
|
-
streamId: `azure-${Date.now()}`,
|
|
209
|
-
startTime: Date.now(),
|
|
210
|
-
},
|
|
212
|
+
...body,
|
|
213
|
+
max_completion_tokens: body.max_tokens,
|
|
214
|
+
max_tokens: undefined,
|
|
211
215
|
};
|
|
212
216
|
}
|
|
213
|
-
|
|
214
|
-
timeoutController?.cleanup();
|
|
215
|
-
throw this.handleProviderError(error);
|
|
216
|
-
}
|
|
217
|
+
return body;
|
|
217
218
|
}
|
|
218
219
|
}
|
|
219
|
-
export default AzureOpenAIProvider;
|
|
220
220
|
//# sourceMappingURL=azureOpenai.js.map
|
|
@@ -1,24 +1,61 @@
|
|
|
1
1
|
import { type AIProviderName } from "../constants/enums.js";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
*
|
|
16
|
-
*
|
|
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
|
-
|
|
30
|
+
protected getDefaultModel(): string;
|
|
21
31
|
protected formatProviderError(error: unknown): Error;
|
|
22
|
-
|
|
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;
|