前端:删掉由 invoke 拒绝驱动的认证重试
- `directCodexSession.ts` 改名 `directCodexSessionKeepalive.ts`,只保留会话保活常量,删除 `withDirectCodexSessionRefresh` 的"刷新 + 重跑整轮"及其登录失效识别 - 发送回合与终止回合两处调用点直接 invoke,不再包一层重试 - controller 的 catch TODO 更新为新形状:命令只接单、拒单返回 typed 错误、整轮结果只由事件载荷回答
This commit is contained in:
+16
-19
@@ -39,10 +39,7 @@ import {
|
||||
isDirectCodexTurnAlreadyRunningError,
|
||||
isDirectCodexTurnInterruptedError,
|
||||
} from '../conversation/directCodexConversation';
|
||||
import {
|
||||
DIRECT_CODEX_SESSION_KEEPALIVE_MS,
|
||||
withDirectCodexSessionRefresh,
|
||||
} from '../conversation/directCodexSession';
|
||||
import { DIRECT_CODEX_SESSION_KEEPALIVE_MS } from '../conversation/directCodexSessionKeepalive';
|
||||
import {
|
||||
type DirectCodexTurnAttachment,
|
||||
toDirectCodexTurnAttachments,
|
||||
@@ -569,23 +566,22 @@ export function useDirectProjectChatController({
|
||||
currentPlatformSessionGeneration,
|
||||
);
|
||||
try {
|
||||
await withDirectCodexSessionRefresh(() =>
|
||||
invoke<string>('chat_with_game_creator_direct_codex', {
|
||||
projectPath: nextProjectPath,
|
||||
clientTurnId: input.clientTurnId,
|
||||
userItem: input.userItem,
|
||||
analyticsAttemptId: runAnalytics.nextAttempt(),
|
||||
...(input.creationType ? { creationType: input.creationType } : {}),
|
||||
}),
|
||||
);
|
||||
await invoke<string>('chat_with_game_creator_direct_codex', {
|
||||
projectPath: nextProjectPath,
|
||||
clientTurnId: input.clientTurnId,
|
||||
userItem: input.userItem,
|
||||
analyticsAttemptId: runAnalytics.nextAttempt(),
|
||||
...(input.creationType ? { creationType: input.creationType } : {}),
|
||||
});
|
||||
} finally {
|
||||
runAnalytics.settle();
|
||||
}
|
||||
// 清单刷新统一交给 startTurn 的 finally:成功与报错路径都覆盖,且只读一次。
|
||||
// TODO(Direct 命令接单化,未实施):下面这个 catch 现在兼职"接单被拒"与"回合失败"两种回执。
|
||||
// 计划(`docs/adr/【ADR】DirectProject命令接单化-2026-09-23.md`,草案)是让命令只负责接单、
|
||||
// 整轮结果只由订阅事件的载荷回答:届时这里只剩接单被拒,文案改成这条消息下面的本地助手
|
||||
// 气泡,状态行改由 reducer 供数据,而 invoke 拒绝驱动的认证重试作废。
|
||||
// 计划(`docs/adr/【ADR】DirectProject命令接单化-2026-09-23.md`)是让命令只负责接单:整轮结果
|
||||
// 只由订阅事件的载荷回答,拒单则返回 typed 错误——届时这里只剩"拒单",认得的前置 / 参数类按变体
|
||||
// 给与用户消息同级的提示且不上报,认不得的错误原样抛出交给既有捕获链路,状态行改由 reducer 供数。
|
||||
// invoke 拒绝驱动的认证重试已按该 ADR 删除(`directCodexSessionKeepalive.ts` 只保留会话保活)。
|
||||
} catch (error) {
|
||||
if (
|
||||
isDirectCodexTurnAlreadyRunningError(error) ||
|
||||
@@ -663,10 +659,11 @@ export function useDirectProjectChatController({
|
||||
setTurnCancelling(true);
|
||||
setComposerNotice('正在终止当前回合');
|
||||
try {
|
||||
const result = await withDirectCodexSessionRefresh(() =>
|
||||
invoke<DirectTurnCancelView>('cancel_direct_codex_turn', {
|
||||
const result = await invoke<DirectTurnCancelView>(
|
||||
'cancel_direct_codex_turn',
|
||||
{
|
||||
projectPath,
|
||||
}),
|
||||
},
|
||||
);
|
||||
const message = result?.message?.trim();
|
||||
if (result?.outcome === 'released') {
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
import {
|
||||
currentPlatformSessionGeneration,
|
||||
requestPlatformSessionRefresh,
|
||||
} from '../../../../services/platformSession';
|
||||
|
||||
/**
|
||||
* 平台 access token 很短命。DirectProject 一个回合可能横跨图片生成、构建和浏览器验证,
|
||||
* 所以回合运行期间由客户端保持原生会话新鲜;`platformSession.ts` 的 singleflight
|
||||
* 会把这里的刷新与 401 触发的刷新合并成同一次请求。
|
||||
*/
|
||||
export const DIRECT_CODEX_SESSION_KEEPALIVE_MS = 5 * 60 * 1000;
|
||||
|
||||
function isDirectCodexAuthenticationRequired(error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
return (
|
||||
message.includes('authentication-required') ||
|
||||
message.includes('codex-app-server-error:unauthorized') ||
|
||||
/kind=codex-app-server-unauthorized(?=\s|$)/.test(message) ||
|
||||
message.includes('登录已失效')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跑一轮 DirectProject 请求:只有 401/登录失效才刷新会话重试一次,其它错误原样抛出。
|
||||
*
|
||||
* 刷新期间账号代际变化(换号、登出)时必须放弃重试:带着旧身份的请求重放会把上一账号
|
||||
* 的回合打进新账号的对话历史。
|
||||
*/
|
||||
export async function withDirectCodexSessionRefresh<T>(
|
||||
operation: () => Promise<T>,
|
||||
) {
|
||||
const generation = currentPlatformSessionGeneration();
|
||||
try {
|
||||
return await operation();
|
||||
} catch (error) {
|
||||
if (!isDirectCodexAuthenticationRequired(error)) throw error;
|
||||
if (currentPlatformSessionGeneration() !== generation) throw error;
|
||||
const refresh = await requestPlatformSessionRefresh();
|
||||
if (refresh.status === 'failed') throw error;
|
||||
if (
|
||||
refresh.status !== 'refreshed' ||
|
||||
currentPlatformSessionGeneration() !== refresh.generation
|
||||
) {
|
||||
throw new Error('登录账号已变化,原对话请求已停止');
|
||||
}
|
||||
return operation();
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* 平台 access token 很短命。DirectProject 一个回合可能横跨图片生成、构建和浏览器验证,
|
||||
* 所以回合运行期间由客户端保持原生会话新鲜;`platformSession.ts` 的 singleflight
|
||||
* 会把这里的刷新与 401 触发的刷新合并成同一次请求。
|
||||
*/
|
||||
export const DIRECT_CODEX_SESSION_KEEPALIVE_MS = 5 * 60 * 1000;
|
||||
Reference in New Issue
Block a user