Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 58 additions & 3 deletions background.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ importScripts(
'background/ip-proxy-core.js',
'background/sub2api-api.js',
'background/cpa-api.js',
'background/remote-account-inject-api.js',
'background/panel-bridge.js',
'background/registration-email-state.js',
'core/flow-kernel/workflow-engine.js',
Expand Down Expand Up @@ -72,6 +73,7 @@ importScripts(
'flows/openai/background/steps/paypal-approve.js',
'flows/openai/background/steps/gopay-approve.js',
'flows/openai/background/steps/plus-return-confirm.js',
'flows/openai/background/steps/remote-account-inject.js',
'flows/openai/background/steps/sub2api-session-import.js',
'flows/openai/background/steps/cpa-session-import.js',
'flows/openai/background/steps/oauth-login.js',
Expand Down Expand Up @@ -929,6 +931,10 @@ function buildResolvedStepDefinitionState(state = {}) {
plusModeEnabled: stepDefinitionOptions.plusModeEnabled === undefined
? plusModeEnabled
: Boolean(stepDefinitionOptions.plusModeEnabled),
...(Boolean(
stepDefinitionOptions.remoteAccountInjectEnabled
?? state?.remoteAccountInjectEnabled
) ? { remoteAccountInjectEnabled: true } : {}),
plusPaymentMethod,
plusAccountAccessStrategy: normalizePlusAccountAccessStrategy(
stepDefinitionOptions.plusAccountAccessStrategy
Expand All @@ -947,14 +953,18 @@ function getStepDefinitionsForState(state = {}) {
if (rootScope.MultiPageStepDefinitions?.getSteps) {
const defaultFlowId = typeof DEFAULT_ACTIVE_FLOW_ID === 'string' ? DEFAULT_ACTIVE_FLOW_ID : 'openai';
const activeFlowId = String(resolvedState?.activeFlowId || '').trim().toLowerCase() || defaultFlowId;
const definitions = rootScope.MultiPageStepDefinitions.getSteps({
const stepOptions = {
activeFlowId,
plusModeEnabled: Boolean(resolvedState?.plusModeEnabled),
plusPaymentMethod: normalizePlusPaymentMethod(resolvedState?.plusPaymentMethod),
plusAccountAccessStrategy: normalizePlusAccountAccessStrategy(resolvedState?.plusAccountAccessStrategy),
signupMethod: getSignupMethodForStepDefinitions(resolvedState),
phoneSignupReloginAfterBindEmailEnabled: Boolean(resolvedState?.phoneSignupReloginAfterBindEmailEnabled),
});
};
if (Boolean(resolvedState?.remoteAccountInjectEnabled)) {
stepOptions.remoteAccountInjectEnabled = true;
}
const definitions = rootScope.MultiPageStepDefinitions.getSteps(stepOptions);
if (Array.isArray(definitions)) {
return definitions;
}
Expand Down Expand Up @@ -1293,6 +1303,11 @@ const PERSISTED_SETTING_DEFAULTS = {
ipProxyRegion: '',
codex2apiUrl: DEFAULT_CODEX2API_URL,
codex2apiAdminKey: '',
remoteAccountInjectEnabled: false,
remoteAccountInjectUrl: '',
remoteAccountInjectAdminKey: '',
grokRemoteAccountInjectUrl: '',
grokRemoteAccountInjectAdminKey: '',
customPassword: '',
plusModeEnabled: false,
plusPaymentMethod: DEFAULT_PLUS_PAYMENT_METHOD,
Expand Down Expand Up @@ -1465,6 +1480,11 @@ const SETTINGS_SCHEMA_VIEW_KEYS = Object.freeze([
'sub2apiDefaultProxyName',
'codex2apiUrl',
'codex2apiAdminKey',
'remoteAccountInjectEnabled',
'remoteAccountInjectUrl',
'remoteAccountInjectAdminKey',
'grokRemoteAccountInjectUrl',
'grokRemoteAccountInjectAdminKey',
'customPassword',
'signupMethod',
'phoneVerificationEnabled',
Expand Down Expand Up @@ -3249,6 +3269,16 @@ function normalizePersistentSettingValue(key, value) {
return normalizeCodex2ApiUrl(value);
case 'codex2apiAdminKey':
return String(value || '').trim();
case 'remoteAccountInjectEnabled':
return Boolean(value);
case 'remoteAccountInjectUrl':
return String(value || '').trim();
case 'remoteAccountInjectAdminKey':
return String(value || '').trim();
case 'grokRemoteAccountInjectUrl':
return String(value || '').trim();
case 'grokRemoteAccountInjectAdminKey':
return String(value || '').trim();
case 'customPassword':
return String(value || '');
case 'signupMethod':
Expand Down Expand Up @@ -3822,6 +3852,11 @@ function buildSettingsStatePatchFromFlatUpdates(updates = {}) {
assignIfUpdated('sub2apiDefaultProxyName', ['flows', 'openai', 'targets', 'sub2api', 'sub2apiDefaultProxyName']);
assignIfUpdated('codex2apiUrl', ['flows', 'openai', 'targets', 'codex2api', 'codex2apiUrl']);
assignIfUpdated('codex2apiAdminKey', ['flows', 'openai', 'targets', 'codex2api', 'codex2apiAdminKey']);
assignIfUpdated('remoteAccountInjectEnabled', ['flows', 'openai', 'remoteAccountInjectEnabled']);
assignIfUpdated('remoteAccountInjectUrl', ['flows', 'openai', 'remoteAccountInjectUrl']);
assignIfUpdated('remoteAccountInjectAdminKey', ['flows', 'openai', 'remoteAccountInjectAdminKey']);
assignIfUpdated('grokRemoteAccountInjectUrl', ['flows', 'grok', 'grokRemoteAccountInjectUrl']);
assignIfUpdated('grokRemoteAccountInjectAdminKey', ['flows', 'grok', 'grokRemoteAccountInjectAdminKey']);
assignIfUpdated('customPassword', ['services', 'account', 'customPassword']);
assignIfUpdated('signupMethod', ['flows', 'openai', 'signup', 'signupMethod']);
assignIfUpdated('phoneVerificationEnabled', ['flows', 'openai', 'signup', 'phoneVerificationEnabled']);
Expand Down Expand Up @@ -9379,7 +9414,7 @@ function isRestartCurrentAttemptError(error) {
return loggingStatus.isRestartCurrentAttemptError(error);
}
const message = String(typeof error === 'string' ? error : error?.message || '');
return /当前邮箱已存在,需要重新开始新一轮|SIGNUP_PHONE_PASSWORD_MISMATCH::/i.test(message);
return /当前邮箱已存在,需要重新开始新一轮|SIGNUP_PHONE_PASSWORD_MISMATCH::|GROK_RESTART_CURRENT_ATTEMPT::/i.test(message);
}

function isSignupPhonePasswordMismatchFailure(error) {
Expand Down Expand Up @@ -10913,6 +10948,7 @@ const AUTO_RUN_BACKGROUND_COMPLETED_STEP_KEYS = new Set([
'plus-checkout-return',
'sub2api-session-import',
'cpa-session-import',
'remote-account-inject',
'oauth-login',
'fetch-login-code',
'post-login-phone-verification',
Expand All @@ -10936,6 +10972,7 @@ const AUTO_RUN_BACKGROUND_COMPLETED_STEP_KEYS = new Set([
'grok-submit-verification-code',
'grok-submit-profile',
'grok-extract-sso-cookie',
'grok-remote-sso-inject',
]);
const STEP_COMPLETION_SIGNAL_STEP_KEYS = new Set([
'fill-password',
Expand Down Expand Up @@ -12034,6 +12071,7 @@ const AUTO_RUN_NODE_DELAYS = Object.freeze({
'gopay-subscription-confirm': 2000,
'paypal-approve': 2000,
'plus-checkout-return': 1000,
'remote-account-inject': 0,
'sub2api-session-import': 0,
'cpa-session-import': 0,
'oauth-login': 2000,
Expand Down Expand Up @@ -13914,6 +13952,20 @@ const cpaSessionImportExecutor = self.MultiPageBackgroundCpaSessionImport?.creat
throwIfStopped,
waitForTabCompleteUntilStopped,
});
const remoteAccountInjectExecutor = self.MultiPageBackgroundRemoteAccountInject?.createRemoteAccountInjectExecutor({
addLog,
chrome,
completeNodeFromBackground,
ensureContentScriptReadyOnTabUntilStopped,
fetchImpl: typeof fetch === 'function' ? fetch.bind(globalThis) : null,
getTabId,
isTabAlive,
registerTab,
sendTabMessageUntilStopped,
sleepWithStop,
throwIfStopped,
waitForTabCompleteUntilStopped,
});
const kiroRegisterRunner = self.MultiPageBackgroundKiroRegisterRunner?.createKiroRegisterRunner({
addLog,
chrome,
Expand Down Expand Up @@ -13943,6 +13995,7 @@ const grokRegisterRunner = self.MultiPageBackgroundGrokRegisterRunner?.createGro
chrome,
ensureContentScriptReadyOnTab,
completeNodeFromBackground,
fetchImpl: typeof fetch === 'function' ? fetch.bind(globalThis) : null,
generatePassword,
generateRandomName,
getTabId,
Expand Down Expand Up @@ -14089,6 +14142,7 @@ const stepExecutorsByKey = {
? goPayApproveExecutor.executeGoPayApprove(state)
: payPalApproveExecutor.executePayPalApprove(state),
'plus-checkout-return': (state) => plusReturnConfirmExecutor.executePlusReturnConfirm(state),
'remote-account-inject': (state) => remoteAccountInjectExecutor.executeRemoteAccountInject(state),
'sub2api-session-import': (state) => sub2ApiSessionImportExecutor.executeSub2ApiSessionImport(state),
'cpa-session-import': (state) => cpaSessionImportExecutor.executeCpaSessionImport(state),
'oauth-login': (state) => step7Executor.executeStep7(state),
Expand All @@ -14115,6 +14169,7 @@ const stepExecutorsByKey = {
'grok-submit-verification-code': (state) => grokRegisterRunner.executeGrokSubmitVerificationCode(state),
'grok-submit-profile': (state) => grokRegisterRunner.executeGrokSubmitProfile(state),
'grok-extract-sso-cookie': (state) => grokRegisterRunner.executeGrokExtractSsoCookie(state),
'grok-remote-sso-inject': (state) => grokRegisterRunner.executeGrokRemoteSsoInject(state),
};
const messageRouter = self.MultiPageBackgroundMessageRouter?.createMessageRouter({
addLog,
Expand Down
2 changes: 1 addition & 1 deletion background/logging-status.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@

function isRestartCurrentAttemptError(error) {
const message = String(typeof error === 'string' ? error : error?.message || '');
return /当前邮箱已存在,需要重新开始新一轮|SIGNUP_PHONE_PASSWORD_MISMATCH::/i.test(message);
return /当前邮箱已存在,需要重新开始新一轮|SIGNUP_PHONE_PASSWORD_MISMATCH::|GROK_RESTART_CURRENT_ATTEMPT::/i.test(message);
}

function isSignupUserAlreadyExistsFailure(error) {
Expand Down
116 changes: 116 additions & 0 deletions background/remote-account-inject-api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
(function attachBackgroundRemoteAccountInjectApi(root, factory) {
root.MultiPageBackgroundRemoteAccountInjectApi = factory();
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundRemoteAccountInjectApiModule() {
function normalizeString(value = '') {
return String(value ?? '').trim();
}

function normalizeRemoteAccountInjectUrl(rawUrl = '') {
const value = normalizeString(rawUrl);
if (!value) {
return '';
}
const withProtocol = /^https?:\/\//i.test(value) ? value : `http://${value}`;
let parsed;
try {
parsed = new URL(withProtocol);
} catch (error) {
throw new Error('远程账号注入地址格式无效,请检查配置。');
}
if (!/^https?:$/i.test(parsed.protocol)) {
throw new Error('远程账号注入地址仅支持 HTTP/HTTPS。');
}
return `${parsed.origin}/api/remote-account/inject`;
}

function getRemoteAccountInjectErrorMessage(payload, responseStatus = 500) {
const candidates = [
payload?.message,
payload?.detail,
payload?.error,
payload?.reason,
];
const message = candidates.map(normalizeString).find(Boolean);
return message || `远程账号注入请求失败(HTTP ${responseStatus})。`;
}

function createRemoteAccountInjectApi(deps = {}) {
const {
fetchImpl = (...args) => fetch(...args),
} = deps;

async function injectRemoteAccounts(options = {}) {
const endpoint = normalizeRemoteAccountInjectUrl(options.url);
const adminKey = normalizeString(options.adminKey);
if (!endpoint) {
return { skipped: true, reason: 'missing_url' };
}
if (!adminKey) {
return { skipped: true, reason: 'missing_admin_key' };
}

const timeoutMs = Math.max(1000, Math.floor(Number(options.timeoutMs) || 30000));
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);

try {
const response = await fetchImpl(endpoint, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${adminKey}`,
},
body: JSON.stringify(options.body || {}),
signal: controller.signal,
});

const text = await response.text();
let payload = null;
try {
payload = text ? JSON.parse(text) : null;
} catch (error) {
payload = null;
}

if (payload && typeof payload === 'object' && Object.prototype.hasOwnProperty.call(payload, 'code')) {
if (Number(payload.code) === 0) {
return {
skipped: false,
endpoint,
payload: payload.data,
};
}
throw new Error(getRemoteAccountInjectErrorMessage(payload, response.status));
}

if (!response.ok) {
throw new Error(getRemoteAccountInjectErrorMessage(payload, response.status));
}

return {
skipped: false,
endpoint,
payload,
};
} catch (error) {
if (error?.name === 'AbortError') {
throw new Error('远程账号注入请求超时,请稍后重试。');
}
throw error;
} finally {
clearTimeout(timer);
}
}

return {
injectRemoteAccounts,
normalizeRemoteAccountInjectUrl,
};
}

return {
createRemoteAccountInjectApi,
normalizeRemoteAccountInjectUrl,
};
});
2 changes: 1 addition & 1 deletion core/flow-kernel/logging-status.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@

function isRestartCurrentAttemptError(error) {
const message = String(typeof error === 'string' ? error : error?.message || '');
return /当前邮箱已存在,需要重新开始新一轮|SIGNUP_PHONE_PASSWORD_MISMATCH::/i.test(message);
return /当前邮箱已存在,需要重新开始新一轮|SIGNUP_PHONE_PASSWORD_MISMATCH::|GROK_RESTART_CURRENT_ATTEMPT::/i.test(message);
}

function isSignupUserAlreadyExistsFailure(error) {
Expand Down
Loading