@ai-sdk/alibaba 1.0.53 → 1.0.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ai-sdk/alibaba
2
2
 
3
+ ## 1.0.55
4
+
5
+ ### Patch Changes
6
+
7
+ - def3cdf: feat(alibaba): preserve reasoning in multi-turn requests by default on supported models
8
+
9
+ ## 1.0.54
10
+
11
+ ### Patch Changes
12
+
13
+ - 4bd2599: fix(deepseek): preserve reasoning streams across empty tool-call deltas
14
+
3
15
  ## 1.0.53
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -63,6 +63,60 @@ console.log('Reasoning:', reasoningText);
63
63
  console.log('Answer:', text);
64
64
  ```
65
65
 
66
+ ## Preserved Thinking Example (Multi-Turn Reasoning)
67
+
68
+ For models that support preserved thinking, the AI SDK sends reasoning from
69
+ previous assistant messages back as Alibaba `reasoning_content` by default
70
+ (`preserve_thinking`), so the model can build on its earlier thought process:
71
+
72
+ ```ts
73
+ import { alibaba } from '@ai-sdk/alibaba';
74
+ import { generateText } from 'ai';
75
+
76
+ const providerOptions = {
77
+ alibaba: {
78
+ enableThinking: true,
79
+ thinkingBudget: 2048,
80
+ },
81
+ };
82
+
83
+ const opening = {
84
+ role: 'user' as const,
85
+ content: 'Is Kafka or RocketMQ a better fit for transactional messages?',
86
+ };
87
+
88
+ const first = await generateText({
89
+ model: alibaba('qwen3.7-max'),
90
+ messages: [opening],
91
+ providerOptions,
92
+ });
93
+
94
+ const second = await generateText({
95
+ model: alibaba('qwen3.7-max'),
96
+ messages: [
97
+ opening,
98
+ ...first.responseMessages, // append unchanged to keep the reasoning parts
99
+ { role: 'user', content: 'Which tradeoff mattered most?' },
100
+ ],
101
+ providerOptions,
102
+ });
103
+ ```
104
+
105
+ When continuing the conversation, append `responseMessages` unchanged so the
106
+ reasoning parts survive to be serialized as `reasoning_content`. Set the
107
+ `preserveThinking` provider option to `false` to opt out. Keep in mind:
108
+
109
+ - `preserveThinking` does not enable thinking by itself.
110
+ - It is enabled by default only for models that Alibaba documents as supporting
111
+ preserved thinking; for other models the option is not sent unless you set it
112
+ explicitly. See Alibaba's
113
+ [preserved-thinking documentation](https://docs.qwencloud.com/developer-guides/text-generation/thinking#preserve-thinking-in-multi-turn).
114
+ - Reasoning from the current tool-call round is always sent back with tool
115
+ results, as Alibaba recommends.
116
+ - Preserved reasoning increases input token usage and billing.
117
+ - Historical reasoning remains separate from visible assistant text; it is never
118
+ merged into `content`.
119
+
66
120
  ## Embedding Model Example
67
121
 
68
122
  ```ts
package/dist/index.d.mts CHANGED
@@ -6,6 +6,7 @@ type AlibabaChatModelId = 'qwen3.7-max' | 'qwen3-max' | 'qwen3-max-preview' | 'q
6
6
  declare const alibabaLanguageModelOptions: z.ZodObject<{
7
7
  enableThinking: z.ZodOptional<z.ZodBoolean>;
8
8
  thinkingBudget: z.ZodOptional<z.ZodNumber>;
9
+ preserveThinking: z.ZodOptional<z.ZodBoolean>;
9
10
  parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
10
11
  }, z.core.$strip>;
11
12
  type AlibabaLanguageModelOptions = z.infer<typeof alibabaLanguageModelOptions>;
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ type AlibabaChatModelId = 'qwen3.7-max' | 'qwen3-max' | 'qwen3-max-preview' | 'q
6
6
  declare const alibabaLanguageModelOptions: z.ZodObject<{
7
7
  enableThinking: z.ZodOptional<z.ZodBoolean>;
8
8
  thinkingBudget: z.ZodOptional<z.ZodNumber>;
9
+ preserveThinking: z.ZodOptional<z.ZodBoolean>;
9
10
  parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
10
11
  }, z.core.$strip>;
