This commit is contained in:
QLHazyCoder
2026-04-23 01:00:44 +08:00
22 changed files with 723 additions and 33 deletions
+55 -6
View File
@@ -156,6 +156,7 @@ const OAUTH_FLOW_TIMEOUT_MS = 5 * 60 * 1000;
const SUB2API_STEP1_RESPONSE_TIMEOUT_MS = 90000;
const SUB2API_STEP9_RESPONSE_TIMEOUT_MS = 120000;
const DEFAULT_SUB2API_URL = 'https://sub2api.hisence.fun/admin/accounts';
const DEFAULT_CODEX2API_URL = 'http://localhost:8080/admin/accounts';
const DEFAULT_SUB2API_GROUP_NAME = 'codex';
const DEFAULT_SUB2API_PROXY_NAME = '';
const DEFAULT_SUB2API_REDIRECT_URI = 'http://localhost:1455/auth/callback';
@@ -252,6 +253,8 @@ const PERSISTED_SETTING_DEFAULTS = {
sub2apiPassword: '',
sub2apiGroupName: DEFAULT_SUB2API_GROUP_NAME,
sub2apiDefaultProxyName: DEFAULT_SUB2API_PROXY_NAME,
codex2apiUrl: DEFAULT_CODEX2API_URL,
codex2apiAdminKey: '',
customPassword: '',
autoRunSkipFailures: false,
autoRunFallbackThreadIntervalMinutes: 0,
@@ -330,6 +333,8 @@ const DEFAULT_STATE = {
sub2apiGroupId: null, // SUB2API 目标分组 ID。
sub2apiDraftName: null, // SUB2API 本轮预生成的账号名称。
sub2apiProxyId: null, // SUB2API 本轮使用的代理 ID。
codex2apiSessionId: null, // Codex2API OAuth 会话 ID。
codex2apiOAuthState: null, // Codex2API OAuth state。
flowStartTime: null, // 当前流程开始时间。
tabRegistry: {}, // 程序维护的标签页注册表。
sourceLastUrls: {}, // 各来源页面最近一次打开的地址记录。
@@ -654,7 +659,14 @@ function normalizeEmailGenerator(value = '') {
}
function normalizePanelMode(value = '') {
return String(value || '').trim().toLowerCase() === 'sub2api' ? 'sub2api' : 'cpa';
const normalized = String(value || '').trim().toLowerCase();
if (normalized === 'sub2api') {
return 'sub2api';
}
if (normalized === 'codex2api') {
return 'codex2api';
}
return 'cpa';
}
function normalizeMailProvider(value = '') {
@@ -876,6 +888,10 @@ function normalizePersistentSettingValue(key, value) {
return String(value || '').trim();
case 'sub2apiDefaultProxyName':
return String(value || '').trim();
case 'codex2apiUrl':
return normalizeCodex2ApiUrl(value);
case 'codex2apiAdminKey':
return String(value || '').trim();
case 'customPassword':
return String(value || '');
case 'autoRunSkipFailures':
@@ -3626,11 +3642,31 @@ function normalizeSub2ApiUrl(rawUrl) {
return parsed.toString();
}
function normalizeCodex2ApiUrl(rawUrl) {
if (typeof navigationUtils !== 'undefined' && navigationUtils?.normalizeCodex2ApiUrl) {
return navigationUtils.normalizeCodex2ApiUrl(rawUrl);
}
const input = (rawUrl || '').trim() || DEFAULT_CODEX2API_URL;
const withProtocol = /^https?:\/\//i.test(input) ? input : `http://${input}`;
const parsed = new URL(withProtocol);
if (!parsed.pathname || parsed.pathname === '/' || parsed.pathname === '/admin') {
parsed.pathname = '/admin/accounts';
}
parsed.hash = '';
return parsed.toString();
}
function getPanelMode(state = {}) {
if (typeof navigationUtils !== 'undefined' && navigationUtils?.getPanelMode) {
return navigationUtils.getPanelMode(state);
}
return state.panelMode === 'sub2api' ? 'sub2api' : 'cpa';
if (state.panelMode === 'sub2api') {
return 'sub2api';
}
if (state.panelMode === 'codex2api') {
return 'codex2api';
}
return 'cpa';
}
function getPanelModeLabel(modeOrState) {
@@ -3638,7 +3674,13 @@ function getPanelModeLabel(modeOrState) {
return navigationUtils.getPanelModeLabel(modeOrState);
}
const mode = typeof modeOrState === 'string' ? modeOrState : getPanelMode(modeOrState);
return mode === 'sub2api' ? 'SUB2API' : 'CPA';
if (mode === 'sub2api') {
return 'SUB2API';
}
if (mode === 'codex2api') {
return 'Codex2API';
}
return 'CPA';
}
function isSignupPageHost(hostname = '') {
@@ -3942,6 +3984,7 @@ function isRetryableContentScriptTransportError(error) {
}
const navigationUtils = self.MultiPageBackgroundNavigationUtils?.createNavigationUtils({
DEFAULT_CODEX2API_URL,
DEFAULT_SUB2API_URL,
normalizeLocalCpaStep9Mode,
});
@@ -4135,6 +4178,8 @@ function getDownstreamStateResets(step) {
sub2apiOAuthState: null,
sub2apiGroupId: null,
sub2apiDraftName: null,
codex2apiSessionId: null,
codex2apiOAuthState: null,
flowStartTime: null,
password: null,
lastEmailTimestamp: null,
@@ -4920,6 +4965,8 @@ async function handleStepData(step, payload) {
if (payload.sub2apiGroupId !== undefined) updates.sub2apiGroupId = payload.sub2apiGroupId || null;
if (payload.sub2apiDraftName !== undefined) updates.sub2apiDraftName = payload.sub2apiDraftName || null;
if (payload.sub2apiProxyId !== undefined) updates.sub2apiProxyId = payload.sub2apiProxyId || null;
if (payload.codex2apiSessionId !== undefined) updates.codex2apiSessionId = payload.codex2apiSessionId || null;
if (payload.codex2apiOAuthState !== undefined) updates.codex2apiOAuthState = payload.codex2apiOAuthState || null;
if (Object.keys(updates).length) {
await setState(updates);
}
@@ -6187,6 +6234,7 @@ const panelBridge = self.MultiPageBackgroundPanelBridge?.createPanelBridge({
closeConflictingTabsForSource,
ensureContentScriptReadyOnTab,
getPanelMode,
normalizeCodex2ApiUrl,
normalizeSub2ApiUrl,
rememberSourceLastUrl,
sendToContentScript,
@@ -6362,6 +6410,7 @@ const step10Executor = self.MultiPageBackgroundStep10?.createStep10Executor({
getTabId,
isLocalhostOAuthCallbackUrl,
isTabAlive,
normalizeCodex2ApiUrl,
normalizeSub2ApiUrl,
rememberSourceLastUrl,
reuseOrCreateTab,
@@ -6812,7 +6861,7 @@ async function runPreStep6CookieCleanup() {
async function refreshOAuthUrlBeforeStep6(state) {
if (state?.contributionModeExpected && !state?.contributionMode) {
throw new Error('步骤 7:当前自动流程预期使用贡献模式,但运行态 contributionMode 已丢失,已阻止回退到普通 CPA / SUB2API 链路。请重新进入贡献模式后再点击自动。');
throw new Error('步骤 7:当前自动流程预期使用贡献模式,但运行态 contributionMode 已丢失,已阻止回退到普通 CPA / SUB2API / Codex2API 链路。请重新进入贡献模式后再点击自动。');
}
if (state?.contributionMode && contributionOAuthManager?.startContributionFlow) {
await addLog('步骤 7contributionMode=true,走公开贡献接口,正在申请 OAuth 登录地址...', 'info');
@@ -6828,7 +6877,7 @@ async function refreshOAuthUrlBeforeStep6(state) {
await handleStepData(1, { oauthUrl });
return oauthUrl;
}
await addLog(`步骤 7contributionMode=false,走普通 CPA / SUB2API 链路(当前面板:${getPanelModeLabel(state)}),正在刷新 OAuth 登录地址...`, 'info');
await addLog(`步骤 7contributionMode=false,走普通 CPA / SUB2API / Codex2API 链路(当前面板:${getPanelModeLabel(state)}),正在刷新 OAuth 登录地址...`, 'info');
console.log(LOG_PREFIX, '[refreshOAuthUrlBeforeStep6] requesting fresh OAuth directly from panel');
const refreshResult = await requestOAuthUrlFromPanel(state, { logLabel: '步骤 7' });
await handleStepData(1, refreshResult);
@@ -7529,7 +7578,7 @@ async function executeContributionStep10(state) {
async function executeStep10(state) {
if (state?.contributionModeExpected && !state?.contributionMode) {
throw new Error('步骤 10:当前自动流程预期使用贡献模式,但运行态 contributionMode 已丢失,已阻止回退到普通 CPA / SUB2API 提交。请重新进入贡献模式后再点击自动。');
throw new Error('步骤 10:当前自动流程预期使用贡献模式,但运行态 contributionMode 已丢失,已阻止回退到普通 CPA / SUB2API / Codex2API 提交。请重新进入贡献模式后再点击自动。');
}
if (state?.contributionMode) {
return executeContributionStep10(state);