@openclaw/qwen-provider 2026.7.1-beta.6 → 2026.7.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.js CHANGED
@@ -1,4 +1,4 @@
1
- import { MODELSTUDIO_BASE_URL, MODELSTUDIO_CN_BASE_URL, MODELSTUDIO_DEFAULT_COST, MODELSTUDIO_DEFAULT_MODEL_ID, MODELSTUDIO_DEFAULT_MODEL_REF, MODELSTUDIO_GLOBAL_BASE_URL, MODELSTUDIO_MODEL_CATALOG, MODELSTUDIO_STANDARD_CN_BASE_URL, MODELSTUDIO_STANDARD_GLOBAL_BASE_URL, QWEN_36_PLUS_MODEL_ID, QWEN_BASE_URL, QWEN_CN_BASE_URL, QWEN_DEFAULT_COST, QWEN_DEFAULT_MODEL_ID, QWEN_DEFAULT_MODEL_REF, QWEN_GLOBAL_BASE_URL, QWEN_MODEL_CATALOG, QWEN_STANDARD_CN_BASE_URL, QWEN_STANDARD_GLOBAL_BASE_URL, applyModelStudioNativeStreamingUsageCompat, applyQwenNativeStreamingUsageCompat, buildModelStudioDefaultModelDefinition, buildModelStudioModelDefinition, buildQwenDefaultModelDefinition, buildQwenModelCatalogForBaseUrl, buildQwenModelDefinition, isNativeModelStudioBaseUrl, isNativeQwenBaseUrl, isQwen36PlusSupportedBaseUrl, isQwenCodingPlanBaseUrl } from "./models.js";
2
- import { buildModelStudioProvider, buildQwenProvider } from "./provider-catalog.js";
1
+ import { MODELSTUDIO_BASE_URL, MODELSTUDIO_CN_BASE_URL, MODELSTUDIO_DEFAULT_COST, MODELSTUDIO_DEFAULT_MODEL_ID, MODELSTUDIO_DEFAULT_MODEL_REF, MODELSTUDIO_GLOBAL_BASE_URL, MODELSTUDIO_MODEL_CATALOG, MODELSTUDIO_STANDARD_CN_BASE_URL, MODELSTUDIO_STANDARD_GLOBAL_BASE_URL, QWEN_36_FLASH_MODEL_ID, QWEN_36_PLUS_MODEL_ID, QWEN_37_MAX_MODEL_ID, QWEN_37_PLUS_MODEL_ID, QWEN_BASE_URL, QWEN_CN_BASE_URL, QWEN_DEFAULT_COST, QWEN_DEFAULT_MODEL_ID, QWEN_DEFAULT_MODEL_REF, QWEN_GLOBAL_BASE_URL, QWEN_MODEL_CATALOG, QWEN_STANDARD_CN_BASE_URL, QWEN_STANDARD_GLOBAL_BASE_URL, QWEN_TOKEN_PLAN_CN_BASE_URL, QWEN_TOKEN_PLAN_DEFAULT_MODEL_ID, QWEN_TOKEN_PLAN_DEFAULT_MODEL_REF, QWEN_TOKEN_PLAN_GLOBAL_BASE_URL, QWEN_TOKEN_PLAN_LEGACY_PROVIDER_ID, QWEN_TOKEN_PLAN_MODEL_CATALOG, QWEN_TOKEN_PLAN_PROVIDER_ID, applyModelStudioNativeStreamingUsageCompat, applyQwenNativeStreamingUsageCompat, buildModelStudioDefaultModelDefinition, buildModelStudioModelDefinition, buildQwenDefaultModelDefinition, buildQwenModelCatalogForBaseUrl, buildQwenModelDefinition, isNativeModelStudioBaseUrl, isNativeQwenBaseUrl, isQwen36PlusSupportedBaseUrl, isQwenCodingPlanBaseUrl, isQwenStandardOnlyModelId, resolveQwenTokenPlanBaseUrl } from "./models.js";
2
+ import { buildModelStudioProvider, buildQwenProvider, buildQwenTokenPlanProvider } from "./provider-catalog.js";
3
3
  import { createQwenThinkingWrapper, wrapQwenProviderStream } from "./stream.js";
4
- export { MODELSTUDIO_BASE_URL, MODELSTUDIO_CN_BASE_URL, MODELSTUDIO_DEFAULT_COST, MODELSTUDIO_DEFAULT_MODEL_ID, MODELSTUDIO_DEFAULT_MODEL_REF, MODELSTUDIO_GLOBAL_BASE_URL, MODELSTUDIO_MODEL_CATALOG, MODELSTUDIO_STANDARD_CN_BASE_URL, MODELSTUDIO_STANDARD_GLOBAL_BASE_URL, QWEN_36_PLUS_MODEL_ID, QWEN_BASE_URL, QWEN_CN_BASE_URL, QWEN_DEFAULT_COST, QWEN_DEFAULT_MODEL_ID, QWEN_DEFAULT_MODEL_REF, QWEN_GLOBAL_BASE_URL, QWEN_MODEL_CATALOG, QWEN_STANDARD_CN_BASE_URL, QWEN_STANDARD_GLOBAL_BASE_URL, applyModelStudioNativeStreamingUsageCompat, applyQwenNativeStreamingUsageCompat, buildModelStudioDefaultModelDefinition, buildModelStudioModelDefinition, buildModelStudioProvider, buildQwenDefaultModelDefinition, buildQwenModelCatalogForBaseUrl, buildQwenModelDefinition, buildQwenProvider, createQwenThinkingWrapper, isNativeModelStudioBaseUrl, isNativeQwenBaseUrl, isQwen36PlusSupportedBaseUrl, isQwenCodingPlanBaseUrl, wrapQwenProviderStream };
4
+ export { MODELSTUDIO_BASE_URL, MODELSTUDIO_CN_BASE_URL, MODELSTUDIO_DEFAULT_COST, MODELSTUDIO_DEFAULT_MODEL_ID, MODELSTUDIO_DEFAULT_MODEL_REF, MODELSTUDIO_GLOBAL_BASE_URL, MODELSTUDIO_MODEL_CATALOG, MODELSTUDIO_STANDARD_CN_BASE_URL, MODELSTUDIO_STANDARD_GLOBAL_BASE_URL, QWEN_36_FLASH_MODEL_ID, QWEN_36_PLUS_MODEL_ID, QWEN_37_MAX_MODEL_ID, QWEN_37_PLUS_MODEL_ID, QWEN_BASE_URL, QWEN_CN_BASE_URL, QWEN_DEFAULT_COST, QWEN_DEFAULT_MODEL_ID, QWEN_DEFAULT_MODEL_REF, QWEN_GLOBAL_BASE_URL, QWEN_MODEL_CATALOG, QWEN_STANDARD_CN_BASE_URL, QWEN_STANDARD_GLOBAL_BASE_URL, QWEN_TOKEN_PLAN_CN_BASE_URL, QWEN_TOKEN_PLAN_DEFAULT_MODEL_ID, QWEN_TOKEN_PLAN_DEFAULT_MODEL_REF, QWEN_TOKEN_PLAN_GLOBAL_BASE_URL, QWEN_TOKEN_PLAN_LEGACY_PROVIDER_ID, QWEN_TOKEN_PLAN_MODEL_CATALOG, QWEN_TOKEN_PLAN_PROVIDER_ID, applyModelStudioNativeStreamingUsageCompat, applyQwenNativeStreamingUsageCompat, buildModelStudioDefaultModelDefinition, buildModelStudioModelDefinition, buildModelStudioProvider, buildQwenDefaultModelDefinition, buildQwenModelCatalogForBaseUrl, buildQwenModelDefinition, buildQwenProvider, buildQwenTokenPlanProvider, createQwenThinkingWrapper, isNativeModelStudioBaseUrl, isNativeQwenBaseUrl, isQwen36PlusSupportedBaseUrl, isQwenCodingPlanBaseUrl, isQwenStandardOnlyModelId, resolveQwenTokenPlanBaseUrl, wrapQwenProviderStream };
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { QWEN_36_PLUS_MODEL_ID, QWEN_DEFAULT_MODEL_REF, QWEN_OAUTH_DEFAULT_MODEL_REF, QWEN_OAUTH_PROVIDER_ID, applyQwenNativeStreamingUsageCompat, isQwenCodingPlanBaseUrl } from "./models.js";
2
- import { buildQwenOAuthProvider, buildQwenProvider } from "./provider-catalog.js";
1
+ import { QWEN_DEFAULT_MODEL_REF, QWEN_OAUTH_DEFAULT_MODEL_REF, QWEN_OAUTH_PROVIDER_ID, QWEN_TOKEN_PLAN_DEFAULT_MODEL_REF, QWEN_TOKEN_PLAN_LEGACY_PROVIDER_ID, QWEN_TOKEN_PLAN_PROVIDER_ID, applyQwenNativeStreamingUsageCompat, isQwenCodingPlanBaseUrl, isQwenStandardOnlyModelId, isQwenTokenPlanDeepSeekV4ModelId, isQwenTokenPlanGlmModelId, isQwenTokenPlanThinkingOnlyModelId, supportsQwenTokenPlanGlmMaxThinking } from "./models.js";
2
+ import { buildQwenOAuthProvider, buildQwenProvider, buildQwenTokenPlanProvider } from "./provider-catalog.js";
3
3
  import { wrapQwenProviderStream } from "./stream.js";
