feat(modelstudio): add standard (pay-as-you-go) endpoints for Alibaba Cloud Bailian

The existing Model Studio integration only exposed the Coding Plan
(subscription) endpoints. This adds the standard pay-as-you-go
DashScope endpoints for both China and International regions so users
can pick the plan that fits their usage.

New onboarding choices:
- modelstudio-standard-api-key-cn  (dashscope.aliyuncs.com)
- modelstudio-standard-api-key     (dashscope-intl.aliyuncs.com)

All four variants (standard/coding-plan × CN/intl) now share the same
`modelstudio` provider and auth profile, which keeps the implicit
provider resolution simple — the API key written during onboarding is
picked up automatically when generating models.json.

Also fixed model name in Coding Plan notes: glm-4.7 → glm-5.
This commit is contained in:
wenmengzhou 2026-03-12 15:47:14 +08:00
parent c65390cbde
commit 7e93bca770
9 changed files with 173 additions and 5 deletions

View File

@ -128,8 +128,13 @@ const AUTH_CHOICE_GROUP_DEFS: {
{
value: "modelstudio",
label: "Alibaba Cloud Model Studio",
hint: "Coding Plan API key (CN / Global)",
choices: ["modelstudio-api-key-cn", "modelstudio-api-key"],
hint: "Standard / Coding Plan (CN / Global)",
choices: [
"modelstudio-standard-api-key-cn",
"modelstudio-standard-api-key",
"modelstudio-api-key-cn",
"modelstudio-api-key",
],
},
{
value: "copilot",
@ -319,6 +324,16 @@ const BASE_AUTH_CHOICE_OPTIONS: ReadonlyArray<AuthChoiceOption> = [
hint: "Official fast tier (legacy: Lightning)",
},
{ value: "qianfan-api-key", label: "Qianfan API key" },
{
value: "modelstudio-standard-api-key-cn",
label: "Standard API Key for China (pay-as-you-go)",
hint: "Endpoint: dashscope.aliyuncs.com",
},
{
value: "modelstudio-standard-api-key",
label: "Standard API Key for Global/Intl (pay-as-you-go)",
hint: "Endpoint: dashscope-intl.aliyuncs.com",
},
{
value: "modelstudio-api-key-cn",
label: "Coding Plan API Key for China (subscription)",

View File

@ -84,6 +84,10 @@ import {
applyModelStudioConfigCn,
applyModelStudioProviderConfig,
applyModelStudioProviderConfigCn,
applyModelStudioStandardConfig,
applyModelStudioStandardConfigCn,
applyModelStudioStandardProviderConfig,
applyModelStudioStandardProviderConfigCn,
setModelStudioApiKey,
} from "./onboard-auth.js";
import type { AuthChoice, SecretInputMode } from "./onboard-types.js";
@ -326,6 +330,46 @@ const SIMPLE_API_KEY_PROVIDER_FLOWS: Partial<Record<AuthChoice, SimpleApiKeyProv
applyProviderConfig: applyKilocodeProviderConfig,
noteDefault: KILOCODE_DEFAULT_MODEL_REF,
},
"modelstudio-standard-api-key-cn": {
provider: "modelstudio",
profileId: "modelstudio:default",
expectedProviders: ["modelstudio"],
envLabel: "MODELSTUDIO_API_KEY",
promptMessage: "Enter Alibaba Cloud Model Studio API key (China)",
setCredential: setModelStudioApiKey,
defaultModel: MODELSTUDIO_DEFAULT_MODEL_REF,
applyDefaultConfig: applyModelStudioStandardConfigCn,
applyProviderConfig: applyModelStudioStandardProviderConfigCn,
noteDefault: MODELSTUDIO_DEFAULT_MODEL_REF,
noteMessage: [
"Get your API key at: https://bailian.console.aliyun.com/",
"Endpoint: dashscope.aliyuncs.com/compatible-mode/v1",
"Models: qwen3.5-plus, qwen3.5-flash, qwen3-coder-plus, etc.",
].join("\n"),
noteTitle: "Alibaba Cloud Model Studio (China)",
normalize: (value) => String(value ?? "").trim(),
validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
},
"modelstudio-standard-api-key": {
provider: "modelstudio",
profileId: "modelstudio:default",
expectedProviders: ["modelstudio"],
envLabel: "MODELSTUDIO_API_KEY",
promptMessage: "Enter Alibaba Cloud Model Studio API key (Global/Intl)",
setCredential: setModelStudioApiKey,
defaultModel: MODELSTUDIO_DEFAULT_MODEL_REF,
applyDefaultConfig: applyModelStudioStandardConfig,
applyProviderConfig: applyModelStudioStandardProviderConfig,
noteDefault: MODELSTUDIO_DEFAULT_MODEL_REF,
noteMessage: [
"Get your API key at: https://modelstudio.console.alibabacloud.com/",
"Endpoint: dashscope-intl.aliyuncs.com/compatible-mode/v1",
"Models: qwen3.5-plus, qwen3.5-flash, qwen3-coder-plus, etc.",
].join("\n"),
noteTitle: "Alibaba Cloud Model Studio (Global/Intl)",
normalize: (value) => String(value ?? "").trim(),
validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
},
"modelstudio-api-key-cn": {
provider: "modelstudio",
profileId: "modelstudio:default",
@ -340,7 +384,7 @@ const SIMPLE_API_KEY_PROVIDER_FLOWS: Partial<Record<AuthChoice, SimpleApiKeyProv
noteMessage: [
"Get your API key at: https://bailian.console.aliyun.com/",
"Endpoint: coding.dashscope.aliyuncs.com",
"Models: qwen3.5-plus, glm-4.7, kimi-k2.5, MiniMax-M2.5, etc.",
"Models: qwen3.5-plus, glm-5, kimi-k2.5, MiniMax-M2.5, etc.",
].join("\n"),
noteTitle: "Alibaba Cloud Model Studio Coding Plan (China)",
normalize: (value) => String(value ?? "").trim(),
@ -360,7 +404,7 @@ const SIMPLE_API_KEY_PROVIDER_FLOWS: Partial<Record<AuthChoice, SimpleApiKeyProv
noteMessage: [
"Get your API key at: https://bailian.console.aliyun.com/",
"Endpoint: coding-intl.dashscope.aliyuncs.com",
"Models: qwen3.5-plus, glm-4.7, kimi-k2.5, MiniMax-M2.5, etc.",
"Models: qwen3.5-plus, glm-5, kimi-k2.5, MiniMax-M2.5, etc.",
].join("\n"),
noteTitle: "Alibaba Cloud Model Studio Coding Plan (Global/Intl)",
normalize: (value) => String(value ?? "").trim(),

View File

@ -82,6 +82,8 @@ import {
XAI_DEFAULT_MODEL_ID,
MODELSTUDIO_CN_BASE_URL,
MODELSTUDIO_GLOBAL_BASE_URL,
MODELSTUDIO_STANDARD_CN_BASE_URL,
MODELSTUDIO_STANDARD_GLOBAL_BASE_URL,
MODELSTUDIO_DEFAULT_MODEL_REF,
} from "./onboard-auth.models.js";
@ -666,3 +668,23 @@ export function applyModelStudioConfigCn(cfg: OpenClawConfig): OpenClawConfig {
const next = applyModelStudioProviderConfigCn(cfg);
return applyAgentDefaultModelPrimary(next, MODELSTUDIO_DEFAULT_MODEL_REF);
}
// Alibaba Cloud Model Studio Standard (pay-as-you-go)
export function applyModelStudioStandardProviderConfig(cfg: OpenClawConfig): OpenClawConfig {
return applyModelStudioProviderConfigWithBaseUrl(cfg, MODELSTUDIO_STANDARD_GLOBAL_BASE_URL);
}
export function applyModelStudioStandardProviderConfigCn(cfg: OpenClawConfig): OpenClawConfig {
return applyModelStudioProviderConfigWithBaseUrl(cfg, MODELSTUDIO_STANDARD_CN_BASE_URL);
}
export function applyModelStudioStandardConfig(cfg: OpenClawConfig): OpenClawConfig {
const next = applyModelStudioStandardProviderConfig(cfg);
return applyAgentDefaultModelPrimary(next, MODELSTUDIO_DEFAULT_MODEL_REF);
}
export function applyModelStudioStandardConfigCn(cfg: OpenClawConfig): OpenClawConfig {
const next = applyModelStudioStandardProviderConfigCn(cfg);
return applyAgentDefaultModelPrimary(next, MODELSTUDIO_DEFAULT_MODEL_REF);
}

View File

@ -225,7 +225,12 @@ export function buildKilocodeModelDefinition(): ModelDefinitionConfig {
};
}
// Alibaba Cloud Model Studio Coding Plan
// Alibaba Cloud Model Studio (百炼)
// Standard (pay-as-you-go) endpoints
export const MODELSTUDIO_STANDARD_CN_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1";
export const MODELSTUDIO_STANDARD_GLOBAL_BASE_URL =
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1";
// Coding Plan (subscription) endpoints
export const MODELSTUDIO_CN_BASE_URL = "https://coding.dashscope.aliyuncs.com/v1";
export const MODELSTUDIO_GLOBAL_BASE_URL = "https://coding-intl.dashscope.aliyuncs.com/v1";
export const MODELSTUDIO_DEFAULT_MODEL_ID = "qwen3.5-plus";

View File

@ -43,6 +43,10 @@ export {
applyModelStudioConfigCn,
applyModelStudioProviderConfig,
applyModelStudioProviderConfigCn,
applyModelStudioStandardConfig,
applyModelStudioStandardConfigCn,
applyModelStudioStandardProviderConfig,
applyModelStudioStandardProviderConfigCn,
KILOCODE_BASE_URL,
} from "./onboard-auth.config-core.js";
export {

View File

@ -31,6 +31,8 @@ type AuthChoiceFlagOptions = Pick<
| "xaiApiKey"
| "litellmApiKey"
| "qianfanApiKey"
| "modelstudioStandardApiKeyCn"
| "modelstudioStandardApiKey"
| "modelstudioApiKeyCn"
| "modelstudioApiKey"
| "volcengineApiKey"

View File

@ -18,6 +18,8 @@ import {
applyQianfanConfig,
applyModelStudioConfig,
applyModelStudioConfigCn,
applyModelStudioStandardConfig,
applyModelStudioStandardConfigCn,
applyKimiCodeConfig,
applyMinimaxApiConfig,
applyMinimaxApiConfigCn,
@ -508,6 +510,60 @@ export async function applyNonInteractiveAuthChoice(params: {
return applyQianfanConfig(nextConfig);
}
if (authChoice === "modelstudio-standard-api-key-cn") {
const resolved = await resolveApiKey({
provider: "modelstudio",
cfg: baseConfig,
flagValue: opts.modelstudioStandardApiKeyCn,
flagName: "--modelstudio-standard-api-key-cn",
envVar: "MODELSTUDIO_API_KEY",
runtime,
});
if (!resolved) {
return null;
}
if (
!(await maybeSetResolvedApiKey(resolved, (value) =>
setModelStudioApiKey(value, undefined, apiKeyStorageOptions),
))
) {
return null;
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "modelstudio:default",
provider: "modelstudio",
mode: "api_key",
});
return applyModelStudioStandardConfigCn(nextConfig);
}
if (authChoice === "modelstudio-standard-api-key") {
const resolved = await resolveApiKey({
provider: "modelstudio",
cfg: baseConfig,
flagValue: opts.modelstudioStandardApiKey,
flagName: "--modelstudio-standard-api-key",
envVar: "MODELSTUDIO_API_KEY",
runtime,
});
if (!resolved) {
return null;
}
if (
!(await maybeSetResolvedApiKey(resolved, (value) =>
setModelStudioApiKey(value, undefined, apiKeyStorageOptions),
))
) {
return null;
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "modelstudio:default",
provider: "modelstudio",
mode: "api_key",
});
return applyModelStudioStandardConfig(nextConfig);
}
if (authChoice === "modelstudio-api-key-cn") {
const resolved = await resolveApiKey({
provider: "modelstudio",

View File

@ -24,6 +24,8 @@ type OnboardProviderAuthOptionKey = keyof Pick<
| "xaiApiKey"
| "litellmApiKey"
| "qianfanApiKey"
| "modelstudioStandardApiKeyCn"
| "modelstudioStandardApiKey"
| "modelstudioApiKeyCn"
| "modelstudioApiKey"
| "volcengineApiKey"
@ -194,6 +196,20 @@ export const ONBOARD_PROVIDER_AUTH_FLAGS: ReadonlyArray<OnboardProviderAuthFlag>
cliOption: "--qianfan-api-key <key>",
description: "QIANFAN API key",
},
{
optionKey: "modelstudioStandardApiKeyCn",
authChoice: "modelstudio-standard-api-key-cn",
cliFlag: "--modelstudio-standard-api-key-cn",
cliOption: "--modelstudio-standard-api-key-cn <key>",
description: "Alibaba Cloud Model Studio API key (China, pay-as-you-go)",
},
{
optionKey: "modelstudioStandardApiKey",
authChoice: "modelstudio-standard-api-key",
cliFlag: "--modelstudio-standard-api-key",
cliOption: "--modelstudio-standard-api-key <key>",
description: "Alibaba Cloud Model Studio API key (Global/Intl, pay-as-you-go)",
},
{
optionKey: "modelstudioApiKeyCn",
authChoice: "modelstudio-api-key-cn",

View File

@ -51,6 +51,8 @@ export type AuthChoice =
| "volcengine-api-key"
| "byteplus-api-key"
| "qianfan-api-key"
| "modelstudio-standard-api-key-cn"
| "modelstudio-standard-api-key"
| "modelstudio-api-key-cn"
| "modelstudio-api-key"
| "custom-api-key"
@ -142,6 +144,8 @@ export type OnboardOptions = {
volcengineApiKey?: string;
byteplusApiKey?: string;
qianfanApiKey?: string;
modelstudioStandardApiKeyCn?: string;
modelstudioStandardApiKey?: string;
modelstudioApiKeyCn?: string;
modelstudioApiKey?: string;
customBaseUrl?: string;