feat: add aliyun qwen backup provider

This commit is contained in:
kris
2026-04-01 05:33:35 +08:00
parent ba01ae5393
commit 60d69eb222
15 changed files with 708 additions and 87 deletions

View File

@@ -19,8 +19,8 @@ import org.json.JSONObject;
public class AiAccountsActivity extends BossScreenActivity {
private static final String[] ROLE_VALUES = {"primary", "backup", "api_fallback"};
private static final String[] ROLE_LABELS = {"主 GPT", "备用 GPT", "API 容灾"};
private static final String[] PROVIDER_VALUES = {"master_codex_node", "openai_api"};
private static final String[] PROVIDER_LABELS = {"Master Codex Node", "OpenAI API"};
private static final String[] PROVIDER_VALUES = {"master_codex_node", "openai_api", "aliyun_qwen_api"};
private static final String[] PROVIDER_LABELS = {"Master Codex Node", "OpenAI API", "阿里百炼 Qwen"};
private boolean refreshOnResume;
@Override
@@ -174,6 +174,15 @@ public class AiAccountsActivity extends BossScreenActivity {
v -> openOpenAiOnboardingScreen()
));
section.addView(BossUi.buildWechatMenuRow(
this,
"接入阿里百炼备用账号",
"把阿里百炼 Qwen 兼容接口接成主 Agent 的备用链路。",
"建议模型qwen3.5-plus 或 qwen3.5-flash。",
null,
v -> openAliyunQwenOnboardingDialog()
));
section.addView(BossUi.buildWechatMenuRow(
this,
"绑定电脑上的 Codex 节点",
@@ -330,6 +339,40 @@ public class AiAccountsActivity extends BossScreenActivity {
.show();
}
private void openAliyunQwenOnboardingDialog() {
final EditText labelInput = BossUi.buildInput(this, "标签,例如 备用 GPT", false);
labelInput.setText("备用 GPT");
final EditText displayNameInput = BossUi.buildInput(this, "显示名称", false);
displayNameInput.setText("阿里百炼备用账号");
final EditText accountIdentifierInput = BossUi.buildInput(this, "账号标识 / 备注", false);
final EditText modelInput = BossUi.buildInput(this, "模型,例如 qwen3.5-plus", false);
modelInput.setText("qwen3.5-plus");
final EditText apiKeyInput = BossUi.buildInput(this, "阿里百炼 API Key", false);
apiKeyInput.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
LinearLayout form = new LinearLayout(this);
form.setOrientation(LinearLayout.VERTICAL);
form.addView(BossUi.buildFormCell(this, "标签", "建议使用 备用 GPT", labelInput));
form.addView(BossUi.buildFormCell(this, "显示名称", "会展示在账号列表中", displayNameInput));
form.addView(BossUi.buildFormCell(this, "账号标识", "可填账号名或自定义备注", accountIdentifierInput));
form.addView(BossUi.buildFormCell(this, "模型", "例如 qwen3.5-plus", modelInput));
form.addView(BossUi.buildFormCell(this, "API Key", "填写后会保存为备用链路,不会抢占当前主控", apiKeyInput));
new AlertDialog.Builder(this)
.setTitle("接入阿里百炼备用账号")
.setMessage("接入成功后,这个账号会作为主 Agent 的备用模型链路,在主节点离线或失败时自动接管。")
.setView(form)
.setNegativeButton("取消", null)
.setPositiveButton("接入", (dialog, which) -> submitAliyunQwenOnboarding(
labelInput.getText().toString().trim(),
displayNameInput.getText().toString().trim(),
accountIdentifierInput.getText().toString().trim(),
modelInput.getText().toString().trim(),
apiKeyInput.getText().toString().trim()
))
.show();
}
private void submitOpenAiOnboarding(
String label,
String displayName,
@@ -428,6 +471,45 @@ public class AiAccountsActivity extends BossScreenActivity {
});
}
private void submitAliyunQwenOnboarding(
String label,
String displayName,
String accountIdentifier,
String model,
String apiKey
) {
if (label.isEmpty() || displayName.isEmpty() || apiKey.isEmpty()) {
showMessage("标签、显示名称和 API Key 不能为空");
return;
}
setRefreshing(true);
executor.execute(() -> {
try {
JSONObject payload = new JSONObject();
payload.put("label", label);
payload.put("displayName", displayName);
payload.put("accountIdentifier", accountIdentifier);
payload.put("model", model);
payload.put("apiKey", apiKey);
BossApiClient.ApiResponse response = apiClient.onboardAliyunQwenAccount(payload);
if (!response.ok()) throw new IllegalStateException(response.message());
runOnUiThread(() -> {
showMessage("阿里百炼备用账号已接入。");
reload();
});
} catch (Exception error) {
runOnUiThread(() -> {
setRefreshing(false);
String detail = error.getMessage();
showMessage(detail == null || detail.trim().isEmpty()
? "阿里百炼备用账号接入失败,请稍后重试。"
: "阿里百炼备用账号接入失败:" + detail);
});
}
});
}
private String extractAccountId(JSONObject json) {
if (json == null) {
return "";
@@ -486,7 +568,7 @@ public class AiAccountsActivity extends BossScreenActivity {
form.addView(BossUi.buildFormCell(this, "节点 ID", "Master Codex Node 的唯一标识", nodeIdInput));
form.addView(BossUi.buildFormCell(this, "节点名称", "用于快速识别节点", nodeLabelInput));
form.addView(BossUi.buildFormCell(this, "模型", "例如 gpt-5.4", modelInput));
form.addView(BossUi.buildFormCell(this, "API Key", "OpenAI API 模式需要", apiKeyInput));
form.addView(BossUi.buildFormCell(this, "API Key", "OpenAI API / 阿里百炼 Qwen 模式需要", apiKeyInput));
form.addView(BossUi.buildFormCell(this, "登录状态备注", "可记录 Plus、有无风控等状态", loginStatusInput));
form.addView(BossUi.buildFormCell(this, "账号角色", null, roleSpinner));
form.addView(BossUi.buildFormCell(this, "提供方", null, providerSpinner));

View File

@@ -396,6 +396,10 @@ public class BossApiClient {
return onboardAccount("/api/v1/accounts/onboard/openai-api", payload);
}
public ApiResponse onboardAliyunQwenAccount(JSONObject payload) throws IOException, JSONException {
return onboardAccount("/api/v1/accounts/onboard/aliyun-qwen", payload);
}
public ApiResponse onboardMasterNodeAccount(JSONObject payload) throws IOException, JSONException {
return onboardAccount("/api/v1/accounts/onboard/master-node", payload);
}