4
4
  import "./api.js";
5
5
  import { buildQwenMediaUnderstandingProvider } from "./media-understanding-provider.js";
6
- import { applyQwenConfig, applyQwenConfigCn, applyQwenOAuthConfig, applyQwenStandardConfig, applyQwenStandardConfigCn } from "./onboard.js";
6
+ import { applyQwenConfig, applyQwenConfigCn, applyQwenOAuthConfig, applyQwenStandardConfig, applyQwenStandardConfigCn, applyQwenTokenPlanConfig } from "./onboard.js";
7
7
  import { buildQwenVideoGenerationProvider } from "./video-generation-provider.js";
8
8
  import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth-api-key";
9
9
  import { defineSingleProviderPluginEntry } from "openclaw/plugin-sdk/provider-entry";
@@ -15,6 +15,16 @@ const QWEN_OAUTH_AUTH_PROVIDER_IDS = [
15
15
  "qwen-portal",
16
16
  "qwen-cli"
17
17
  ];
18
+ const QWEN_TOKEN_PLAN_THINKING_LEVEL_IDS = [
19
+ "off",
20
+ "minimal",
21
+ "low",
22
+ "medium",
23
+ "high",
24
+ "xhigh",
25
+ "max"
26
+ ];
27
+ const QWEN_TOKEN_PLAN_GLM_NO_MAX_THINKING_LEVEL_IDS = QWEN_TOKEN_PLAN_THINKING_LEVEL_IDS.filter((id) => id !== "max");
18
28
  function normalizeProviderId(value) {
19
29
  return value.trim().toLowerCase();
20
30
  }
@@ -28,6 +38,58 @@ function resolveConfiguredQwenBaseUrl(config) {
28
38
  if (baseUrl) return baseUrl;
29
39
  }
30
40
  }
