Refactor auto-run flow state preservation
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
AUTO_RUN_TIMER_KIND_BETWEEN_ROUNDS,
|
||||
broadcastAutoRunStatus,
|
||||
broadcastStopToContentScripts,
|
||||
buildFreshAutoRunKeepState,
|
||||
cancelPendingCommands,
|
||||
clearStopRequest,
|
||||
createAutoRunSessionId,
|
||||
@@ -77,6 +78,67 @@
|
||||
throw new Error('自动运行节点执行器未接入。');
|
||||
}
|
||||
|
||||
function buildFreshStartStateSnapshot(state = {}) {
|
||||
return {
|
||||
...(state || {}),
|
||||
currentNodeId: '',
|
||||
nodeStatuses: {},
|
||||
stepStatuses: {},
|
||||
};
|
||||
}
|
||||
|
||||
function resolveFreshStartNodeId(state = {}) {
|
||||
const freshState = buildFreshStartStateSnapshot(state);
|
||||
return String(getFirstUnfinishedWorkflowNode(freshState) || '').trim();
|
||||
}
|
||||
|
||||
function buildFreshAttemptKeepState(state = {}, context = {}) {
|
||||
if (typeof buildFreshAutoRunKeepState === 'function') {
|
||||
const helperPatch = buildFreshAutoRunKeepState(state, context);
|
||||
if (helperPatch && typeof helperPatch === 'object' && !Array.isArray(helperPatch)) {
|
||||
return {
|
||||
...helperPatch,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
activeFlowId: state.activeFlowId,
|
||||
flowId: state.flowId || state.activeFlowId,
|
||||
panelMode: state.panelMode,
|
||||
kiroSourceId: state.kiroSourceId,
|
||||
vpsUrl: state.vpsUrl,
|
||||
vpsPassword: state.vpsPassword,
|
||||
customPassword: state.customPassword,
|
||||
plusModeEnabled: state.plusModeEnabled,
|
||||
plusPaymentMethod: state.plusPaymentMethod,
|
||||
phoneVerificationEnabled: state.phoneVerificationEnabled,
|
||||
phoneSignupReloginAfterBindEmailEnabled: state.phoneSignupReloginAfterBindEmailEnabled,
|
||||
paypalEmail: state.paypalEmail,
|
||||
paypalPassword: state.paypalPassword,
|
||||
kiroRsUrl: state.kiroRsUrl,
|
||||
kiroRsKey: state.kiroRsKey,
|
||||
autoRunSkipFailures: state.autoRunSkipFailures,
|
||||
autoRunFallbackThreadIntervalMinutes: state.autoRunFallbackThreadIntervalMinutes,
|
||||
autoRunDelayEnabled: state.autoRunDelayEnabled,
|
||||
autoRunDelayMinutes: state.autoRunDelayMinutes,
|
||||
autoStepDelaySeconds: state.autoStepDelaySeconds,
|
||||
stepExecutionRangeByFlow: state.stepExecutionRangeByFlow,
|
||||
signupMethod: state.signupMethod,
|
||||
mailProvider: state.mailProvider,
|
||||
emailGenerator: state.emailGenerator,
|
||||
gmailBaseEmail: state.gmailBaseEmail,
|
||||
mail2925BaseEmail: state.mail2925BaseEmail,
|
||||
currentMail2925AccountId: state.currentMail2925AccountId,
|
||||
emailPrefix: state.emailPrefix,
|
||||
inbucketHost: state.inbucketHost,
|
||||
inbucketMailbox: state.inbucketMailbox,
|
||||
cloudflareDomain: state.cloudflareDomain,
|
||||
cloudflareDomains: state.cloudflareDomains,
|
||||
reusablePhoneActivation: state.reusablePhoneActivation,
|
||||
};
|
||||
}
|
||||
|
||||
function createAutoRunRoundSummary(round) {
|
||||
return {
|
||||
round,
|
||||
@@ -502,12 +564,13 @@
|
||||
autoRunAttemptRun: attemptRun,
|
||||
});
|
||||
roundSummary.attempts = attemptRun;
|
||||
const defaultStartNodeId = typeof runAutoSequenceFromNode === 'function' ? 'open-chatgpt' : 1;
|
||||
const attemptState = await getState();
|
||||
const defaultStartNodeId = resolveFreshStartNodeId(attemptState);
|
||||
let startNodeId = defaultStartNodeId;
|
||||
let useExistingProgress = false;
|
||||
|
||||
if (reuseExistingProgress) {
|
||||
let currentState = await getState();
|
||||
let currentState = attemptState;
|
||||
if (getRunningWorkflowNodes(currentState).length) {
|
||||
currentState = await waitForRunningWorkflowNodesToFinish({
|
||||
currentRun: targetRun,
|
||||
@@ -525,32 +588,14 @@
|
||||
}
|
||||
|
||||
if (!useExistingProgress) {
|
||||
const prevState = await getState();
|
||||
const prevState = attemptState;
|
||||
const keepSettings = {
|
||||
vpsUrl: prevState.vpsUrl,
|
||||
vpsPassword: prevState.vpsPassword,
|
||||
customPassword: prevState.customPassword,
|
||||
plusModeEnabled: prevState.plusModeEnabled,
|
||||
paypalEmail: prevState.paypalEmail,
|
||||
paypalPassword: prevState.paypalPassword,
|
||||
autoRunSkipFailures: prevState.autoRunSkipFailures,
|
||||
autoRunFallbackThreadIntervalMinutes: prevState.autoRunFallbackThreadIntervalMinutes,
|
||||
autoRunDelayEnabled: prevState.autoRunDelayEnabled,
|
||||
autoRunDelayMinutes: prevState.autoRunDelayMinutes,
|
||||
autoStepDelaySeconds: prevState.autoStepDelaySeconds,
|
||||
stepExecutionRangeByFlow: prevState.stepExecutionRangeByFlow,
|
||||
signupMethod: prevState.signupMethod,
|
||||
mailProvider: prevState.mailProvider,
|
||||
emailGenerator: prevState.emailGenerator,
|
||||
gmailBaseEmail: prevState.gmailBaseEmail,
|
||||
mail2925BaseEmail: prevState.mail2925BaseEmail,
|
||||
currentMail2925AccountId: prevState.currentMail2925AccountId,
|
||||
emailPrefix: prevState.emailPrefix,
|
||||
inbucketHost: prevState.inbucketHost,
|
||||
inbucketMailbox: prevState.inbucketMailbox,
|
||||
cloudflareDomain: prevState.cloudflareDomain,
|
||||
cloudflareDomains: prevState.cloudflareDomains,
|
||||
reusablePhoneActivation: prevState.reusablePhoneActivation,
|
||||
...buildFreshAttemptKeepState(prevState, {
|
||||
targetRun,
|
||||
totalRuns,
|
||||
attemptRun,
|
||||
sessionId,
|
||||
}),
|
||||
autoRunRoundSummaries: serializeAutoRunRoundSummaries(totalRuns, roundSummaries),
|
||||
autoRunSessionId: sessionId,
|
||||
tabRegistry: {},
|
||||
|
||||
@@ -191,6 +191,59 @@
|
||||
verifyHotmailAccount,
|
||||
} = deps;
|
||||
|
||||
function normalizeMessageFlowId(value = '', fallback = 'openai') {
|
||||
const rootScope = typeof self !== 'undefined' ? self : globalThis;
|
||||
if (typeof rootScope.MultiPageFlowRegistry?.normalizeFlowId === 'function') {
|
||||
return rootScope.MultiPageFlowRegistry.normalizeFlowId(value, fallback);
|
||||
}
|
||||
const fallbackFlowId = String(fallback || 'openai').trim().toLowerCase() || 'openai';
|
||||
const normalized = String(value || '').trim().toLowerCase();
|
||||
if (!normalized || normalized === 'codex') {
|
||||
return fallbackFlowId;
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function normalizeMessageSourceId(flowId, sourceId = '', fallback = '') {
|
||||
const rootScope = typeof self !== 'undefined' ? self : globalThis;
|
||||
if (typeof rootScope.MultiPageFlowRegistry?.normalizeSourceId === 'function') {
|
||||
return rootScope.MultiPageFlowRegistry.normalizeSourceId(flowId, sourceId, fallback);
|
||||
}
|
||||
const fallbackSourceId = String(
|
||||
fallback || (normalizeMessageFlowId(flowId) === 'kiro' ? 'kiro-rs' : 'cpa')
|
||||
).trim().toLowerCase();
|
||||
return String(sourceId || fallbackSourceId).trim().toLowerCase() || fallbackSourceId;
|
||||
}
|
||||
|
||||
function mapAutoRunSourceIdToPanelMode(sourceId = '', fallback = 'cpa') {
|
||||
const rootScope = typeof self !== 'undefined' ? self : globalThis;
|
||||
if (typeof rootScope.MultiPageFlowRegistry?.mapSourceIdToPanelMode === 'function') {
|
||||
return rootScope.MultiPageFlowRegistry.mapSourceIdToPanelMode('openai', sourceId, fallback);
|
||||
}
|
||||
return String(sourceId || fallback || 'cpa').trim().toLowerCase() || 'cpa';
|
||||
}
|
||||
|
||||
function buildAutoRunFlowStateUpdates(payload = {}) {
|
||||
const hasActiveFlowId = Object.prototype.hasOwnProperty.call(payload, 'activeFlowId');
|
||||
const hasSourceId = Object.prototype.hasOwnProperty.call(payload, 'sourceId');
|
||||
if (!hasActiveFlowId && !hasSourceId) {
|
||||
return {};
|
||||
}
|
||||
const activeFlowId = normalizeMessageFlowId(payload.activeFlowId, 'openai');
|
||||
const updates = {
|
||||
activeFlowId,
|
||||
flowId: activeFlowId,
|
||||
};
|
||||
if (hasSourceId) {
|
||||
if (activeFlowId === 'kiro') {
|
||||
updates.kiroSourceId = normalizeMessageSourceId('kiro', payload.sourceId, 'kiro-rs');
|
||||
} else {
|
||||
updates.panelMode = mapAutoRunSourceIdToPanelMode(payload.sourceId, 'cpa');
|
||||
}
|
||||
}
|
||||
return updates;
|
||||
}
|
||||
|
||||
function preserveKeyFromState(updates, currentState, key) {
|
||||
if (!Object.prototype.hasOwnProperty.call(updates, key)) {
|
||||
return;
|
||||
@@ -1208,8 +1261,16 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
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, { state });
|
||||
const autoRunStartValidation = validateAutoRunStart(state, {
|
||||
activeFlowId: autoRunFlowStateUpdates.activeFlowId ?? state?.activeFlowId,
|
||||
panelMode: autoRunFlowStateUpdates.panelMode ?? state?.panelMode,
|
||||
state,
|
||||
});
|
||||
if (autoRunStartValidation?.ok === false) {
|
||||
throw new Error(autoRunStartValidation.errors?.[0]?.message || '当前设置不支持启动自动流程。');
|
||||
}
|
||||
@@ -1240,8 +1301,16 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
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, { state });
|
||||
const autoRunStartValidation = validateAutoRunStart(state, {
|
||||
activeFlowId: autoRunFlowStateUpdates.activeFlowId ?? state?.activeFlowId,
|
||||
panelMode: autoRunFlowStateUpdates.panelMode ?? state?.panelMode,
|
||||
state,
|
||||
});
|
||||
if (autoRunStartValidation?.ok === false) {
|
||||
throw new Error(autoRunStartValidation.errors?.[0]?.message || '当前设置不支持启动自动流程。');
|
||||
}
|
||||
@@ -1374,6 +1443,10 @@
|
||||
oauthFlowDeadlineSourceUrl: null,
|
||||
} : {}),
|
||||
};
|
||||
if (Object.prototype.hasOwnProperty.call(updates, 'activeFlowId')
|
||||
&& !Object.prototype.hasOwnProperty.call(stateUpdates, 'flowId')) {
|
||||
stateUpdates.flowId = updates.activeFlowId;
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(updates, 'icloudHostPreference')) {
|
||||
const nextHostPreference = String(updates.icloudHostPreference || '').trim().toLowerCase();
|
||||
stateUpdates.preferredIcloudHost = nextHostPreference === 'icloud.com' || nextHostPreference === 'icloud.com.cn'
|
||||
|
||||
@@ -321,13 +321,13 @@
|
||||
...cloneValue(normalizePlainObject(state.runtimeState)),
|
||||
};
|
||||
const activeFlowId = normalizeFlowId(
|
||||
Object.prototype.hasOwnProperty.call(state, 'flowId')
|
||||
? state.flowId
|
||||
: Object.prototype.hasOwnProperty.call(state, 'activeFlowId')
|
||||
Object.prototype.hasOwnProperty.call(state, 'activeFlowId')
|
||||
? state.activeFlowId
|
||||
: Object.prototype.hasOwnProperty.call(baseRuntimeState, 'flowId')
|
||||
? baseRuntimeState.flowId
|
||||
: baseRuntimeState.activeFlowId
|
||||
: Object.prototype.hasOwnProperty.call(state, 'flowId')
|
||||
? state.flowId
|
||||
: Object.prototype.hasOwnProperty.call(baseRuntimeState, 'activeFlowId')
|
||||
? baseRuntimeState.activeFlowId
|
||||
: baseRuntimeState.flowId
|
||||
);
|
||||
const currentNodeId = String(
|
||||
Object.prototype.hasOwnProperty.call(state, 'currentNodeId')
|
||||
|
||||
@@ -326,7 +326,7 @@
|
||||
try {
|
||||
const latestState = await getExecutionState(state);
|
||||
const auth = await startBuilderIdDeviceLogin(
|
||||
latestState.kiroRegion || DEFAULT_REGION,
|
||||
DEFAULT_REGION,
|
||||
fetchImpl
|
||||
);
|
||||
const loginUrl = cleanString(auth.verificationUriComplete || auth.verificationUri);
|
||||
@@ -379,7 +379,7 @@
|
||||
const clientId = cleanString(latestState.kiroClientId);
|
||||
const clientSecret = String(latestState.kiroClientSecret || '');
|
||||
const deviceCode = String(latestState.kiroDeviceAuthorizationCode || '');
|
||||
const region = normalizeRegion(latestState.kiroAuthRegion || latestState.kiroRegion || DEFAULT_REGION);
|
||||
const region = normalizeRegion(latestState.kiroAuthRegion, DEFAULT_REGION);
|
||||
const expiresAt = Math.max(0, Number(latestState.kiroAuthExpiresAt) || 0);
|
||||
if (!clientId || !clientSecret || !deviceCode) {
|
||||
throw new Error('Kiro device login has not been started yet.');
|
||||
@@ -443,7 +443,7 @@
|
||||
const refreshToken = String(latestState.kiroRefreshToken || '');
|
||||
const clientId = cleanString(latestState.kiroClientId);
|
||||
const clientSecret = String(latestState.kiroClientSecret || '');
|
||||
const region = normalizeRegion(latestState.kiroAuthRegion || latestState.kiroRegion || DEFAULT_REGION);
|
||||
const region = normalizeRegion(latestState.kiroAuthRegion, DEFAULT_REGION);
|
||||
const kiroRsUrl = String(latestState.kiroRsUrl || '');
|
||||
const kiroRsKey = String(latestState.kiroRsKey || '');
|
||||
if (!refreshToken || !clientId || !clientSecret) {
|
||||
|
||||
Reference in New Issue
Block a user