11
12
  type AlibabaLanguageModelOptions = z.infer<typeof alibabaLanguageModelOptions>;
package/dist/index.js CHANGED
@@ -50,6 +50,15 @@ var alibabaLanguageModelOptions = import_v4.z.object({
50
50
  * Maximum number of reasoning tokens to generate.
51
51
  */
52
52
  thinkingBudget: import_v4.z.number().positive().optional(),
53
+ /**
54
+ * Whether to preserve reasoning from previous assistant messages.
55
+ *
56
+ * When enabled, historical reasoning is sent separately as
57
+ * `reasoning_content` and Alibaba receives `preserve_thinking: true`.
58
+ * Defaults to `true` for models that support preserved thinking; set to
59
+ * `false` to opt out.
60
+ */
61
+ preserveThinking: import_v4.z.boolean().optional(),
53
62
  /**
54
63
  * Whether to enable parallel function calling during tool use.
55
64
  *
@@ -101,11 +110,21 @@ function formatImageUrl({
101
110
  }
102
111
  function convertToAlibabaChatMessages({
103
112
  prompt,
104
- cacheControlValidator
113
+ cacheControlValidator,
114
+ preserveThinking = false
105
115
  }) {
106
116
  var _a, _b;
107
117
  const messages = [];
118
+ let lastUserMessageIndex = -1;
119
+ for (let i = prompt.length - 1; i >= 0; i--) {
120
+ if (prompt[i].role === "user") {
121
+ lastUserMessageIndex = i;
122
+ break;
123
+ }
124
+ }
125
+ let index = -1;
108
126
  for (const { role, content, ...message } of prompt) {
127
+ index++;
109
128
  const messageCacheControl = cacheControlValidator == null ? void 0 : cacheControlValidator.getCacheControl(
110
129
  message.providerOptions
111
130
  );
@@ -130,9 +149,9 @@ function convertToAlibabaChatMessages({
130
149
  case "user": {
131
150
  messages.push({
132
151
  role: "user",
133
- content: content.map((part, index) => {
152
+ content: content.map((part, index2) => {
134
153
  var _a2;
135
- const isLastPart = index === content.length - 1;
154
+ const isLastPart = index2 === content.length - 1;
136
155
  const partCacheControl = (_a2 = cacheControlValidator == null ? void 0 : cacheControlValidator.getCacheControl(part.providerOptions)) != null ? _a2 : isLastPart ? messageCacheControl : void 0;
137
156
  switch (part.type) {
138
157
  case "text": {
@@ -165,6 +184,7 @@ function convertToAlibabaChatMessages({
165
184
  }
166
185
  case "assistant": {
167
186
  let text = "";
187
+ let reasoningContent = "";
168
188
  const toolCalls = [];
169
189
  for (const part of content) {
170
190
  switch (part.type) {
@@ -184,14 +204,20 @@ function convertToAlibabaChatMessages({
184
204
  break;
185
205
  }
186
206
  case "reasoning": {
187
- text += part.text;
207
+ if (preserveThinking || index > lastUserMessageIndex) {
208
+ reasoningContent += part.text;
209
+ }
188
210
  break;
189
211
  }
190
212
  }
191
213
  }
214
+ if (text.length === 0 && toolCalls.length === 0 && reasoningContent.length === 0) {
215
+ break;
216
+ }
192
217
  messages.push({
193
218
  role: "assistant",
194
- content: messageCacheControl ? [{ type: "text", text, cache_control: messageCacheControl }] : text || null,
219
+ content: text.length === 0 && toolCalls.length === 0 && reasoningContent.length > 0 ? null : messageCacheControl ? [{ type: "text", text, cache_control: messageCacheControl }] : text || null,
220
+ ...reasoningContent.length > 0 ? { reasoning_content: reasoningContent } : {},
195
221
  tool_calls: toolCalls.length > 0 ? toolCalls : void 0
196
222
  });
197
223
  break;
@@ -277,6 +303,29 @@ var CacheControlValidator = class {
277
303
  }
278
304
  };
279
305
 
306
+ // src/supports-preserved-thinking.ts
307
+ var preservedThinkingModelIds = /* @__PURE__ */ new Set([
308
+ "kimi-k2.7-code",
309
+ "qwen3.6-max-preview",
310
+ "qwen3.6-plus",
311
+ "qwen3.6-plus-2026-04-02",
312
+ "qwen3.7-flash",
313
+ "qwen3.7-flash-2026-07-15",
314
+ "qwen3.7-max",
315
+ "qwen3.7-max-2026-05-17",
316
+ "qwen3.7-max-2026-05-20",
317
+ "qwen3.7-max-2026-06-08",
318
+ "qwen3.7-max-preview",
319
+ "qwen3.7-plus",
320
+ "qwen3.7-plus-2026-05-26",
321
+ "qwen3.8-flash",
322
+ "qwen3.8-max",
323
+ "qwen3.8-max-0902"
324
+ ]);
325
+ function supportsPreservedThinking(modelId) {
326
+ return preservedThinkingModelIds.has(modelId);
327
+ }
328
+
280
329
  // src/alibaba-chat-language-model.ts
281
330
  var AlibabaLanguageModel = class {
282
331
  constructor(modelId, config) {
@@ -309,7 +358,7 @@ var AlibabaLanguageModel = class {
309
358
  tools,
310
359
  toolChoice
311
360
  }) {
312
- var _a;
361
+ var _a, _b;
313
362
  const warnings = [];
314
363
  const cacheControlValidator = new CacheControlValidator();
315
364
  const alibabaOptions = await (0, import_provider_utils3.parseProviderOptions)({
@@ -320,6 +369,7 @@ var AlibabaLanguageModel = class {
320
369
  if (frequencyPenalty != null) {
321
370
  warnings.push({ type: "unsupported", feature: "frequencyPenalty" });
322
371
  }
372
+ const preserveThinking = (_a = alibabaOptions == null ? void 0 : alibabaOptions.preserveThinking) != null ? _a : supportsPreservedThinking(this.modelId) ? true : void 0;
323
373
  const baseArgs = {
324
374
  model: this.modelId,
325
375
  max_tokens: maxOutputTokens,
@@ -333,17 +383,19 @@ var AlibabaLanguageModel = class {
333
383
  type: "json_schema",
334
384
  json_schema: {
335
385
  schema: responseFormat.schema,
336
- name: (_a = responseFormat.name) != null ? _a : "response",
386
+ name: (_b = responseFormat.name) != null ? _b : "response",
337
387
  description: responseFormat.description
338
388
  }
339
389
  } : { type: "json_object" } : void 0,
340
390
  // Alibaba-specific options
341
391
  ...(alibabaOptions == null ? void 0 : alibabaOptions.enableThinking) != null ? { enable_thinking: alibabaOptions.enableThinking } : {},
342
392
  ...(alibabaOptions == null ? void 0 : alibabaOptions.thinkingBudget) != null ? { thinking_budget: alibabaOptions.thinkingBudget } : {},
393
+ ...preserveThinking != null ? { preserve_thinking: preserveThinking } : {},
343
394
  // Convert messages with cache control support
344
395
  messages: convertToAlibabaChatMessages({
345
396
  prompt,
346
- cacheControlValidator
397
+ cacheControlValidator,
398
+ preserveThinking: preserveThinking != null ? preserveThinking : false
347
399
  })
348
400
  };
349
401
  const {
@@ -513,7 +565,7 @@ var AlibabaLanguageModel = class {
513
565
  delta: delta.content
514
566
  });
515
567
  }
516
- if (delta.tool_calls != null) {
568
+ if (delta.tool_calls != null && delta.tool_calls.length > 0) {
517
569
  if (activeReasoningId != null) {
518
570
  controller.enqueue({
519
571
  type: "reasoning-end",
@@ -1312,7 +1364,7 @@ var AlibabaVideoModel = class {
1312
1364
  };
1313
1365
 
1314
1366
  // src/version.ts
1315
- var VERSION = true ? "1.0.53" : "0.0.0-test";
1367
+ var VERSION = true ? "1.0.55" : "0.0.0-test";
1316
1368
 
1317
1369
  // src/alibaba-provider.ts
1318
1370
  function createAlibaba(options = {}) {