41
+ function resolveConfiguredQwenTokenPlanBaseUrl(config) {
42
+ const providers = config?.models?.providers;
43
+ if (!providers) return;
44
+ for (const [providerId, provider] of Object.entries(providers)) {
45
+ if (normalizeProviderId(providerId) !== "qwen-token-plan") continue;
46
+ const baseUrl = provider?.baseUrl?.trim();
47
+ if (baseUrl) return baseUrl;
48
+ }
49
+ }
50
+ function createQwenTokenPlanAuthMethod(region) {
51
+ const isCn = region === "cn";
52
+ const regionLabel = isCn ? "China" : "Global/Intl";
53
+ const host = isCn ? "token-plan.cn-beijing.maas.aliyuncs.com" : "token-plan.ap-southeast-1.maas.aliyuncs.com";
54
+ return createProviderApiKeyAuthMethod({
55
+ providerId: QWEN_TOKEN_PLAN_PROVIDER_ID,
56
+ methodId: isCn ? "api-key-cn" : "api-key",
57
+ label: `Qwen Token Plan API Key for ${regionLabel} (subscription)`,
58
+ hint: `Endpoint: ${host}`,
59
+ optionKey: isCn ? "qwenTokenPlanApiKeyCn" : "qwenTokenPlanApiKey",
60
+ flagName: isCn ? "--qwen-token-plan-api-key-cn" : "--qwen-token-plan-api-key",
61
+ envVar: "QWEN_TOKEN_PLAN_API_KEY",
62
+ promptMessage: `Enter Alibaba Qwen Token Plan API key (${regionLabel}, sk-sp-...)`,
63
+ defaultModel: QWEN_TOKEN_PLAN_DEFAULT_MODEL_REF,
64
+ applyConfig: (cfg) => applyQwenTokenPlanConfig(cfg, region),
65
+ wizard: {
66
+ choiceId: isCn ? "qwen-token-plan-cn" : "qwen-token-plan",
67
+ choiceLabel: `Qwen Token Plan (${regionLabel})`,
68
+ choiceHint: `Endpoint: ${host}`,
69
+ groupId: "qwen",
70
+ groupLabel: "Qwen Cloud",
71
+ groupHint: "Standard / Coding Plan / Token Plan / OAuth"
72
+ }
73
+ });
74
+ }
75
+ function resolveQwenTokenPlanThinkingProfile(modelId) {
76
+ if (isQwenTokenPlanThinkingOnlyModelId(modelId)) return {
77
+ levels: [{
78
+ id: "low",
79
+ label: "on"
80
+ }],
81
+ defaultLevel: "low",
82
+ preserveWhenCatalogReasoningFalse: true
83
+ };
84
+ if (isQwenTokenPlanDeepSeekV4ModelId(modelId)) return {
85
+ levels: QWEN_TOKEN_PLAN_THINKING_LEVEL_IDS.map((id) => ({ id })),
86
+ defaultLevel: "high"
87
+ };
88
+ if (isQwenTokenPlanGlmModelId(modelId)) return {
89
+ levels: (supportsQwenTokenPlanGlmMaxThinking(modelId) ? QWEN_TOKEN_PLAN_THINKING_LEVEL_IDS : QWEN_TOKEN_PLAN_GLM_NO_MAX_THINKING_LEVEL_IDS).map((id) => ({ id })),
90
+ defaultLevel: "high"
91
+ };
92
+ }
31
93
  var qwen_default = defineSingleProviderPluginEntry({
32
94
  id: PROVIDER_ID,
33
95
  name: "Qwen Provider",
@@ -51,7 +113,7 @@ var qwen_default = defineSingleProviderPluginEntry({
51
113
  "Manage API keys: https://home.qwencloud.com/api-keys",
52
114
  "Docs: https://docs.qwencloud.com/",
53
115
  "Endpoint: dashscope.aliyuncs.com/compatible-mode/v1",
54
- "Models: qwen3.6-plus, qwen3.5-plus, qwen3-coder-plus, etc."
116
+ "Models: qwen3.7-max, qwen3.7-plus, qwen3.6-plus, qwen3.6-flash, qwen3.5-plus, etc."
55
117
  ].join("\n"),
56
118
  noteTitle: "Qwen Cloud Standard (China)",
57
119
  wizard: {
@@ -74,7 +136,7 @@ var qwen_default = defineSingleProviderPluginEntry({
74
136
  "Manage API keys: https://home.qwencloud.com/api-keys",
75
137
  "Docs: https://docs.qwencloud.com/",
76
138
  "Endpoint: dashscope-intl.aliyuncs.com/compatible-mode/v1",
77
- "Models: qwen3.6-plus, qwen3.5-plus, qwen3-coder-plus, etc."
139
+ "Models: qwen3.7-max, qwen3.7-plus, qwen3.6-plus, qwen3.6-flash, qwen3.5-plus, etc."
78
140
  ].join("\n"),
79
141
  noteTitle: "Qwen Cloud Standard (Global/Intl)",
80
142
  wizard: {
@@ -142,7 +204,7 @@ var qwen_default = defineSingleProviderPluginEntry({
142
204
  wrapStreamFn: wrapQwenProviderStream,
143
205
  normalizeConfig: ({ providerConfig }) => {
144
206
  if (!isQwenCodingPlanBaseUrl(providerConfig.baseUrl)) return;
145
- const models = providerConfig.models?.filter((model) => model.id !== QWEN_36_PLUS_MODEL_ID);
207
+ const models = providerConfig.models?.filter((model) => !isQwenStandardOnlyModelId(model.id));
146
208
  return models && models.length !== providerConfig.models?.length ? {
147
209
  ...providerConfig,
148
210
  models
@@ -193,6 +255,39 @@ var qwen_default = defineSingleProviderPluginEntry({
193
255
  },
194
256
  wrapStreamFn: wrapQwenProviderStream
195
257
  });
258
+ api.registerProvider({
259
+ id: QWEN_TOKEN_PLAN_PROVIDER_ID,
260
+ label: "Qwen Token Plan",
261
+ docsPath: "/providers/qwen",
262
+ envVars: ["QWEN_TOKEN_PLAN_API_KEY"],
263
+ auth: [createQwenTokenPlanAuthMethod("global"), createQwenTokenPlanAuthMethod("cn")],
264
+ catalog: {
265
+ order: "simple",
266
+ run: async (ctx) => {
267
+ const apiKey = ctx.resolveProviderApiKey(QWEN_TOKEN_PLAN_PROVIDER_ID).apiKey;
268
+ if (!apiKey) return null;
269
+ return { provider: {
270
+ ...buildQwenTokenPlanProvider({ baseUrl: resolveConfiguredQwenTokenPlanBaseUrl(ctx.config) }),
271
+ apiKey
272
+ } };
273
+ }
274
+ },
275
+ staticCatalog: {
276
+ order: "simple",
277
+ run: async () => ({ provider: buildQwenTokenPlanProvider() })
278
+ },
279
+ applyNativeStreamingUsageCompat: ({ providerConfig }) => applyQwenNativeStreamingUsageCompat(providerConfig),
280
+ wrapStreamFn: wrapQwenProviderStream,
281
+ resolveThinkingProfile: ({ modelId }) => resolveQwenTokenPlanThinkingProfile(modelId)
282
+ });
283
+ api.registerProvider({
284
+ id: QWEN_TOKEN_PLAN_LEGACY_PROVIDER_ID,
285
+ label: "Alibaba Token Plan (legacy custom config)",
286
+ docsPath: "/providers/qwen",
287
+ auth: [],
288
+ applyNativeStreamingUsageCompat: ({ providerConfig }) => applyQwenNativeStreamingUsageCompat(providerConfig),
289
+ wrapStreamFn: wrapQwenProviderStream
290
+ });
196
291
  api.registerMediaUnderstandingProvider(buildQwenMediaUnderstandingProvider());
197
292
  api.registerVideoGenerationProvider(buildQwenVideoGenerationProvider());
198
293
  }
package/dist/models.js CHANGED
@@ -7,8 +7,15 @@ const QWEN_STANDARD_CN_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mod
7
7
  const QWEN_STANDARD_GLOBAL_BASE_URL = "https://dashscope-intl.aliyuncs.com/compatible-mode/v1";
8
8
  const QWEN_OAUTH_PROVIDER_ID = "qwen-oauth";
9
9
  const QWEN_OAUTH_BASE_URL = "https://portal.qwen.ai/v1";
10
+ const QWEN_TOKEN_PLAN_PROVIDER_ID = "qwen-token-plan";
11
+ const QWEN_TOKEN_PLAN_LEGACY_PROVIDER_ID = "bailian-token-plan";
12
+ const QWEN_TOKEN_PLAN_GLOBAL_BASE_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1";
13
+ const QWEN_TOKEN_PLAN_CN_BASE_URL = "https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1";
10
14
  const QWEN_DEFAULT_MODEL_ID = "qwen3.5-plus";
15
+ const QWEN_36_FLASH_MODEL_ID = "qwen3.6-flash";
11
16
  const QWEN_36_PLUS_MODEL_ID = "qwen3.6-plus";
17
+ const QWEN_37_MAX_MODEL_ID = "qwen3.7-max";
18
+ const QWEN_37_PLUS_MODEL_ID = "qwen3.7-plus";
12
19
  const QWEN_DEFAULT_COST = {
13
20
  input: 0,
14
21
  output: 0,
@@ -17,6 +24,174 @@ const QWEN_DEFAULT_COST = {
17
24
  };
18
25
  const QWEN_DEFAULT_MODEL_REF = `qwen/${QWEN_DEFAULT_MODEL_ID}`;
19
26
  const QWEN_OAUTH_DEFAULT_MODEL_REF = `qwen-oauth/${QWEN_DEFAULT_MODEL_ID}`;
27
+ const QWEN_TOKEN_PLAN_DEFAULT_MODEL_ID = QWEN_37_PLUS_MODEL_ID;
28
+ const QWEN_TOKEN_PLAN_DEFAULT_MODEL_REF = `${QWEN_TOKEN_PLAN_PROVIDER_ID}/${QWEN_TOKEN_PLAN_DEFAULT_MODEL_ID}`;
29
+ const QWEN_TOKEN_PLAN_THINKING_ONLY_MODEL_IDS = /* @__PURE__ */ new Set(["kimi-k2.7-code", "minimax-m2.5"]);
30
+ const QWEN_TOKEN_PLAN_DEEPSEEK_V4_MODEL_IDS = /* @__PURE__ */ new Set(["deepseek-v4-pro", "deepseek-v4-flash"]);
31
+ const QWEN_TOKEN_PLAN_KIMI_MODEL_IDS = /* @__PURE__ */ new Set([
32
+ "kimi-k2.7-code",
33
+ "kimi-k2.6",
34
+ "kimi-k2.5"
35
+ ]);
36
+ const QWEN_TOKEN_PLAN_GLM_MODEL_IDS = /* @__PURE__ */ new Set([
37
+ "glm-5.2",
38
+ "glm-5.1",
39
+ "glm-5"
40
+ ]);
41
+ function isQwenTokenPlanThinkingOnlyModelId(modelId) {
42
+ return QWEN_TOKEN_PLAN_THINKING_ONLY_MODEL_IDS.has(modelId.trim().toLowerCase());
43
+ }
44
+ function isQwenTokenPlanDeepSeekV4ModelId(modelId) {
45
+ return QWEN_TOKEN_PLAN_DEEPSEEK_V4_MODEL_IDS.has(modelId.trim().toLowerCase());
46
+ }
47
+ function isQwenTokenPlanKimiModelId(modelId) {
48
+ return QWEN_TOKEN_PLAN_KIMI_MODEL_IDS.has(modelId.trim().toLowerCase());
49
+ }
50
+ function isQwenTokenPlanGlmModelId(modelId) {
51
+ return QWEN_TOKEN_PLAN_GLM_MODEL_IDS.has(modelId.trim().toLowerCase());
52
+ }
53
+ function supportsQwenTokenPlanGlmMaxThinking(modelId) {
54
+ return modelId.trim().toLowerCase() === "glm-5.2";
55
+ }
56
+ const QWEN_TOKEN_PLAN_BASE_URLS = {
57
+ global: QWEN_TOKEN_PLAN_GLOBAL_BASE_URL,
58
+ cn: QWEN_TOKEN_PLAN_CN_BASE_URL
59
+ };
60
+ function resolveQwenTokenPlanBaseUrl(region) {
61
+ return QWEN_TOKEN_PLAN_BASE_URLS[region];
62
+ }
63
+ const QWEN_TOKEN_PLAN_MODEL_CATALOG = [
64
+ {
65
+ id: QWEN_37_MAX_MODEL_ID,
66
+ name: QWEN_37_MAX_MODEL_ID,
67
+ reasoning: true,
68
+ input: ["text"],
69
+ cost: QWEN_DEFAULT_COST,
70
+ contextWindow: 1e6,
71
+ maxTokens: 65536
72
+ },
73
+ {
74
+ id: QWEN_37_PLUS_MODEL_ID,
75
+ name: QWEN_37_PLUS_MODEL_ID,
76
+ reasoning: true,
77
+ input: ["text", "image"],
78
+ cost: QWEN_DEFAULT_COST,
79
+ contextWindow: 1e6,
80
+ maxTokens: 65536
81
+ },
82
+ {
83
+ id: QWEN_36_PLUS_MODEL_ID,
84
+ name: QWEN_36_PLUS_MODEL_ID,
85
+ reasoning: true,
86
+ input: ["text", "image"],
87
+ cost: QWEN_DEFAULT_COST,
88
+ contextWindow: 1e6,
89
+ maxTokens: 65536
90
+ },
91
+ {
92
+ id: QWEN_36_FLASH_MODEL_ID,
93
+ name: QWEN_36_FLASH_MODEL_ID,
94
+ reasoning: true,
95
+ input: ["text", "image"],
96
+ cost: QWEN_DEFAULT_COST,
97
+ contextWindow: 1e6,
98
+ maxTokens: 65536
99
+ },
100
+ {
101
+ id: "deepseek-v4-pro",
102
+ name: "deepseek-v4-pro",
103
+ reasoning: true,
104
+ input: ["text"],
105
+ cost: QWEN_DEFAULT_COST,
106
+ contextWindow: 1e6,
107
+ maxTokens: 393216
108
+ },
109
+ {
110
+ id: "deepseek-v4-flash",
111
+ name: "deepseek-v4-flash",
112
+ reasoning: true,
113
+ input: ["text"],
114
+ cost: QWEN_DEFAULT_COST,
115
+ contextWindow: 1e6,
116
+ maxTokens: 393216
117
+ },
118
+ {
119
+ id: "deepseek-v3.2",
120
+ name: "deepseek-v3.2",
121
+ reasoning: true,
122
+ input: ["text"],
123
+ cost: QWEN_DEFAULT_COST,
124
+ contextWindow: 131072,
125
+ maxTokens: 65536
126
+ },
127
+ {
128
+ id: "kimi-k2.7-code",
129
+ name: "kimi-k2.7-code",
130
+ reasoning: true,
131
+ input: ["text", "image"],
132
+ cost: QWEN_DEFAULT_COST,
133
+ contextWindow: 262144,
134
+ maxTokens: 98304
135
+ },
136
+ {
137
+ id: "kimi-k2.6",
138
+ name: "kimi-k2.6",
139
+ reasoning: true,
140
+ input: ["text", "image"],
141
+ cost: QWEN_DEFAULT_COST,
142
+ contextWindow: 262144,
143
+ maxTokens: 98304
144
+ },
145
+ {
146
+ id: "kimi-k2.5",
147
+ name: "kimi-k2.5",
148
+ reasoning: true,
149
+ input: ["text", "image"],
150
+ cost: QWEN_DEFAULT_COST,
151
+ contextWindow: 262144,
152
+ maxTokens: 98304
153
+ },
154
+ {
155
+ id: "glm-5.2",
156
+ name: "glm-5.2",
157
+ reasoning: true,
158
+ input: ["text"],
159
+ cost: QWEN_DEFAULT_COST,
160
+ contextWindow: 1e6,
161
+ maxTokens: 131072
162
+ },
163
+ {
164
+ id: "glm-5.1",
165
+ name: "glm-5.1",
166
+ reasoning: true,
167
+ input: ["text"],
168
+ cost: QWEN_DEFAULT_COST,
169
+ contextWindow: 202752,
170
+ maxTokens: 131072
171
+ },
172
+ {
173
+ id: "glm-5",
174
+ name: "glm-5",
175
+ reasoning: true,
176
+ input: ["text"],
177
+ cost: QWEN_DEFAULT_COST,
178
+ contextWindow: 202752,
179
+ maxTokens: 16384
180
+ },
181
+ {
182
+ id: "MiniMax-M2.5",
183
+ name: "MiniMax-M2.5",
184
+ reasoning: true,
185
+ input: ["text"],
186
+ cost: QWEN_DEFAULT_COST,
187
+ contextWindow: 196608,
188
+ maxTokens: 32768
189
+ }
190
+ ];
191
+ function isQwenTokenPlanModelId(modelId) {
192
+ const normalized = modelId.trim().toLowerCase();
193
+ return QWEN_TOKEN_PLAN_MODEL_CATALOG.some((model) => model.id.toLowerCase() === normalized);
194
+ }
20
195
  const QWEN_MODEL_CATALOG = [
21
196
  {
22
197
  id: "qwen3.5-plus",
@@ -27,10 +202,37 @@ const QWEN_MODEL_CATALOG = [
27
202
  contextWindow: 1e6,
28
203
  maxTokens: 65536
29
204
  },
205
+ {
206
+ id: QWEN_36_FLASH_MODEL_ID,
207
+ name: QWEN_36_FLASH_MODEL_ID,
208
+ reasoning: true,
209
+ input: ["text", "image"],
210
+ cost: QWEN_DEFAULT_COST,
211
+ contextWindow: 1e6,
212
+ maxTokens: 65536
213
+ },
30
214
  {
31
215
  id: QWEN_36_PLUS_MODEL_ID,
32
216
  name: QWEN_36_PLUS_MODEL_ID,
33
- reasoning: false,
217
+ reasoning: true,
218
+ input: ["text", "image"],
219
+ cost: QWEN_DEFAULT_COST,
220
+ contextWindow: 1e6,
221
+ maxTokens: 65536
222
+ },
223
+ {
224
+ id: QWEN_37_MAX_MODEL_ID,
225
+ name: QWEN_37_MAX_MODEL_ID,
226
+ reasoning: true,
227
+ input: ["text"],
228
+ cost: QWEN_DEFAULT_COST,
229
+ contextWindow: 1e6,
230
+ maxTokens: 65536
231
+ },
232
+ {
233
+ id: QWEN_37_PLUS_MODEL_ID,
234
+ name: QWEN_37_PLUS_MODEL_ID,
235
+ reasoning: true,
34
236
  input: ["text", "image"],
35
237
  cost: QWEN_DEFAULT_COST,
36
238
  contextWindow: 1e6,
@@ -110,11 +312,20 @@ function isQwenCodingPlanBaseUrl(baseUrl) {
110
312
  return false;
111
313
  }
112
314
  }
113
- function isQwen36PlusSupportedBaseUrl(baseUrl) {
114
- return !isQwenCodingPlanBaseUrl(baseUrl);
315
+ function isQwen36PlusSupportedBaseUrl(_baseUrl) {
316
+ return true;
317
+ }
318
+ const QWEN_STANDARD_ONLY_MODEL_IDS = /* @__PURE__ */ new Set([QWEN_36_FLASH_MODEL_ID, QWEN_37_MAX_MODEL_ID]);
319
+ const QWEN_OAUTH_UNSUPPORTED_MODEL_IDS = /* @__PURE__ */ new Set([
320
+ QWEN_36_FLASH_MODEL_ID,
321
+ QWEN_37_MAX_MODEL_ID,
322
+ QWEN_37_PLUS_MODEL_ID
323
+ ]);
324
+ function isQwenStandardOnlyModelId(modelId) {
325
+ return QWEN_STANDARD_ONLY_MODEL_IDS.has(modelId);
115
326
  }
116
327
  function buildQwenModelCatalogForBaseUrl(baseUrl) {
117
- return isQwen36PlusSupportedBaseUrl(baseUrl) ? QWEN_MODEL_CATALOG : QWEN_MODEL_CATALOG.filter((model) => model.id !== QWEN_36_PLUS_MODEL_ID);
328
+ return isQwenCodingPlanBaseUrl(baseUrl) ? QWEN_MODEL_CATALOG.filter((model) => !isQwenStandardOnlyModelId(model.id)) : QWEN_MODEL_CATALOG;
118
329
  }
119
330
  function isNativeQwenBaseUrl(baseUrl) {
120
331
  return supportsNativeStreamingUsageCompat({
@@ -144,10 +355,7 @@ function buildQwenDefaultModelDefinition() {
144
355
  return buildQwenModelDefinition({ id: QWEN_DEFAULT_MODEL_ID });
145
356
  }
146
357
  function buildQwenOAuthModelCatalog() {
147
- return QWEN_MODEL_CATALOG.map((model) => ({
148
- ...model,
149
- maxTokens: 65536
150
- }));
358
+ return QWEN_MODEL_CATALOG.filter((model) => !QWEN_OAUTH_UNSUPPORTED_MODEL_IDS.has(model.id)).map((model) => Object.assign({}, model, { maxTokens: 65536 }));
151
359
  }
152
360
  /** @deprecated Use QWEN_BASE_URL. */
153
361
  const MODELSTUDIO_BASE_URL = QWEN_BASE_URL;
@@ -172,4 +380,4 @@ const applyModelStudioNativeStreamingUsageCompat = applyQwenNativeStreamingUsage
172
380
  const buildModelStudioModelDefinition = buildQwenModelDefinition;
173
381
  const buildModelStudioDefaultModelDefinition = buildQwenDefaultModelDefinition;
174
382
  //#endregion
175
- export { MODELSTUDIO_BASE_URL, MODELSTUDIO_CN_BASE_URL, MODELSTUDIO_DEFAULT_COST, MODELSTUDIO_DEFAULT_MODEL_ID, MODELSTUDIO_DEFAULT_MODEL_REF, MODELSTUDIO_GLOBAL_BASE_URL, MODELSTUDIO_MODEL_CATALOG, MODELSTUDIO_STANDARD_CN_BASE_URL, MODELSTUDIO_STANDARD_GLOBAL_BASE_URL, QWEN_36_PLUS_MODEL_ID, QWEN_BASE_URL, QWEN_CN_BASE_URL, QWEN_DEFAULT_COST, QWEN_DEFAULT_MODEL_ID, QWEN_DEFAULT_MODEL_REF, QWEN_GLOBAL_BASE_URL, QWEN_MODEL_CATALOG, QWEN_OAUTH_BASE_URL, QWEN_OAUTH_DEFAULT_MODEL_REF, QWEN_OAUTH_PROVIDER_ID, QWEN_STANDARD_CN_BASE_URL, QWEN_STANDARD_GLOBAL_BASE_URL, applyModelStudioNativeStreamingUsageCompat, applyQwenNativeStreamingUsageCompat, buildModelStudioDefaultModelDefinition, buildModelStudioModelDefinition, buildQwenDefaultModelDefinition, buildQwenModelCatalogForBaseUrl, buildQwenModelDefinition, buildQwenOAuthModelCatalog, isNativeModelStudioBaseUrl, isNativeQwenBaseUrl, isQwen36PlusSupportedBaseUrl, isQwenCodingPlanBaseUrl };
383
+ export { MODELSTUDIO_BASE_URL, MODELSTUDIO_CN_BASE_URL, MODELSTUDIO_DEFAULT_COST, MODELSTUDIO_DEFAULT_MODEL_ID, MODELSTUDIO_DEFAULT_MODEL_REF, MODELSTUDIO_GLOBAL_BASE_URL, MODELSTUDIO_MODEL_CATALOG, MODELSTUDIO_STANDARD_CN_BASE_URL, MODELSTUDIO_STANDARD_GLOBAL_BASE_URL, QWEN_36_FLASH_MODEL_ID, QWEN_36_PLUS_MODEL_ID, QWEN_37_MAX_MODEL_ID, QWEN_37_PLUS_MODEL_ID, QWEN_BASE_URL, QWEN_CN_BASE_URL, QWEN_DEFAULT_COST, QWEN_DEFAULT_MODEL_ID, QWEN_DEFAULT_MODEL_REF, QWEN_GLOBAL_BASE_URL, QWEN_MODEL_CATALOG, QWEN_OAUTH_BASE_URL, QWEN_OAUTH_DEFAULT_MODEL_REF, QWEN_OAUTH_PROVIDER_ID, QWEN_STANDARD_CN_BASE_URL, QWEN_STANDARD_GLOBAL_BASE_URL, QWEN_TOKEN_PLAN_CN_BASE_URL, QWEN_TOKEN_PLAN_DEFAULT_MODEL_ID, QWEN_TOKEN_PLAN_DEFAULT_MODEL_REF, QWEN_TOKEN_PLAN_GLOBAL_BASE_URL, QWEN_TOKEN_PLAN_LEGACY_PROVIDER_ID, QWEN_TOKEN_PLAN_MODEL_CATALOG, QWEN_TOKEN_PLAN_PROVIDER_ID, applyModelStudioNativeStreamingUsageCompat, applyQwenNativeStreamingUsageCompat, buildModelStudioDefaultModelDefinition, buildModelStudioModelDefinition, buildQwenDefaultModelDefinition, buildQwenModelCatalogForBaseUrl, buildQwenModelDefinition, buildQwenOAuthModelCatalog, isNativeModelStudioBaseUrl, isNativeQwenBaseUrl, isQwen36PlusSupportedBaseUrl, isQwenCodingPlanBaseUrl, isQwenStandardOnlyModelId, isQwenTokenPlanDeepSeekV4ModelId, isQwenTokenPlanGlmModelId, isQwenTokenPlanKimiModelId, isQwenTokenPlanModelId, isQwenTokenPlanThinkingOnlyModelId, resolveQwenTokenPlanBaseUrl, supportsQwenTokenPlanGlmMaxThinking };
package/dist/onboard.js CHANGED
@@ -1,5 +1,5 @@
1
- import { QWEN_CN_BASE_URL, QWEN_DEFAULT_MODEL_REF, QWEN_GLOBAL_BASE_URL, QWEN_OAUTH_DEFAULT_MODEL_REF, QWEN_OAUTH_PROVIDER_ID, QWEN_STANDARD_CN_BASE_URL, QWEN_STANDARD_GLOBAL_BASE_URL } from "./models.js";
2
- import { buildQwenOAuthProvider, buildQwenProvider } from "./provider-catalog.js";
1
+ import { QWEN_CN_BASE_URL, QWEN_DEFAULT_MODEL_REF, QWEN_GLOBAL_BASE_URL, QWEN_OAUTH_DEFAULT_MODEL_REF, QWEN_OAUTH_PROVIDER_ID, QWEN_STANDARD_CN_BASE_URL, QWEN_STANDARD_GLOBAL_BASE_URL, QWEN_TOKEN_PLAN_DEFAULT_MODEL_REF, QWEN_TOKEN_PLAN_PROVIDER_ID, resolveQwenTokenPlanBaseUrl } from "./models.js";
2
+ import { buildQwenOAuthProvider, buildQwenProvider, buildQwenTokenPlanProvider } from "./provider-catalog.js";
3
3
  import { createModelCatalogPresetAppliers } from "openclaw/plugin-sdk/provider-onboard";
4
4
  //#region extensions/qwen/onboard.ts
5
5
  const qwenPresetAppliers = createModelCatalogPresetAppliers({
@@ -34,6 +34,22 @@ const qwenOAuthPresetAppliers = createModelCatalogPresetAppliers({
34
34
  };
35
35
  }
36
36
  });
37
+ const qwenTokenPlanPresetAppliers = createModelCatalogPresetAppliers({
38
+ primaryModelRef: QWEN_TOKEN_PLAN_DEFAULT_MODEL_REF,
39
+ resolveParams: (_cfg, baseUrl) => {
40
+ const provider = buildQwenTokenPlanProvider({ baseUrl });
41
+ return {
42
+ providerId: QWEN_TOKEN_PLAN_PROVIDER_ID,
43
+ api: provider.api ?? "openai-completions",
44
+ baseUrl,
45
+ catalogModels: provider.models ?? [],
46
+ aliases: [...(provider.models ?? []).map((model) => `${QWEN_TOKEN_PLAN_PROVIDER_ID}/${model.id}`), {
47
+ modelRef: QWEN_TOKEN_PLAN_DEFAULT_MODEL_REF,
48
+ alias: "Qwen Token Plan"
49
+ }]
50
+ };
51
+ }
52
+ });
37
53
  function applyQwenConfig(cfg) {
38
54
  return qwenPresetAppliers.applyConfig(cfg, QWEN_GLOBAL_BASE_URL);
39
55
  }
@@ -49,5 +65,8 @@ function applyQwenStandardConfigCn(cfg) {
49
65
  function applyQwenOAuthConfig(cfg) {
50
66
  return qwenOAuthPresetAppliers.applyConfig(cfg);
51
67
  }
68
+ function applyQwenTokenPlanConfig(cfg, region) {
69
+ return qwenTokenPlanPresetAppliers.applyConfig(cfg, resolveQwenTokenPlanBaseUrl(region));
70
+ }
52
71
  //#endregion
53
- export { applyQwenConfig, applyQwenConfigCn, applyQwenOAuthConfig, applyQwenStandardConfig, applyQwenStandardConfigCn };
72
+ export { applyQwenConfig, applyQwenConfigCn, applyQwenOAuthConfig, applyQwenStandardConfig, applyQwenStandardConfigCn, applyQwenTokenPlanConfig };
@@ -1,4 +1,4 @@
1
- import { QWEN_OAUTH_BASE_URL, buildQwenModelCatalogForBaseUrl, buildQwenOAuthModelCatalog } from "./models.js";
1
+ import { QWEN_OAUTH_BASE_URL, QWEN_TOKEN_PLAN_MODEL_CATALOG, buildQwenModelCatalogForBaseUrl, buildQwenOAuthModelCatalog } from "./models.js";
2
2
  //#region extensions/qwen/provider-catalog.ts
3
3
  function buildQwenProvider(params) {
4
4
  const baseUrl = params?.baseUrl ?? "https://coding-intl.dashscope.aliyuncs.com/v1";
@@ -15,6 +15,13 @@ function buildQwenOAuthProvider() {
15
15
  models: buildQwenOAuthModelCatalog().map((model) => Object.assign({}, model))
16
16
  };
17
17
  }
18
+ function buildQwenTokenPlanProvider(params) {
19
+ return {
20
+ baseUrl: params?.baseUrl ?? "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
21
+ api: "openai-completions",
22
+ models: QWEN_TOKEN_PLAN_MODEL_CATALOG.map((model) => Object.assign({}, model))
23
+ };
24
+ }
18
25
  const buildModelStudioProvider = buildQwenProvider;
19
26
  //#endregion
20
- export { buildModelStudioProvider, buildQwenOAuthProvider, buildQwenProvider };
27
+ export { buildModelStudioProvider, buildQwenOAuthProvider, buildQwenProvider, buildQwenTokenPlanProvider };
package/dist/stream.js CHANGED
@@ -1,9 +1,153 @@
1
+ import { isQwenTokenPlanDeepSeekV4ModelId, isQwenTokenPlanGlmModelId, isQwenTokenPlanKimiModelId, isQwenTokenPlanModelId, isQwenTokenPlanThinkingOnlyModelId, supportsQwenTokenPlanGlmMaxThinking } from "./models.js";
2
+ import { streamSimple } from "openclaw/plugin-sdk/llm";
1
3
  import { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
2
4
  import { createPayloadPatchStreamWrapper, isOpenAICompatibleThinkingEnabled, setQwenChatTemplateThinking } from "openclaw/plugin-sdk/provider-stream-shared";
3
5
  //#region extensions/qwen/stream.ts
6
+ function asPayloadRecord(value) {
7
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
8
+ }
9
+ function resolveQwenThinkingLevel(thinkingLevel, options) {
10
+ const runtimeOptions = options ?? {};
11
+ const raw = runtimeOptions.reasoningEffort ?? runtimeOptions.reasoning ?? thinkingLevel;
12
+ if (typeof raw !== "string") return thinkingLevel;
13
+ const normalized = raw.trim().toLowerCase();
14
+ if (normalized === "none") return "off";
15
+ switch (normalized) {
16
+ case "off":
17
+ case "minimal":
18
+ case "low":
19
+ case "medium":
20
+ case "high":
21
+ case "xhigh":
22
+ case "max": return normalized;
23
+ default: return thinkingLevel;
24
+ }
25
+ }
4
26
  function isQwenProviderId(providerId) {
5
27
  const normalized = normalizeProviderId(providerId);
6
- return normalized === "qwen" || normalized === "qwen-oauth" || normalized === "qwen-portal" || normalized === "qwen-cli" || normalized === "modelstudio" || normalized === "qwencloud" || normalized === "dashscope";
28
+ return normalized === "qwen" || normalized === "qwen-oauth" || normalized === "qwen-portal" || normalized === "qwen-cli" || normalized === "qwen-token-plan" || normalized === "bailian-token-plan" || normalized === "modelstudio" || normalized === "qwencloud" || normalized === "dashscope";
29
+ }
30
+ function isQwenTokenPlanProviderId(providerId) {
31
+ const normalized = normalizeProviderId(providerId);
32
+ return normalized === "qwen-token-plan" || normalized === "bailian-token-plan";
33
+ }
34
+ function resolveQwenTokenPlanThinkingContract(providerId, modelId) {
35
+ if (!isQwenTokenPlanProviderId(providerId)) return;
36
+ if (isQwenTokenPlanDeepSeekV4ModelId(modelId)) return { family: "deepseek-v4" };
37
+ if (isQwenTokenPlanKimiModelId(modelId)) return { family: "kimi" };
38
+ if (isQwenTokenPlanGlmModelId(modelId)) return {
39
+ family: "glm",
40
+ supportsMax: supportsQwenTokenPlanGlmMaxThinking(modelId)
41
+ };
42
+ }
43
+ function patchTokenPlanDeepSeekV4Payload(payload, thinkingLevel, enableThinking) {
44
+ delete payload.thinking;
45
+ if (!enableThinking) {
46
+ delete payload.reasoning_effort;
47
+ if (Array.isArray(payload.messages)) {
48
+ for (const message of payload.messages) if (message && typeof message === "object") delete message.reasoning_content;
49
+ }
50
+ return;
51
+ }
52
+ payload.reasoning_effort = thinkingLevel === "xhigh" || thinkingLevel === "max" ? "max" : "high";
53
+ if (!Array.isArray(payload.messages)) return;
54
+ for (const message of payload.messages) {
55
+ if (!message || typeof message !== "object") continue;
56
+ const record = message;
57
+ if (record.role === "assistant" && !("reasoning_content" in record)) record.reasoning_content = "";
58
+ }
59
+ }
60
+ function patchTokenPlanKimiPayload(payload, enableThinking) {
61
+ delete payload.thinking;
62
+ delete payload.reasoning_effort;
63
+ if (!enableThinking || !Array.isArray(payload.messages)) return;
64
+ for (const message of payload.messages) {
65
+ if (!message || typeof message !== "object") continue;
66
+ const record = message;
67
+ if (record.role === "assistant" && Array.isArray(record.tool_calls) && record.tool_calls.length > 0 && !("reasoning_content" in record)) record.reasoning_content = "";
68
+ }
69
+ }
70
+ function normalizeTokenPlanThinkingToolChoice(payload, enableThinking, forceThinking) {
71
+ if (!enableThinking) return false;
72
+ const toolChoice = payload.tool_choice;
73
+ const toolChoiceType = asPayloadRecord(toolChoice)?.type;
74
+ if (toolChoiceType === "auto" || toolChoiceType === "none") {
75
+ payload.tool_choice = toolChoiceType;
76
+ return true;
77
+ }
78
+ if (toolChoice == null || toolChoice === "auto" || toolChoice === "none") return true;
79
+ if (!forceThinking && (toolChoiceType === "tool" || toolChoiceType === "function")) {
80
+ payload.enable_thinking = false;
81
+ return false;
82
+ }
83
+ payload.tool_choice = "auto";
84
+ return true;
85
+ }
86
+ function enforceQwenTokenPlanPayloadAfterCaller(payload, tokenPlanContract, forceThinking, requestedEnableThinking, requestedThinkingLevel) {
87
+ const hasPayloadThinking = typeof payload.enable_thinking === "boolean";
88
+ let enableThinking = forceThinking || (hasPayloadThinking ? payload.enable_thinking !== false : requestedEnableThinking);
89
+ const rawThinkingLevel = typeof payload.reasoning_effort === "string" ? payload.reasoning_effort : hasPayloadThinking ? void 0 : requestedThinkingLevel;
90
+ if (!forceThinking && rawThinkingLevel === "off") enableThinking = false;
91
+ payload.enable_thinking = enableThinking;
92
+ enableThinking = normalizeTokenPlanThinkingToolChoice(payload, enableThinking, forceThinking);
93
+ if (tokenPlanContract?.family === "deepseek-v4") patchTokenPlanDeepSeekV4Payload(payload, rawThinkingLevel === "xhigh" || rawThinkingLevel === "max" ? "max" : "high", enableThinking);
94
+ else if (tokenPlanContract?.family === "kimi") patchTokenPlanKimiPayload(payload, enableThinking);
95
+ else if (tokenPlanContract?.family === "glm") {
96
+ if (Array.isArray(payload.tools) && payload.tools.length > 0) payload.tool_stream = true;
97
+ if (rawThinkingLevel === "none" && enableThinking) delete payload.thinking;
98
+ else patchTokenPlanGlmPayload(payload, typeof rawThinkingLevel === "string" ? resolveQwenThinkingLevel(rawThinkingLevel, void 0) : void 0, enableThinking, tokenPlanContract.supportsMax);
99
+ } else {
100
+ delete payload.thinking;
101
+ delete payload.reasoning_effort;
102
+ }
103
+ delete payload.reasoningEffort;
104
+ delete payload.reasoning;
105
+ }
106
+ function finalizeQwenTokenPlanPayloadAfterCaller(value, fallbackPayload, tokenPlanContract, forceThinking, requestedEnableThinking, requestedThinkingLevel) {
107
+ const finalPayload = asPayloadRecord(value) ?? fallbackPayload;
108
+ if (finalPayload) enforceQwenTokenPlanPayloadAfterCaller(finalPayload, tokenPlanContract, forceThinking, requestedEnableThinking, requestedThinkingLevel);
109
+ return value;
110
+ }
111
+ function createQwenTokenPlanConstraintWrapper(baseStreamFn, tokenPlanContract, forceThinking, thinkingLevel) {
112
+ const underlying = baseStreamFn ?? streamSimple;
113
+ return (model, context, options) => {
114
+ if (model.api !== "openai-completions" || !model.reasoning && !forceThinking) return underlying(model, context, options);
115
+ const requestedThinkingLevel = resolveQwenThinkingLevel(thinkingLevel, options);
116
+ const requestedEnableThinking = forceThinking || isOpenAICompatibleThinkingEnabled({
117
+ thinkingLevel,
118
+ options
119
+ });
120
+ const originalOnPayload = options?.onPayload;
121
+ return underlying(model, context, {
122
+ ...options,
123
+ onPayload(payload, payloadModel) {
124
+ const payloadObj = asPayloadRecord(payload);
125
+ const result = originalOnPayload?.(payload, payloadModel);
126
+ if (result && typeof result.then === "function") return Promise.resolve(result).then((resolved) => finalizeQwenTokenPlanPayloadAfterCaller(resolved, payloadObj, tokenPlanContract, forceThinking, requestedEnableThinking, requestedThinkingLevel));
127
+ return finalizeQwenTokenPlanPayloadAfterCaller(result, payloadObj, tokenPlanContract, forceThinking, requestedEnableThinking, requestedThinkingLevel);
128
+ }
129
+ });
130
+ };
131
+ }
132
+ function patchTokenPlanGlmPayload(payload, thinkingLevel, enableThinking, supportsMax) {
133
+ delete payload.thinking;
134
+ if (!enableThinking) {
135
+ delete payload.reasoning_effort;
136
+ return;
137
+ }
138
+ switch (thinkingLevel) {
139
+ case "minimal":
140
+ case "low":
141
+ case "medium":
142
+ case "high":
143
+ case "xhigh":
144
+ payload.reasoning_effort = thinkingLevel;
145
+ return;
146
+ case "max":
147
+ payload.reasoning_effort = supportsMax ? "max" : "xhigh";
148
+ return;
149
+ default: delete payload.reasoning_effort;
150
+ }
7
151
  }
8
152
  function isQwenOAuthProviderId(providerId) {
9
153
  const normalized = normalizeProviderId(providerId);
@@ -42,9 +186,10 @@ function readQwenThinkingFormatFromModel(model) {
42
186
  const compat = model.compat && typeof model.compat === "object" ? model.compat : void 0;
43
187
  return typeof compat?.thinkingFormat === "string" ? compat.thinkingFormat : void 0;
44
188
  }
45
- function createQwenThinkingWrapper(baseStreamFn, thinkingLevel, thinkingFormat) {
189
+ function createQwenThinkingWrapper(baseStreamFn, thinkingLevel, thinkingFormat, forceThinking = false, tokenPlanContract) {
46
190
  return createPayloadPatchStreamWrapper(baseStreamFn, ({ payload: payloadObj, model, options }) => {
47
- const enableThinking = isOpenAICompatibleThinkingEnabled({
191
+ const effectiveThinkingLevel = resolveQwenThinkingLevel(thinkingLevel, options);
192
+ const enableThinking = forceThinking || isOpenAICompatibleThinkingEnabled({
48
193
  thinkingLevel,
49
194
  options
50
195
  });
@@ -52,14 +197,24 @@ function createQwenThinkingWrapper(baseStreamFn, thinkingLevel, thinkingFormat)
52
197
  setQwenChatTemplateThinking(payloadObj, enableThinking);
53
198
  delete payloadObj.enable_thinking;
54
199
  } else payloadObj.enable_thinking = enableThinking;
55
- delete payloadObj.reasoning_effort;
200
+ if (tokenPlanContract?.family === "deepseek-v4") patchTokenPlanDeepSeekV4Payload(payloadObj, effectiveThinkingLevel, enableThinking);
201
+ else if (tokenPlanContract?.family === "kimi") patchTokenPlanKimiPayload(payloadObj, false);
202
+ else if (tokenPlanContract?.family === "glm") patchTokenPlanGlmPayload(payloadObj, effectiveThinkingLevel, enableThinking, tokenPlanContract.supportsMax);
203
+ else delete payloadObj.reasoning_effort;
56
204
  delete payloadObj.reasoningEffort;
57
205
  delete payloadObj.reasoning;
58
- }, { shouldPatch: ({ model }) => model.api === "openai-completions" && model.reasoning });
206
+ }, { shouldPatch: ({ model }) => model.api === "openai-completions" && (model.reasoning || forceThinking) });
59
207
  }
60
208
  function wrapQwenProviderStream(ctx) {
61
209
  if (!isQwenProviderId(ctx.provider) || ctx.model && ctx.model.api !== "openai-completions") return;
62
- const streamFn = createQwenThinkingWrapper(ctx.streamFn, ctx.thinkingLevel, ctx.model ? readQwenThinkingFormatFromModel(ctx.model) : void 0);
210
+ const thinkingFormat = ctx.model ? readQwenThinkingFormatFromModel(ctx.model) : void 0;
211
+ const explicitLegacyThinkingFormat = normalizeProviderId(ctx.provider) === "bailian-token-plan" && thinkingFormat !== void 0;
212
+ if (explicitLegacyThinkingFormat && thinkingFormat !== "qwen-chat-template") return ctx.streamFn;
213
+ const tokenPlanContract = explicitLegacyThinkingFormat ? void 0 : resolveQwenTokenPlanThinkingContract(ctx.provider, ctx.modelId);
214
+ const tokenPlanModel = isQwenTokenPlanProviderId(ctx.provider) && isQwenTokenPlanModelId(ctx.modelId) && !explicitLegacyThinkingFormat;
215
+ const forceThinking = tokenPlanModel && isQwenTokenPlanThinkingOnlyModelId(ctx.modelId);
216
+ let streamFn = createQwenThinkingWrapper(ctx.streamFn, ctx.thinkingLevel, thinkingFormat, forceThinking, tokenPlanContract);
217
+ if (tokenPlanModel) streamFn = createQwenTokenPlanConstraintWrapper(streamFn, tokenPlanContract, forceThinking, ctx.thinkingLevel);
63
218
  if (!isQwenOAuthProviderId(ctx.provider)) return streamFn;
64
219
  return createPayloadPatchStreamWrapper(streamFn, ({ payload, model }) => {
65
220
  if (model.api === "openai-completions") patchQwenOAuthPayload(payload);
@@ -1,5 +1,5 @@
1
1
  import "./models.js";
2
- import { resolveProviderHttpRequestConfig } from "openclaw/plugin-sdk/provider-http";
2
+ import { resolveProviderHttpRequestConfig, sanitizeConfiguredModelProviderRequest } from "openclaw/plugin-sdk/provider-http";
3
3
  import { isProviderApiKeyConfigured } from "openclaw/plugin-sdk/provider-auth";
4
4
  import { resolveApiKeyForProvider } from "openclaw/plugin-sdk/provider-auth-runtime";
5
5
  import { DASHSCOPE_WAN_VIDEO_CAPABILITIES, DASHSCOPE_WAN_VIDEO_MODELS, DEFAULT_DASHSCOPE_WAN_VIDEO_MODEL, DEFAULT_VIDEO_GENERATION_TIMEOUT_MS, runDashscopeVideoGenerationTask } from "openclaw/plugin-sdk/video-generation";
@@ -44,6 +44,7 @@ function buildQwenVideoGenerationProvider() {
44
44
  store: req.authStore
45
45
  });
46
46
  if (!auth.apiKey) throw new Error("Qwen API key missing");
47
+ const providerConfig = req.cfg?.models?.providers?.qwen;
47
48
  const { baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } = resolveProviderHttpRequestConfig({
48
49
  baseUrl: resolveQwenVideoBaseUrl(req),
49
50
  defaultBaseUrl: DEFAULT_QWEN_VIDEO_BASE_URL,
@@ -54,7 +55,8 @@ function buildQwenVideoGenerationProvider() {
54
55
  },
55
56
  provider: "qwen",
56
57
  capability: "video",
57
- transport: "http"
58
+ transport: "http",
59
+ request: sanitizeConfiguredModelProviderRequest(providerConfig?.request)
58
60
  });
59
61
  return await runDashscopeVideoGenerationTask({
60
62
  providerLabel: "Qwen",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/qwen-provider",
3
- "version": "2026.7.1-beta.6",
3
+ "version": "2026.7.2-beta.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/qwen-provider",
9
- "version": "2026.7.1-beta.6"
9
+ "version": "2026.7.2-beta.1"
10
10
  }
11
11
  }
12
12
  }
@@ -5,7 +5,17 @@
5
5
  "onStartup": false
6
6
  },
7
7
  "enabledByDefault": true,
8
- "providers": ["qwen", "qwencloud", "modelstudio", "dashscope", "qwen-oauth", "qwen-portal", "qwen-cli"],
8
+ "providers": [
9
+ "qwen",
10
+ "qwencloud",
11
+ "modelstudio",
12
+ "dashscope",
13
+ "qwen-oauth",
14
+ "qwen-portal",
15
+ "qwen-cli",
16
+ "qwen-token-plan",
17
+ "bailian-token-plan"
18
+ ],
9
19
  "providerAuthAliases": {
10
20
  "qwen-portal": "qwen-oauth",
11
21
  "qwen-cli": "qwen-oauth"
@@ -17,7 +27,9 @@
17
27
  "https://coding-intl.dashscope.aliyuncs.com/v1",
18
28
  "https://coding.dashscope.aliyuncs.com/v1",
19
29
  "https://dashscope.aliyuncs.com/compatible-mode/v1",
20
- "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
30
+ "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
31
+ "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
32
+ "https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1"
21
33
  ]
22
34
  },
23
35
  {
@@ -47,6 +59,12 @@
47
59
  },
48
60
  "qwen-cli": {
49
61
  "family": "qwen-portal"
62
+ },
63
+ "qwen-token-plan": {
64
+ "family": "modelstudio"
65
+ },
66
+ "bailian-token-plan": {
67
+ "family": "modelstudio"
50
68
  }
51
69
  }
52
70
  },
@@ -62,8 +80,17 @@
62
80
  "suppressions": [
63
81
  {
64
82
  "provider": "qwen",
65
- "model": "qwen3.6-plus",
66
- "reason": "qwen3.6-plus is not supported on the Qwen Coding Plan endpoint; use a Standard pay-as-you-go Qwen endpoint or choose qwen/qwen3.5-plus.",
83
+ "model": "qwen3.6-flash",
84
+ "reason": "qwen3.6-flash is not supported on the Qwen Coding Plan endpoint; use a Standard pay-as-you-go Qwen endpoint.",
85
+ "when": {
86
+ "baseUrlHosts": ["coding.dashscope.aliyuncs.com", "coding-intl.dashscope.aliyuncs.com"],
87
+ "providerConfigApiIn": ["qwen", "modelstudio"]
88
+ }
89
+ },
90
+ {
91
+ "provider": "qwen",
92
+ "model": "qwen3.7-max",
93
+ "reason": "qwen3.7-max is not supported on the Qwen Coding Plan endpoint; use a Standard pay-as-you-go Qwen endpoint.",
67
94
  "when": {
68
95
  "baseUrlHosts": ["coding.dashscope.aliyuncs.com", "coding-intl.dashscope.aliyuncs.com"],
69
96
  "providerConfigApiIn": ["qwen", "modelstudio"]
@@ -71,8 +98,17 @@
71
98
  },
72
99
  {
73
100
  "provider": "modelstudio",
74
- "model": "qwen3.6-plus",
75
- "reason": "qwen3.6-plus is not supported on the Qwen Coding Plan endpoint; use a Standard pay-as-you-go Qwen endpoint or choose qwen/qwen3.5-plus.",
101
+ "model": "qwen3.6-flash",
102
+ "reason": "qwen3.6-flash is not supported on the Qwen Coding Plan endpoint; use a Standard pay-as-you-go Qwen endpoint.",
103
+ "when": {
104
+ "baseUrlHosts": ["coding.dashscope.aliyuncs.com", "coding-intl.dashscope.aliyuncs.com"],
105
+ "providerConfigApiIn": ["qwen", "modelstudio"]
106
+ }
107
+ },
108
+ {
109
+ "provider": "modelstudio",
110
+ "model": "qwen3.7-max",
111
+ "reason": "qwen3.7-max is not supported on the Qwen Coding Plan endpoint; use a Standard pay-as-you-go Qwen endpoint.",
76
112
  "when": {
77
113
  "baseUrlHosts": ["coding.dashscope.aliyuncs.com", "coding-intl.dashscope.aliyuncs.com"],
78
114
  "providerConfigApiIn": ["qwen", "modelstudio"]
@@ -101,7 +137,7 @@
101
137
  {
102
138
  "id": "qwen3.6-plus",
103
139
  "name": "qwen3.6-plus",
104
- "reasoning": false,
140
+ "reasoning": true,
105
141
  "input": ["text", "image"],
106
142
  "cost": {
107
143
  "input": 0,
@@ -211,7 +247,142 @@
211
247
  "maxTokens": 65536
212
248
  }
213
249
  ]
250
+ },
251
+ "qwen-token-plan": {
252
+ "baseUrl": "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
253
+ "api": "openai-completions",
254
+ "models": [
255
+ {
256
+ "id": "qwen3.7-max",
257
+ "name": "qwen3.7-max",
258
+ "reasoning": true,
259
+ "input": ["text"],
260
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
261
+ "contextWindow": 1000000,
262
+ "maxTokens": 65536
263
+ },
264
+ {
265
+ "id": "qwen3.7-plus",
266
+ "name": "qwen3.7-plus",
267
+ "reasoning": true,
268
+ "input": ["text", "image"],
269
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
270
+ "contextWindow": 1000000,
271
+ "maxTokens": 65536
272
+ },
273
+ {
274
+ "id": "qwen3.6-plus",
275
+ "name": "qwen3.6-plus",
276
+ "reasoning": true,
277
+ "input": ["text", "image"],
278
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
279
+ "contextWindow": 1000000,
280
+ "maxTokens": 65536
281
+ },
282
+ {
283
+ "id": "qwen3.6-flash",
284
+ "name": "qwen3.6-flash",
285
+ "reasoning": true,
286
+ "input": ["text", "image"],
287
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
288
+ "contextWindow": 1000000,
289
+ "maxTokens": 65536
290
+ },
291
+ {
292
+ "id": "deepseek-v4-pro",
293
+ "name": "deepseek-v4-pro",
294
+ "reasoning": true,
295
+ "input": ["text"],
296
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
297
+ "contextWindow": 1000000,
298
+ "maxTokens": 393216
299
+ },
300
+ {
301
+ "id": "deepseek-v4-flash",
302
+ "name": "deepseek-v4-flash",
303
+ "reasoning": true,
304
+ "input": ["text"],
305
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
306
+ "contextWindow": 1000000,
307
+ "maxTokens": 393216
308
+ },
309
+ {
310
+ "id": "deepseek-v3.2",
311
+ "name": "deepseek-v3.2",
312
+ "reasoning": true,
313
+ "input": ["text"],
314
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
315
+ "contextWindow": 131072,
316
+ "maxTokens": 65536
317
+ },
318
+ {
319
+ "id": "kimi-k2.7-code",
320
+ "name": "kimi-k2.7-code",
321
+ "reasoning": true,
322
+ "input": ["text", "image"],
323
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
324
+ "contextWindow": 262144,
325
+ "maxTokens": 98304
326
+ },
327
+ {
328
+ "id": "kimi-k2.6",
329
+ "name": "kimi-k2.6",
330
+ "reasoning": true,
331
+ "input": ["text", "image"],
332
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
333
+ "contextWindow": 262144,
334
+ "maxTokens": 98304
335
+ },
336
+ {
337
+ "id": "kimi-k2.5",
338
+ "name": "kimi-k2.5",
339
+ "reasoning": true,
340
+ "input": ["text", "image"],
341
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
342
+ "contextWindow": 262144,
343
+ "maxTokens": 98304
344
+ },
345
+ {
346
+ "id": "glm-5.2",
347
+ "name": "glm-5.2",
348
+ "reasoning": true,
349
+ "input": ["text"],
350
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
351
+ "contextWindow": 1000000,
352
+ "maxTokens": 131072
353
+ },
354
+ {
355
+ "id": "glm-5.1",
356
+ "name": "glm-5.1",
357
+ "reasoning": true,
358
+ "input": ["text"],
359
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
360
+ "contextWindow": 202752,
361
+ "maxTokens": 131072
362
+ },
363
+ {
364
+ "id": "glm-5",
365
+ "name": "glm-5",
366
+ "reasoning": true,
367
+ "input": ["text"],
368
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
369
+ "contextWindow": 202752,
370
+ "maxTokens": 16384
371
+ },
372
+ {
373
+ "id": "MiniMax-M2.5",
374
+ "name": "MiniMax-M2.5",
375
+ "reasoning": true,
376
+ "input": ["text"],
377
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
378
+ "contextWindow": 196608,
379
+ "maxTokens": 32768
380
+ }
381
+ ]
214
382
  }
383
+ },
384
+ "discovery": {
385
+ "qwen-token-plan": "static"
215
386
  }
216
387
  },
217
388
  "contracts": {
@@ -239,6 +410,10 @@
239
410
  {
240
411
  "id": "qwen-oauth",
241
412
  "envVars": ["QWEN_API_KEY"]
413
+ },
414
+ {
415
+ "id": "qwen-token-plan",
416
+ "envVars": ["QWEN_TOKEN_PLAN_API_KEY"]
242
417
  }
243
418
  ]
244
419
  },
@@ -321,6 +496,36 @@
321
496
  "cliFlag": "--qwen-oauth-token",
322
497
  "cliOption": "--qwen-oauth-token <token>",
323
498
  "cliDescription": "Qwen OAuth token"
499
+ },
500
+ {
501
+ "provider": "qwen-token-plan",
502
+ "method": "api-key",
503
+ "choiceId": "qwen-token-plan",
504
+ "appGuidedSecret": true,
505
+ "choiceLabel": "Qwen Token Plan (Global/Intl)",
506
+ "choiceHint": "Endpoint: token-plan.ap-southeast-1.maas.aliyuncs.com",
507
+ "groupId": "qwen",
508
+ "groupLabel": "Qwen Cloud",
509
+ "groupHint": "Standard / Coding Plan / Token Plan / OAuth",
510
+ "optionKey": "qwenTokenPlanApiKey",
511
+ "cliFlag": "--qwen-token-plan-api-key",
512
+ "cliOption": "--qwen-token-plan-api-key <key>",
513
+ "cliDescription": "Qwen Token Plan API key (Global/Intl)"
514
+ },
515
+ {
516
+ "provider": "qwen-token-plan",
517
+ "method": "api-key-cn",
518
+ "choiceId": "qwen-token-plan-cn",
519
+ "appGuidedSecret": true,
520
+ "choiceLabel": "Qwen Token Plan (China)",
521
+ "choiceHint": "Endpoint: token-plan.cn-beijing.maas.aliyuncs.com",
522
+ "groupId": "qwen",
523
+ "groupLabel": "Qwen Cloud",
524
+ "groupHint": "Standard / Coding Plan / Token Plan / OAuth",
525
+ "optionKey": "qwenTokenPlanApiKeyCn",
526
+ "cliFlag": "--qwen-token-plan-api-key-cn",
527
+ "cliOption": "--qwen-token-plan-api-key-cn <key>",
528
+ "cliDescription": "Qwen Token Plan API key (China)"
324
529
  }
325
530
  ],
326
531
  "configSchema": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/qwen-provider",
3
- "version": "2026.7.1-beta.6",
3
+ "version": "2026.7.2-beta.1",
4
4
  "description": "OpenClaw Qwen Cloud provider plugin.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,10 +18,10 @@
18
18
  "minHostVersion": ">=2026.6.8"
19
19
  },
20
20
  "compat": {
21
- "pluginApi": ">=2026.7.1-beta.6"
21
+ "pluginApi": ">=2026.7.2-beta.1"
22
22
  },
23
23
  "build": {
24
- "openclawVersion": "2026.7.1-beta.6",
24
+ "openclawVersion": "2026.7.2-beta.1",
25
25
  "bundledDist": false
26
26
  },
27
27
  "release": {
@@ -39,7 +39,7 @@
39
39
  "README.md"
40
40
  ],
41
41
  "peerDependencies": {
42
- "openclaw": ">=2026.7.1-beta.6"
42
+ "openclaw": ">=2026.7.2-beta.1"
43
43
  },
44
44
  "peerDependenciesMeta": {
45
45
  "openclaw": {