fix: preserve phone identity on oauth-login completion

- Merge latest origin/dev into PR #245 for the current review baseline.\n- Sync Step 7 completion identity before oauth-login step-key handling returns.\n- Cover the real oauth-login stepKey route in the message-router regression test.
This commit is contained in:
QLHazyCoder
2026-05-15 03:10:34 +08:00
66 changed files with 6953 additions and 542 deletions
+292 -22
View File
@@ -1,6 +1,8 @@
// background.js — Service Worker: orchestration, state, tab management, message routing
importScripts(
'shared/source-registry.js',
'shared/flow-capabilities.js',
'managed-alias-utils.js',
'mail2925-utils.js',
'paypal-utils.js',
@@ -15,10 +17,14 @@ importScripts(
'background/paypal-account-store.js',
'background/ip-proxy-provider-711proxy.js',
'background/ip-proxy-core.js',
'background/sub2api-api.js',
'background/panel-bridge.js',
'background/registration-email-state.js',
'background/runtime-state.js',
'background/generated-email-helpers.js',
'background/signup-flow-helpers.js',
'background/mail-rule-registry.js',
'flows/openai/mail-rules.js',
'background/message-router.js',
'background/verification-flow.js',
'background/auto-run-controller.js',
@@ -56,21 +62,30 @@ importScripts(
'content/activation-utils.js'
);
const NORMAL_STEP_DEFINITIONS = self.MultiPageStepDefinitions?.getSteps?.({ plusModeEnabled: false }) || [];
const DEFAULT_ACTIVE_FLOW_ID = 'openai';
const NORMAL_STEP_DEFINITIONS = self.MultiPageStepDefinitions?.getSteps?.({
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
plusModeEnabled: false,
}) || [];
const PLUS_PAYPAL_STEP_DEFINITIONS = self.MultiPageStepDefinitions?.getSteps?.({
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
plusModeEnabled: true,
plusPaymentMethod: 'paypal',
}) || NORMAL_STEP_DEFINITIONS;
const PLUS_GOPAY_STEP_DEFINITIONS = self.MultiPageStepDefinitions?.getSteps?.({
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
plusModeEnabled: true,
plusPaymentMethod: 'gopay',
}) || PLUS_PAYPAL_STEP_DEFINITIONS;
const PLUS_GPC_STEP_DEFINITIONS = self.MultiPageStepDefinitions?.getSteps?.({
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
plusModeEnabled: true,
plusPaymentMethod: 'gpc-helper',
}) || PLUS_GOPAY_STEP_DEFINITIONS;
const PLUS_STEP_DEFINITIONS = PLUS_PAYPAL_STEP_DEFINITIONS;
const ALL_STEP_DEFINITIONS = self.MultiPageStepDefinitions?.getAllSteps?.() || [
const ALL_STEP_DEFINITIONS = self.MultiPageStepDefinitions?.getAllSteps?.({
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
}) || [
...NORMAL_STEP_DEFINITIONS,
...PLUS_PAYPAL_STEP_DEFINITIONS,
...PLUS_GOPAY_STEP_DEFINITIONS,
@@ -80,6 +95,7 @@ const STEP_IDS = Array.from(new Set(ALL_STEP_DEFINITIONS
.map((definition) => Number(definition?.id))
.filter(Number.isFinite)))
.sort((left, right) => left - right);
const DEFAULT_STEP_STATUSES = Object.fromEntries(STEP_IDS.map((stepId) => [stepId, 'pending']));
const NORMAL_STEP_IDS = NORMAL_STEP_DEFINITIONS
.map((definition) => Number(definition?.id))
.filter(Number.isFinite)
@@ -205,6 +221,11 @@ const {
isRecoverableStep9AuthFailure,
} = self.MultiPageActivationUtils;
const registrationEmailStateHelpers = self.MultiPageRegistrationEmailState?.createRegistrationEmailStateHelpers?.() || null;
const runtimeStateHelpers = self.MultiPageBackgroundRuntimeState?.createRuntimeStateHelpers?.({
DEFAULT_ACTIVE_FLOW_ID,
defaultStepStatuses: DEFAULT_STEP_STATUSES,
getStepDefinitionForState: (step, state) => getStepDefinitionForState(step, state),
}) || null;
const DEFAULT_REGISTRATION_EMAIL_STATE = registrationEmailStateHelpers?.DEFAULT_REGISTRATION_EMAIL_STATE || {
current: '',
previous: '',
@@ -269,6 +290,20 @@ function getPreservedPhoneIdentity(state = {}) {
return null;
}
function buildStateViewWithRuntimeState(state = {}) {
if (runtimeStateHelpers?.buildStateView) {
return runtimeStateHelpers.buildStateView(state);
}
return state;
}
function buildStatePatchWithRuntimeState(currentState = {}, updates = {}) {
if (runtimeStateHelpers?.buildSessionStatePatch) {
return runtimeStateHelpers.buildSessionStatePatch(currentState, updates);
}
return updates;
}
function statePatchHasChanges(state = {}, patch = {}) {
return Object.keys(patch).some((key) => JSON.stringify(state?.[key] ?? null) !== JSON.stringify(patch[key] ?? null));
}
@@ -571,11 +606,21 @@ function getSignupMethodForStepDefinitions(state = {}) {
function getStepDefinitionsForState(state = {}) {
const rootScope = typeof self !== 'undefined' ? self : globalThis;
if (rootScope.MultiPageStepDefinitions?.getSteps) {
return rootScope.MultiPageStepDefinitions.getSteps({
const defaultFlowId = typeof DEFAULT_ACTIVE_FLOW_ID === 'string' ? DEFAULT_ACTIVE_FLOW_ID : 'openai';
const activeFlowId = String(state?.activeFlowId || '').trim().toLowerCase() || defaultFlowId;
const definitions = rootScope.MultiPageStepDefinitions.getSteps({
activeFlowId,
plusModeEnabled: isPlusModeState(state),
plusPaymentMethod: normalizePlusPaymentMethod(state?.plusPaymentMethod),
signupMethod: getSignupMethodForStepDefinitions(state),
});
if (Array.isArray(definitions)) {
return definitions;
}
}
const activeFlowId = String(state?.activeFlowId || '').trim().toLowerCase();
if (activeFlowId && activeFlowId !== DEFAULT_ACTIVE_FLOW_ID) {
return [];
}
if (!isPlusModeState(state)) {
return NORMAL_STEP_DEFINITIONS;
@@ -607,10 +652,19 @@ function getStepIdsForState(state = {}) {
function getLastStepIdForState(state = {}) {
const ids = getStepIdsForState(state);
return ids[ids.length - 1] || 10;
if (ids.length) {
return ids[ids.length - 1];
}
return String(state?.activeFlowId || '').trim().toLowerCase() === DEFAULT_ACTIVE_FLOW_ID ? 10 : 0;
}
function getAuthChainStartStepId(state = {}) {
const authStepId = typeof getStepIdByKeyForState === 'function'
? getStepIdByKeyForState('oauth-login', state)
: null;
if (Number.isInteger(authStepId) && authStepId > 0) {
return authStepId;
}
return isPlusModeState(state) ? 10 : FINAL_OAUTH_CHAIN_START_STEP;
}
@@ -844,8 +898,13 @@ const SETTINGS_EXPORT_FILENAME_PREFIX = 'multipage-settings';
const STEP6_REGISTRATION_SUCCESS_WAIT_MS = 20000;
const DEFAULT_STATE = {
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
activeRunId: '',
currentNodeId: '',
nodeStatuses: {},
currentStep: 0, // 当前流程执行到的步骤编号。
stepStatuses: Object.fromEntries(STEP_IDS.map((stepId) => [stepId, 'pending'])),
stepStatuses: { ...DEFAULT_STEP_STATUSES },
runtimeState: runtimeStateHelpers?.buildDefaultRuntimeState?.() || null,
...CONTRIBUTION_RUNTIME_DEFAULTS,
oauthUrl: null, // 运行时抓取到的 OAuth 地址,不要手动预填。
resolvedSignupMethod: null, // 当前自动轮次冻结后的实际注册方式。
@@ -869,6 +928,7 @@ const DEFAULT_STATE = {
sub2apiSessionId: null, // SUB2API OpenAI Auth 会话 ID。
sub2apiOAuthState: null, // SUB2API OpenAI Auth state。
sub2apiGroupId: null, // SUB2API 目标分组 ID。
sub2apiGroupIds: [], // SUB2API 多目标分组 ID。
sub2apiDraftName: null, // SUB2API 本轮预生成的账号名称。
sub2apiProxyId: null, // SUB2API 本轮使用的代理 ID。
codex2apiSessionId: null, // Codex2API OAuth 会话 ID。
@@ -1320,7 +1380,81 @@ function normalizeSignupMethod(value = '') {
: 'email';
}
function getFlowCapabilityRegistry() {
const rootScope = typeof self !== 'undefined' ? self : globalThis;
if (typeof flowCapabilityRegistry !== 'undefined' && flowCapabilityRegistry) {
return flowCapabilityRegistry;
}
return rootScope.MultiPageFlowCapabilities?.createFlowCapabilityRegistry?.({
defaultFlowId: typeof DEFAULT_ACTIVE_FLOW_ID === 'string' ? DEFAULT_ACTIVE_FLOW_ID : 'openai',
}) || null;
}
function resolveCurrentFlowCapabilities(state = {}, options = {}) {
const registry = getFlowCapabilityRegistry();
if (!registry?.resolveSidepanelCapabilities) {
return null;
}
return registry.resolveSidepanelCapabilities({
activeFlowId: options?.activeFlowId ?? state?.activeFlowId,
panelMode: options?.panelMode ?? state?.panelMode,
signupMethod: options?.signupMethod ?? state?.signupMethod,
state,
});
}
function validateAutoRunStartState(state = {}, options = {}) {
const registry = getFlowCapabilityRegistry();
if (!registry?.validateAutoRunStart) {
return { ok: true, errors: [] };
}
return registry.validateAutoRunStart({
activeFlowId: options?.activeFlowId ?? state?.activeFlowId,
panelMode: options?.panelMode ?? state?.panelMode,
signupMethod: options?.signupMethod ?? state?.signupMethod,
state,
});
}
function validateModeSwitchState(state = {}, options = {}) {
const registry = getFlowCapabilityRegistry();
if (!registry?.validateModeSwitch) {
return {
ok: true,
changedKeys: Array.isArray(options?.changedKeys) ? options.changedKeys : [],
errors: [],
normalizedUpdates: {},
};
}
return registry.validateModeSwitch({
activeFlowId: options?.activeFlowId ?? state?.activeFlowId,
changedKeys: options?.changedKeys,
panelMode: options?.panelMode ?? state?.panelMode,
signupMethod: options?.signupMethod ?? state?.signupMethod,
state,
});
}
function canUsePhoneSignup(state = {}) {
const capabilityState = typeof resolveCurrentFlowCapabilities === 'function'
? resolveCurrentFlowCapabilities(state)
: (() => {
const rootScope = typeof self !== 'undefined' ? self : globalThis;
const registry = rootScope.MultiPageFlowCapabilities?.createFlowCapabilityRegistry?.({
defaultFlowId: typeof DEFAULT_ACTIVE_FLOW_ID === 'string' ? DEFAULT_ACTIVE_FLOW_ID : 'openai',
}) || null;
return registry?.resolveSidepanelCapabilities
? registry.resolveSidepanelCapabilities({
activeFlowId: state?.activeFlowId,
panelMode: state?.panelMode,
signupMethod: state?.signupMethod,
state,
})
: null;
})();
if (capabilityState && typeof capabilityState.canUsePhoneSignup === 'boolean') {
return capabilityState.canUsePhoneSignup;
}
return Boolean(state?.phoneVerificationEnabled)
&& !Boolean(state?.plusModeEnabled)
&& !Boolean(state?.contributionMode);
@@ -1332,9 +1466,26 @@ function resolveSignupMethod(state = {}) {
return normalizeSignupMethod(frozenMethod);
}
const method = normalizeSignupMethod(state?.signupMethod);
return method === SIGNUP_METHOD_PHONE && canUsePhoneSignup(state)
? SIGNUP_METHOD_PHONE
: SIGNUP_METHOD_EMAIL;
const capabilityState = typeof resolveCurrentFlowCapabilities === 'function'
? resolveCurrentFlowCapabilities(state, { signupMethod: method })
: (() => {
const rootScope = typeof self !== 'undefined' ? self : globalThis;
const registry = rootScope.MultiPageFlowCapabilities?.createFlowCapabilityRegistry?.({
defaultFlowId: typeof DEFAULT_ACTIVE_FLOW_ID === 'string' ? DEFAULT_ACTIVE_FLOW_ID : 'openai',
}) || null;
return registry?.resolveSidepanelCapabilities
? registry.resolveSidepanelCapabilities({
activeFlowId: state?.activeFlowId,
panelMode: state?.panelMode,
signupMethod: method,
state,
})
: null;
})();
if (capabilityState?.effectiveSignupMethod) {
return normalizeSignupMethod(capabilityState.effectiveSignupMethod);
}
return method === SIGNUP_METHOD_PHONE && canUsePhoneSignup(state) ? SIGNUP_METHOD_PHONE : SIGNUP_METHOD_EMAIL;
}
async function ensureResolvedSignupMethodForRun(options = {}) {
@@ -2762,7 +2913,9 @@ function buildPersistentSettingsPayload(input = {}, options = {}) {
};
if (Object.prototype.hasOwnProperty.call(payload, 'phoneVerificationEnabled')
|| Object.prototype.hasOwnProperty.call(payload, 'plusModeEnabled')
|| Object.prototype.hasOwnProperty.call(payload, 'signupMethod')) {
|| Object.prototype.hasOwnProperty.call(payload, 'signupMethod')
|| Object.prototype.hasOwnProperty.call(payload, 'panelMode')
|| Object.prototype.hasOwnProperty.call(payload, 'activeFlowId')) {
payload.signupMethod = resolveSignupMethod(nextSignupConstraintState);
}
if (payload.ipProxyServiceProfiles) {
@@ -2838,7 +2991,13 @@ async function getState() {
getPersistedAliasState(),
accountRunHistoryHelpers?.getPersistedAccountRunHistory?.() || [],
]);
return { ...DEFAULT_STATE, ...persistedSettings, ...persistedAliasState, ...state, accountRunHistory };
return buildStateViewWithRuntimeState({
...DEFAULT_STATE,
...persistedSettings,
...persistedAliasState,
...state,
accountRunHistory,
});
}
async function initializeSessionStorageAccess() {
@@ -2857,19 +3016,24 @@ async function initializeSessionStorageAccess() {
async function setState(updates) {
console.log(LOG_PREFIX, 'storage.set:', JSON.stringify(updates).slice(0, 200));
if (Object.keys(updates || {}).length > 0) {
await chrome.storage.session.set(updates);
const currentSessionState = await chrome.storage.session.get(null);
const sessionUpdates = buildStatePatchWithRuntimeState({
...DEFAULT_STATE,
...currentSessionState,
}, updates);
await chrome.storage.session.set(sessionUpdates);
const persistentAliasUpdates = {};
if (Object.prototype.hasOwnProperty.call(updates, 'manualAliasUsage')) {
persistentAliasUpdates.manualAliasUsage = normalizeBooleanMap(updates.manualAliasUsage);
if (Object.prototype.hasOwnProperty.call(sessionUpdates, 'manualAliasUsage')) {
persistentAliasUpdates.manualAliasUsage = normalizeBooleanMap(sessionUpdates.manualAliasUsage);
}
if (Object.prototype.hasOwnProperty.call(updates, 'preservedAliases')) {
persistentAliasUpdates.preservedAliases = normalizeBooleanMap(updates.preservedAliases);
if (Object.prototype.hasOwnProperty.call(sessionUpdates, 'preservedAliases')) {
persistentAliasUpdates.preservedAliases = normalizeBooleanMap(sessionUpdates.preservedAliases);
}
if (Object.prototype.hasOwnProperty.call(updates, 'icloudAliasCache')) {
persistentAliasUpdates.icloudAliasCache = normalizeIcloudAliasCacheList(updates.icloudAliasCache);
if (Object.prototype.hasOwnProperty.call(sessionUpdates, 'icloudAliasCache')) {
persistentAliasUpdates.icloudAliasCache = normalizeIcloudAliasCacheList(sessionUpdates.icloudAliasCache);
}
if (Object.prototype.hasOwnProperty.call(updates, 'icloudAliasCacheAt')) {
persistentAliasUpdates.icloudAliasCacheAt = Math.max(0, Number(updates.icloudAliasCacheAt) || 0);
if (Object.prototype.hasOwnProperty.call(sessionUpdates, 'icloudAliasCacheAt')) {
persistentAliasUpdates.icloudAliasCacheAt = Math.max(0, Number(sessionUpdates.icloudAliasCacheAt) || 0);
}
if (Object.keys(persistentAliasUpdates).length > 0) {
await chrome.storage.local.set(persistentAliasUpdates);
@@ -2926,6 +3090,30 @@ async function importSettingsBundle(configBundle) {
fillDefaults: true,
requireKnownKeys: true,
});
const importModeValidation = validateModeSwitchState({
...state,
...importedSettings,
resolvedSignupMethod: null,
}, {
changedKeys: Object.keys(importedSettings),
});
if (importModeValidation?.normalizedUpdates && Object.keys(importModeValidation.normalizedUpdates).length > 0) {
Object.assign(importedSettings, importModeValidation.normalizedUpdates);
}
if (
Object.prototype.hasOwnProperty.call(importedSettings, 'phoneVerificationEnabled')
|| Object.prototype.hasOwnProperty.call(importedSettings, 'plusModeEnabled')
|| Object.prototype.hasOwnProperty.call(importedSettings, 'signupMethod')
|| Object.prototype.hasOwnProperty.call(importedSettings, 'panelMode')
|| Object.prototype.hasOwnProperty.call(importedSettings, 'activeFlowId')
|| Object.prototype.hasOwnProperty.call(importedSettings, 'contributionMode')
) {
importedSettings.signupMethod = resolveSignupMethod({
...state,
...importedSettings,
resolvedSignupMethod: null,
});
}
await setPersistentSettings(importedSettings);
@@ -3463,7 +3651,7 @@ async function resetState() {
? prev.freeReusablePhoneActivation
: null;
await chrome.storage.session.clear();
await chrome.storage.session.set({
const resetPayload = buildStatePatchWithRuntimeState({}, {
...DEFAULT_STATE,
...persistedSettings,
...persistedAliasState,
@@ -3493,6 +3681,7 @@ async function resetState() {
? Number(prev.automationWindowId)
: null,
});
await chrome.storage.session.set(resetPayload);
}
/**
@@ -4055,6 +4244,8 @@ async function requestHotmailLocalCode(account, pollPayload = {}) {
top: 5,
senderFilters: pollPayload.senderFilters || [],
subjectFilters: pollPayload.subjectFilters || [],
requiredKeywords: pollPayload.requiredKeywords || [],
codePatterns: pollPayload.codePatterns || [],
excludeCodes: pollPayload.excludeCodes || [],
filterAfterTimestamp: Number(pollPayload.filterAfterTimestamp || 0) || 0,
}),
@@ -4331,6 +4522,8 @@ async function pollHotmailVerificationCode(step, state, pollPayload = {}) {
afterTimestamp: pollPayload.filterAfterTimestamp || 0,
senderFilters: pollPayload.senderFilters || [],
subjectFilters: pollPayload.subjectFilters || [],
requiredKeywords: pollPayload.requiredKeywords || [],
codePatterns: pollPayload.codePatterns || [],
excludeCodes: pollPayload.excludeCodes || [],
});
const match = matchResult.match;
@@ -5513,6 +5706,8 @@ async function pollCloudflareTempEmailVerificationCode(step, state, pollPayload
afterTimestamp: pollPayload.filterAfterTimestamp || 0,
senderFilters: pollPayload.senderFilters || [],
subjectFilters: pollPayload.subjectFilters || [],
requiredKeywords: pollPayload.requiredKeywords || [],
codePatterns: pollPayload.codePatterns || [],
excludeCodes: pollPayload.excludeCodes || [],
});
const match = matchResult.match;
@@ -7218,7 +7413,7 @@ function isSignupEntryHost(hostname = '') {
if (typeof navigationUtils !== 'undefined' && navigationUtils?.isSignupEntryHost) {
return navigationUtils.isSignupEntryHost(hostname);
}
return ['chatgpt.com', 'chat.openai.com'].includes(hostname);
return ['chatgpt.com', 'www.chatgpt.com', 'chat.openai.com'].includes(hostname);
}
function isLikelyLoggedInChatgptHomeUrl(rawUrl) {
@@ -7302,6 +7497,7 @@ function matchesSourceUrlFamily(source, candidateUrl, referenceUrl) {
if (!candidate) return false;
const reference = parseUrlSafely(referenceUrl);
switch (source) {
case 'openai-auth':
case 'signup-page':
return isSignupPageHost(candidate.hostname) || isSignupEntryHost(candidate.hostname);
case 'duck-mail':
@@ -7312,6 +7508,8 @@ function matchesSourceUrlFamily(source, candidateUrl, referenceUrl) {
return is163MailHost(candidate.hostname);
case 'gmail-mail':
return candidate.hostname === 'mail.google.com';
case 'icloud-mail':
return candidate.hostname === 'www.icloud.com' || candidate.hostname === 'www.icloud.com.cn';
case 'inbucket-mail':
return Boolean(reference) && candidate.origin === reference.origin && candidate.pathname.startsWith('/m/');
case 'mail-2925':
@@ -7322,11 +7520,24 @@ function matchesSourceUrlFamily(source, candidateUrl, referenceUrl) {
return Boolean(reference)
&& candidate.origin === reference.origin
&& (candidate.pathname.startsWith('/admin/accounts') || candidate.pathname.startsWith('/login') || candidate.pathname === '/');
case 'codex2api-panel':
return Boolean(reference)
&& candidate.origin === reference.origin
&& (candidate.pathname.startsWith('/admin/accounts') || candidate.pathname === '/admin' || candidate.pathname === '/');
default:
return false;
}
}
function sourcesMatch(leftSource, rightSource) {
if (sourceRegistry?.resolveCanonicalSource) {
const left = sourceRegistry.resolveCanonicalSource(leftSource);
const right = sourceRegistry.resolveCanonicalSource(rightSource);
return Boolean(left && right && left === right);
}
return String(leftSource || '').trim() === String(rightSource || '').trim();
}
async function rememberSourceLastUrl(source, url) {
return tabRuntime.rememberSourceLastUrl(source, url);
}
@@ -7407,7 +7618,7 @@ async function ensureContentScriptReadyOnTab(source, tabId, options = {}) {
function isContentScriptReadyPong(source, pong) {
if (!pong?.ok) return false;
if (pong.source && pong.source !== source) return false;
if (pong.source && !sourcesMatch(pong.source, source)) return false;
if (source === 'plus-checkout') {
return Boolean(pong.plusCheckoutReady);
}
@@ -7598,11 +7809,13 @@ function getSourceLabel(source) {
return loggingStatus.getSourceLabel(source);
}
const labels = {
'openai-auth': '认证页',
'gmail-mail': 'Gmail 邮箱',
'sidepanel': '侧边栏',
'signup-page': '认证页',
'vps-panel': 'CPA 面板',
'sub2api-panel': 'SUB2API 后台',
'codex2api-panel': 'Codex2API 后台',
'qq-mail': 'QQ 邮箱',
'mail-163': '163 邮箱',
'mail-2925': '2925 邮箱',
@@ -7614,6 +7827,8 @@ function getSourceLabel(source) {
'cloudmail': 'Cloud Mail',
'plus-checkout': 'Plus Checkout',
'paypal-flow': 'PayPal 授权页',
'gopay-flow': 'GoPay 授权页',
'unknown-source': '未知来源',
};
return labels[source] || source || '未知来源';
}
@@ -7667,10 +7882,16 @@ function getStepFetchNetworkRetryPolicy(step) {
};
}
const sourceRegistry = self.MultiPageSourceRegistry?.createSourceRegistry?.() || null;
const flowCapabilityRegistry = self.MultiPageFlowCapabilities?.createFlowCapabilityRegistry?.({
defaultFlowId: DEFAULT_ACTIVE_FLOW_ID,
}) || null;
const navigationUtils = self.MultiPageBackgroundNavigationUtils?.createNavigationUtils({
DEFAULT_CODEX2API_URL,
DEFAULT_SUB2API_URL,
normalizeLocalCpaStep9Mode,
sourceRegistry,
});
const loggingStatus = self.MultiPageBackgroundLoggingStatus?.createLoggingStatus({
@@ -7680,6 +7901,7 @@ const loggingStatus = self.MultiPageBackgroundLoggingStatus?.createLoggingStatus
isRecoverableStep9AuthFailure,
LOG_PREFIX,
setState,
sourceRegistry,
STOP_ERROR_MESSAGE,
});
@@ -7692,6 +7914,7 @@ const tabRuntime = self.MultiPageBackgroundTabRuntime?.createTabRuntime({
isRetryableContentScriptTransportError,
LOG_PREFIX,
matchesSourceUrlFamily,
sourceRegistry,
setState,
sleepWithStop,
STOP_ERROR_MESSAGE,
@@ -8057,7 +8280,9 @@ function getDownstreamStateResets(step, state = {}) {
sub2apiSessionId: null,
sub2apiOAuthState: null,
sub2apiGroupId: null,
sub2apiGroupIds: [],
sub2apiDraftName: null,
sub2apiProxyId: null,
codex2apiSessionId: null,
codex2apiOAuthState: null,
flowStartTime: null,
@@ -8556,6 +8781,30 @@ async function launchAutoRunTimerPlan(trigger = 'alarm', options = {}) {
return false;
}
if (plan.kind === AUTO_RUN_TIMER_KIND_SCHEDULED_START) {
const autoRunStartValidation = typeof validateAutoRunStartState === 'function'
? validateAutoRunStartState(state, { state })
: { ok: true, errors: [] };
if (autoRunStartValidation?.ok === false) {
const validationMessage = autoRunStartValidation.errors?.[0]?.message || '当前设置不支持启动自动流程。';
await clearAutoRunTimerAlarm();
await broadcastAutoRunStatus('idle', {
currentRun: 0,
totalRuns: 1,
attemptRun: 0,
}, {
autoRunRoundSummaries: [],
autoRunTimerPlan: null,
scheduledAutoRunPlan: null,
});
await addLog(`自动运行计划已取消:${validationMessage}`, 'error');
if (trigger === 'manual') {
throw new Error(validationMessage);
}
return false;
}
}
await clearAutoRunTimerAlarm();
if (plan.autoRunSessionId && !isCurrentAutoRunSessionId(plan.autoRunSessionId)) {
return false;
@@ -8962,6 +9211,9 @@ async function handleStepData(step, payload) {
if (payload.sub2apiSessionId !== undefined) updates.sub2apiSessionId = payload.sub2apiSessionId || null;
if (payload.sub2apiOAuthState !== undefined) updates.sub2apiOAuthState = payload.sub2apiOAuthState || null;
if (payload.sub2apiGroupId !== undefined) updates.sub2apiGroupId = payload.sub2apiGroupId || null;
if (payload.sub2apiGroupIds !== undefined) updates.sub2apiGroupIds = Array.isArray(payload.sub2apiGroupIds)
? payload.sub2apiGroupIds
: [];
if (payload.sub2apiDraftName !== undefined) updates.sub2apiDraftName = payload.sub2apiDraftName || null;
if (payload.sub2apiProxyId !== undefined) updates.sub2apiProxyId = payload.sub2apiProxyId || null;
if (payload.cpaOAuthState !== undefined) updates.cpaOAuthState = payload.cpaOAuthState || null;
@@ -11296,8 +11548,20 @@ const signupFlowHelpers = self.MultiPageSignupFlowHelpers?.createSignupFlowHelpe
waitForTabStableComplete,
waitForTabUrlMatch,
});
const openAiMailRules = self.MultiPageOpenAiMailRules?.createOpenAiMailRules({
getHotmailVerificationRequestTimestamp,
MAIL_2925_VERIFICATION_INTERVAL_MS,
MAIL_2925_VERIFICATION_MAX_ATTEMPTS,
});
const mailRuleRegistry = self.MultiPageBackgroundMailRuleRegistry?.createMailRuleRegistry({
defaultFlowId: DEFAULT_ACTIVE_FLOW_ID,
flowBuilders: {
openai: openAiMailRules,
},
});
const verificationFlowHelpers = self.MultiPageBackgroundVerificationFlow?.createVerificationFlowHelpers({
addLog,
buildVerificationPollPayload: mailRuleRegistry?.buildVerificationPollPayload,
chrome,
closeConflictingTabsForSource,
CLOUDFLARE_TEMP_EMAIL_PROVIDER,
@@ -11638,6 +11902,7 @@ const step10Executor = self.MultiPageBackgroundStep10?.createStep10Executor({
sendToContentScript,
sendToContentScriptResilient,
shouldBypassStep9ForLocalCpa,
DEFAULT_SUB2API_GROUP_NAME,
SUB2API_STEP9_RESPONSE_TIMEOUT_MS,
});
const stepExecutorsByKey = {
@@ -11716,6 +11981,7 @@ const messageRouter = self.MultiPageBackgroundMessageRouter?.createMessageRouter
normalizeSignupMethod,
canUsePhoneSignup,
resolveSignupMethod,
validateAutoRunStart: validateAutoRunStartState,
getTabId,
getStopRequested: () => stopRequested,
handleCloudflareSecurityBlocked,
@@ -11805,6 +12071,10 @@ const plusGoPayStepRegistry = buildStepRegistry(PLUS_GOPAY_STEP_DEFINITIONS);
const plusGpcStepRegistry = buildStepRegistry(PLUS_GPC_STEP_DEFINITIONS);
function getStepRegistryForState(state = {}) {
const activeFlowId = String(state?.activeFlowId || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase() || DEFAULT_ACTIVE_FLOW_ID;
if (activeFlowId !== DEFAULT_ACTIVE_FLOW_ID) {
throw new Error(`当前尚未注册 flow=${activeFlowId} 的步骤执行器。`);
}
if (!isPlusModeState(state)) {
return normalStepRegistry;
}