@nquandt/azure-ai-sdk 0.1.3

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/README.md ADDED
@@ -0,0 +1,254 @@
1
+ # @nquandt/azure-ai-sdk
2
+
3
+ A [Vercel AI SDK](https://sdk.vercel.ai) custom provider for [Azure AI Foundry](https://ai.azure.com) that authenticates using **Azure Entra identity** — no API keys required.
4
+
5
+ Works with any Azure-hosted chat model: GPT-4o, DeepSeek-R1, Llama, Cohere, Phi, and others.
6
+
7
+ [![npm](https://img.shields.io/npm/v/@nquandt/azure-ai-sdk)](https://www.npmjs.com/package/@nquandt/azure-ai-sdk)
8
+ [![JSR](https://jsr.io/badges/@nquandt/azure-ai-sdk)](https://jsr.io/@nquandt/azure-ai-sdk)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
+
11
+ ---
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @nquandt/azure-ai-sdk
17
+ ```
18
+
19
+ Or from JSR:
20
+
21
+ ```bash
22
+ npx jsr add @nquandt/azure-ai-sdk
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Prerequisites
28
+
29
+ - An [Azure AI Foundry](https://ai.azure.com) resource or Azure OpenAI resource
30
+ - A deployed model (e.g. `gpt-4o`, `DeepSeek-R1`)
31
+ - One of the following authentication methods (resolved automatically by `DefaultAzureCredential`):
32
+ - `az login` for local development
33
+ - Environment variables (`AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`) for a service principal
34
+ - Managed identity or workload identity for Azure-hosted compute
35
+
36
+ ---
37
+
38
+ ## Quick start
39
+
40
+ ```ts
41
+ import { createAzureFoundry } from '@nquandt/azure-ai-sdk';
42
+ import { generateText } from 'ai';
43
+
44
+ const foundry = createAzureFoundry({
45
+ endpoint: 'https://my-resource.cognitiveservices.azure.com',
46
+ });
47
+
48
+ const { text } = await generateText({
49
+ model: foundry('gpt-4o'),
50
+ prompt: 'Explain quantum entanglement in one paragraph.',
51
+ });
52
+
53
+ console.log(text);
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Endpoint formats
59
+
60
+ Two endpoint styles are supported and detected automatically:
61
+
62
+ | Endpoint format | URL called | Model location |
63
+ |---|---|---|
64
+ | `https://<resource>.cognitiveservices.azure.com` | `/openai/deployments/{model}/chat/completions?api-version=...` | URL path |
65
+ | `https://<project>.services.ai.azure.com/models` | `/chat/completions` | Request body |
66
+
67
+ ---
68
+
69
+ ## Authentication
70
+
71
+ By default the provider uses `DefaultAzureCredential` from `@azure/identity`, which tries the following in order:
72
+
73
+ 1. Environment variables — `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`
74
+ 2. Workload identity (Kubernetes federated credentials)
75
+ 3. Managed identity (Azure-hosted compute)
76
+ 4. Azure CLI (`az login`)
77
+ 5. Azure PowerShell
78
+ 6. VS Code account
79
+
80
+ For local development, `az login` is all you need.
81
+
82
+ ### Custom credential
83
+
84
+ Credential types are re-exported from the package so you don't need a direct `@azure/identity` dependency:
85
+
86
+ ```ts
87
+ import { createAzureFoundry, ManagedIdentityCredential } from '@nquandt/azure-ai-sdk';
88
+
89
+ const foundry = createAzureFoundry({
90
+ endpoint: 'https://my-resource.cognitiveservices.azure.com',
91
+ credential: new ManagedIdentityCredential('<client-id>'),
92
+ });
93
+ ```
94
+
95
+ ### Service principal (CI / GitHub Actions)
96
+
97
+ Set these environment variables — `DefaultAzureCredential` picks them up automatically:
98
+
99
+ ```bash
100
+ AZURE_TENANT_ID=<tenant-id>
101
+ AZURE_CLIENT_ID=<app-registration-client-id>
102
+ AZURE_CLIENT_SECRET=<client-secret>
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Configuration options
108
+
109
+ ```ts
110
+ createAzureFoundry({
111
+ // Required. Azure resource endpoint URL.
112
+ // Can also be set via the AZURE_AI_FOUNDRY_ENDPOINT environment variable.
113
+ endpoint: 'https://my-resource.cognitiveservices.azure.com',
114
+
115
+ // Optional. API version query param (cognitiveservices endpoints only).
116
+ // Defaults to '2024-10-21'.
117
+ apiVersion: '2024-10-21',
118
+
119
+ // Optional. Custom TokenCredential. Defaults to DefaultAzureCredential.
120
+ credential: new ManagedIdentityCredential(),
121
+
122
+ // Optional. OAuth2 scope. Defaults to 'https://cognitiveservices.azure.com/.default'.
123
+ scope: 'https://cognitiveservices.azure.com/.default',
124
+
125
+ // Optional. Extra headers sent with every request.
126
+ headers: { 'x-custom-header': 'value' },
127
+ });
128
+ ```
129
+
130
+ ### Per-model settings
131
+
132
+ ```ts
133
+ const model = foundry('gpt-4o', {
134
+ maxTokens: 1024,
135
+ temperature: 0.7,
136
+ topP: 0.95,
137
+ });
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Usage examples
143
+
144
+ ### Generate text
145
+
146
+ ```ts
147
+ import { createAzureFoundry } from '@nquandt/azure-ai-sdk';
148
+ import { generateText } from 'ai';
149
+
150
+ const foundry = createAzureFoundry({
151
+ endpoint: process.env.AZURE_AI_FOUNDRY_ENDPOINT,
152
+ });
153
+
154
+ const { text, usage } = await generateText({
155
+ model: foundry('gpt-4o'),
156
+ messages: [
157
+ { role: 'system', content: 'You are a helpful assistant.' },
158
+ { role: 'user', content: 'What is the capital of France?' },
159
+ ],
160
+ });
161
+ ```
162
+
163
+ ### Stream text
164
+
165
+ ```ts
166
+ import { createAzureFoundry } from '@nquandt/azure-ai-sdk';
167
+ import { streamText } from 'ai';
168
+
169
+ const foundry = createAzureFoundry({
170
+ endpoint: process.env.AZURE_AI_FOUNDRY_ENDPOINT,
171
+ });
172
+
173
+ const result = streamText({
174
+ model: foundry('gpt-4o'),
175
+ prompt: 'Write a haiku about mountains.',
176
+ });
177
+
178
+ for await (const chunk of result.textStream) {
179
+ process.stdout.write(chunk);
180
+ }
181
+ ```
182
+
183
+ ### Tool calling
184
+
185
+ ```ts
186
+ import { createAzureFoundry } from '@nquandt/azure-ai-sdk';
187
+ import { generateText, tool } from 'ai';
188
+ import { z } from 'zod';
189
+
190
+ const foundry = createAzureFoundry({
191
+ endpoint: process.env.AZURE_AI_FOUNDRY_ENDPOINT,
192
+ });
193
+
194
+ const { text } = await generateText({
195
+ model: foundry('gpt-4o'),
196
+ tools: {
197
+ getWeather: tool({
198
+ description: 'Get current weather for a city',
199
+ parameters: z.object({ city: z.string() }),
200
+ execute: async ({ city }) => ({ temperature: 22, condition: 'sunny', city }),
201
+ }),
202
+ },
203
+ prompt: 'What is the weather in London?',
204
+ });
205
+ ```
206
+
207
+ ### AI Foundry inference endpoint (serverless models)
208
+
209
+ ```ts
210
+ const foundry = createAzureFoundry({
211
+ endpoint: 'https://my-project.services.ai.azure.com/models',
212
+ });
213
+
214
+ const { text } = await generateText({
215
+ model: foundry('DeepSeek-R1'),
216
+ prompt: 'Solve: what is 17 * 23?',
217
+ });
218
+ ```
219
+
220
+ ---
221
+
222
+ ## Environment variable
223
+
224
+ You can omit the `endpoint` option and set it via the environment instead:
225
+
226
+ ```bash
227
+ AZURE_AI_FOUNDRY_ENDPOINT=https://my-resource.cognitiveservices.azure.com
228
+ ```
229
+
230
+ ```ts
231
+ // endpoint is read from AZURE_AI_FOUNDRY_ENDPOINT automatically
232
+ const foundry = createAzureFoundry({});
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Integration tests
238
+
239
+ Integration tests in `test/chat.test.ts` are skipped automatically unless the required environment variables are set:
240
+
241
+ ```bash
242
+ cp .env.example .env
243
+ # fill in AZURE_FOUNDRY_ENDPOINT and AZURE_FOUNDRY_MODEL, then:
244
+ az login
245
+ npm test
246
+ ```
247
+
248
+ The unit tests (`provider`, `generate`, `stream`) run entirely with in-memory mocks and require no Azure access.
249
+
250
+ ---
251
+
252
+ ## License
253
+
254
+ MIT
@@ -0,0 +1,41 @@
1
+ import { LanguageModelV1, LanguageModelV1CallOptions } from '@ai-sdk/provider';
2
+ import { FetchFunction } from '@ai-sdk/provider-utils';
3
+ import { AzureFoundryChatModelId, AzureFoundryChatSettings } from './azure-foundry-chat-options.js';
4
+ type AzureFoundryChatConfig = {
5
+ provider: string;
6
+ /**
7
+ * Builds the full chat completions URL for a given deployment/model ID.
8
+ * Called once per request so the URL can encode the model in the path
9
+ * (Azure OpenAI / cognitiveservices style) or use a shared endpoint
10
+ * (AI Foundry inference style, model sent in request body).
11
+ */
12
+ url: (modelId: string) => string;
13
+ /**
14
+ * When true, the model ID is sent in the request body as `model`.
15
+ * Used for AI Foundry inference endpoints (services.ai.azure.com/models).
16
+ * Azure OpenAI endpoints encode the model in the URL path instead.
17
+ */
18
+ modelInBody: boolean;
19
+ /**
20
+ * Returns Bearer token headers for every request. Async because Azure
21
+ * identity credential.getToken() is async.
22
+ */
23
+ headers: () => Promise<Record<string, string>>;
24
+ fetch?: FetchFunction;
25
+ generateId?: () => string;
26
+ };
27
+ export declare class AzureFoundryChatLanguageModel implements LanguageModelV1 {
28
+ readonly specificationVersion: "v1";
29
+ readonly defaultObjectGenerationMode: "json";
30
+ readonly modelId: AzureFoundryChatModelId;
31
+ private readonly settings;
32
+ private readonly config;
33
+ private readonly _generateId;
34
+ constructor(modelId: AzureFoundryChatModelId, settings: AzureFoundryChatSettings, config: AzureFoundryChatConfig);
35
+ get provider(): string;
36
+ private getArgs;
37
+ doGenerate(options: LanguageModelV1CallOptions): Promise<Awaited<ReturnType<LanguageModelV1['doGenerate']>>>;
38
+ doStream(options: LanguageModelV1CallOptions): Promise<Awaited<ReturnType<LanguageModelV1['doStream']>>>;
39
+ }
40
+ export {};
41
+ //# sourceMappingURL=azure-foundry-chat-language-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-foundry-chat-language-model.d.ts","sourceRoot":"","sources":["../src/azure-foundry-chat-language-model.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,0BAA0B,EAM3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EAOd,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,iCAAiC,CAAC;AAOzC,KAAK,sBAAsB,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IACjC;;;;OAIG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/C,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC;CAC3B,CAAC;AAsNF,qBAAa,6BAA8B,YAAW,eAAe;IACnE,QAAQ,CAAC,oBAAoB,EAAG,IAAI,CAAU;IAC9C,QAAQ,CAAC,2BAA2B,EAAG,MAAM,CAAU;IAEvD,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAE1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;gBAGzC,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,wBAAwB,EAClC,MAAM,EAAE,sBAAsB;IAQhC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAMD,OAAO,CAAC,OAAO;IAuHT,UAAU,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAwD5G,QAAQ,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CAuI/G"}
@@ -0,0 +1,461 @@
1
+ import { combineHeaders, createEventSourceResponseHandler, createJsonResponseHandler, generateId, postJsonToApi, } from '@ai-sdk/provider-utils';
2
+ import { z } from 'zod';
3
+ import { azureFoundryFailedResponseHandler } from './azure-foundry-error.js';
4
+ import { VERSION } from './version.js';
5
+ // ---------------------------------------------------------------------------
6
+ // Zod schemas for response parsing
7
+ // ---------------------------------------------------------------------------
8
+ const toolCallSchema = z.object({
9
+ id: z.string(),
10
+ type: z.literal('function'),
11
+ function: z.object({
12
+ name: z.string(),
13
+ arguments: z.string(),
14
+ }),
15
+ });
16
+ const chatResponseSchema = z.object({
17
+ id: z.string().nullish(),
18
+ model: z.string().nullish(),
19
+ created: z.number().nullish(),
20
+ choices: z.array(z.object({
21
+ index: z.number(),
22
+ message: z.object({
23
+ role: z.literal('assistant'),
24
+ content: z.string().nullish(),
25
+ tool_calls: z.array(toolCallSchema).nullish(),
26
+ }),
27
+ finish_reason: z.string().nullish(),
28
+ })),
29
+ usage: z
30
+ .object({
31
+ prompt_tokens: z.number(),
32
+ completion_tokens: z.number(),
33
+ total_tokens: z.number().nullish(),
34
+ })
35
+ .nullish(),
36
+ });
37
+ const chatChunkSchema = z.object({
38
+ id: z.string().nullish(),
39
+ model: z.string().nullish(),
40
+ choices: z.array(z.object({
41
+ index: z.number(),
42
+ delta: z.object({
43
+ role: z.enum(['assistant']).optional(),
44
+ content: z.string().nullish(),
45
+ tool_calls: z
46
+ .array(z.object({
47
+ index: z.number(),
48
+ id: z.string().nullish(),
49
+ type: z.literal('function').nullish(),
50
+ function: z.object({
51
+ name: z.string().nullish(),
52
+ arguments: z.string().nullish(),
53
+ }),
54
+ }))
55
+ .nullish(),
56
+ }),
57
+ finish_reason: z.string().nullish(),
58
+ })),
59
+ usage: z
60
+ .object({
61
+ prompt_tokens: z.number().nullish(),
62
+ completion_tokens: z.number().nullish(),
63
+ total_tokens: z.number().nullish(),
64
+ })
65
+ .nullish(),
66
+ });
67
+ // ---------------------------------------------------------------------------
68
+ // Helpers
69
+ // ---------------------------------------------------------------------------
70
+ function mapFinishReason(reason) {
71
+ switch (reason) {
72
+ case 'stop':
73
+ return 'stop';
74
+ case 'length':
75
+ return 'length';
76
+ case 'content_filter':
77
+ return 'content-filter';
78
+ case 'tool_calls':
79
+ return 'tool-calls';
80
+ default:
81
+ return 'other';
82
+ }
83
+ }
84
+ function convertToAzureMessages(prompt) {
85
+ const messages = [];
86
+ for (const message of prompt) {
87
+ switch (message.role) {
88
+ case 'system': {
89
+ messages.push({ role: 'system', content: message.content });
90
+ break;
91
+ }
92
+ case 'user': {
93
+ const parts = [];
94
+ for (const part of message.content) {
95
+ switch (part.type) {
96
+ case 'text':
97
+ parts.push({ type: 'text', text: part.text });
98
+ break;
99
+ case 'image': {
100
+ const image = part.image;
101
+ if (image instanceof URL) {
102
+ parts.push({
103
+ type: 'image_url',
104
+ image_url: { url: image.href },
105
+ });
106
+ }
107
+ else {
108
+ // Uint8Array → base64 data URL
109
+ const b64 = Buffer.from(image).toString('base64');
110
+ const mime = part.mimeType ?? 'image/jpeg';
111
+ parts.push({
112
+ type: 'image_url',
113
+ image_url: { url: `data:${mime};base64,${b64}` },
114
+ });
115
+ }
116
+ break;
117
+ }
118
+ case 'file':
119
+ // Files are not natively supported; skip with a warning handled
120
+ // in getArgs.
121
+ break;
122
+ }
123
+ }
124
+ messages.push({ role: 'user', content: parts });
125
+ break;
126
+ }
127
+ case 'assistant': {
128
+ let textContent = null;
129
+ const toolCalls = [];
130
+ for (const part of message.content) {
131
+ switch (part.type) {
132
+ case 'text':
133
+ textContent = (textContent ?? '') + part.text;
134
+ break;
135
+ case 'tool-call':
136
+ toolCalls.push({
137
+ id: part.toolCallId,
138
+ type: 'function',
139
+ function: {
140
+ name: part.toolName,
141
+ arguments: typeof part.args === 'string'
142
+ ? part.args
143
+ : JSON.stringify(part.args),
144
+ },
145
+ });
146
+ break;
147
+ // reasoning / redacted-reasoning: skip
148
+ }
149
+ }
150
+ messages.push({
151
+ role: 'assistant',
152
+ content: textContent,
153
+ ...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),
154
+ });
155
+ break;
156
+ }
157
+ case 'tool': {
158
+ for (const part of message.content) {
159
+ messages.push({
160
+ role: 'tool',
161
+ tool_call_id: part.toolCallId,
162
+ content: typeof part.result === 'string'
163
+ ? part.result
164
+ : JSON.stringify(part.result),
165
+ });
166
+ }
167
+ break;
168
+ }
169
+ }
170
+ }
171
+ return messages;
172
+ }
173
+ // ---------------------------------------------------------------------------
174
+ // Language model implementation
175
+ // ---------------------------------------------------------------------------
176
+ export class AzureFoundryChatLanguageModel {
177
+ specificationVersion = 'v1';
178
+ defaultObjectGenerationMode = 'json';
179
+ modelId;
180
+ settings;
181
+ config;
182
+ _generateId;
183
+ constructor(modelId, settings, config) {
184
+ this.modelId = modelId;
185
+ this.settings = settings;
186
+ this.config = config;
187
+ this._generateId = config.generateId ?? generateId;
188
+ }
189
+ get provider() {
190
+ return this.config.provider;
191
+ }
192
+ // -------------------------------------------------------------------------
193
+ // Build request body
194
+ // -------------------------------------------------------------------------
195
+ getArgs(options) {
196
+ const warnings = [];
197
+ if (options.topK != null) {
198
+ warnings.push({ type: 'unsupported-setting', setting: 'topK' });
199
+ }
200
+ if (options.presencePenalty != null) {
201
+ warnings.push({
202
+ type: 'unsupported-setting',
203
+ setting: 'presencePenalty',
204
+ });
205
+ }
206
+ if (options.frequencyPenalty != null) {
207
+ warnings.push({
208
+ type: 'unsupported-setting',
209
+ setting: 'frequencyPenalty',
210
+ });
211
+ }
212
+ const messages = convertToAzureMessages(options.prompt);
213
+ // Tool setup
214
+ let tools;
215
+ let tool_choice;
216
+ if (options.mode.type === 'regular') {
217
+ if (options.mode.tools && options.mode.tools.length > 0) {
218
+ tools = options.mode.tools
219
+ .filter((t) => t.type === 'function')
220
+ .map((t) => ({
221
+ type: 'function',
222
+ function: {
223
+ name: t.name,
224
+ description: t.description,
225
+ parameters: t.parameters,
226
+ },
227
+ }));
228
+ }
229
+ if (options.mode.toolChoice) {
230
+ const tc = options.mode.toolChoice;
231
+ if (tc.type === 'auto') {
232
+ tool_choice = 'auto';
233
+ }
234
+ else if (tc.type === 'none') {
235
+ tool_choice = 'none';
236
+ }
237
+ else if (tc.type === 'required') {
238
+ tool_choice = 'required';
239
+ }
240
+ else if (tc.type === 'tool') {
241
+ tool_choice = {
242
+ type: 'function',
243
+ function: { name: tc.toolName },
244
+ };
245
+ }
246
+ }
247
+ }
248
+ else if (options.mode.type === 'object-json') {
249
+ // Instruct the model to respond with JSON
250
+ // We don't set response_format here because Azure AI Foundry
251
+ // may not support it for all models.
252
+ messages.push({
253
+ role: 'user',
254
+ content: [
255
+ {
256
+ type: 'text',
257
+ text: 'Respond with a valid JSON object only. Do not include any markdown formatting or additional text.',
258
+ },
259
+ ],
260
+ });
261
+ }
262
+ else if (options.mode.type === 'object-tool') {
263
+ tools = [
264
+ {
265
+ type: 'function',
266
+ function: {
267
+ name: options.mode.tool.name,
268
+ description: options.mode.tool.description,
269
+ parameters: options.mode.tool.parameters,
270
+ },
271
+ },
272
+ ];
273
+ tool_choice = {
274
+ type: 'function',
275
+ function: { name: options.mode.tool.name },
276
+ };
277
+ }
278
+ // Only include temperature / top_p when they are explicitly configured.
279
+ // The Vercel AI SDK passes temperature=0 as its default, but some models
280
+ // (e.g. gpt-5-nano) only accept the server-side default (1) and reject 0.
281
+ // By omitting these fields we let the model use its own defaults.
282
+ const explicitTemperature = this.settings.temperature ?? (options.temperature !== 0 ? options.temperature : undefined);
283
+ const explicitTopP = this.settings.topP ?? (options.topP !== 0 ? options.topP : undefined);
284
+ const body = {
285
+ ...(this.config.modelInBody ? { model: this.modelId } : {}),
286
+ messages,
287
+ max_tokens: options.maxTokens ?? this.settings.maxTokens,
288
+ temperature: explicitTemperature,
289
+ top_p: explicitTopP,
290
+ stop: options.stopSequences,
291
+ seed: options.seed,
292
+ ...(tools != null ? { tools } : {}),
293
+ ...(tool_choice != null ? { tool_choice } : {}),
294
+ };
295
+ // Remove undefined values
296
+ for (const key of Object.keys(body)) {
297
+ if (body[key] === undefined) {
298
+ delete body[key];
299
+ }
300
+ }
301
+ return { body, warnings };
302
+ }
303
+ // -------------------------------------------------------------------------
304
+ // doGenerate
305
+ // -------------------------------------------------------------------------
306
+ async doGenerate(options) {
307
+ const { body, warnings } = this.getArgs(options);
308
+ const headers = await this.config.headers();
309
+ const { value: response, responseHeaders } = await postJsonToApi({
310
+ url: this.config.url(this.modelId),
311
+ headers: combineHeaders(headers, options.headers, { 'x-ms-useragent': `@nquandt/azure-ai-sdk/${VERSION}` }),
312
+ body,
313
+ failedResponseHandler: azureFoundryFailedResponseHandler,
314
+ successfulResponseHandler: createJsonResponseHandler(chatResponseSchema),
315
+ abortSignal: options.abortSignal,
316
+ fetch: this.config.fetch,
317
+ });
318
+ const choice = response.choices[0];
319
+ const message = choice?.message;
320
+ const text = message?.content ?? undefined;
321
+ const toolCalls = message?.tool_calls && message.tool_calls.length > 0
322
+ ? message.tool_calls.map((tc) => ({
323
+ toolCallType: 'function',
324
+ toolCallId: tc.id,
325
+ toolName: tc.function.name,
326
+ args: tc.function.arguments,
327
+ }))
328
+ : undefined;
329
+ return {
330
+ text,
331
+ toolCalls,
332
+ finishReason: mapFinishReason(choice?.finish_reason),
333
+ usage: {
334
+ promptTokens: response.usage?.prompt_tokens ?? 0,
335
+ completionTokens: response.usage?.completion_tokens ?? 0,
336
+ },
337
+ rawCall: {
338
+ rawPrompt: body,
339
+ rawSettings: {},
340
+ },
341
+ rawResponse: {
342
+ headers: responseHeaders,
343
+ },
344
+ warnings,
345
+ };
346
+ }
347
+ // -------------------------------------------------------------------------
348
+ // doStream
349
+ // -------------------------------------------------------------------------
350
+ async doStream(options) {
351
+ const { body, warnings } = this.getArgs(options);
352
+ const headers = await this.config.headers();
353
+ const { value: stream, responseHeaders: streamResponseHeaders } = await postJsonToApi({
354
+ url: this.config.url(this.modelId),
355
+ headers: combineHeaders(headers, options.headers, { 'x-ms-useragent': `@nquandt/azure-ai-sdk/${VERSION}` }),
356
+ body: { ...body, stream: true },
357
+ failedResponseHandler: azureFoundryFailedResponseHandler,
358
+ successfulResponseHandler: createEventSourceResponseHandler(chatChunkSchema),
359
+ abortSignal: options.abortSignal,
360
+ fetch: this.config.fetch,
361
+ });
362
+ let finishReason = 'other';
363
+ let promptTokens = 0;
364
+ let completionTokens = 0;
365
+ // Track streaming tool calls (assembled across multiple deltas)
366
+ const toolCallAccumulators = new Map();
367
+ const generateIdFn = this._generateId;
368
+ return {
369
+ stream: stream.pipeThrough(new TransformStream({
370
+ transform(chunk, controller) {
371
+ if (!chunk.success) {
372
+ controller.enqueue({ type: 'error', error: chunk.error });
373
+ return;
374
+ }
375
+ const value = chunk.value;
376
+ if (value.usage) {
377
+ promptTokens = value.usage.prompt_tokens ?? 0;
378
+ completionTokens = value.usage.completion_tokens ?? 0;
379
+ }
380
+ for (const choice of value.choices) {
381
+ const delta = choice.delta;
382
+ // Text delta
383
+ if (delta.content) {
384
+ controller.enqueue({
385
+ type: 'text-delta',
386
+ textDelta: delta.content,
387
+ });
388
+ }
389
+ // Tool call deltas
390
+ if (delta.tool_calls) {
391
+ for (const tc of delta.tool_calls) {
392
+ const idx = tc.index;
393
+ if (!toolCallAccumulators.has(idx)) {
394
+ // First delta for this tool call
395
+ const toolCallId = tc.id ?? generateIdFn();
396
+ toolCallAccumulators.set(idx, {
397
+ id: toolCallId,
398
+ name: tc.function?.name ?? '',
399
+ argumentsText: tc.function?.arguments ?? '',
400
+ });
401
+ controller.enqueue({
402
+ type: 'tool-call-delta',
403
+ toolCallType: 'function',
404
+ toolCallId,
405
+ toolName: tc.function?.name ?? '',
406
+ argsTextDelta: tc.function?.arguments ?? '',
407
+ });
408
+ }
409
+ else {
410
+ // Subsequent delta — accumulate arguments
411
+ const acc = toolCallAccumulators.get(idx);
412
+ const argsDelta = tc.function?.arguments ?? '';
413
+ acc.argumentsText += argsDelta;
414
+ controller.enqueue({
415
+ type: 'tool-call-delta',
416
+ toolCallType: 'function',
417
+ toolCallId: acc.id,
418
+ toolName: acc.name,
419
+ argsTextDelta: argsDelta,
420
+ });
421
+ }
422
+ }
423
+ }
424
+ if (choice.finish_reason != null) {
425
+ finishReason = mapFinishReason(choice.finish_reason);
426
+ }
427
+ }
428
+ },
429
+ flush(controller) {
430
+ // Emit completed tool calls
431
+ for (const acc of toolCallAccumulators.values()) {
432
+ controller.enqueue({
433
+ type: 'tool-call',
434
+ toolCallType: 'function',
435
+ toolCallId: acc.id,
436
+ toolName: acc.name,
437
+ args: acc.argumentsText,
438
+ });
439
+ }
440
+ controller.enqueue({
441
+ type: 'finish',
442
+ finishReason,
443
+ usage: {
444
+ promptTokens,
445
+ completionTokens,
446
+ },
447
+ });
448
+ },
449
+ })),
450
+ rawCall: {
451
+ rawPrompt: body,
452
+ rawSettings: {},
453
+ },
454
+ rawResponse: {
455
+ headers: streamResponseHeaders,
456
+ },
457
+ warnings,
458
+ };
459
+ }
460
+ }
461
+ //# sourceMappingURL=azure-foundry-chat-language-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-foundry-chat-language-model.js","sourceRoot":"","sources":["../src/azure-foundry-chat-language-model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export type AzureFoundryChatModelId = string;
2
+ export interface AzureFoundryChatSettings {
3
+ /**
4
+ * Maximum number of tokens to generate in the response.
5
+ */
6
+ maxTokens?: number;
7
+ /**
8
+ * Sampling temperature. Higher values make output more random.
9
+ * Range: 0-2.
10
+ */
11
+ temperature?: number;
12
+ /**
13
+ * Top-p nucleus sampling. Alternative to temperature.
14
+ */
15
+ topP?: number;
16
+ }
17
+ //# sourceMappingURL=azure-foundry-chat-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-foundry-chat-options.d.ts","sourceRoot":"","sources":["../src/azure-foundry-chat-options.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=azure-foundry-chat-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-foundry-chat-options.js","sourceRoot":"","sources":["../src/azure-foundry-chat-options.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import { z } from 'zod';
2
+ declare const azureFoundryErrorSchema: z.ZodObject<{
3
+ error: z.ZodObject<{
4
+ code: z.ZodOptional<z.ZodNullable<z.ZodString>>;
5
+ message: z.ZodString;
6
+ status: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ message: string;
9
+ code?: string | null | undefined;
10
+ status?: number | null | undefined;
11
+ }, {
12
+ message: string;
13
+ code?: string | null | undefined;
14
+ status?: number | null | undefined;
15
+ }>;
16
+ }, "strip", z.ZodTypeAny, {
17
+ error: {
18
+ message: string;
19
+ code?: string | null | undefined;
20
+ status?: number | null | undefined;
21
+ };
22
+ }, {
23
+ error: {
24
+ message: string;
25
+ code?: string | null | undefined;
26
+ status?: number | null | undefined;
27
+ };
28
+ }>;
29
+ export type AzureFoundryErrorData = z.infer<typeof azureFoundryErrorSchema>;
30
+ export declare const azureFoundryFailedResponseHandler: import("@ai-sdk/provider-utils").ResponseHandler<import("@ai-sdk/provider").APICallError>;
31
+ export {};
32
+ //# sourceMappingURL=azure-foundry-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-foundry-error.d.ts","sourceRoot":"","sources":["../src/azure-foundry-error.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;EAM3B,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE5E,eAAO,MAAM,iCAAiC,2FAM1C,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';
2
+ import { z } from 'zod';
3
+ const azureFoundryErrorSchema = z.object({
4
+ error: z.object({
5
+ code: z.string().nullish(),
6
+ message: z.string(),
7
+ status: z.number().nullish(),
8
+ }),
9
+ });
10
+ export const azureFoundryFailedResponseHandler = createJsonErrorResponseHandler({
11
+ errorSchema: azureFoundryErrorSchema,
12
+ errorToMessage: (data) => data.error.message,
13
+ isRetryable: (response) => response.status === 429 || response.status >= 500,
14
+ });
15
+ //# sourceMappingURL=azure-foundry-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-foundry-error.js","sourceRoot":"","sources":["../src/azure-foundry-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;QAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;QACnB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;KAC7B,CAAC;CACH,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,iCAAiC,GAC5C,8BAA8B,CAAC;IAC7B,WAAW,EAAE,uBAAuB;IACpC,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO;IAC5C,WAAW,EAAE,CAAC,QAAQ,EAAE,EAAE,CACxB,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG;CACpD,CAAC,CAAC"}
@@ -0,0 +1,107 @@
1
+ import { LanguageModelV1, ProviderV1 } from '@ai-sdk/provider';
2
+ import { FetchFunction } from '@ai-sdk/provider-utils';
3
+ import { DefaultAzureCredential, ManagedIdentityCredential, TokenCredential, WorkloadIdentityCredential } from '@azure/identity';
4
+ import { AzureFoundryChatModelId, AzureFoundryChatSettings } from './azure-foundry-chat-options.js';
5
+ export interface AzureFoundryProviderSettings {
6
+ /**
7
+ * Azure resource base URL. Two formats are supported:
8
+ *
9
+ * Azure OpenAI / Cognitive Services (cognitiveservices.azure.com):
10
+ * https://<resource>.cognitiveservices.azure.com
11
+ * → calls /openai/deployments/{model}/chat/completions?api-version=...
12
+ *
13
+ * AI Foundry inference (services.ai.azure.com):
14
+ * https://<project>.services.ai.azure.com/models
15
+ * → calls /chat/completions with model in the request body
16
+ *
17
+ * Can also be provided via the AZURE_AI_FOUNDRY_ENDPOINT environment variable.
18
+ */
19
+ endpoint?: string;
20
+ /**
21
+ * API version query parameter appended to every request.
22
+ * Only relevant for cognitiveservices.azure.com endpoints.
23
+ * Defaults to '2024-10-21'.
24
+ */
25
+ apiVersion?: string;
26
+ /**
27
+ * Azure token credential to use for authentication.
28
+ * Defaults to DefaultAzureCredential which supports:
29
+ * - Environment variables (AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET)
30
+ * - Workload identity (Kubernetes)
31
+ * - Managed identity (Azure-hosted compute)
32
+ * - Azure CLI (`az login`)
33
+ * - Azure PowerShell
34
+ * - Visual Studio Code
35
+ *
36
+ * You can pass any `TokenCredential` from `@azure/identity`, for example:
37
+ * - new ClientSecretCredential(tenantId, clientId, clientSecret)
38
+ * - new ManagedIdentityCredential(clientId)
39
+ * - new WorkloadIdentityCredential()
40
+ */
41
+ credential?: TokenCredential;
42
+ /**
43
+ * OAuth2 scope to request.
44
+ * Defaults to 'https://cognitiveservices.azure.com/.default'.
45
+ */
46
+ scope?: string;
47
+ /**
48
+ * Custom headers to include in every request.
49
+ */
50
+ headers?: Record<string, string>;
51
+ /**
52
+ * Custom fetch implementation. Useful for testing / middleware.
53
+ */
54
+ fetch?: FetchFunction;
55
+ generateId?: () => string;
56
+ }
57
+ export interface AzureFoundryProvider extends ProviderV1 {
58
+ /**
59
+ * Create a language model instance for the given deployment name.
60
+ */
61
+ (modelId: AzureFoundryChatModelId, settings?: AzureFoundryChatSettings): LanguageModelV1;
62
+ /**
63
+ * Create a language model instance for the given deployment name.
64
+ */
65
+ languageModel(modelId: AzureFoundryChatModelId, settings?: AzureFoundryChatSettings): LanguageModelV1;
66
+ /**
67
+ * Create a chat model instance for the given deployment name.
68
+ */
69
+ chat(modelId: AzureFoundryChatModelId, settings?: AzureFoundryChatSettings): LanguageModelV1;
70
+ }
71
+ /**
72
+ * Create an Azure AI Foundry provider instance.
73
+ *
74
+ * Authentication is handled via Azure Identity. The credential is resolved
75
+ * in the following order (when no `credential` is specified):
76
+ *
77
+ * 1. `AZURE_CLIENT_ID` / `AZURE_CLIENT_SECRET` / `AZURE_TENANT_ID` env vars
78
+ * 2. Workload identity (Kubernetes pods with federated credentials)
79
+ * 3. Managed identity (Azure-hosted compute)
80
+ * 4. Azure CLI (`az login`)
81
+ * 5. Azure PowerShell
82
+ * 6. VS Code account
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * import { createAzureFoundry } from '@nquandt/azure-ai-sdk';
87
+ * import { generateText } from 'ai';
88
+ *
89
+ * // Azure OpenAI / Cognitive Services endpoint:
90
+ * const foundry = createAzureFoundry({
91
+ * endpoint: 'https://my-resource.cognitiveservices.azure.com',
92
+ * });
93
+ *
94
+ * // AI Foundry inference endpoint:
95
+ * const foundry = createAzureFoundry({
96
+ * endpoint: 'https://my-project.services.ai.azure.com/models',
97
+ * });
98
+ *
99
+ * const { text } = await generateText({
100
+ * model: foundry('DeepSeek-R1'),
101
+ * prompt: 'Hello world',
102
+ * });
103
+ * ```
104
+ */
105
+ export declare function createAzureFoundry(options?: AzureFoundryProviderSettings): AzureFoundryProvider;
106
+ export { DefaultAzureCredential, ManagedIdentityCredential, WorkloadIdentityCredential, };
107
+ //# sourceMappingURL=azure-foundry-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-foundry-provider.d.ts","sourceRoot":"","sources":["../src/azure-foundry-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAoB,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,aAAa,EAAwB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,eAAe,EACf,0BAA0B,EAE3B,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,iCAAiC,CAAC;AAWzC,MAAM,WAAW,4BAA4B;IAC3C;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,eAAe,CAAC;IAE7B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC;;OAEG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;IAEtB,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC;CAC3B;AAMD,MAAM,WAAW,oBAAqB,SAAQ,UAAU;IACtD;;OAEG;IACH,CACE,OAAO,EAAE,uBAAuB,EAChC,QAAQ,CAAC,EAAE,wBAAwB,GAClC,eAAe,CAAC;IAEnB;;OAEG;IACH,aAAa,CACX,OAAO,EAAE,uBAAuB,EAChC,QAAQ,CAAC,EAAE,wBAAwB,GAClC,eAAe,CAAC;IAEnB;;OAEG;IACH,IAAI,CACF,OAAO,EAAE,uBAAuB,EAChC,QAAQ,CAAC,EAAE,wBAAwB,GAClC,eAAe,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,4BAAiC,GACzC,oBAAoB,CAuFtB;AAMD,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,GAC3B,CAAC"}
@@ -0,0 +1,110 @@
1
+ import { NoSuchModelError } from '@ai-sdk/provider';
2
+ import { withoutTrailingSlash } from '@ai-sdk/provider-utils';
3
+ import { DefaultAzureCredential, ManagedIdentityCredential, WorkloadIdentityCredential, getBearerTokenProvider, } from '@azure/identity';
4
+ import { AzureFoundryChatLanguageModel, } from './azure-foundry-chat-language-model.js';
5
+ // ---------------------------------------------------------------------------
6
+ // Scope used to obtain tokens for Azure AI Foundry / Azure ML endpoints
7
+ // ---------------------------------------------------------------------------
8
+ const AZURE_AI_SCOPE = 'https://cognitiveservices.azure.com/.default';
9
+ // ---------------------------------------------------------------------------
10
+ // Factory
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Create an Azure AI Foundry provider instance.
14
+ *
15
+ * Authentication is handled via Azure Identity. The credential is resolved
16
+ * in the following order (when no `credential` is specified):
17
+ *
18
+ * 1. `AZURE_CLIENT_ID` / `AZURE_CLIENT_SECRET` / `AZURE_TENANT_ID` env vars
19
+ * 2. Workload identity (Kubernetes pods with federated credentials)
20
+ * 3. Managed identity (Azure-hosted compute)
21
+ * 4. Azure CLI (`az login`)
22
+ * 5. Azure PowerShell
23
+ * 6. VS Code account
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { createAzureFoundry } from '@nquandt/azure-ai-sdk';
28
+ * import { generateText } from 'ai';
29
+ *
30
+ * // Azure OpenAI / Cognitive Services endpoint:
31
+ * const foundry = createAzureFoundry({
32
+ * endpoint: 'https://my-resource.cognitiveservices.azure.com',
33
+ * });
34
+ *
35
+ * // AI Foundry inference endpoint:
36
+ * const foundry = createAzureFoundry({
37
+ * endpoint: 'https://my-project.services.ai.azure.com/models',
38
+ * });
39
+ *
40
+ * const { text } = await generateText({
41
+ * model: foundry('DeepSeek-R1'),
42
+ * prompt: 'Hello world',
43
+ * });
44
+ * ```
45
+ */
46
+ export function createAzureFoundry(options = {}) {
47
+ const endpoint = withoutTrailingSlash(options.endpoint ??
48
+ (typeof process !== 'undefined'
49
+ ? process.env.AZURE_AI_FOUNDRY_ENDPOINT
50
+ : undefined)) ?? '';
51
+ if (!endpoint) {
52
+ throw new Error('@nquandt/azure-ai-sdk: An Azure AI Foundry endpoint is required. ' +
53
+ 'Provide it via the `endpoint` option or the AZURE_AI_FOUNDRY_ENDPOINT environment variable.');
54
+ }
55
+ const credential = options.credential ?? new DefaultAzureCredential();
56
+ const scope = options.scope ?? AZURE_AI_SCOPE;
57
+ // getToken is cached and auto-refreshed by the Azure SDK
58
+ const getToken = getBearerTokenProvider(credential, scope);
59
+ const getHeaders = async () => {
60
+ const token = await getToken();
61
+ return {
62
+ Authorization: `Bearer ${token}`,
63
+ ...options.headers,
64
+ };
65
+ };
66
+ // Detect endpoint style and build the appropriate chat completions URL.
67
+ //
68
+ // cognitiveservices.azure.com → Azure OpenAI deployment-path style:
69
+ // {endpoint}/openai/deployments/{modelId}/chat/completions?api-version=...
70
+ //
71
+ // services.ai.azure.com/models → AI Foundry inference style:
72
+ // {endpoint}/chat/completions (model sent in request body)
73
+ //
74
+ const isCognitiveServices = endpoint.includes('cognitiveservices.azure.com');
75
+ const apiVersion = options.apiVersion ?? '2024-10-21';
76
+ const buildUrl = (modelId) => {
77
+ if (isCognitiveServices) {
78
+ return `${endpoint}/openai/deployments/${encodeURIComponent(modelId)}/chat/completions?api-version=${apiVersion}`;
79
+ }
80
+ return `${endpoint}/chat/completions`;
81
+ };
82
+ const createChatModel = (modelId, settings = {}) => new AzureFoundryChatLanguageModel(modelId, settings, {
83
+ provider: 'azure-foundry.chat',
84
+ url: buildUrl,
85
+ modelInBody: !isCognitiveServices,
86
+ headers: getHeaders,
87
+ fetch: options.fetch,
88
+ generateId: options.generateId,
89
+ });
90
+ const provider = function (modelId, settings) {
91
+ if (new.target) {
92
+ throw new Error('The AzureFoundry model function cannot be called with the new keyword.');
93
+ }
94
+ return createChatModel(modelId, settings);
95
+ };
96
+ provider.languageModel = createChatModel;
97
+ provider.chat = createChatModel;
98
+ provider.textEmbeddingModel = (modelId) => {
99
+ throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });
100
+ };
101
+ provider.imageModel = (modelId) => {
102
+ throw new NoSuchModelError({ modelId, modelType: 'imageModel' });
103
+ };
104
+ return provider;
105
+ }
106
+ // ---------------------------------------------------------------------------
107
+ // Convenience exports for well-known credential types
108
+ // ---------------------------------------------------------------------------
109
+ export { DefaultAzureCredential, ManagedIdentityCredential, WorkloadIdentityCredential, };
110
+ //# sourceMappingURL=azure-foundry-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-foundry-provider.js","sourceRoot":"","sources":["../src/azure-foundry-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { createAzureFoundry } from './azure-foundry-provider.js';
2
+ export type { AzureFoundryProvider, AzureFoundryProviderSettings } from './azure-foundry-provider.js';
3
+ export type { AzureFoundryChatModelId, AzureFoundryChatSettings } from './azure-foundry-chat-options.js';
4
+ export { AzureFoundryChatLanguageModel } from './azure-foundry-chat-language-model.js';
5
+ export { DefaultAzureCredential, ManagedIdentityCredential, WorkloadIdentityCredential, } from './azure-foundry-provider.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,YAAY,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAMtG,YAAY,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAMzG,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AAYvF,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,6BAA6B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,35 @@
1
+ // =============================================================================
2
+ // @nquandt/azure-ai-sdk
3
+ //
4
+ // Vercel AI SDK custom provider for Azure AI Foundry using Entra authentication.
5
+ // =============================================================================
6
+ // ---------------------------------------------------------------------------
7
+ // Primary entrypoint — everything a consumer needs is re-exported here.
8
+ // ---------------------------------------------------------------------------
9
+ // -- Provider factory --------------------------------------------------------
10
+ // `createAzureFoundry` is the main entrypoint. Call it with your endpoint
11
+ // (and optionally a credential) to get a provider instance:
12
+ //
13
+ // const foundry = createAzureFoundry({ endpoint: '...' });
14
+ // const model = foundry('DeepSeek-R1'); // LanguageModelV1
15
+ // const model = foundry.chat('DeepSeek-R1'); // same, explicit
16
+ // const model = foundry.languageModel('DeepSeek-R1'); // same, via ProviderV1
17
+ //
18
+ export { createAzureFoundry } from './azure-foundry-provider.js';
19
+ // -- Language model class ----------------------------------------------------
20
+ // Exposed for advanced use — e.g. constructing a model directly without the
21
+ // provider factory, or wrapping it in another abstraction.
22
+ //
23
+ export { AzureFoundryChatLanguageModel } from './azure-foundry-chat-language-model.js';
24
+ // -- Azure Identity credentials ----------------------------------------------
25
+ // Re-exported from @azure/identity so consumers don't need a direct dependency
26
+ // just to pass a custom credential:
27
+ //
28
+ // import { createAzureFoundry, ManagedIdentityCredential } from '@nquandt/azure-ai-sdk';
29
+ // const foundry = createAzureFoundry({
30
+ // endpoint: '...',
31
+ // credential: new ManagedIdentityCredential('<client-id>'),
32
+ // });
33
+ //
34
+ export { DefaultAzureCredential, ManagedIdentityCredential, WorkloadIdentityCredential, } from './azure-foundry-provider.js';
35
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,wBAAwB;AACxB,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAEhF,8EAA8E;AAC9E,wEAAwE;AACxE,8EAA8E;AAE9E,+EAA+E;AAC/E,0EAA0E;AAC1E,4DAA4D;AAC5D,EAAE;AACF,6DAA6D;AAC7D,6EAA6E;AAC7E,6EAA6E;AAC7E,kFAAkF;AAClF,EAAE;AACF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AASjE,+EAA+E;AAC/E,4EAA4E;AAC5E,2DAA2D;AAC3D,EAAE;AACF,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AAEvF,+EAA+E;AAC/E,+EAA+E;AAC/E,oCAAoC;AACpC,EAAE;AACF,2FAA2F;AAC3F,yCAAyC;AACzC,uBAAuB;AACvB,gEAAgE;AAChE,QAAQ;AACR,EAAE;AACF,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const VERSION = "0.1.0";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const VERSION = '0.1.0';
2
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@nquandt/azure-ai-sdk",
3
+ "version": "0.1.3",
4
+ "description": "Vercel AI SDK custom provider for Azure AI Foundry using Azure Entra identity authentication",
5
+ "license": "MIT",
6
+ "author": "nquandt",
7
+ "homepage": "https://github.com/nquandt/azure-ai-sdk",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/nquandt/azure-ai-sdk.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/nquandt/azure-ai-sdk/issues"
14
+ },
15
+ "keywords": [
16
+ "ai",
17
+ "azure",
18
+ "azure-ai-foundry",
19
+ "vercel-ai-sdk",
20
+ "ai-sdk",
21
+ "custom-provider",
22
+ "llm"
23
+ ],
24
+ "type": "module",
25
+ "main": "./dist/index.js",
26
+ "module": "./dist/index.js",
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "import": "./dist/index.js",
31
+ "types": "./dist/index.d.ts"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "scripts": {
38
+ "build": "tsc -p tsconfig.build.json",
39
+ "dev": "tsc -p tsconfig.build.json --watch",
40
+ "typecheck": "tsc --noEmit",
41
+ "clean": "rm -rf dist",
42
+ "test": "vitest run",
43
+ "test:watch": "vitest"
44
+ },
45
+ "peerDependencies": {
46
+ "ai": ">=4.0.0"
47
+ },
48
+ "dependencies": {
49
+ "@ai-sdk/provider": "^1.1.3",
50
+ "@ai-sdk/provider-utils": "^2.2.8",
51
+ "@azure/identity": "^4.10.0",
52
+ "zod": "^3.24.2"
53
+ },
54
+ "devDependencies": {
55
+ "@types/node": "^22.13.9",
56
+ "ai": "^4.3.15",
57
+ "tsx": "^4.21.0",
58
+ "typescript": "^5.8.2",
59
+ "vitest": "^4.0.18"
60
+ }
61
+ }