From e955d799849166b9b4c1c84b5777f87145ac4cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Fri, 2 Oct 2026 02:42:30 +0800 Subject: [PATCH] =?UTF-8?q?AGC=E8=AE=A4=E8=AF=81=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E6=8C=89=E7=B1=BB=E5=88=AB=E5=8F=98=E4=BD=93=E4=B8=8E=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=8C=96reason=E5=88=86=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AuthenticatedClient 三个 catch 把 authNetworkFailure/authResponseInvalid 收成一个分支,服务地址 7 种失败与响应契约 5 种破损改为在 payload.reason 上二次 switch - 每个带载荷分支先 as 取自己的具名类型,reason/default 用 expectNever 让漏接 reason 也在编译期失败 - 系统变体仍原样 throw,经全局 unhandledrejection 交给错误池 --- .../src/app/AuthenticatedClient.tsx | 213 +++++++++--------- 1 file changed, 101 insertions(+), 112 deletions(-) diff --git a/apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx b/apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx index a03f53d93..825c7e98d 100644 --- a/apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx +++ b/apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx @@ -38,6 +38,7 @@ import { import type { PasswordLoginRejected } from '../services/generated/PasswordLoginRejected'; import type { PhoneCodeLoginRejected } from '../services/generated/PhoneCodeLoginRejected'; import type { SendCodeRejected } from '../services/generated/SendCodeRejected'; +import type { ServerAddressRejected } from '../services/generated/ServerAddressRejected'; import { beginPlatformSessionClearTransition, beginPlatformSessionTransition, @@ -272,44 +273,36 @@ export function AuthenticatedClient({ const failure = error.error; switch (failure.type) { // 预期业务拒绝:调用方补上本次操作的上下文,展示后不进错误池。 - case 'serverAddressEmptyOrTooLong': { - const text = '服务器地址非法: 不能为空或超长'; - setAuthCheckError(text); - setLoginStatus(text); - break; - } - case 'serverAddressNotAUrl': { - const text = '服务器地址非法: 不是合法地址'; - setAuthCheckError(text); - setLoginStatus(text); - break; - } - case 'serverAddressHasCredentials': { - const text = '服务器地址非法: 不能包含用户名或密码'; - setAuthCheckError(text); - setLoginStatus(text); - break; - } - case 'serverAddressHasPathOrQueryOrFragment': { - const text = '服务器地址非法: 不能带路径、查询或片段'; - setAuthCheckError(text); - setLoginStatus(text); - break; - } - case 'serverAddressNotHttps': { - const text = '服务器地址非法: 远程地址必须使用 https'; - setAuthCheckError(text); - setLoginStatus(text); - break; - } - case 'serverAddressUnsupportedScheme': { - const text = '服务器地址非法: 只支持 http 或 https'; - setAuthCheckError(text); - setLoginStatus(text); - break; - } - case 'serverAddressOutsideChannel': { - const text = '服务器地址非法: 不在当前构建渠道范围内'; + case 'serverAddressRejected': { + const payload = failure as ServerAddressRejected; + let text: string; + switch (payload.reason) { + case 'emptyOrTooLong': + text = '服务器地址非法: 不能为空或超长'; + break; + case 'notAUrl': + text = '服务器地址非法: 不是合法地址'; + break; + case 'hasCredentials': + text = '服务器地址非法: 不能包含用户名或密码'; + break; + case 'hasPathOrQueryOrFragment': + text = '服务器地址非法: 不能带路径、查询或片段'; + break; + case 'notHttps': + text = '服务器地址非法: 远程地址必须使用 https'; + break; + case 'unsupportedScheme': + text = '服务器地址非法: 只支持 http 或 https'; + break; + case 'outsideChannel': + text = '服务器地址非法: 不在当前构建渠道范围内'; + break; + default: { + expectNever(payload.reason); + text = '服务器地址非法'; + } + } setAuthCheckError(text); setLoginStatus(text); break; @@ -376,15 +369,10 @@ export function AuthenticatedClient({ case 'permissionDenied': break; // 系统失败:调用方处理不了,原样抛出 → 全局 unhandledrejection 交给错误池。 - case 'authNetworkTimeout': - case 'authNetworkUnreachable': + case 'authNetworkFailure': case 'authServiceUnavailable': case 'unexpectedRejection': - case 'authResponseNotJson': - case 'authResponseInvalidBody': - case 'authResponseMissingRefreshCookie': - case 'authResponseMissingUserIdentity': - case 'authResponseServerRejected': + case 'authResponseInvalid': case 'clientSessionPersistFailed': case 'runtimeSessionInstallFailed': case 'authClientInitFailed': @@ -457,7 +445,8 @@ export function AuthenticatedClient({ * - 承载:命令失败由 `invokeClientAuth` 装进 `ClientAuthErrorWrapper`,`error` 就是判别联合, * `failure.type` 是唯一分流键; * - 业务 / 会话变体:无载荷变体用本 catch 的固定文案;带载荷变体先 `as` 取具名类型, - * 再用它自己的 `serverMessage` 拼上下文(Rust 不预拼用户可见文案),永不进错误池; + * 可枚举的细分再用 `switch (payload.reason)` 在类型化 reason 上分流并拼上下文 + * (Rust 不预拼用户可见文案),永不进错误池; * - 系统变体:原样 `throw`,经全局 `unhandledrejection` 交给错误池; * - `default: expectNever` 保证 Rust 新增变体时这里编译失败。 * @@ -489,32 +478,37 @@ export function AuthenticatedClient({ const failure = error.error; switch (failure.type) { // 预期业务拒绝:调用方补上本次操作的上下文,展示后不进错误池。 - case 'serverAddressEmptyOrTooLong': { - setLoginStatus('服务器地址非法: 不能为空或超长'); - break; - } - case 'serverAddressNotAUrl': { - setLoginStatus('服务器地址非法: 不是合法地址'); - break; - } - case 'serverAddressHasCredentials': { - setLoginStatus('服务器地址非法: 不能包含用户名或密码'); - break; - } - case 'serverAddressHasPathOrQueryOrFragment': { - setLoginStatus('服务器地址非法: 不能带路径、查询或片段'); - break; - } - case 'serverAddressNotHttps': { - setLoginStatus('服务器地址非法: 远程地址必须使用 https'); - break; - } - case 'serverAddressUnsupportedScheme': { - setLoginStatus('服务器地址非法: 只支持 http 或 https'); - break; - } - case 'serverAddressOutsideChannel': { - setLoginStatus('服务器地址非法: 不在当前构建渠道范围内'); + case 'serverAddressRejected': { + const payload = failure as ServerAddressRejected; + let text: string; + switch (payload.reason) { + case 'emptyOrTooLong': + text = '服务器地址非法: 不能为空或超长'; + break; + case 'notAUrl': + text = '服务器地址非法: 不是合法地址'; + break; + case 'hasCredentials': + text = '服务器地址非法: 不能包含用户名或密码'; + break; + case 'hasPathOrQueryOrFragment': + text = '服务器地址非法: 不能带路径、查询或片段'; + break; + case 'notHttps': + text = '服务器地址非法: 远程地址必须使用 https'; + break; + case 'unsupportedScheme': + text = '服务器地址非法: 只支持 http 或 https'; + break; + case 'outsideChannel': + text = '服务器地址非法: 不在当前构建渠道范围内'; + break; + default: { + expectNever(payload.reason); + text = '服务器地址非法'; + } + } + setLoginStatus(text); break; } case 'phoneNumberInvalid': { @@ -571,15 +565,10 @@ export function AuthenticatedClient({ break; } // 系统失败:调用方处理不了,原样抛出 → 全局 unhandledrejection 交给错误池。 - case 'authNetworkTimeout': - case 'authNetworkUnreachable': + case 'authNetworkFailure': case 'authServiceUnavailable': case 'unexpectedRejection': - case 'authResponseNotJson': - case 'authResponseInvalidBody': - case 'authResponseMissingRefreshCookie': - case 'authResponseMissingUserIdentity': - case 'authResponseServerRejected': + case 'authResponseInvalid': case 'clientSessionPersistFailed': case 'runtimeSessionInstallFailed': case 'authClientInitFailed': @@ -657,32 +646,37 @@ export function AuthenticatedClient({ const failure = error.error; switch (failure.type) { // 预期业务拒绝:调用方补上本次操作的上下文,展示后不进错误池。 - case 'serverAddressEmptyOrTooLong': { - setLoginStatus('服务器地址非法: 不能为空或超长'); - break; - } - case 'serverAddressNotAUrl': { - setLoginStatus('服务器地址非法: 不是合法地址'); - break; - } - case 'serverAddressHasCredentials': { - setLoginStatus('服务器地址非法: 不能包含用户名或密码'); - break; - } - case 'serverAddressHasPathOrQueryOrFragment': { - setLoginStatus('服务器地址非法: 不能带路径、查询或片段'); - break; - } - case 'serverAddressNotHttps': { - setLoginStatus('服务器地址非法: 远程地址必须使用 https'); - break; - } - case 'serverAddressUnsupportedScheme': { - setLoginStatus('服务器地址非法: 只支持 http 或 https'); - break; - } - case 'serverAddressOutsideChannel': { - setLoginStatus('服务器地址非法: 不在当前构建渠道范围内'); + case 'serverAddressRejected': { + const payload = failure as ServerAddressRejected; + let text: string; + switch (payload.reason) { + case 'emptyOrTooLong': + text = '服务器地址非法: 不能为空或超长'; + break; + case 'notAUrl': + text = '服务器地址非法: 不是合法地址'; + break; + case 'hasCredentials': + text = '服务器地址非法: 不能包含用户名或密码'; + break; + case 'hasPathOrQueryOrFragment': + text = '服务器地址非法: 不能带路径、查询或片段'; + break; + case 'notHttps': + text = '服务器地址非法: 远程地址必须使用 https'; + break; + case 'unsupportedScheme': + text = '服务器地址非法: 只支持 http 或 https'; + break; + case 'outsideChannel': + text = '服务器地址非法: 不在当前构建渠道范围内'; + break; + default: { + expectNever(payload.reason); + text = '服务器地址非法'; + } + } + setLoginStatus(text); break; } case 'phoneNumberInvalid': { @@ -739,15 +733,10 @@ export function AuthenticatedClient({ break; } // 系统失败:调用方处理不了,原样抛出 → 全局 unhandledrejection 交给错误池。 - case 'authNetworkTimeout': - case 'authNetworkUnreachable': + case 'authNetworkFailure': case 'authServiceUnavailable': case 'unexpectedRejection': - case 'authResponseNotJson': - case 'authResponseInvalidBody': - case 'authResponseMissingRefreshCookie': - case 'authResponseMissingUserIdentity': - case 'authResponseServerRejected': + case 'authResponseInvalid': case 'clientSessionPersistFailed': case 'runtimeSessionInstallFailed': case 'authClientInitFailed':