feat(sidepanel): support configurable auto step delay

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
leon
2026-04-13 15:17:51 +08:00
parent 347c5fe2e7
commit e6211921e6
4 changed files with 260 additions and 0 deletions
+72
View File
@@ -39,6 +39,10 @@ const DEFAULT_SUB2API_REDIRECT_URI = 'http://localhost:1455/auth/callback';
const AUTO_RUN_ALARM_NAME = 'scheduled-auto-run';
const AUTO_RUN_DELAY_MIN_MINUTES = 1;
const AUTO_RUN_DELAY_MAX_MINUTES = 1440;
const AUTO_STEP_RANDOM_DELAY_MIN_ALLOWED_SECONDS = 0;
const AUTO_STEP_RANDOM_DELAY_MAX_ALLOWED_SECONDS = 600;
const AUTO_STEP_RANDOM_DELAY_DEFAULT_MIN_SECONDS = 12;
const AUTO_STEP_RANDOM_DELAY_DEFAULT_MAX_SECONDS = 18;
const DEFAULT_LOCAL_CPA_STEP9_MODE = 'submit';
initializeSessionStorageAccess();
@@ -60,6 +64,8 @@ const PERSISTED_SETTING_DEFAULTS = {
autoRunSkipFailures: false, // 自动运行遇到失败步骤后,是否继续执行后续流程。
autoRunDelayEnabled: false, // 自动运行是否启用启动前倒计时。
autoRunDelayMinutes: 30, // 自动运行倒计时分钟数。
autoStepRandomDelayMinSeconds: AUTO_STEP_RANDOM_DELAY_DEFAULT_MIN_SECONDS, // 自动运行每一步执行前的最小随机等待秒数。
autoStepRandomDelayMaxSeconds: AUTO_STEP_RANDOM_DELAY_DEFAULT_MAX_SECONDS, // 自动运行每一步执行前的最大随机等待秒数。
mailProvider: '163', // 验证码邮箱来源(163 / 163-vip / qq / inbucket)。
emailGenerator: 'duck', // 注册邮箱生成方式:duck / cloudflare。
inbucketHost: '', // 仅当 mailProvider 为 inbucket 时填写 Inbucket 地址,其他情况保持为空。
@@ -119,6 +125,32 @@ function normalizeAutoRunDelayMinutes(value) {
);
}
function normalizeAutoStepRandomDelaySeconds(value, fallback = AUTO_STEP_RANDOM_DELAY_DEFAULT_MIN_SECONDS) {
const numeric = Number(value);
if (!Number.isFinite(numeric)) {
return fallback;
}
return Math.min(
AUTO_STEP_RANDOM_DELAY_MAX_ALLOWED_SECONDS,
Math.max(AUTO_STEP_RANDOM_DELAY_MIN_ALLOWED_SECONDS, Math.floor(numeric))
);
}
function normalizeAutoStepRandomDelayRange(settings = {}) {
const minSeconds = normalizeAutoStepRandomDelaySeconds(
settings.autoStepRandomDelayMinSeconds,
PERSISTED_SETTING_DEFAULTS.autoStepRandomDelayMinSeconds
);
const maxSeconds = Math.max(
minSeconds,
normalizeAutoStepRandomDelaySeconds(
settings.autoStepRandomDelayMaxSeconds,
PERSISTED_SETTING_DEFAULTS.autoStepRandomDelayMaxSeconds
)
);
return { minSeconds, maxSeconds };
}
function normalizeRunCount(value) {
const numeric = Number(value);
if (!Number.isFinite(numeric)) {
@@ -216,6 +248,16 @@ function normalizePersistentSettingValue(key, value) {
return Boolean(value);
case 'autoRunDelayMinutes':
return normalizeAutoRunDelayMinutes(value);
case 'autoStepRandomDelayMinSeconds':
return normalizeAutoStepRandomDelaySeconds(
value,
PERSISTED_SETTING_DEFAULTS.autoStepRandomDelayMinSeconds
);
case 'autoStepRandomDelayMaxSeconds':
return normalizeAutoStepRandomDelaySeconds(
value,
PERSISTED_SETTING_DEFAULTS.autoStepRandomDelayMaxSeconds
);
case 'mailProvider':
return normalizeMailProvider(value);
case 'emailGenerator':
@@ -264,6 +306,15 @@ function buildPersistentSettingsPayload(input = {}, options = {}) {
payload.cloudflareDomains = domains;
}
if (payload.autoStepRandomDelayMinSeconds !== undefined || payload.autoStepRandomDelayMaxSeconds !== undefined) {
const normalizedDelayRange = normalizeAutoStepRandomDelayRange({
autoStepRandomDelayMinSeconds: payload.autoStepRandomDelayMinSeconds,
autoStepRandomDelayMaxSeconds: payload.autoStepRandomDelayMaxSeconds,
});
payload.autoStepRandomDelayMinSeconds = normalizedDelayRange.minSeconds;
payload.autoStepRandomDelayMaxSeconds = normalizedDelayRange.maxSeconds;
}
return payload;
}
@@ -2422,6 +2473,12 @@ async function humanStepDelay(min = HUMAN_STEP_DELAY_MIN, max = HUMAN_STEP_DELAY
await sleepWithStop(duration);
}
function getAutoStepRandomDelayMs(min, max) {
const normalizedMin = Math.max(0, Math.floor(Number(min) || 0));
const normalizedMax = Math.max(normalizedMin, Math.floor(Number(max) || normalizedMin));
return Math.floor(Math.random() * (normalizedMax - normalizedMin + 1)) + normalizedMin;
}
async function clickWithDebugger(tabId, rect) {
throwIfStopped();
if (!tabId) {
@@ -3028,6 +3085,19 @@ async function executeStep(step) {
async function executeStepAndWait(step, delayAfter = 2000) {
throwIfStopped();
const delaySettings = normalizeAutoStepRandomDelayRange(await getState());
const randomDelayMs = getAutoStepRandomDelayMs(
delaySettings.minSeconds * 1000,
delaySettings.maxSeconds * 1000
);
if (randomDelayMs > 0) {
await addLog(
`自动运行:步骤 ${step} 执行前随机等待 ${delaySettings.minSeconds}-${delaySettings.maxSeconds} 秒,本次约 ${Math.round(randomDelayMs / 1000)} 秒,避免节奏过快。`,
'info'
);
await sleepWithStop(randomDelayMs);
}
if (AUTO_RUN_BACKGROUND_COMPLETED_STEPS.has(step)) {
await addLog(`自动运行:步骤 ${step} 由后台流程负责收尾,执行函数返回后将直接进入下一步。`, 'info');
await executeStep(step);
@@ -3376,6 +3446,8 @@ async function autoRunLoop(totalRuns, options = {}) {
autoRunSkipFailures: prevState.autoRunSkipFailures,
autoRunDelayEnabled: prevState.autoRunDelayEnabled,
autoRunDelayMinutes: prevState.autoRunDelayMinutes,
autoStepRandomDelayMinSeconds: prevState.autoStepRandomDelayMinSeconds,
autoStepRandomDelayMaxSeconds: prevState.autoStepRandomDelayMaxSeconds,
mailProvider: prevState.mailProvider,
emailGenerator: prevState.emailGenerator,
inbucketHost: prevState.inbucketHost,