From 3a60560e277fd6369e392c1c97ec8b50e8b910b6 Mon Sep 17 00:00:00 2001 From: QLHazyCoder <2825305047@qq.com> Date: Sun, 24 May 2026 19:36:08 +0800 Subject: [PATCH] refactor shared flow settings and runtime cleanup --- background.js | 236 +----------------- background/auto-run-controller.js | 4 - background/logging-status.js | 4 +- background/message-router.js | 67 +---- core/flow-kernel/flow-registry.js | 14 ++ core/flow-kernel/logging-status.js | 4 +- core/flow-kernel/settings-schema.js | 114 ++++----- flows/grok/background/register-runner.js | 68 ++++- flows/grok/content/register-page.js | 27 +- flows/grok/index.js | 2 +- flows/kiro/index.js | 8 +- flows/openai/index.js | 50 +++- sidepanel/ip-proxy-panel.js | 2 +- sidepanel/sidepanel.css | 42 ++-- sidepanel/sidepanel.html | 99 ++++---- sidepanel/sidepanel.js | 211 ++++------------ tests/auto-run-add-phone-stop.test.js | 48 ++-- tests/auto-run-fresh-attempt-reset.test.js | 4 - tests/auto-run-hotmail-preflight.test.js | 6 +- tests/auto-run-kiro-flow-selection.test.js | 14 +- tests/auto-run-timer-session-guard.test.js | 117 +-------- ...ackground-account-history-settings.test.js | 1 - ...und-cloudflare-temp-email-settings.test.js | 2 - tests/background-contribution-mode.test.js | 19 +- tests/background-icloud.test.js | 3 - ...und-message-router-plus-final-step.test.js | 3 - ...ckground-message-router-step2-skip.test.js | 3 - tests/background-stop-gap-record.test.js | 2 - tests/flow-capabilities-module.test.js | 4 +- tests/flow-registry-settings-schema.test.js | 26 +- tests/grok-runner.test.js | 76 +++++- tests/run-count-unlimited.test.js | 10 +- ...sidepanel-auto-run-content-refresh.test.js | 6 - tests/sidepanel-contribution-mode.test.js | 3 - tests/sidepanel-flow-source-registry.test.js | 9 + tests/sidepanel-icloud-provider.test.js | 7 - tests/sidepanel-mail2925-base-email.test.js | 3 - tests/sidepanel-operation-delay.test.js | 22 +- ...epanel-phone-verification-settings.test.js | 4 - tests/step8-stop-cleanup.test.js | 4 - 40 files changed, 487 insertions(+), 861 deletions(-) diff --git a/background.js b/background.js index ce206b3..987cbaf 100644 --- a/background.js +++ b/background.js @@ -638,14 +638,11 @@ const IP_PROXY_TARGET_HOST_PATTERNS = [ ]; const AUTO_RUN_TIMER_ALARM_NAME = 'auto-run-timer'; const IP_PROXY_AUTO_SYNC_ALARM_NAME = 'ip-proxy-auto-sync'; -const AUTO_RUN_TIMER_KIND_SCHEDULED_START = 'scheduled_start'; const AUTO_RUN_TIMER_KIND_BETWEEN_ROUNDS = 'between_rounds'; const AUTO_RUN_TIMER_KIND_BEFORE_RETRY = 'before_retry'; const IP_PROXY_AUTO_SYNC_INTERVAL_MIN_MINUTES = 1; const IP_PROXY_AUTO_SYNC_INTERVAL_MAX_MINUTES = 1440; const IP_PROXY_AUTO_SYNC_DEFAULT_INTERVAL_MINUTES = 15; -const AUTO_RUN_DELAY_MIN_MINUTES = 1; -const AUTO_RUN_DELAY_MAX_MINUTES = 1440; const AUTO_RUN_RETRY_DELAY_MS = 3000; const AUTO_RUN_MAX_RETRIES_PER_ROUND = 3; const AUTO_STEP_DELAY_MIN_ALLOWED_SECONDS = 0; @@ -1354,9 +1351,7 @@ const PERSISTED_SETTING_DEFAULTS = { autoRunSkipFailures: false, autoRunFallbackThreadIntervalMinutes: 0, oauthFlowTimeoutEnabled: true, - autoRunDelayEnabled: false, operationDelayEnabled: true, - autoRunDelayMinutes: 30, autoStepDelaySeconds: null, step6CookieCleanupEnabled: false, stepExecutionRangeByFlow: {}, @@ -1530,7 +1525,6 @@ const DEFAULT_STATE = { autoRunAttemptRun: 0, // 当前轮次的重试序号。 autoRunSessionId: 0, autoRunRoundSummaries: [], // 自动运行轮次摘要。 - scheduledAutoRunAt: null, // 自动运行计划启动时间戳。 autoRunTimerPlan: null, // 自动运行可恢复计时计划快照。 autoRunCountdownAt: null, autoRunCountdownTitle: '', @@ -1560,17 +1554,6 @@ const DEFAULT_STATE = { ipProxyAppliedExitSource: '', }; -function normalizeAutoRunDelayMinutes(value) { - const numeric = Number(value); - if (!Number.isFinite(numeric)) { - return PERSISTED_SETTING_DEFAULTS.autoRunDelayMinutes; - } - return Math.min( - AUTO_RUN_DELAY_MAX_MINUTES, - Math.max(AUTO_RUN_DELAY_MIN_MINUTES, Math.floor(numeric)) - ); -} - function normalizeAutoRunFallbackThreadIntervalMinutes(value) { const rawValue = String(value ?? '').trim(); if (!rawValue) { @@ -1583,7 +1566,7 @@ function normalizeAutoRunFallbackThreadIntervalMinutes(value) { } return Math.min( - AUTO_RUN_DELAY_MAX_MINUTES, + 1440, Math.max(0, Math.floor(numeric)) ); } @@ -2009,7 +1992,6 @@ function isPhoneSignupIdentityStateForReuse(state = {}) { const runtimeActive = ( (typeof isAutoRunLockedState === 'function' && isAutoRunLockedState(state)) || (typeof isAutoRunPausedState === 'function' && isAutoRunPausedState(state)) - || (typeof isAutoRunScheduledState === 'function' && isAutoRunScheduledState(state)) || Boolean(state?.autoRunning) ); if (!runtimeActive) { @@ -2311,9 +2293,6 @@ function normalizeRunCount(value) { function normalizeAutoRunTimerKind(value = '') { const normalized = String(value || '').trim().toLowerCase(); - if (normalized === AUTO_RUN_TIMER_KIND_SCHEDULED_START) { - return AUTO_RUN_TIMER_KIND_SCHEDULED_START; - } if (normalized === AUTO_RUN_TIMER_KIND_BETWEEN_ROUNDS) { return AUTO_RUN_TIMER_KIND_BETWEEN_ROUNDS; } @@ -2393,22 +2372,6 @@ function normalizeAutoRunTimerPlan(plan) { const countdownTitle = String(plan.countdownTitle || '').trim(); const countdownNote = String(plan.countdownNote || '').trim(); - if (kind === AUTO_RUN_TIMER_KIND_SCHEDULED_START) { - return { - kind, - fireAt, - totalRuns, - autoRunSkipFailures, - mode, - currentRun: 0, - attemptRun: 0, - autoRunSessionId, - roundSummaries: [], - countdownTitle: countdownTitle || '已计划自动运行', - countdownNote: countdownNote || `计划于 ${formatAutoRunScheduleTime(fireAt)} 开始`, - }; - } - if (kind === AUTO_RUN_TIMER_KIND_BETWEEN_ROUNDS) { const normalizedCurrentRun = Math.max(1, Math.min(totalRuns, currentRun)); const normalizedAttemptRun = Math.max(1, attemptRun); @@ -2449,28 +2412,11 @@ function normalizeAutoRunTimerPlanFromState(state = {}) { if (directPlan) { return directPlan; } - - if (state.autoRunPhase !== 'scheduled') { - return null; - } - - const legacyScheduledAt = Number(state.scheduledAutoRunAt); - if (!Number.isFinite(legacyScheduledAt)) { - return null; - } - - return normalizeAutoRunTimerPlan({ - kind: AUTO_RUN_TIMER_KIND_SCHEDULED_START, - fireAt: legacyScheduledAt, - totalRuns: state.scheduledAutoRunPlan?.totalRuns ?? state.autoRunTotalRuns, - autoRunSkipFailures: state.scheduledAutoRunPlan?.autoRunSkipFailures ?? state.autoRunSkipFailures, - autoRunSessionId: state.autoRunSessionId, - mode: state.scheduledAutoRunPlan?.mode, - }); + return null; } function getAutoRunTimerPlanPhase(kind = '') { - return kind === AUTO_RUN_TIMER_KIND_SCHEDULED_START ? 'scheduled' : 'waiting_interval'; + return 'waiting_interval'; } function getAutoRunTimerStatusPayload(plan) { @@ -2486,7 +2432,6 @@ function getAutoRunTimerStatusPayload(plan) { totalRuns: normalizedPlan.totalRuns, attemptRun: normalizedPlan.attemptRun, sessionId: normalizedPlan.autoRunSessionId, - scheduledAt: phase === 'scheduled' ? normalizedPlan.fireAt : null, countdownAt: normalizedPlan.fireAt, countdownTitle: normalizedPlan.countdownTitle, countdownNote: normalizedPlan.countdownNote, @@ -3387,7 +3332,6 @@ function normalizePersistentSettingValue(key, value) { case 'oauthFlowTimeoutEnabled': case 'gopayHelperLocalSmsHelperEnabled': case 'gopayHelperAutoModeEnabled': - case 'autoRunDelayEnabled': return Boolean(value); case 'operationDelayEnabled': return true; @@ -3408,8 +3352,6 @@ function normalizePersistentSettingValue(key, value) { return normalizePhoneSmsProviderOrder(value); case 'autoRunFallbackThreadIntervalMinutes': return normalizeAutoRunFallbackThreadIntervalMinutes(value); - case 'autoRunDelayMinutes': - return normalizeAutoRunDelayMinutes(value); case 'autoStepDelaySeconds': return normalizeAutoStepDelaySeconds(value, PERSISTED_SETTING_DEFAULTS.autoStepDelaySeconds); case 'verificationResendCount': @@ -10090,8 +10032,7 @@ function getAutoRunStatusPayload(phase, payload = {}) { return loggingStatus.getAutoRunStatusPayload(phase, normalizedPayload); } return { - autoRunning: phase === 'scheduled' - || phase === 'running' + autoRunning: phase === 'running' || phase === 'waiting_step' || phase === 'waiting_email' || phase === 'retrying' @@ -10101,7 +10042,6 @@ function getAutoRunStatusPayload(phase, payload = {}) { autoRunTotalRuns: normalizedPayload.totalRuns ?? 1, autoRunAttemptRun: normalizedPayload.attemptRun ?? 0, autoRunSessionId: normalizeAutoRunSessionId(normalizedPayload.sessionId), - scheduledAutoRunAt: Number.isFinite(Number(normalizedPayload.scheduledAt)) ? Number(normalizedPayload.scheduledAt) : null, autoRunCountdownAt: Number.isFinite(Number(normalizedPayload.countdownAt)) ? Number(normalizedPayload.countdownAt) : null, autoRunCountdownTitle: normalizedPayload.countdownTitle === undefined ? '' : String(normalizedPayload.countdownTitle || ''), autoRunCountdownNote: normalizedPayload.countdownNote === undefined ? '' : String(normalizedPayload.countdownNote || ''), @@ -10109,9 +10049,6 @@ function getAutoRunStatusPayload(phase, payload = {}) { } async function broadcastAutoRunStatus(phase, payload = {}, extraState = {}) { - const rawScheduledAt = phase === 'scheduled' - ? (payload.scheduledAt ?? payload.scheduledAutoRunAt ?? null) - : null; const rawCountdownAt = payload.countdownAt ?? payload.autoRunCountdownAt ?? null; const statusPayload = { phase, @@ -10119,7 +10056,6 @@ async function broadcastAutoRunStatus(phase, payload = {}, extraState = {}) { totalRuns: payload.totalRuns ?? autoRunTotalRuns, attemptRun: payload.attemptRun ?? autoRunAttemptRun, sessionId: payload.sessionId ?? payload.autoRunSessionId ?? autoRunSessionId, - scheduledAt: rawScheduledAt === null ? null : Number(rawScheduledAt), countdownAt: rawCountdownAt === null ? null : Number(rawCountdownAt), countdownTitle: payload.countdownTitle === undefined ? '' : String(payload.countdownTitle || ''), countdownNote: payload.countdownNote === undefined ? '' : String(payload.countdownNote || ''), @@ -10149,38 +10085,10 @@ function isAutoRunPausedState(state) { return Boolean(state.autoRunning) && state.autoRunPhase === 'waiting_email'; } -function isAutoRunScheduledState(state) { - const plan = normalizeAutoRunTimerPlanFromState(state); - const scheduledAt = state.scheduledAutoRunAt === null ? null : Number(state.scheduledAutoRunAt); - return Boolean(state.autoRunning) - && state.autoRunPhase === 'scheduled' - && Number.isFinite(scheduledAt) - && plan?.kind === AUTO_RUN_TIMER_KIND_SCHEDULED_START; -} - function getPendingAutoRunTimerPlan(state = {}) { return normalizeAutoRunTimerPlanFromState(state); } -function formatAutoRunScheduleTime(timestamp) { - return new Date(timestamp).toLocaleString('zh-CN', { - hour12: false, - timeZone: DISPLAY_TIMEZONE, - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - }); -} - -async function setAutoRunDelayEnabledState(enabled) { - const normalized = Boolean(enabled); - await setPersistentSettings({ autoRunDelayEnabled: normalized }); - await setState({ autoRunDelayEnabled: normalized }); - broadcastDataUpdate({ autoRunDelayEnabled: normalized }); -} - async function ensureAutoRunTimerAlarm(fireAt) { if (!Number.isFinite(fireAt) || fireAt <= Date.now()) { return false; @@ -10212,7 +10120,6 @@ async function persistAutoRunTimerPlan(plan, extraState = {}) { { ...extraState, autoRunTimerPlan: normalizedPlan, - scheduledAutoRunPlan: null, } ); await ensureAutoRunTimerAlarm(normalizedPlan.fireAt); @@ -10225,22 +10132,6 @@ function getAutoRunTimerResumeOptions(plan) { return null; } - if (normalizedPlan.kind === AUTO_RUN_TIMER_KIND_SCHEDULED_START) { - return { - loopOptions: { - autoRunSessionId: normalizedPlan.autoRunSessionId, - autoRunSkipFailures: normalizedPlan.autoRunSkipFailures, - mode: normalizedPlan.mode, - }, - statusPayload: { - currentRun: 0, - totalRuns: normalizedPlan.totalRuns, - attemptRun: 0, - sessionId: normalizedPlan.autoRunSessionId, - }, - }; - } - if (normalizedPlan.kind === AUTO_RUN_TIMER_KIND_BETWEEN_ROUNDS) { const nextRun = Math.min(normalizedPlan.currentRun + 1, normalizedPlan.totalRuns); return { @@ -10314,35 +10205,10 @@ async function launchAutoRunTimerPlan(trigger = 'alarm', options = {}) { }, { autoRunRoundSummaries: [], autoRunTimerPlan: null, - scheduledAutoRunPlan: null, }); 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; @@ -10351,9 +10217,6 @@ async function launchAutoRunTimerPlan(trigger = 'alarm', options = {}) { autoRunTotalRuns = plan.totalRuns; autoRunAttemptRun = resumeOptions.statusPayload.attemptRun; autoRunSessionId = normalizeAutoRunSessionId(plan.autoRunSessionId); - if (plan.kind === AUTO_RUN_TIMER_KIND_SCHEDULED_START && trigger !== 'manual' && state.autoRunDelayEnabled) { - await setAutoRunDelayEnabledState(false); - } await broadcastAutoRunStatus( 'running', resumeOptions.statusPayload, @@ -10361,7 +10224,6 @@ async function launchAutoRunTimerPlan(trigger = 'alarm', options = {}) { autoRunSkipFailures: plan.autoRunSkipFailures, autoRunRoundSummaries: serializeAutoRunRoundSummaries(plan.totalRuns, plan.roundSummaries), autoRunTimerPlan: null, - scheduledAutoRunPlan: null, } ); @@ -10393,81 +10255,12 @@ async function launchAutoRunTimerPlan(trigger = 'alarm', options = {}) { } } -async function scheduleAutoRun(totalRuns, options = {}) { - const state = await getState(); - if (isAutoRunLockedState(state) || isAutoRunPausedState(state) || autoRunActive) { - throw new Error('自动运行已在进行中,请先停止后再重新计划。'); - } - if (getPendingAutoRunTimerPlan(state)) { - throw new Error('已有自动运行倒计时计划,请先取消或立即开始。'); - } - - const delayMinutes = normalizeAutoRunDelayMinutes(options.delayMinutes); - const sessionId = createAutoRunSessionId(); - const timerPlan = normalizeAutoRunTimerPlan({ - kind: AUTO_RUN_TIMER_KIND_SCHEDULED_START, - fireAt: Date.now() + delayMinutes * 60 * 1000, - totalRuns, - autoRunSkipFailures: options.autoRunSkipFailures, - autoRunSessionId: sessionId, - mode: options.mode, - }); - - autoRunCurrentRun = 0; - autoRunTotalRuns = timerPlan.totalRuns; - autoRunAttemptRun = 0; - autoRunSessionId = sessionId; - - await persistAutoRunTimerPlan(timerPlan, { - autoRunSkipFailures: timerPlan.autoRunSkipFailures, - autoRunRoundSummaries: serializeAutoRunRoundSummaries(timerPlan.totalRuns, []), - }); - await addLog( - `自动运行已计划:${delayMinutes} 分钟后启动(${formatAutoRunScheduleTime(timerPlan.fireAt)}),目标 ${timerPlan.totalRuns} 轮。`, - 'info' - ); - return { ok: true, scheduledAt: timerPlan.fireAt }; -} - -async function cancelScheduledAutoRun(options = {}) { - const state = await getState(); - const plan = getPendingAutoRunTimerPlan(state); - if (!plan || plan.kind !== AUTO_RUN_TIMER_KIND_SCHEDULED_START) { - return false; - } - - autoRunCurrentRun = 0; - autoRunTotalRuns = plan.totalRuns; - autoRunAttemptRun = 0; - clearCurrentAutoRunSessionId(plan.autoRunSessionId); - await broadcastAutoRunStatus( - 'idle', - { - currentRun: 0, - totalRuns: plan.totalRuns, - attemptRun: 0, - sessionId: 0, - }, - { - autoRunSessionId: 0, - autoRunRoundSummaries: [], - autoRunTimerPlan: null, - scheduledAutoRunPlan: null, - } - ); - await clearAutoRunTimerAlarm(); - if (options.logMessage !== false) { - await addLog(options.logMessage || '已取消自动运行倒计时计划。', 'warn'); - } - return true; -} - async function restoreAutoRunTimerIfNeeded() { const state = await getState(); let plan = getPendingAutoRunTimerPlan(state); if (!plan) { clearCurrentAutoRunSessionId(); - if (state.autoRunPhase === 'scheduled' || state.autoRunPhase === 'waiting_interval') { + if (state.autoRunPhase === 'waiting_interval') { await clearAutoRunTimerAlarm(); await broadcastAutoRunStatus('idle', { currentRun: 0, @@ -10478,7 +10271,6 @@ async function restoreAutoRunTimerIfNeeded() { autoRunSessionId: 0, autoRunRoundSummaries: [], autoRunTimerPlan: null, - scheduledAutoRunPlan: null, }); } return; @@ -10511,7 +10303,6 @@ async function restoreAutoRunTimerIfNeeded() { autoRunSkipFailures: plan.autoRunSkipFailures, autoRunRoundSummaries: serializeAutoRunRoundSummaries(plan.totalRuns, plan.roundSummaries), autoRunTimerPlan: plan, - scheduledAutoRunPlan: null, } ); await ensureAutoRunTimerAlarm(plan.fireAt); @@ -10526,9 +10317,6 @@ async function ensureManualInteractionAllowed(actionLabel) { if (isAutoRunPausedState(state)) { throw new Error(`自动流程当前已暂停。请点击“继续”,或先确认接管自动流程后再${actionLabel}。`); } - if (isAutoRunScheduledState(state)) { - throw new Error(`自动流程已计划启动。请先取消计划,或立即开始后再${actionLabel}。`); - } return state; } @@ -11495,15 +11283,6 @@ async function requestStop(options = {}) { const inferredStopNode = inferStoppedRecordNode(state); const timerPlan = getPendingAutoRunTimerPlan(state); - if (timerPlan?.kind === AUTO_RUN_TIMER_KIND_SCHEDULED_START && !autoRunActive) { - await cancelScheduledAutoRun({ - logMessage: options.logMessage === false - ? false - : (options.logMessage || '已取消自动运行倒计时计划。'), - }); - return; - } - if (timerPlan && !autoRunActive) { autoRunCurrentRun = timerPlan.currentRun; autoRunTotalRuns = timerPlan.totalRuns; @@ -11522,7 +11301,6 @@ async function requestStop(options = {}) { autoRunSkipFailures: timerPlan.autoRunSkipFailures, autoRunRoundSummaries: serializeAutoRunRoundSummaries(timerPlan.totalRuns, timerPlan.roundSummaries), autoRunTimerPlan: null, - scheduledAutoRunPlan: null, }); await clearAutoRunTimerAlarm(); clearStopRequest(); @@ -11582,7 +11360,6 @@ async function requestStop(options = {}) { }, { autoRunSessionId: 0, autoRunTimerPlan: null, - scheduledAutoRunPlan: null, }); } @@ -14153,7 +13930,6 @@ const messageRouter = self.MultiPageBackgroundMessageRouter?.createMessageRouter buildPersistentSettingsPayload, broadcastDataUpdate, applyIpProxySettingsFromState, - cancelScheduledAutoRun, checkIcloudSession, clearAccountRunHistory: (...args) => clearAndBroadcastAccountRunHistory(...args), deleteAccountRunHistoryRecords: (...args) => deleteAndBroadcastAccountRunHistoryRecords(...args), @@ -14260,7 +14036,6 @@ const messageRouter = self.MultiPageBackgroundMessageRouter?.createMessageRouter normalizeMail2925Accounts, normalizePayPalAccounts, normalizeRunCount, - AUTO_RUN_TIMER_KIND_SCHEDULED_START, notifyNodeComplete, notifyNodeError, patchHotmailAccount, @@ -14270,7 +14045,6 @@ const messageRouter = self.MultiPageBackgroundMessageRouter?.createMessageRouter probeIpProxyExit, resetState, resumeAutoRun, - scheduleAutoRun, selectLuckmailPurchase, switchIpProxy, changeIpProxyExit, diff --git a/background/auto-run-controller.js b/background/auto-run-controller.js index 82f0ed8..3fb405c 100644 --- a/background/auto-run-controller.js +++ b/background/auto-run-controller.js @@ -158,8 +158,6 @@ kiroRsKey: state.kiroRsKey, autoRunSkipFailures: state.autoRunSkipFailures, autoRunFallbackThreadIntervalMinutes: state.autoRunFallbackThreadIntervalMinutes, - autoRunDelayEnabled: state.autoRunDelayEnabled, - autoRunDelayMinutes: state.autoRunDelayMinutes, autoStepDelaySeconds: state.autoStepDelaySeconds, stepExecutionRangeByFlow: state.stepExecutionRangeByFlow, signupMethod: state.signupMethod, @@ -502,7 +500,6 @@ }, { autoRunSessionId: 0, autoRunTimerPlan: null, - scheduledAutoRunPlan: null, }); clearStopRequest(); } @@ -1159,7 +1156,6 @@ autoRunSessionId: 0, autoRunRoundSummaries: serializeAutoRunRoundSummaries(totalRuns, roundSummaries), autoRunTimerPlan: null, - scheduledAutoRunPlan: null, ...getAutoRunStatusPayload(deps.getStopRequested() || stoppedEarly ? 'stopped' : 'complete', { currentRun: deps.getStopRequested() || stoppedEarly ? afterRuntime.autoRunCurrentRun : afterRuntime.autoRunTotalRuns, totalRuns: afterRuntime.autoRunTotalRuns, diff --git a/background/logging-status.js b/background/logging-status.js index 64bd29f..b3de763 100644 --- a/background/logging-status.js +++ b/background/logging-status.js @@ -209,8 +209,7 @@ function getAutoRunStatusPayload(phase, payload = {}) { return { - autoRunning: phase === 'scheduled' - || phase === 'running' + autoRunning: phase === 'running' || phase === 'waiting_step' || phase === 'waiting_email' || phase === 'retrying' @@ -220,7 +219,6 @@ autoRunTotalRuns: payload.totalRuns ?? 1, autoRunAttemptRun: payload.attemptRun ?? 0, autoRunSessionId: Math.max(0, Math.floor(Number(payload.sessionId ?? payload.autoRunSessionId) || 0)), - scheduledAutoRunAt: Number.isFinite(Number(payload.scheduledAt)) ? Number(payload.scheduledAt) : null, autoRunCountdownAt: Number.isFinite(Number(payload.countdownAt)) ? Number(payload.countdownAt) : null, autoRunCountdownTitle: payload.countdownTitle === undefined ? '' : String(payload.countdownTitle || ''), autoRunCountdownNote: payload.countdownNote === undefined ? '' : String(payload.countdownNote || ''), diff --git a/background/message-router.js b/background/message-router.js index 242ea50..8a9adbe 100644 --- a/background/message-router.js +++ b/background/message-router.js @@ -11,7 +11,6 @@ buildPersistentSettingsPayload, broadcastDataUpdate, applyIpProxySettingsFromState, - cancelScheduledAutoRun, checkIcloudSession, clearAccountRunHistory, deleteAccountRunHistoryRecords, @@ -145,7 +144,6 @@ normalizeMail2925Accounts, normalizePayPalAccounts, normalizeRunCount, - AUTO_RUN_TIMER_KIND_SCHEDULED_START, notifyNodeComplete, notifyNodeError, patchMail2925Account, @@ -158,7 +156,6 @@ handleCloudflareSecurityBlocked, resetState, resumeAutoRun, - scheduleAutoRun, selectLuckmailPurchase, switchIpProxy, changeIpProxyExit, @@ -1324,7 +1321,7 @@ throw new Error(autoRunStartValidation.errors?.[0]?.message || '当前设置不支持启动自动流程。'); } if (getPendingAutoRunTimerPlan(state)) { - throw new Error('已有自动运行倒计时计划,请先取消或立即开始。'); + throw new Error('已有线程间隔等待,请先停止或立即继续。'); } const totalRuns = normalizeRunCount(message.payload?.totalRuns || 1); const autoRunSkipFailures = Boolean(message.payload?.autoRunSkipFailures); @@ -1334,68 +1331,6 @@ return { ok: true }; } - case 'SCHEDULE_AUTO_RUN': { - clearStopRequest(); - if (message.source === 'sidepanel') { - await lockAutomationWindowFromMessage(message, sender); - } - if (Boolean(message.payload?.accountContributionEnabled) && typeof setAccountContributionMode === 'function') { - await setAccountContributionMode(true, { - adapterId: message.payload?.contributionAdapterId, - flowId: message.payload?.activeFlowId || message.payload?.flowId, - }); - if (typeof setState === 'function') { - const contributionNickname = String(message.payload?.contributionNickname || '').trim(); - const contributionQq = String(message.payload?.contributionQq || '').trim(); - await setState({ - contributionNickname, - contributionQq, - }); - } - } - const autoRunFlowStateUpdates = buildAutoRunFlowStateUpdates(message.payload || {}); - if (Object.keys(autoRunFlowStateUpdates).length > 0 && typeof setState === 'function') { - await setState(autoRunFlowStateUpdates); - } - const state = await getState(); - const autoRunStartValidation = validateAutoRunStart(state, { - activeFlowId: autoRunFlowStateUpdates.activeFlowId ?? state?.activeFlowId, - targetId: autoRunFlowStateUpdates.targetId ?? state?.targetId, - state, - }); - if (autoRunStartValidation?.ok === false) { - throw new Error(autoRunStartValidation.errors?.[0]?.message || '当前设置不支持启动自动流程。'); - } - const totalRuns = normalizeRunCount(message.payload?.totalRuns || 1); - return await scheduleAutoRun(totalRuns, { - delayMinutes: message.payload?.delayMinutes, - autoRunSkipFailures: Boolean(message.payload?.autoRunSkipFailures), - mode: message.payload?.mode, - }); - } - - case 'START_SCHEDULED_AUTO_RUN_NOW': { - clearStopRequest(); - if (message.source === 'sidepanel') { - await lockAutomationWindowFromMessage(message, sender); - } - const started = await launchAutoRunTimerPlan('manual', { - expectedKinds: [AUTO_RUN_TIMER_KIND_SCHEDULED_START], - }); - if (!started) { - throw new Error('当前没有可立即开始的倒计时计划。'); - } - return { ok: true }; - } - - case 'CANCEL_SCHEDULED_AUTO_RUN': { - const cancelled = await cancelScheduledAutoRun(); - if (!cancelled) { - throw new Error('当前没有可取消的倒计时计划。'); - } - return { ok: true }; - } - case 'SKIP_AUTO_RUN_COUNTDOWN': { clearStopRequest(); if (message.source === 'sidepanel') { diff --git a/core/flow-kernel/flow-registry.js b/core/flow-kernel/flow-registry.js index eff14fe..4ad595f 100644 --- a/core/flow-kernel/flow-registry.js +++ b/core/flow-kernel/flow-registry.js @@ -49,6 +49,20 @@ label: 'IP \u4ee3\u7406', sectionIds: ['ip-proxy-section'], }, + 'shared-auto-run': { + id: 'shared-auto-run', + label: '\u81ea\u52a8\u8fd0\u884c', + rowIds: [ + 'row-shared-auto-run', + 'row-auto-run-thread-interval', + 'row-step-execution-range', + ], + }, + 'shared-settings-actions': { + id: 'shared-settings-actions', + label: '\u8bbe\u7f6e\u64cd\u4f5c', + rowIds: ['row-settings-actions'], + }, }); function buildFlowDefinitions() { diff --git a/core/flow-kernel/logging-status.js b/core/flow-kernel/logging-status.js index 64bd29f..b3de763 100644 --- a/core/flow-kernel/logging-status.js +++ b/core/flow-kernel/logging-status.js @@ -209,8 +209,7 @@ function getAutoRunStatusPayload(phase, payload = {}) { return { - autoRunning: phase === 'scheduled' - || phase === 'running' + autoRunning: phase === 'running' || phase === 'waiting_step' || phase === 'waiting_email' || phase === 'retrying' @@ -220,7 +219,6 @@ autoRunTotalRuns: payload.totalRuns ?? 1, autoRunAttemptRun: payload.attemptRun ?? 0, autoRunSessionId: Math.max(0, Math.floor(Number(payload.sessionId ?? payload.autoRunSessionId) || 0)), - scheduledAutoRunAt: Number.isFinite(Number(payload.scheduledAt)) ? Number(payload.scheduledAt) : null, autoRunCountdownAt: Number.isFinite(Number(payload.countdownAt)) ? Number(payload.countdownAt) : null, autoRunCountdownTitle: payload.countdownTitle === undefined ? '' : String(payload.countdownTitle || ''), autoRunCountdownNote: payload.countdownNote === undefined ? '' : String(payload.countdownNote || ''), diff --git a/core/flow-kernel/settings-schema.js b/core/flow-kernel/settings-schema.js index d5a41fd..0f2cd70 100644 --- a/core/flow-kernel/settings-schema.js +++ b/core/flow-kernel/settings-schema.js @@ -115,48 +115,11 @@ if (isPlainObject(range)) { return normalizeStepExecutionRangeEntry(range, { enabled: false, fromStep: 1, toStep: 1 }); } - if (flowId === 'openai') { - return { enabled: false, fromStep: 1, toStep: 11 }; - } - if (flowId === 'kiro') { - return { enabled: false, fromStep: 1, toStep: 9 }; - } const lastStep = Math.max(1, Number(getFlowDefinition(flowId)?.workflowStepCount) || 1); return { enabled: false, fromStep: 1, toStep: lastStep }; } function buildDefaultTargetState(flowId, targetId) { - if (flowId === 'openai' && targetId === 'cpa') { - return { - vpsUrl: '', - vpsPassword: '', - localCpaStep9Mode: 'submit', - }; - } - if (flowId === 'openai' && targetId === 'sub2api') { - return { - sub2apiUrl: '', - sub2apiEmail: '', - sub2apiPassword: '', - sub2apiGroupName: 'codex', - sub2apiGroupNames: ['codex', 'openai-plus'], - sub2apiAccountPriority: 1, - sub2apiDefaultProxyName: '', - }; - } - if (flowId === 'openai' && targetId === 'codex2api') { - return { - codex2apiUrl: '', - codex2apiAdminKey: '', - }; - } - if (flowId === 'kiro' && targetId === 'kiro-rs') { - return { - baseUrl: defaultKiroRsUrl, - apiKey: '', - }; - } - const definition = getFlowDefinition(flowId) || {}; const flowDefaults = getFlowSettingsDefaults(flowId); const targetDefaults = isPlainObject(flowDefaults?.targets?.[targetId]) @@ -200,24 +163,7 @@ stepExecutionRange: getDefaultStepExecutionRange(flowId), }, }; - if (flowId === 'openai') { - return mergePlainObjects(base, { - signup: { - signupMethod: 'email', - phoneVerificationEnabled: false, - phoneSignupReloginAfterBindEmailEnabled: false, - }, - plus: { - plusModeEnabled: false, - plusPaymentMethod: 'paypal-hosted', - plusAccountAccessStrategy: 'oauth', - hostedCheckoutVerificationUrl: '', - hostedCheckoutPhoneNumber: '', - plusHostedCheckoutOauthDelaySeconds: 3, - }, - }); - } - return base; + return mergePlainObjects(base, getFlowSettingsDefaults(flowId)); } function buildDefaultFlows() { @@ -364,6 +310,18 @@ } function normalizeOpenAiSettings(input = {}, nested = {}, defaults = {}, currentFlow = {}) { + const defaultOpenAiFlow = isPlainObject(defaults?.flows?.openai) + ? defaults.flows.openai + : {}; + const defaultOpenAiTargets = isPlainObject(defaultOpenAiFlow.targets) + ? defaultOpenAiFlow.targets + : {}; + const defaultOpenAiSignup = isPlainObject(defaultOpenAiFlow.signup) + ? defaultOpenAiFlow.signup + : {}; + const defaultOpenAiPlus = isPlainObject(defaultOpenAiFlow.plus) + ? defaultOpenAiFlow.plus + : {}; const cpaSource = { ...currentFlow.targets.cpa, ...getTargetValue( @@ -407,66 +365,82 @@ ...currentFlow, targets: { ...currentFlow.targets, - cpa: normalizeFlowTargetState('openai', 'cpa', cpaSource, defaults.flows.openai.targets.cpa), - sub2api: normalizeFlowTargetState('openai', 'sub2api', sub2apiSource, defaults.flows.openai.targets.sub2api), - codex2api: normalizeFlowTargetState('openai', 'codex2api', codex2apiSource, defaults.flows.openai.targets.codex2api), + cpa: normalizeFlowTargetState('openai', 'cpa', cpaSource, defaultOpenAiTargets.cpa || {}), + sub2api: normalizeFlowTargetState('openai', 'sub2api', sub2apiSource, defaultOpenAiTargets.sub2api || {}), + codex2api: normalizeFlowTargetState('openai', 'codex2api', codex2apiSource, defaultOpenAiTargets.codex2api || {}), }, signup: { signupMethod: String( input?.signupMethod ?? currentFlow.signup?.signupMethod - ?? defaults.flows.openai.signup.signupMethod + ?? defaultOpenAiSignup.signupMethod + ?? 'email' ).trim().toLowerCase() === 'phone' ? 'phone' : 'email', phoneVerificationEnabled: Boolean( input?.phoneVerificationEnabled ?? currentFlow.signup?.phoneVerificationEnabled - ?? defaults.flows.openai.signup.phoneVerificationEnabled + ?? defaultOpenAiSignup.phoneVerificationEnabled + ?? false ), phoneSignupReloginAfterBindEmailEnabled: Boolean( input?.phoneSignupReloginAfterBindEmailEnabled ?? currentFlow.signup?.phoneSignupReloginAfterBindEmailEnabled - ?? defaults.flows.openai.signup.phoneSignupReloginAfterBindEmailEnabled + ?? defaultOpenAiSignup.phoneSignupReloginAfterBindEmailEnabled + ?? false ), }, plus: { plusModeEnabled: Boolean( input?.plusModeEnabled ?? currentFlow.plus?.plusModeEnabled - ?? defaults.flows.openai.plus.plusModeEnabled + ?? defaultOpenAiPlus.plusModeEnabled + ?? false ), plusPaymentMethod: String( input?.plusPaymentMethod ?? currentFlow.plus?.plusPaymentMethod - ?? defaults.flows.openai.plus.plusPaymentMethod - ).trim() || defaults.flows.openai.plus.plusPaymentMethod, + ?? defaultOpenAiPlus.plusPaymentMethod + ?? 'paypal-hosted' + ).trim() || defaultOpenAiPlus.plusPaymentMethod || 'paypal-hosted', plusAccountAccessStrategy: normalizePlusAccountAccessStrategy( input?.plusAccountAccessStrategy ?? currentFlow.plus?.plusAccountAccessStrategy - ?? defaults.flows.openai.plus.plusAccountAccessStrategy + ?? defaultOpenAiPlus.plusAccountAccessStrategy + ?? 'oauth' ), hostedCheckoutVerificationUrl: String( input?.hostedCheckoutVerificationUrl ?? currentFlow.plus?.hostedCheckoutVerificationUrl - ?? defaults.flows.openai.plus.hostedCheckoutVerificationUrl + ?? defaultOpenAiPlus.hostedCheckoutVerificationUrl + ?? '' ).trim(), hostedCheckoutPhoneNumber: String( input?.hostedCheckoutPhoneNumber ?? currentFlow.plus?.hostedCheckoutPhoneNumber - ?? defaults.flows.openai.plus.hostedCheckoutPhoneNumber + ?? defaultOpenAiPlus.hostedCheckoutPhoneNumber + ?? '' ).trim(), plusHostedCheckoutOauthDelaySeconds: (() => { const numeric = Number( input?.plusHostedCheckoutOauthDelaySeconds ?? currentFlow.plus?.plusHostedCheckoutOauthDelaySeconds - ?? defaults.flows.openai.plus.plusHostedCheckoutOauthDelaySeconds + ?? defaultOpenAiPlus.plusHostedCheckoutOauthDelaySeconds + ?? 3 ); - return Math.min(120, Math.max(0, Math.floor(Number.isFinite(numeric) ? numeric : defaults.flows.openai.plus.plusHostedCheckoutOauthDelaySeconds))); + const fallback = Number(defaultOpenAiPlus.plusHostedCheckoutOauthDelaySeconds ?? 3) || 3; + return Math.min(120, Math.max(0, Math.floor(Number.isFinite(numeric) ? numeric : fallback))); })(), }, }; } function normalizeKiroSettings(input = {}, defaults = {}, currentFlow = {}) { + const defaultKiroFlow = isPlainObject(defaults?.flows?.kiro) + ? defaults.flows.kiro + : {}; + const defaultKiroTargets = isPlainObject(defaultKiroFlow.targets) + ? defaultKiroFlow.targets + : {}; const targetSource = { ...currentFlow.targets['kiro-rs'], baseUrl: input?.kiroRsUrl ?? input?.kiroRsBaseUrl ?? currentFlow.targets['kiro-rs'].baseUrl, @@ -476,7 +450,7 @@ ...currentFlow, targets: { ...currentFlow.targets, - 'kiro-rs': normalizeFlowTargetState('kiro', 'kiro-rs', targetSource, defaults.flows.kiro.targets['kiro-rs']), + 'kiro-rs': normalizeFlowTargetState('kiro', 'kiro-rs', targetSource, defaultKiroTargets['kiro-rs'] || {}), }, }; } diff --git a/flows/grok/background/register-runner.js b/flows/grok/background/register-runner.js index bfcdc81..d8f3014 100644 --- a/flows/grok/background/register-runner.js +++ b/flows/grok/background/register-runner.js @@ -4,6 +4,8 @@ const GROK_SIGNUP_URL = 'https://accounts.x.ai/sign-up?redirect=grok-com'; const GROK_REGISTER_PAGE_SOURCE_ID = 'grok-register-page'; const DEFAULT_GROK_PAGE_TIMEOUT_MS = 90 * 1000; + const GROK_VERIFICATION_PAGE_STATE = 'verification_code_entry'; + const GROK_VERIFICATION_READY_TIMEOUT_MS = 90 * 1000; const GROK_POST_PROFILE_CF_WAIT_MS = 20 * 1000; const GROK_PRE_SSO_EXTRACT_WAIT_MS = 10 * 1000; const MAIL_2925_FILTER_LOOKBACK_MS = 10 * 60 * 1000; @@ -191,6 +193,50 @@ return result || {}; } + async function getGrokRegisterPageState(options = {}) { + return sendGrokCommand('GET_PAGE_STATE', {}, { + step: options.step || 0, + timeoutMs: options.timeoutMs || 15000, + logMessage: options.logMessage || '', + }); + } + + async function waitForGrokVerificationPageReady(tabId, options = {}) { + const timeoutMs = Math.max(1000, Number(options.timeoutMs) || GROK_VERIFICATION_READY_TIMEOUT_MS); + const intervalMs = Math.max(250, Number(options.intervalMs) || 1000); + const deadline = Date.now() + timeoutMs; + let lastState = null; + let lastError = ''; + + while (Date.now() <= deadline) { + throwIfStopped(); + try { + await ensureContentReady(tabId, { + timeoutMs: Math.min(DEFAULT_GROK_PAGE_TIMEOUT_MS, Math.max(5000, intervalMs + 3000)), + stableMs: 500, + initialDelayMs: 0, + logMessage: options.logMessage || '', + }); + lastState = await getGrokRegisterPageState({ + step: options.step || 0, + timeoutMs: Math.max(5000, intervalMs + 3000), + }); + lastError = ''; + if (lastState?.state === GROK_VERIFICATION_PAGE_STATE) { + return lastState; + } + } catch (error) { + lastError = getErrorMessage(error); + } + await sleepWithStop(Math.min(intervalMs, Math.max(0, deadline - Date.now()))); + } + + const stateLabel = cleanString(lastState?.state) || 'unknown'; + const urlLabel = cleanString(lastState?.url); + const errorLabel = lastError ? `,最后通信错误:${lastError}` : ''; + throw new Error(`Grok 邮箱提交后尚未进入验证码页面,当前状态:${stateLabel}${urlLabel ? `,URL:${urlLabel}` : ''}${errorLabel}。`); + } + function shouldClearGrokCookie(cookie = {}) { const domain = cleanString(cookie.domain).replace(/^\.+/, '').toLowerCase(); return GROK_COOKIE_CLEAR_DOMAINS.some((target) => ( @@ -395,8 +441,12 @@ }); const result = await sendGrokCommand(nodeId, { email }, { step: 2, + timeoutMs: GROK_VERIFICATION_READY_TIMEOUT_MS + 15000, logMessage: '步骤 2:正在提交 Grok 注册邮箱...', }); + if (result.state !== GROK_VERIFICATION_PAGE_STATE) { + throw new Error(`Grok 邮箱提交后尚未进入验证码页面,当前状态:${cleanString(result.state) || 'unknown'}${cleanString(result.url) ? `,URL:${cleanString(result.url)}` : ''}。`); + } await log(`步骤 2:已提交 Grok 注册邮箱 ${email}。`, 'ok', nodeId); await completeNode(nodeId, { grokEmail: email, @@ -456,6 +506,23 @@ || currentState.runtimeState?.flowState?.grok?.register?.email || currentState.email ).toLowerCase(); + const tabId = await ensureGrokRegisterTab(currentState, { openIfMissing: false }); + await activateTab(tabId); + const readyState = await waitForGrokVerificationPageReady(tabId, { + step: 3, + logMessage: '步骤 3:正在等待 Grok 验证码页面就绪...', + }); + await persistState({ + grokPageState: readyState.state || '', + grokPageUrl: readyState.url || '', + ...buildGrokRuntimePatch({ + session: { + pageState: readyState.state || '', + pageUrl: readyState.url || '', + lastError: '', + }, + }), + }); const pollResult = await pollFlowVerificationCode({ actionLabel: 'Grok 验证码', filterAfterTimestamp, @@ -478,7 +545,6 @@ if (!code) { throw new Error('未能获取到 xAI 邮箱验证码。'); } - const tabId = await ensureGrokRegisterTab(currentState, { openIfMissing: false }); await activateTab(tabId); await ensureContentReady(tabId); const result = await sendGrokCommand(nodeId, { code }, { diff --git a/flows/grok/content/register-page.js b/flows/grok/content/register-page.js index 8d2ea5a..eac3204 100644 --- a/flows/grok/content/register-page.js +++ b/flows/grok/content/register-page.js @@ -5,6 +5,7 @@ const GROK_SIGNUP_URL = 'https://accounts.x.ai/sign-up?redirect=grok-com'; const GROK_EMAIL_SIGNUP_TEXT_PATTERN = /使用邮箱注册|sign\s*up\s*with\s*email|continue\s*with\s*email|email/i; const GROK_CONTINUE_TEXT_PATTERN = /continue|next|sign\s*up|submit|verify|继续|下一步|注册|提交|验证/i; const GROK_PROFILE_TEXT_PATTERN = /given\s*name|family\s*name|first\s*name|last\s*name|password|名字|姓氏|密码/i; +const GROK_EMAIL_VERIFICATION_READY_TIMEOUT_MS = 90 * 1000; const GROK_PROFILE_SUBMIT_PRE_CLICK_DELAY_MS = 2000; function isVisibleGrokElement(element) { @@ -174,6 +175,29 @@ function getGrokEmailErrorText() { return ''; } +async function waitForGrokVerificationPageAfterEmailSubmit() { + const settledState = await waitForGrok(() => { + const errorText = getGrokEmailErrorText(); + if (errorText) return { state: 'email_error', error: errorText, url: location.href }; + const state = getGrokPageState(); + return state === 'verification_code_entry' ? { state, url: location.href } : null; + }, { timeoutMs: GROK_EMAIL_VERIFICATION_READY_TIMEOUT_MS, intervalMs: 500 }); + + if (settledState?.error) { + throw new Error(settledState.error); + } + if (settledState?.state === 'verification_code_entry') { + return settledState; + } + + const errorText = getGrokEmailErrorText(); + if (errorText) { + throw new Error(errorText); + } + const finalState = getGrokPageState(); + throw new Error(`提交 Grok 注册邮箱后未进入验证码页面,当前页面状态:${finalState || 'unknown'}。请确认页面已跳转到“验证您的邮箱”后再继续。`); +} + async function submitGrokEmail(payload = {}) { const email = String(payload.email || '').trim(); if (!email) throw new Error('缺少 Grok 注册邮箱。'); @@ -189,7 +213,8 @@ async function submitGrokEmail(payload = {}) { if (errorText) { throw new Error(errorText); } - return { submitted: true, state: getGrokPageState(), url: location.href }; + const readyState = await waitForGrokVerificationPageAfterEmailSubmit(); + return { submitted: true, state: readyState.state, url: readyState.url || location.href }; } function getGrokVerificationErrorText() { diff --git a/flows/grok/index.js b/flows/grok/index.js index 55fa451..90a4ff3 100644 --- a/flows/grok/index.js +++ b/flows/grok/index.js @@ -35,7 +35,7 @@ stepDefinitionMode: 'grok', targetSelectorLabel: '来源', }, - baseGroups: ['grok-runtime-status'], + baseGroups: ['grok-runtime-status', 'shared-auto-run', 'shared-settings-actions'], targets: { webchat2api: { id: 'webchat2api', diff --git a/flows/kiro/index.js b/flows/kiro/index.js index df4b0b2..b46e59b 100644 --- a/flows/kiro/index.js +++ b/flows/kiro/index.js @@ -40,12 +40,18 @@ "targetSelectorLabel": "来源" }, "baseGroups": [ - "kiro-runtime-status" + "kiro-runtime-status", + "shared-auto-run", + "shared-settings-actions" ], "targets": { "kiro-rs": { "id": "kiro-rs", "label": "kiro.rs", + "defaultState": { + "baseUrl": "", + "apiKey": "" + }, "groups": [ "kiro-target-kiro-rs" ] diff --git a/flows/openai/index.js b/flows/openai/index.js index d98c68e..3e99221 100644 --- a/flows/openai/index.js +++ b/flows/openai/index.js @@ -46,13 +46,20 @@ "baseGroups": [ "openai-plus", "openai-phone", + "shared-auto-run", "openai-oauth", - "openai-step6" + "openai-step6", + "shared-settings-actions" ], "targets": { "cpa": { "id": "cpa", "label": "CPA 面板", + "defaultState": { + "vpsUrl": "", + "vpsPassword": "", + "localCpaStep9Mode": "submit" + }, "groups": [ "openai-target-cpa" ] @@ -60,6 +67,18 @@ "sub2api": { "id": "sub2api", "label": "SUB2API", + "defaultState": { + "sub2apiUrl": "", + "sub2apiEmail": "", + "sub2apiPassword": "", + "sub2apiGroupName": "codex", + "sub2apiGroupNames": [ + "codex", + "openai-plus" + ], + "sub2apiAccountPriority": 1, + "sub2apiDefaultProxyName": "" + }, "groups": [ "openai-target-sub2api" ] @@ -67,11 +86,37 @@ "codex2api": { "id": "codex2api", "label": "Codex2API", + "defaultState": { + "codex2apiUrl": "", + "codex2apiAdminKey": "" + }, "groups": [ "openai-target-codex2api" ] } }, + "settingsDefaults": { + "signup": { + "signupMethod": "email", + "phoneVerificationEnabled": false, + "phoneSignupReloginAfterBindEmailEnabled": false + }, + "plus": { + "plusModeEnabled": false, + "plusPaymentMethod": "paypal-hosted", + "plusAccountAccessStrategy": "oauth", + "hostedCheckoutVerificationUrl": "", + "hostedCheckoutPhoneNumber": "", + "plusHostedCheckoutOauthDelaySeconds": 3 + }, + "autoRun": { + "stepExecutionRange": { + "enabled": false, + "fromStep": 1, + "toStep": 11 + } + } + }, "runtimeSources": { "openai-auth": { "flowId": "openai", @@ -383,7 +428,8 @@ "label": "OAuth", "rowIds": [ "row-oauth-flow-timeout", - "row-oauth-display" + "row-oauth-display", + "row-oauth-callback" ] }, "openai-step6": { diff --git a/sidepanel/ip-proxy-panel.js b/sidepanel/ip-proxy-panel.js index 97d7641..a664c0f 100644 --- a/sidepanel/ip-proxy-panel.js +++ b/sidepanel/ip-proxy-panel.js @@ -1263,7 +1263,7 @@ function updateIpProxyUI(state = latestState) { const isAccountMode = mode === 'account'; const showSessionOptions = isAccountMode && service === '711proxy'; const hasAccountListConfigured = accountListAvailable && isAccountMode && hasCurrentInputAccountListEntries(); - const canOperate = !isAutoRunLockedPhase() && !isAutoRunScheduledPhase(); + const canOperate = !isAutoRunLockedPhase(); const actionState = getIpProxyActionState(); const actionBusy = Boolean(actionState.busy); const busyAction = normalizeIpProxyActionType(actionState.action); diff --git a/sidepanel/sidepanel.css b/sidepanel/sidepanel.css index 9853aee..c6cb51d 100644 --- a/sidepanel/sidepanel.css +++ b/sidepanel/sidepanel.css @@ -1268,6 +1268,19 @@ header { width: 76px; } +#row-flow-selector .data-label, +#row-source-selector .data-label, +#row-grok-webchat2api-url .data-label, +#row-grok-webchat2api-key .data-label, +#row-grok-register-status .data-label, +#row-grok-sso-status .data-label, +#row-grok-webchat2api-upload-status .data-label, +#row-grok-sso-settings .data-label { + width: 76px; + text-transform: none; + letter-spacing: 0.02em; +} + #row-codex2api-url .data-label { font-size: 10px; letter-spacing: 0.02em; @@ -2197,15 +2210,6 @@ header { justify-content: flex-end; } -.auto-delay-setting-pair { - flex-wrap: nowrap; -} - -#row-auto-delay-settings .setting-group-secondary { - margin-left: auto; - min-width: 0; -} - .step6-cookie-cleanup-setting { gap: 8px; } @@ -2227,10 +2231,6 @@ header { text-align: center; } -.auto-run-delay-setting { - margin-left: auto !important; -} - .oauth-flow-timeout-setting { gap: 8px; min-width: 0; @@ -2242,10 +2242,6 @@ header { text-overflow: ellipsis; } -#row-auto-delay-settings .setting-caption { - min-width: auto; -} - .setting-caption-left { text-align: left; } @@ -2720,7 +2716,7 @@ header { .auto-continue-bar svg { color: var(--orange); flex-shrink: 0; } .auto-hint { font-size: 13px; color: var(--orange); flex: 1; font-weight: 500; } -.auto-schedule-bar { +.auto-countdown-bar { margin-top: 8px; padding: 10px; background: var(--blue-soft); @@ -2732,12 +2728,12 @@ header { gap: 10px; } -.auto-schedule-bar svg { +.auto-countdown-bar svg { color: var(--blue); flex-shrink: 0; } -.auto-schedule-copy { +.auto-countdown-copy { display: flex; flex-direction: column; gap: 2px; @@ -2745,19 +2741,19 @@ header { min-width: 0; } -.auto-schedule-title { +.auto-countdown-title { font-size: 13px; font-weight: 700; color: var(--blue); } -.auto-schedule-meta { +.auto-countdown-meta { font-size: 12px; line-height: 1.5; color: var(--text-secondary); } -.auto-schedule-actions { +.auto-countdown-actions { display: flex; align-items: center; flex-wrap: wrap; diff --git a/sidepanel/sidepanel.html b/sidepanel/sidepanel.html index 1b7cb69..bc5ebc9 100644 --- a/sidepanel/sidepanel.html +++ b/sidepanel/sidepanel.html @@ -121,7 +121,7 @@
-
+
注册
-
+
来源 - +
+ + +
+ + +
-
- 启动前 -
-
- 延迟 - -
- - 分钟 -
-
-
-
-
+
自动重试
@@ -734,6 +718,16 @@
+
+ 线程间隔 +
+
+ + 分钟 +
+
+
授权总超时
@@ -748,14 +742,6 @@ 关闭后只取消 Step 7 后链总预算
-
- 线程间隔 -
- - 分钟 -
-
@@ -782,10 +768,15 @@ OAuth 等待中...
-
+
回调
等待中... +
+
+
+ 设置 +
@@ -1798,16 +1789,16 @@ 先自动获取邮箱,或手动粘贴邮箱后再继续
-