feat(desktop): add Wenxin monitoring adapter and surface platform risk control

Introduces the Wenxin (文心一言) monitoring adapter and registers it in
the runtime controller and adapter index. Adds a new risk_control
failure classification with custom classifiers for Doubao and Wenxin
that recognize rate-limit, 频控 and 访问环境异常 signals, and propagates
this state through account-health, runtime activity alerts, and the
renderer views so users see "触发风控" instead of a generic challenge
message on the Home, Accounts, and AI Platforms screens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 15:26:24 +08:00
parent bd4ee8feef
commit ca40657c5a
12 changed files with 2552 additions and 21 deletions
@@ -27,8 +27,10 @@ function normalizeFailureText(input: PlatformFailureInput): string {
input.summary,
input.message,
typeof input.error?.code === "string" ? input.error.code : null,
typeof input.error?.reason_code === "string" ? input.error.reason_code : null,
typeof input.error?.message === "string" ? input.error.message : null,
typeof input.error?.detail === "string" ? input.error.detail : null,
typeof input.error?.page_error === "string" ? input.error.page_error : null,
typeof input.error?.verify_scene === "string" ? input.error.verify_scene : null,
];
@@ -67,6 +69,38 @@ function classifyFailure(input: PlatformFailureInput): PlatformFailureClassifica
return "ok";
}
function classifyDoubaoFailure(input: PlatformFailureInput): PlatformFailureClassification {
const text = normalizeFailureText(input);
if (!text) {
return "ok";
}
if (
/(rate limited|rate limit|too many requests|request limit|frequency limit|请求过于频繁|频率过快|访问过于频繁|限流|风控|服务繁忙|请稍后|稍后再试)/i
.test(text)
) {
return "risk_control";
}
return classifyFailure(input);
}
function classifyWenxinFailure(input: PlatformFailureInput): PlatformFailureClassification {
const text = normalizeFailureText(input);
if (!text) {
return "ok";
}
if (
/(当前访问环境存在异常|访问环境存在异常|环境存在异常|更换浏览器再尝试提问|当前环境异常|访问受限|环境异常)/i
.test(text)
) {
return "risk_control";
}
return classifyFailure(input);
}
const genericAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
@@ -77,6 +111,26 @@ const genericAdapter: PlatformAdapter = {
classifyFailure,
};
const doubaoAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
},
async silentRefresh(account, partition) {
return await silentRefreshPublishAccountSession(account, partition);
},
classifyFailure: classifyDoubaoFailure,
};
const wenxinAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
},
async silentRefresh(account, partition) {
return await silentRefreshPublishAccountSession(account, partition);
},
classifyFailure: classifyWenxinFailure,
};
const adapterRegistry = new Map<string, PlatformAdapter>(
[
...aiPlatformCatalog.map((platform) => platform.id),
@@ -93,10 +147,16 @@ const adapterRegistry = new Map<string, PlatformAdapter>(
"weixin_gzh",
"zol",
"dongchedi",
].map((platform) => [platform, genericAdapter]),
].map((platform) => [
platform,
platform === "doubao"
? doubaoAdapter
: platform === "wenxin"
? wenxinAdapter
: genericAdapter,
]),
);
export function getPlatformAdapter(platformId: string): PlatformAdapter {
return adapterRegistry.get(platformId) ?? genericAdapter;
}