重构 OAuth 总超时为 CPA 来源专属策略

This commit is contained in:
QLHazyCoder
2026-05-24 20:53:32 +08:00
parent 3a60560e27
commit a1793334db
21 changed files with 111 additions and 88 deletions
+51 -6
View File
@@ -48,6 +48,33 @@ function extractFunction(name) {
return source.slice(start, end);
}
const OAUTH_TIMEOUT_BUDGET_TEST_REGISTRY = `
const DEFAULT_ACTIVE_FLOW_ID = 'openai';
const self = {
MultiPageFlowRegistry: {
normalizeFlowId(value, fallback = 'openai') {
const normalized = String(value || '').trim().toLowerCase();
return ['openai', 'kiro', 'grok'].includes(normalized) ? normalized : fallback;
},
normalizeTargetId(flowId, value, fallback = 'cpa') {
const normalized = String(value || '').trim().toLowerCase();
if (flowId === 'openai' && ['cpa', 'sub2api', 'codex2api'].includes(normalized)) return normalized;
if (flowId === 'kiro') return 'kiro-rs';
if (flowId === 'grok') return 'webchat2api';
return fallback;
},
getDefaultTargetId(flowId) {
return flowId === 'openai' ? 'cpa' : '';
},
getTargetCapabilities(flowId, targetId) {
return flowId === 'openai' && targetId === 'cpa'
? { usesOauthTimeoutBudget: true }
: { usesOauthTimeoutBudget: false };
},
},
};
`;
test('background auth chain set does not include Plus session import nodes', () => {
const authChainStart = source.indexOf('const AUTH_CHAIN_NODE_IDS = new Set([');
const authChainEnd = source.indexOf(']);', authChainStart);
@@ -431,6 +458,9 @@ test('oauth timeout budget ignores stale deadlines from an old oauth url', async
const api = new Function(`
const LOG_PREFIX = '[test]';
const OAUTH_FLOW_TIMEOUT_MS = 5 * 60 * 1000;
${OAUTH_TIMEOUT_BUDGET_TEST_REGISTRY}
${extractFunction('resolveOAuthTimeoutBudgetScope')}
${extractFunction('shouldUseOAuthTimeoutBudget')}
${extractFunction('normalizeOAuthFlowDeadlineAt')}
${extractFunction('normalizeOAuthFlowSourceUrl')}
${extractFunction('getOAuthFlowRemainingMs')}
@@ -444,6 +474,8 @@ return {
step: 8,
actionLabel: '登录验证码流程',
state: {
activeFlowId: 'openai',
targetId: 'cpa',
oauthUrl: 'https://oauth.example/current',
oauthFlowDeadlineAt: Date.now() + 1200,
oauthFlowDeadlineSourceUrl: 'https://oauth.example/old',
@@ -457,7 +489,10 @@ test('oauth timeout budget clamps local timeout when enabled by default', async
const api = new Function(`
const LOG_PREFIX = '[test]';
const OAUTH_FLOW_TIMEOUT_MS = 5 * 60 * 1000;
${OAUTH_TIMEOUT_BUDGET_TEST_REGISTRY}
${extractFunction('buildOAuthFlowTimeoutError')}
${extractFunction('resolveOAuthTimeoutBudgetScope')}
${extractFunction('shouldUseOAuthTimeoutBudget')}
${extractFunction('normalizeOAuthFlowDeadlineAt')}
${extractFunction('normalizeOAuthFlowSourceUrl')}
${extractFunction('getOAuthFlowRemainingMs')}
@@ -471,6 +506,8 @@ return {
step: 8,
actionLabel: '登录验证码流程',
state: {
activeFlowId: 'openai',
targetId: 'cpa',
oauthUrl: 'https://oauth.example/current',
oauthFlowDeadlineAt: Date.now() + 1200,
oauthFlowDeadlineSourceUrl: 'https://oauth.example/current',
@@ -481,11 +518,14 @@ return {
assert(timeoutMs >= 1000);
});
test('oauth timeout budget disabled mode ignores active deadlines', async () => {
test('oauth timeout budget ignores active deadlines outside openai cpa target', async () => {
const api = new Function(`
const LOG_PREFIX = '[test]';
const OAUTH_FLOW_TIMEOUT_MS = 5 * 60 * 1000;
${OAUTH_TIMEOUT_BUDGET_TEST_REGISTRY}
${extractFunction('buildOAuthFlowTimeoutError')}
${extractFunction('resolveOAuthTimeoutBudgetScope')}
${extractFunction('shouldUseOAuthTimeoutBudget')}
${extractFunction('normalizeOAuthFlowDeadlineAt')}
${extractFunction('normalizeOAuthFlowSourceUrl')}
${extractFunction('getOAuthFlowRemainingMs')}
@@ -499,7 +539,8 @@ return {
step: 9,
actionLabel: 'OAuth localhost 回调',
state: {
oauthFlowTimeoutEnabled: false,
activeFlowId: 'openai',
targetId: 'sub2api',
oauthUrl: 'https://oauth.example/current',
oauthFlowDeadlineAt: Date.now() - 1000,
oauthFlowDeadlineSourceUrl: 'https://oauth.example/current',
@@ -509,16 +550,18 @@ return {
assert.equal(timeoutMs, 15000);
});
test('startOAuthFlowTimeoutWindow clears stale deadline when timeout is disabled', async () => {
test('startOAuthFlowTimeoutWindow clears stale deadline outside openai cpa target', async () => {
const events = {
stateUpdates: [],
logs: [],
};
const api = new Function('events', `
const api = new Function('events', `
const OAUTH_FLOW_TIMEOUT_MS = 5 * 60 * 1000;
${OAUTH_TIMEOUT_BUDGET_TEST_REGISTRY}
async function getState() {
return {
oauthFlowTimeoutEnabled: false,
activeFlowId: 'openai',
targetId: 'sub2api',
oauthFlowDeadlineAt: Date.now() - 1000,
oauthFlowDeadlineSourceUrl: 'https://oauth.example/old',
};
@@ -529,6 +572,8 @@ async function setState(update) {
async function addLog(message, level) {
events.logs.push({ message, level });
}
${extractFunction('resolveOAuthTimeoutBudgetScope')}
${extractFunction('shouldUseOAuthTimeoutBudget')}
${extractFunction('normalizeOAuthFlowSourceUrl')}
${extractFunction('startOAuthFlowTimeoutWindow')}
return {
@@ -546,7 +591,7 @@ return {
oauthFlowDeadlineAt: null,
oauthFlowDeadlineSourceUrl: null,
}]);
assert.match(events.logs[0].message, /授权后链总超时已关闭/);
assert.deepStrictEqual(events.logs, []);
});
test('oauth localhost timeout recovery resumes from bound-email relogin tail when present', async () => {