@ai-sdk/alibaba 0.0.0-6b196531-20260710185421

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.
@@ -0,0 +1,220 @@
1
+ import {
2
+ UnsupportedFunctionalityError,
3
+ type LanguageModelV4FilePart,
4
+ type LanguageModelV4Prompt,
5
+ } from '@ai-sdk/provider';
6
+ import {
7
+ convertToBase64,
8
+ getTopLevelMediaType,
9
+ resolveFullMediaType,
10
+ } from '@ai-sdk/provider-utils';
11
+ import type { AlibabaChatPrompt } from './alibaba-chat-prompt';
12
+ import type { CacheControlValidator } from './get-cache-control';
13
+
14
+ function formatImageUrl({ part }: { part: LanguageModelV4FilePart }): string {
15
+ if (part.data.type === 'url') {
16
+ return part.data.url.toString();
17
+ }
18
+
19
+ if (part.data.type === 'data') {
20
+ return `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}`;
21
+ }
22
+
23
+ throw new UnsupportedFunctionalityError({
24
+ functionality: `file part data type ${part.data.type}`,
25
+ });
26
+ }
27
+
28
+ export function convertToAlibabaChatMessages({
29
+ prompt,
30
+ cacheControlValidator,
31
+ }: {
32
+ prompt: LanguageModelV4Prompt;
33
+ cacheControlValidator?: CacheControlValidator;
34
+ }): AlibabaChatPrompt {
35
+ const messages: AlibabaChatPrompt = [];
36
+
37
+ for (const { role, content, ...message } of prompt) {
38
+ const messageCacheControl = cacheControlValidator?.getCacheControl(
39
+ message.providerOptions,
40
+ );
41
+
42
+ switch (role) {
43
+ case 'system': {
44
+ if (messageCacheControl) {
45
+ messages.push({
46
+ role: 'system',
47
+ content: [
48
+ {
49
+ type: 'text',
50
+ text: content,
51
+ cache_control: messageCacheControl,
52
+ },
53
+ ],
54
+ });
55
+ } else {
56
+ messages.push({ role: 'system', content });
57
+ }
58
+ break;
59
+ }
60
+
61
+ case 'user': {
62
+ messages.push({
63
+ role: 'user',
64
+ content: content.map((part, index) => {
65
+ const isLastPart = index === content.length - 1;
66
+ const partCacheControl =
67
+ cacheControlValidator?.getCacheControl(part.providerOptions) ??
68
+ (isLastPart ? messageCacheControl : undefined);
69
+
70
+ switch (part.type) {
71
+ case 'text': {
72
+ return {
73
+ type: 'text',
74
+ text: part.text,
75
+ ...(partCacheControl
76
+ ? { cache_control: partCacheControl }
77
+ : {}),
78
+ };
79
+ }
80
+
81
+ case 'file': {
82
+ switch (part.data.type) {
83
+ case 'reference': {
84
+ throw new UnsupportedFunctionalityError({
85
+ functionality: 'file parts with provider references',
86
+ });
87
+ }
88
+ case 'text': {
89
+ throw new UnsupportedFunctionalityError({
90
+ functionality: 'text file parts',
91
+ });
92
+ }
93
+ case 'url':
94
+ case 'data': {
95
+ if (getTopLevelMediaType(part.mediaType) === 'image') {
96
+ return {
97
+ type: 'image_url',
98
+ image_url: {
99
+ url: formatImageUrl({ part }),
100
+ },
101
+ ...(partCacheControl
102
+ ? { cache_control: partCacheControl }
103
+ : {}),
104
+ };
105
+ } else {
106
+ throw new UnsupportedFunctionalityError({
107
+ functionality: 'Only image file parts are supported',
108
+ });
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }),
115
+ });
116
+ break;
117
+ }
118
+
119
+ case 'assistant': {
120
+ let text = '';
121
+ const toolCalls: Array<{
122
+ id: string;
123
+ type: 'function';
124
+ function: { name: string; arguments: string };
125
+ }> = [];
126
+
127
+ for (const part of content) {
128
+ switch (part.type) {
129
+ case 'text': {
130
+ text += part.text;
131
+ break;
132
+ }
133
+ case 'tool-call': {
134
+ toolCalls.push({
135
+ id: part.toolCallId,
136
+ type: 'function',
137
+ function: {
138
+ name: part.toolName,
139
+ arguments: JSON.stringify(part.input),
140
+ },
141
+ });
142
+ break;
143
+ }
144
+ case 'reasoning': {
145
+ // Reasoning content is handled separately in the response
146
+ // but may appear in assistant messages during multi-turn conversations
147
+ text += part.text;
148
+ break;
149
+ }
150
+ }
151
+ }
152
+
153
+ messages.push({
154
+ role: 'assistant',
155
+ content: messageCacheControl
156
+ ? [{ type: 'text', text, cache_control: messageCacheControl }]
157
+ : text || null,
158
+ tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
159
+ });
160
+
161
+ break;
162
+ }
163
+
164
+ case 'tool': {
165
+ const toolResponses = content.filter(
166
+ r => r.type !== 'tool-approval-response',
167
+ );
168
+
169
+ for (let i = 0; i < toolResponses.length; i++) {
170
+ const toolResponse = toolResponses[i];
171
+ const output = toolResponse.output;
172
+ const isLastPart = i === toolResponses.length - 1;
173
+
174
+ const partCacheControl =
175
+ cacheControlValidator?.getCacheControl(
176
+ toolResponse.providerOptions,
177
+ ) ?? (isLastPart ? messageCacheControl : undefined);
178
+
179
+ let contentValue: string;
180
+ switch (output.type) {
181
+ case 'text':
182
+ case 'error-text':
183
+ contentValue = output.value;
184
+ break;
185
+ case 'execution-denied':
186
+ contentValue = output.reason ?? 'Tool call execution denied.';
187
+ break;
188
+ case 'content':
189
+ case 'json':
190
+ case 'error-json':
191
+ contentValue = JSON.stringify(output.value);
192
+ break;
193
+ }
194
+
195
+ messages.push({
196
+ role: 'tool',
197
+ tool_call_id: toolResponse.toolCallId,
198
+ content: partCacheControl
199
+ ? [
200
+ {
201
+ type: 'text',
202
+ text: contentValue,
203
+ cache_control: partCacheControl,
204
+ },
205
+ ]
206
+ : contentValue,
207
+ });
208
+ }
209
+ break;
210
+ }
211
+
212
+ default: {
213
+ const _exhaustiveCheck: never = role;
214
+ throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
215
+ }
216
+ }
217
+ }
218
+
219
+ return messages;
220
+ }
@@ -0,0 +1,49 @@
1
+ import type {
2
+ SharedV4ProviderMetadata,
3
+ SharedV4Warning,
4
+ } from '@ai-sdk/provider';
5
+ import type { AlibabaCacheControl } from './alibaba-chat-prompt';
6
+
7
+ // Alibaba allows a maximum of 4 cache breakpoints per request
8
+ const MAX_CACHE_BREAKPOINTS = 4;
9
+
10
+ function getCacheControl(
11
+ providerMetadata: SharedV4ProviderMetadata | undefined,
12
+ ): AlibabaCacheControl | undefined {
13
+ const alibaba = providerMetadata?.alibaba;
14
+
15
+ const cacheControlValue = alibaba?.cacheControl ?? alibaba?.cache_control;
16
+
17
+ // Pass through value assuming it is of the correct type.
18
+ // The Alibaba API will validate the value.
19
+ return cacheControlValue as AlibabaCacheControl | undefined;
20
+ }
21
+
22
+ export class CacheControlValidator {
23
+ private breakpointCount = 0;
24
+ private warnings: SharedV4Warning[] = [];
25
+
26
+ getCacheControl(
27
+ providerMetadata: SharedV4ProviderMetadata | undefined,
28
+ ): AlibabaCacheControl | undefined {
29
+ const cacheControlValue = getCacheControl(providerMetadata);
30
+
31
+ if (!cacheControlValue) {
32
+ return undefined;
33
+ }
34
+
35
+ this.breakpointCount++;
36
+ if (this.breakpointCount > MAX_CACHE_BREAKPOINTS) {
37
+ this.warnings.push({
38
+ type: 'other',
39
+ message: `Max breakpoint limit exceeded. Only the last ${MAX_CACHE_BREAKPOINTS} cache markers will take effect.`,
40
+ });
41
+ }
42
+
43
+ return cacheControlValue;
44
+ }
45
+
46
+ getWarnings(): SharedV4Warning[] {
47
+ return this.warnings;
48
+ }
49
+ }
package/src/index.ts ADDED
@@ -0,0 +1,27 @@
1
+ export type {
2
+ AlibabaChatModelId,
3
+ AlibabaLanguageModelChatOptions,
4
+ /** @deprecated Use `AlibabaLanguageModelChatOptions` instead. */
5
+ AlibabaLanguageModelChatOptions as AlibabaLanguageModelOptions,
6
+ /** @deprecated Use `AlibabaLanguageModelChatOptions` instead. */
7
+ AlibabaLanguageModelChatOptions as AlibabaProviderOptions,
8
+ } from './alibaba-chat-language-model-options';
9
+ export type { AlibabaCacheControl } from './alibaba-chat-prompt';
10
+ export type {
11
+ AlibabaEmbeddingModelId,
12
+ AlibabaEmbeddingModelOptions,
13
+ } from './alibaba-embedding-model-options';
14
+ export {
15
+ type AlibabaProvider,
16
+ type AlibabaProviderSettings,
17
+ alibaba,
18
+ createAlibaba,
19
+ } from './alibaba-provider';
20
+ export type {
21
+ AlibabaVideoModelOptions,
22
+ /** @deprecated Use `AlibabaVideoModelOptions` instead. */
23
+ AlibabaVideoModelOptions as AlibabaVideoProviderOptions,
24
+ } from './alibaba-video-model-options';
25
+ export type { AlibabaVideoModelId } from './alibaba-video-settings';
26
+ export type { AlibabaUsage } from './convert-alibaba-usage';
27
+ export { VERSION } from './version';
package/src/version.ts ADDED
@@ -0,0 +1,6 @@
1
+ // Version string of this package injected at build time.
2
+ declare const __PACKAGE_VERSION__: string | undefined;
3
+ export const VERSION: string =
4
+ typeof __PACKAGE_VERSION__ !== 'undefined'
5
+ ? __PACKAGE_VERSION__
6
+ : '0.0.0-test';