@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 +254 -0
- package/dist/azure-foundry-chat-language-model.d.ts +41 -0
- package/dist/azure-foundry-chat-language-model.d.ts.map +1 -0
- package/dist/azure-foundry-chat-language-model.js +461 -0
- package/dist/azure-foundry-chat-language-model.js.map +1 -0
- package/dist/azure-foundry-chat-options.d.ts +17 -0
- package/dist/azure-foundry-chat-options.d.ts.map +1 -0
- package/dist/azure-foundry-chat-options.js +2 -0
- package/dist/azure-foundry-chat-options.js.map +1 -0
- package/dist/azure-foundry-error.d.ts +32 -0
- package/dist/azure-foundry-error.d.ts.map +1 -0
- package/dist/azure-foundry-error.js +15 -0
- package/dist/azure-foundry-error.js.map +1 -0
- package/dist/azure-foundry-provider.d.ts +107 -0
- package/dist/azure-foundry-provider.d.ts.map +1 -0
- package/dist/azure-foundry-provider.js +110 -0
- package/dist/azure-foundry-provider.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +61 -0
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
|
+
[](https://www.npmjs.com/package/@nquandt/azure-ai-sdk)
|
|
8
|
+
[](https://jsr.io/@nquandt/azure-ai-sdk)
|
|
9
|
+
[](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 @@
|
|
|
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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
package/dist/version.js
ADDED
|
@@ -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
|
+
}
|