refactor flows into canonical runtime architecture
This commit is contained in:
+139
-121
@@ -1,11 +1,17 @@
|
|||||||
// background.js — Service Worker: orchestration, state, tab management, message routing
|
// background.js — Service Worker: orchestration, state, tab management, message routing
|
||||||
|
|
||||||
importScripts(
|
importScripts(
|
||||||
'shared/flow-registry.js',
|
'flows/openai/index.js',
|
||||||
|
'flows/openai/workflow.js',
|
||||||
|
'flows/kiro/index.js',
|
||||||
|
'flows/kiro/workflow.js',
|
||||||
|
'flows/index.js',
|
||||||
|
'core/flow-kernel/flow-registry.js',
|
||||||
'shared/contribution-registry.js',
|
'shared/contribution-registry.js',
|
||||||
'shared/settings-schema.js',
|
'core/flow-kernel/settings-schema.js',
|
||||||
'shared/source-registry.js',
|
'imports/legacy/settings-importer.js',
|
||||||
'shared/flow-capabilities.js',
|
'core/flow-kernel/source-registry.js',
|
||||||
|
'core/flow-kernel/flow-capabilities.js',
|
||||||
'shared/kiro-timeouts.js',
|
'shared/kiro-timeouts.js',
|
||||||
'managed-alias-utils.js',
|
'managed-alias-utils.js',
|
||||||
'mail2925-utils.js',
|
'mail2925-utils.js',
|
||||||
@@ -25,15 +31,15 @@ importScripts(
|
|||||||
'background/cpa-api.js',
|
'background/cpa-api.js',
|
||||||
'background/panel-bridge.js',
|
'background/panel-bridge.js',
|
||||||
'background/registration-email-state.js',
|
'background/registration-email-state.js',
|
||||||
'background/workflow-engine.js',
|
'core/flow-kernel/workflow-engine.js',
|
||||||
'background/runtime-state.js',
|
'core/flow-kernel/runtime-state.js',
|
||||||
'background/kiro/state.js',
|
'flows/kiro/background/state.js',
|
||||||
'background/kiro/credential-artifact.js',
|
'flows/kiro/background/credential-artifact.js',
|
||||||
'background/contribution/adapters/kiro-builder-id.js',
|
'background/contribution/adapters/kiro-builder-id.js',
|
||||||
'background/kiro/register-runner.js',
|
'flows/kiro/background/register-runner.js',
|
||||||
'background/kiro/desktop-client.js',
|
'flows/kiro/background/desktop-client.js',
|
||||||
'background/kiro/desktop-authorize-runner.js',
|
'flows/kiro/background/desktop-authorize-runner.js',
|
||||||
'background/kiro/publisher-kiro-rs.js',
|
'flows/kiro/background/publisher-kiro-rs.js',
|
||||||
'background/generated-email-helpers.js',
|
'background/generated-email-helpers.js',
|
||||||
'background/signup-flow-helpers.js',
|
'background/signup-flow-helpers.js',
|
||||||
'background/mail-rule-registry.js',
|
'background/mail-rule-registry.js',
|
||||||
@@ -41,30 +47,30 @@ importScripts(
|
|||||||
'background/message-router.js',
|
'background/message-router.js',
|
||||||
'background/verification-flow.js',
|
'background/verification-flow.js',
|
||||||
'background/auto-run-controller.js',
|
'background/auto-run-controller.js',
|
||||||
'background/tab-runtime.js',
|
'core/flow-kernel/tab-runtime.js',
|
||||||
'background/navigation-utils.js',
|
'background/navigation-utils.js',
|
||||||
'background/logging-status.js',
|
'core/flow-kernel/logging-status.js',
|
||||||
'background/steps/registry.js',
|
'core/flow-kernel/step-registry.js',
|
||||||
'data/step-definitions.js',
|
'data/step-definitions.js',
|
||||||
'data/address-sources.js',
|
'data/address-sources.js',
|
||||||
'background/steps/open-chatgpt.js',
|
'flows/openai/background/steps/open-chatgpt.js',
|
||||||
'background/steps/submit-signup-email.js',
|
'flows/openai/background/steps/submit-signup-email.js',
|
||||||
'background/steps/fill-password.js',
|
'flows/openai/background/steps/fill-password.js',
|
||||||
'background/steps/fetch-signup-code.js',
|
'flows/openai/background/steps/fetch-signup-code.js',
|
||||||
'background/steps/fill-profile.js',
|
'flows/openai/background/steps/fill-profile.js',
|
||||||
'background/steps/wait-registration-success.js',
|
'flows/openai/background/steps/wait-registration-success.js',
|
||||||
'background/steps/create-plus-checkout.js',
|
'flows/openai/background/steps/create-plus-checkout.js',
|
||||||
'background/steps/fill-plus-checkout.js',
|
'flows/openai/background/steps/fill-plus-checkout.js',
|
||||||
'background/steps/gopay-manual-confirm.js',
|
'flows/openai/background/steps/gopay-manual-confirm.js',
|
||||||
'background/steps/paypal-approve.js',
|
'flows/openai/background/steps/paypal-approve.js',
|
||||||
'background/steps/gopay-approve.js',
|
'flows/openai/background/steps/gopay-approve.js',
|
||||||
'background/steps/plus-return-confirm.js',
|
'flows/openai/background/steps/plus-return-confirm.js',
|
||||||
'background/steps/sub2api-session-import.js',
|
'flows/openai/background/steps/sub2api-session-import.js',
|
||||||
'background/steps/cpa-session-import.js',
|
'flows/openai/background/steps/cpa-session-import.js',
|
||||||
'background/steps/oauth-login.js',
|
'flows/openai/background/steps/oauth-login.js',
|
||||||
'background/steps/fetch-login-code.js',
|
'flows/openai/background/steps/fetch-login-code.js',
|
||||||
'background/steps/confirm-oauth.js',
|
'flows/openai/background/steps/confirm-oauth.js',
|
||||||
'background/steps/platform-verify.js',
|
'flows/openai/background/steps/platform-verify.js',
|
||||||
'data/names.js',
|
'data/names.js',
|
||||||
'hotmail-utils.js',
|
'hotmail-utils.js',
|
||||||
'microsoft-email.js',
|
'microsoft-email.js',
|
||||||
@@ -498,15 +504,6 @@ function buildStatePatchWithRuntimeState(currentState = {}, updates = {}) {
|
|||||||
if (runtimeStateHelpers?.buildSessionStatePatch) {
|
if (runtimeStateHelpers?.buildSessionStatePatch) {
|
||||||
nextPatch = runtimeStateHelpers.buildSessionStatePatch(currentState, nextPatch);
|
nextPatch = runtimeStateHelpers.buildSessionStatePatch(currentState, nextPatch);
|
||||||
}
|
}
|
||||||
if (kiroStateHelpers?.buildSessionStatePatch) {
|
|
||||||
const kiroPatch = kiroStateHelpers.buildSessionStatePatch(currentState, updates);
|
|
||||||
if (kiroPatch && Object.keys(kiroPatch).length > 0) {
|
|
||||||
nextPatch = {
|
|
||||||
...nextPatch,
|
|
||||||
...kiroPatch,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nextPatch;
|
return nextPatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,7 +891,7 @@ function buildResolvedStepDefinitionState(state = {}) {
|
|||||||
signupMethod: requestedSignupMethod,
|
signupMethod: requestedSignupMethod,
|
||||||
}, {
|
}, {
|
||||||
activeFlowId: requestedActiveFlowId,
|
activeFlowId: requestedActiveFlowId,
|
||||||
panelMode: state?.panelMode,
|
targetId: state?.targetId,
|
||||||
signupMethod: requestedSignupMethod,
|
signupMethod: requestedSignupMethod,
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
@@ -910,7 +907,6 @@ function buildResolvedStepDefinitionState(state = {}) {
|
|||||||
...state,
|
...state,
|
||||||
activeFlowId: resolvedActiveFlowId,
|
activeFlowId: resolvedActiveFlowId,
|
||||||
flowId: resolvedActiveFlowId,
|
flowId: resolvedActiveFlowId,
|
||||||
panelMode: stepDefinitionOptions.panelMode || capabilityState?.effectivePanelMode || state?.panelMode,
|
|
||||||
targetId: stepDefinitionOptions.targetId || capabilityState?.effectiveTargetId || state?.targetId,
|
targetId: stepDefinitionOptions.targetId || capabilityState?.effectiveTargetId || state?.targetId,
|
||||||
plusModeEnabled: stepDefinitionOptions.plusModeEnabled === undefined
|
plusModeEnabled: stepDefinitionOptions.plusModeEnabled === undefined
|
||||||
? plusModeEnabled
|
? plusModeEnabled
|
||||||
@@ -1178,9 +1174,8 @@ function setupDeclarativeNetRequestRules() {
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
const PERSISTED_SETTING_DEFAULTS = {
|
const PERSISTED_SETTING_DEFAULTS = {
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
|
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
kiroTargetId: 'kiro-rs',
|
|
||||||
kiroRsUrl: String(self.MultiPageFlowRegistry?.DEFAULT_KIRO_RS_URL || '').trim(),
|
kiroRsUrl: String(self.MultiPageFlowRegistry?.DEFAULT_KIRO_RS_URL || '').trim(),
|
||||||
kiroRsKey: '',
|
kiroRsKey: '',
|
||||||
vpsUrl: '',
|
vpsUrl: '',
|
||||||
@@ -1371,9 +1366,7 @@ const PERSISTED_SETTING_KEYS = Object.keys(PERSISTED_SETTING_DEFAULTS);
|
|||||||
const PERSISTED_SETTINGS_SCHEMA_KEYS = ['settingsSchemaVersion', 'settingsState'];
|
const PERSISTED_SETTINGS_SCHEMA_KEYS = ['settingsSchemaVersion', 'settingsState'];
|
||||||
const SETTINGS_SCHEMA_VIEW_KEYS = Object.freeze([
|
const SETTINGS_SCHEMA_VIEW_KEYS = Object.freeze([
|
||||||
'activeFlowId',
|
'activeFlowId',
|
||||||
'openaiIntegrationTargetId',
|
'targetId',
|
||||||
'panelMode',
|
|
||||||
'kiroTargetId',
|
|
||||||
'vpsUrl',
|
'vpsUrl',
|
||||||
'vpsPassword',
|
'vpsPassword',
|
||||||
'localCpaStep9Mode',
|
'localCpaStep9Mode',
|
||||||
@@ -1417,7 +1410,6 @@ const DEFAULT_STATE = {
|
|||||||
currentNodeId: '',
|
currentNodeId: '',
|
||||||
nodeStatuses: { ...DEFAULT_NODE_STATUSES },
|
nodeStatuses: { ...DEFAULT_NODE_STATUSES },
|
||||||
runtimeState: runtimeStateHelpers?.buildDefaultRuntimeState?.() || null,
|
runtimeState: runtimeStateHelpers?.buildDefaultRuntimeState?.() || null,
|
||||||
kiroRuntime: kiroStateHelpers?.buildDefaultRuntimeState?.() || null,
|
|
||||||
...CONTRIBUTION_RUNTIME_DEFAULTS,
|
...CONTRIBUTION_RUNTIME_DEFAULTS,
|
||||||
accounts: [], // 已生成账号记录:{ email, password, createdAt }。
|
accounts: [], // 已生成账号记录:{ email, password, createdAt }。
|
||||||
accountRunHistory: [], // 账号运行历史快照,实际持久化在 chrome.storage.local。
|
accountRunHistory: [], // 账号运行历史快照,实际持久化在 chrome.storage.local。
|
||||||
@@ -1819,7 +1811,7 @@ function resolveCurrentFlowCapabilities(state = {}, options = {}) {
|
|||||||
}
|
}
|
||||||
return registry.resolveSidepanelCapabilities({
|
return registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId: options?.activeFlowId ?? state?.activeFlowId,
|
activeFlowId: options?.activeFlowId ?? state?.activeFlowId,
|
||||||
panelMode: options?.panelMode ?? state?.panelMode,
|
targetId: options?.targetId ?? state?.targetId,
|
||||||
signupMethod: options?.signupMethod ?? state?.signupMethod,
|
signupMethod: options?.signupMethod ?? state?.signupMethod,
|
||||||
state,
|
state,
|
||||||
});
|
});
|
||||||
@@ -1832,7 +1824,7 @@ function validateAutoRunStartState(state = {}, options = {}) {
|
|||||||
}
|
}
|
||||||
return registry.validateAutoRunStart({
|
return registry.validateAutoRunStart({
|
||||||
activeFlowId: options?.activeFlowId ?? state?.activeFlowId,
|
activeFlowId: options?.activeFlowId ?? state?.activeFlowId,
|
||||||
panelMode: options?.panelMode ?? state?.panelMode,
|
targetId: options?.targetId ?? state?.targetId,
|
||||||
signupMethod: options?.signupMethod ?? state?.signupMethod,
|
signupMethod: options?.signupMethod ?? state?.signupMethod,
|
||||||
state,
|
state,
|
||||||
});
|
});
|
||||||
@@ -1851,7 +1843,7 @@ function validateModeSwitchState(state = {}, options = {}) {
|
|||||||
return registry.validateModeSwitch({
|
return registry.validateModeSwitch({
|
||||||
activeFlowId: options?.activeFlowId ?? state?.activeFlowId,
|
activeFlowId: options?.activeFlowId ?? state?.activeFlowId,
|
||||||
changedKeys: options?.changedKeys,
|
changedKeys: options?.changedKeys,
|
||||||
panelMode: options?.panelMode ?? state?.panelMode,
|
targetId: options?.targetId ?? state?.targetId,
|
||||||
signupMethod: options?.signupMethod ?? state?.signupMethod,
|
signupMethod: options?.signupMethod ?? state?.signupMethod,
|
||||||
state,
|
state,
|
||||||
});
|
});
|
||||||
@@ -1868,7 +1860,7 @@ function canUsePhoneSignup(state = {}) {
|
|||||||
return registry?.resolveSidepanelCapabilities
|
return registry?.resolveSidepanelCapabilities
|
||||||
? registry.resolveSidepanelCapabilities({
|
? registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId: state?.activeFlowId,
|
activeFlowId: state?.activeFlowId,
|
||||||
panelMode: state?.panelMode,
|
targetId: state?.targetId,
|
||||||
signupMethod: state?.signupMethod,
|
signupMethod: state?.signupMethod,
|
||||||
state,
|
state,
|
||||||
})
|
})
|
||||||
@@ -1898,7 +1890,7 @@ function resolveSignupMethod(state = {}) {
|
|||||||
return registry?.resolveSidepanelCapabilities
|
return registry?.resolveSidepanelCapabilities
|
||||||
? registry.resolveSidepanelCapabilities({
|
? registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId: state?.activeFlowId,
|
activeFlowId: state?.activeFlowId,
|
||||||
panelMode: state?.panelMode,
|
targetId: state?.targetId,
|
||||||
signupMethod: method,
|
signupMethod: method,
|
||||||
state,
|
state,
|
||||||
})
|
})
|
||||||
@@ -3049,18 +3041,13 @@ function normalizeStepExecutionRangeByFlow(value = {}) {
|
|||||||
|
|
||||||
function normalizePersistentSettingValue(key, value) {
|
function normalizePersistentSettingValue(key, value) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'panelMode':
|
case 'targetId':
|
||||||
return normalizePanelMode(value);
|
return String(value || '').trim().toLowerCase();
|
||||||
case 'activeFlowId':
|
case 'activeFlowId':
|
||||||
if (typeof self.MultiPageFlowRegistry?.normalizeFlowId === 'function') {
|
if (typeof self.MultiPageFlowRegistry?.normalizeFlowId === 'function') {
|
||||||
return self.MultiPageFlowRegistry.normalizeFlowId(value, DEFAULT_ACTIVE_FLOW_ID);
|
return self.MultiPageFlowRegistry.normalizeFlowId(value, DEFAULT_ACTIVE_FLOW_ID);
|
||||||
}
|
}
|
||||||
return String(value || '').trim().toLowerCase() === 'kiro' ? 'kiro' : DEFAULT_ACTIVE_FLOW_ID;
|
return String(value || '').trim().toLowerCase() === 'kiro' ? 'kiro' : DEFAULT_ACTIVE_FLOW_ID;
|
||||||
case 'kiroTargetId':
|
|
||||||
if (typeof self.MultiPageFlowRegistry?.normalizeTargetId === 'function') {
|
|
||||||
return self.MultiPageFlowRegistry.normalizeTargetId('kiro', value, 'kiro-rs');
|
|
||||||
}
|
|
||||||
return String(value || '').trim().toLowerCase() === 'kiro-rs' ? 'kiro-rs' : 'kiro-rs';
|
|
||||||
case 'kiroRsUrl':
|
case 'kiroRsUrl':
|
||||||
return String(value || '').trim();
|
return String(value || '').trim();
|
||||||
case 'kiroRsKey':
|
case 'kiroRsKey':
|
||||||
@@ -3575,7 +3562,7 @@ function buildPersistentSettingsPayload(input = {}, options = {}) {
|
|||||||
if (Object.prototype.hasOwnProperty.call(payload, 'phoneVerificationEnabled')
|
if (Object.prototype.hasOwnProperty.call(payload, 'phoneVerificationEnabled')
|
||||||
|| Object.prototype.hasOwnProperty.call(payload, 'plusModeEnabled')
|
|| Object.prototype.hasOwnProperty.call(payload, 'plusModeEnabled')
|
||||||
|| Object.prototype.hasOwnProperty.call(payload, 'signupMethod')
|
|| Object.prototype.hasOwnProperty.call(payload, 'signupMethod')
|
||||||
|| Object.prototype.hasOwnProperty.call(payload, 'panelMode')
|
|| Object.prototype.hasOwnProperty.call(payload, 'targetId')
|
||||||
|| Object.prototype.hasOwnProperty.call(payload, 'activeFlowId')) {
|
|| Object.prototype.hasOwnProperty.call(payload, 'activeFlowId')) {
|
||||||
payload.signupMethod = resolveSignupMethod(nextSignupConstraintState);
|
payload.signupMethod = resolveSignupMethod(nextSignupConstraintState);
|
||||||
}
|
}
|
||||||
@@ -3689,6 +3676,13 @@ function mergeSettingsStatePatch(baseValue = {}, patchValue = {}) {
|
|||||||
function buildSettingsStatePatchFromFlatUpdates(updates = {}) {
|
function buildSettingsStatePatchFromFlatUpdates(updates = {}) {
|
||||||
const patch = {};
|
const patch = {};
|
||||||
const hasUpdate = (key) => Object.prototype.hasOwnProperty.call(updates, key);
|
const hasUpdate = (key) => Object.prototype.hasOwnProperty.call(updates, key);
|
||||||
|
const normalizePatchFlowId = (value = '', fallback = DEFAULT_ACTIVE_FLOW_ID) => {
|
||||||
|
if (typeof self.MultiPageFlowRegistry?.normalizeFlowId === 'function') {
|
||||||
|
return self.MultiPageFlowRegistry.normalizeFlowId(value, fallback);
|
||||||
|
}
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
return normalized || String(fallback || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase() || DEFAULT_ACTIVE_FLOW_ID;
|
||||||
|
};
|
||||||
const assignIfUpdated = (key, path) => {
|
const assignIfUpdated = (key, path) => {
|
||||||
if (hasUpdate(key)) {
|
if (hasUpdate(key)) {
|
||||||
setSettingsStatePatchValue(patch, path, updates[key]);
|
setSettingsStatePatchValue(patch, path, updates[key]);
|
||||||
@@ -3696,26 +3690,29 @@ function buildSettingsStatePatchFromFlatUpdates(updates = {}) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
assignIfUpdated('activeFlowId', ['activeFlowId']);
|
assignIfUpdated('activeFlowId', ['activeFlowId']);
|
||||||
if (hasUpdate('openaiIntegrationTargetId') || hasUpdate('panelMode')) {
|
if (hasUpdate('selectedTargetId') || hasUpdate('targetId')) {
|
||||||
|
const flowId = normalizePatchFlowId(
|
||||||
|
updates.activeFlowId ?? updates.flowId,
|
||||||
|
DEFAULT_ACTIVE_FLOW_ID
|
||||||
|
);
|
||||||
setSettingsStatePatchValue(
|
setSettingsStatePatchValue(
|
||||||
patch,
|
patch,
|
||||||
['flows', 'openai', 'integrationTargetId'],
|
['flows', flowId, 'selectedTargetId'],
|
||||||
hasUpdate('openaiIntegrationTargetId') ? updates.openaiIntegrationTargetId : updates.panelMode
|
hasUpdate('selectedTargetId') ? updates.selectedTargetId : updates.targetId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assignIfUpdated('kiroTargetId', ['flows', 'kiro', 'targetId']);
|
assignIfUpdated('vpsUrl', ['flows', 'openai', 'targets', 'cpa', 'vpsUrl']);
|
||||||
assignIfUpdated('vpsUrl', ['flows', 'openai', 'integrationTargets', 'cpa', 'vpsUrl']);
|
assignIfUpdated('vpsPassword', ['flows', 'openai', 'targets', 'cpa', 'vpsPassword']);
|
||||||
assignIfUpdated('vpsPassword', ['flows', 'openai', 'integrationTargets', 'cpa', 'vpsPassword']);
|
assignIfUpdated('localCpaStep9Mode', ['flows', 'openai', 'targets', 'cpa', 'localCpaStep9Mode']);
|
||||||
assignIfUpdated('localCpaStep9Mode', ['flows', 'openai', 'integrationTargets', 'cpa', 'localCpaStep9Mode']);
|
assignIfUpdated('sub2apiUrl', ['flows', 'openai', 'targets', 'sub2api', 'sub2apiUrl']);
|
||||||
assignIfUpdated('sub2apiUrl', ['flows', 'openai', 'integrationTargets', 'sub2api', 'sub2apiUrl']);
|
assignIfUpdated('sub2apiEmail', ['flows', 'openai', 'targets', 'sub2api', 'sub2apiEmail']);
|
||||||
assignIfUpdated('sub2apiEmail', ['flows', 'openai', 'integrationTargets', 'sub2api', 'sub2apiEmail']);
|
assignIfUpdated('sub2apiPassword', ['flows', 'openai', 'targets', 'sub2api', 'sub2apiPassword']);
|
||||||
assignIfUpdated('sub2apiPassword', ['flows', 'openai', 'integrationTargets', 'sub2api', 'sub2apiPassword']);
|
assignIfUpdated('sub2apiGroupName', ['flows', 'openai', 'targets', 'sub2api', 'sub2apiGroupName']);
|
||||||
assignIfUpdated('sub2apiGroupName', ['flows', 'openai', 'integrationTargets', 'sub2api', 'sub2apiGroupName']);
|
assignIfUpdated('sub2apiGroupNames', ['flows', 'openai', 'targets', 'sub2api', 'sub2apiGroupNames']);
|
||||||
assignIfUpdated('sub2apiGroupNames', ['flows', 'openai', 'integrationTargets', 'sub2api', 'sub2apiGroupNames']);
|
assignIfUpdated('sub2apiAccountPriority', ['flows', 'openai', 'targets', 'sub2api', 'sub2apiAccountPriority']);
|
||||||
assignIfUpdated('sub2apiAccountPriority', ['flows', 'openai', 'integrationTargets', 'sub2api', 'sub2apiAccountPriority']);
|
assignIfUpdated('sub2apiDefaultProxyName', ['flows', 'openai', 'targets', 'sub2api', 'sub2apiDefaultProxyName']);
|
||||||
assignIfUpdated('sub2apiDefaultProxyName', ['flows', 'openai', 'integrationTargets', 'sub2api', 'sub2apiDefaultProxyName']);
|
assignIfUpdated('codex2apiUrl', ['flows', 'openai', 'targets', 'codex2api', 'codex2apiUrl']);
|
||||||
assignIfUpdated('codex2apiUrl', ['flows', 'openai', 'integrationTargets', 'codex2api', 'codex2apiUrl']);
|
assignIfUpdated('codex2apiAdminKey', ['flows', 'openai', 'targets', 'codex2api', 'codex2apiAdminKey']);
|
||||||
assignIfUpdated('codex2apiAdminKey', ['flows', 'openai', 'integrationTargets', 'codex2api', 'codex2apiAdminKey']);
|
|
||||||
assignIfUpdated('customPassword', ['services', 'account', 'customPassword']);
|
assignIfUpdated('customPassword', ['services', 'account', 'customPassword']);
|
||||||
assignIfUpdated('signupMethod', ['flows', 'openai', 'signup', 'signupMethod']);
|
assignIfUpdated('signupMethod', ['flows', 'openai', 'signup', 'signupMethod']);
|
||||||
assignIfUpdated('phoneVerificationEnabled', ['flows', 'openai', 'signup', 'phoneVerificationEnabled']);
|
assignIfUpdated('phoneVerificationEnabled', ['flows', 'openai', 'signup', 'phoneVerificationEnabled']);
|
||||||
@@ -3850,6 +3847,18 @@ function buildAutoRunFreshResetSettingsState(prevState = {}, activeFlowId = DEFA
|
|||||||
const currentSettingsState = isPlainObjectValue(prevState?.settingsState)
|
const currentSettingsState = isPlainObjectValue(prevState?.settingsState)
|
||||||
? prevState.settingsState
|
? prevState.settingsState
|
||||||
: {};
|
: {};
|
||||||
|
const settingsSchemaApi = typeof getSettingsSchemaApi === 'function'
|
||||||
|
? getSettingsSchemaApi()
|
||||||
|
: null;
|
||||||
|
const normalizedCurrentSettingsState = settingsSchemaApi?.normalizeSettingsState
|
||||||
|
? settingsSchemaApi.normalizeSettingsState({
|
||||||
|
...prevState,
|
||||||
|
activeFlowId,
|
||||||
|
settingsState: currentSettingsState,
|
||||||
|
}, {
|
||||||
|
activeFlowId,
|
||||||
|
})
|
||||||
|
: currentSettingsState;
|
||||||
const normalizedStepExecutionRangeByFlow = normalizeStepExecutionRangeByFlow(prevState?.stepExecutionRangeByFlow || {});
|
const normalizedStepExecutionRangeByFlow = normalizeStepExecutionRangeByFlow(prevState?.stepExecutionRangeByFlow || {});
|
||||||
const nextSettingsStatePatch = {
|
const nextSettingsStatePatch = {
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
@@ -3868,7 +3877,9 @@ function buildAutoRunFreshResetSettingsState(prevState = {}, activeFlowId = DEFA
|
|||||||
},
|
},
|
||||||
flows: {
|
flows: {
|
||||||
openai: {
|
openai: {
|
||||||
integrationTargetId: prevState?.openaiIntegrationTargetId || prevState?.panelMode,
|
selectedTargetId: settingsSchemaApi?.getSelectedTargetId
|
||||||
|
? settingsSchemaApi.getSelectedTargetId(normalizedCurrentSettingsState, 'openai')
|
||||||
|
: undefined,
|
||||||
autoRun: normalizedStepExecutionRangeByFlow.openai
|
autoRun: normalizedStepExecutionRangeByFlow.openai
|
||||||
? {
|
? {
|
||||||
stepExecutionRange: normalizedStepExecutionRangeByFlow.openai,
|
stepExecutionRange: normalizedStepExecutionRangeByFlow.openai,
|
||||||
@@ -3876,7 +3887,9 @@ function buildAutoRunFreshResetSettingsState(prevState = {}, activeFlowId = DEFA
|
|||||||
: undefined,
|
: undefined,
|
||||||
},
|
},
|
||||||
kiro: {
|
kiro: {
|
||||||
targetId: prevState?.kiroTargetId,
|
selectedTargetId: settingsSchemaApi?.getSelectedTargetId
|
||||||
|
? settingsSchemaApi.getSelectedTargetId(normalizedCurrentSettingsState, 'kiro')
|
||||||
|
: undefined,
|
||||||
autoRun: normalizedStepExecutionRangeByFlow.kiro
|
autoRun: normalizedStepExecutionRangeByFlow.kiro
|
||||||
? {
|
? {
|
||||||
stepExecutionRange: normalizedStepExecutionRangeByFlow.kiro,
|
stepExecutionRange: normalizedStepExecutionRangeByFlow.kiro,
|
||||||
@@ -3918,15 +3931,14 @@ function buildFreshAutoRunKeepState(prevState = {}) {
|
|||||||
|
|
||||||
keepState.activeFlowId = activeFlowId;
|
keepState.activeFlowId = activeFlowId;
|
||||||
keepState.flowId = activeFlowId;
|
keepState.flowId = activeFlowId;
|
||||||
if (Object.prototype.hasOwnProperty.call(sourceState, 'panelMode')) {
|
const settingsSchemaApi = typeof getSettingsSchemaApi === 'function'
|
||||||
keepState.panelMode = normalizePanelMode(sourceState.panelMode);
|
? getSettingsSchemaApi()
|
||||||
|
: null;
|
||||||
|
if (settingsSchemaApi?.getSelectedTargetId) {
|
||||||
|
keepState.targetId = settingsSchemaApi.getSelectedTargetId(settingsState, activeFlowId);
|
||||||
}
|
}
|
||||||
if (typeof kiroStateHelpers?.buildFreshKeepState === 'function') {
|
if (typeof kiroStateHelpers?.buildFreshKeepState === 'function') {
|
||||||
Object.assign(keepState, kiroStateHelpers.buildFreshKeepState(sourceState));
|
Object.assign(keepState, kiroStateHelpers.buildFreshKeepState(sourceState));
|
||||||
} else if (Object.prototype.hasOwnProperty.call(sourceState, 'kiroTargetId')) {
|
|
||||||
keepState.kiroTargetId = self.MultiPageFlowRegistry?.normalizeTargetId
|
|
||||||
? self.MultiPageFlowRegistry.normalizeTargetId('kiro', sourceState.kiroTargetId, 'kiro-rs')
|
|
||||||
: String(sourceState.kiroTargetId || 'kiro-rs').trim().toLowerCase();
|
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(sourceState, 'settingsSchemaVersion')) {
|
if (Object.prototype.hasOwnProperty.call(sourceState, 'settingsSchemaVersion')) {
|
||||||
keepState.settingsSchemaVersion = Number(sourceState.settingsSchemaVersion) || 0;
|
keepState.settingsSchemaVersion = Number(sourceState.settingsSchemaVersion) || 0;
|
||||||
@@ -4172,7 +4184,15 @@ async function importSettingsBundle(configBundle) {
|
|||||||
throw new Error('\u914d\u7f6e\u6587\u4ef6\u7f3a\u5c11 settings \u914d\u7f6e\u6bb5\u3002');
|
throw new Error('\u914d\u7f6e\u6587\u4ef6\u7f3a\u5c11 settings \u914d\u7f6e\u6bb5\u3002');
|
||||||
}
|
}
|
||||||
|
|
||||||
const importedSettings = buildPersistentSettingsPayload(configBundle.settings, {
|
const settingsImporter = self.MultiPageLegacySettingsImporter?.createSettingsImporter?.({
|
||||||
|
flowRegistry: self.MultiPageFlowRegistry,
|
||||||
|
settingsSchemaApi: typeof getSettingsSchemaApi === 'function' ? getSettingsSchemaApi() : null,
|
||||||
|
defaultFlowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
|
}) || null;
|
||||||
|
const importedSettingsSource = typeof settingsImporter?.importSettings === 'function'
|
||||||
|
? settingsImporter.importSettings(configBundle.settings)
|
||||||
|
: configBundle.settings;
|
||||||
|
const importedSettings = buildPersistentSettingsPayload(importedSettingsSource, {
|
||||||
fillDefaults: true,
|
fillDefaults: true,
|
||||||
requireKnownKeys: true,
|
requireKnownKeys: true,
|
||||||
});
|
});
|
||||||
@@ -4190,7 +4210,7 @@ async function importSettingsBundle(configBundle) {
|
|||||||
Object.prototype.hasOwnProperty.call(importedSettings, 'phoneVerificationEnabled')
|
Object.prototype.hasOwnProperty.call(importedSettings, 'phoneVerificationEnabled')
|
||||||
|| Object.prototype.hasOwnProperty.call(importedSettings, 'plusModeEnabled')
|
|| Object.prototype.hasOwnProperty.call(importedSettings, 'plusModeEnabled')
|
||||||
|| Object.prototype.hasOwnProperty.call(importedSettings, 'signupMethod')
|
|| Object.prototype.hasOwnProperty.call(importedSettings, 'signupMethod')
|
||||||
|| Object.prototype.hasOwnProperty.call(importedSettings, 'panelMode')
|
|| Object.prototype.hasOwnProperty.call(importedSettings, 'targetId')
|
||||||
|| Object.prototype.hasOwnProperty.call(importedSettings, 'activeFlowId')
|
|| Object.prototype.hasOwnProperty.call(importedSettings, 'activeFlowId')
|
||||||
|| Object.prototype.hasOwnProperty.call(importedSettings, 'accountContributionEnabled')
|
|| Object.prototype.hasOwnProperty.call(importedSettings, 'accountContributionEnabled')
|
||||||
) {
|
) {
|
||||||
@@ -4436,7 +4456,7 @@ function buildAccountContributionState(enabled, persistedSettings = {}, currentS
|
|||||||
...(routing ? {
|
...(routing ? {
|
||||||
contributionSource: routing.source,
|
contributionSource: routing.source,
|
||||||
contributionTargetGroupName: routing.targetGroupName,
|
contributionTargetGroupName: routing.targetGroupName,
|
||||||
panelMode: routing.source,
|
targetId: routing.source,
|
||||||
} : {}),
|
} : {}),
|
||||||
customPassword: '',
|
customPassword: '',
|
||||||
accountRunHistoryTextEnabled: false,
|
accountRunHistoryTextEnabled: false,
|
||||||
@@ -4449,7 +4469,7 @@ function buildAccountContributionState(enabled, persistedSettings = {}, currentS
|
|||||||
accountContributionExpected: false,
|
accountContributionExpected: false,
|
||||||
contributionAdapterId: '',
|
contributionAdapterId: '',
|
||||||
flowContributionRuntime: {},
|
flowContributionRuntime: {},
|
||||||
panelMode: persistedSettings.panelMode || DEFAULT_STATE.panelMode,
|
targetId: persistedSettings.targetId || DEFAULT_STATE.targetId,
|
||||||
customPassword: persistedSettings.customPassword || '',
|
customPassword: persistedSettings.customPassword || '',
|
||||||
accountRunHistoryTextEnabled: Boolean(persistedSettings.accountRunHistoryTextEnabled),
|
accountRunHistoryTextEnabled: Boolean(persistedSettings.accountRunHistoryTextEnabled),
|
||||||
};
|
};
|
||||||
@@ -4472,7 +4492,7 @@ async function setAccountContributionMode(enabled, options = {}) {
|
|||||||
}
|
}
|
||||||
broadcastDataUpdate({
|
broadcastDataUpdate({
|
||||||
...contributionBroadcast,
|
...contributionBroadcast,
|
||||||
panelMode: nextState.panelMode,
|
targetId: nextState.targetId,
|
||||||
customPassword: nextState.customPassword,
|
customPassword: nextState.customPassword,
|
||||||
accountRunHistoryTextEnabled: nextState.accountRunHistoryTextEnabled,
|
accountRunHistoryTextEnabled: nextState.accountRunHistoryTextEnabled,
|
||||||
accountRunHistoryHelperBaseUrl: nextState.accountRunHistoryHelperBaseUrl,
|
accountRunHistoryHelperBaseUrl: nextState.accountRunHistoryHelperBaseUrl,
|
||||||
@@ -8542,10 +8562,10 @@ function getPanelMode(state = {}) {
|
|||||||
if (typeof navigationUtils !== 'undefined' && navigationUtils?.getPanelMode) {
|
if (typeof navigationUtils !== 'undefined' && navigationUtils?.getPanelMode) {
|
||||||
return navigationUtils.getPanelMode(state);
|
return navigationUtils.getPanelMode(state);
|
||||||
}
|
}
|
||||||
if (state.panelMode === 'sub2api') {
|
if (state.targetId === 'sub2api') {
|
||||||
return 'sub2api';
|
return 'sub2api';
|
||||||
}
|
}
|
||||||
if (state.panelMode === 'codex2api') {
|
if (state.targetId === 'codex2api') {
|
||||||
return 'codex2api';
|
return 'codex2api';
|
||||||
}
|
}
|
||||||
return 'cpa';
|
return 'cpa';
|
||||||
@@ -8661,7 +8681,6 @@ function matchesSourceUrlFamily(source, candidateUrl, referenceUrl) {
|
|||||||
const reference = parseUrlSafely(referenceUrl);
|
const reference = parseUrlSafely(referenceUrl);
|
||||||
switch (source) {
|
switch (source) {
|
||||||
case 'openai-auth':
|
case 'openai-auth':
|
||||||
case 'signup-page':
|
|
||||||
return isSignupPageHost(candidate.hostname) || isSignupEntryHost(candidate.hostname);
|
return isSignupPageHost(candidate.hostname) || isSignupEntryHost(candidate.hostname);
|
||||||
case 'duck-mail':
|
case 'duck-mail':
|
||||||
return candidate.hostname === 'duckduckgo.com' && candidate.pathname.startsWith('/email/');
|
return candidate.hostname === 'duckduckgo.com' && candidate.pathname.startsWith('/email/');
|
||||||
@@ -8975,7 +8994,6 @@ function getSourceLabel(source) {
|
|||||||
'openai-auth': '认证页',
|
'openai-auth': '认证页',
|
||||||
'gmail-mail': 'Gmail 邮箱',
|
'gmail-mail': 'Gmail 邮箱',
|
||||||
'sidepanel': '侧边栏',
|
'sidepanel': '侧边栏',
|
||||||
'signup-page': '认证页',
|
|
||||||
'vps-panel': 'CPA 面板',
|
'vps-panel': 'CPA 面板',
|
||||||
'sub2api-panel': 'SUB2API 后台',
|
'sub2api-panel': 'SUB2API 后台',
|
||||||
'codex2api-panel': 'Codex2API 后台',
|
'codex2api-panel': 'Codex2API 后台',
|
||||||
@@ -11544,7 +11562,7 @@ async function executeNodeAndWait(nodeId, delayAfter = 2000) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (normalizedNodeId === 'fill-profile') {
|
if (normalizedNodeId === 'fill-profile') {
|
||||||
const signupTabId = await getTabId('signup-page');
|
const signupTabId = await getTabId('openai-auth');
|
||||||
if (signupTabId) {
|
if (signupTabId) {
|
||||||
await addLog('自动运行:填写资料节点已收到完成信号,正在等待当前页面完成加载并稳定...', 'info');
|
await addLog('自动运行:填写资料节点已收到完成信号,正在等待当前页面完成加载并稳定...', 'info');
|
||||||
await waitForTabStableComplete(signupTabId, {
|
await waitForTabStableComplete(signupTabId, {
|
||||||
@@ -12953,7 +12971,7 @@ async function runAutoSequenceFromNodeGraph(startNodeId, context = {}) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const signupTabId = await getTabId('signup-page');
|
const signupTabId = await getTabId('openai-auth');
|
||||||
if (signupTabId) {
|
if (signupTabId) {
|
||||||
await chrome.tabs.update(signupTabId, { active: true });
|
await chrome.tabs.update(signupTabId, { active: true });
|
||||||
}
|
}
|
||||||
@@ -13236,9 +13254,9 @@ async function resumeAutoRun() {
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
const SIGNUP_ENTRY_URL = 'https://chatgpt.com/';
|
const SIGNUP_ENTRY_URL = 'https://chatgpt.com/';
|
||||||
const SIGNUP_PAGE_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'content/auth-page-recovery.js', 'content/phone-country-utils.js', 'content/phone-auth.js', 'content/signup-page.js'];
|
const OPENAI_AUTH_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'flows/openai/content/auth-page-recovery.js', 'flows/openai/content/phone-country-utils.js', 'flows/openai/content/phone-auth.js', 'flows/openai/content/openai-auth.js'];
|
||||||
const KIRO_REGISTER_INJECT_FILES = ['shared/source-registry.js', 'shared/kiro-timeouts.js', 'content/utils.js', 'content/kiro/register-page.js'];
|
const KIRO_REGISTER_INJECT_FILES = ['flows/openai/index.js', 'flows/kiro/index.js', 'flows/index.js', 'core/flow-kernel/flow-registry.js', 'core/flow-kernel/source-registry.js', 'shared/kiro-timeouts.js', 'content/utils.js', 'flows/kiro/content/register-page.js'];
|
||||||
const KIRO_DESKTOP_AUTHORIZE_INJECT_FILES = ['shared/source-registry.js', 'shared/kiro-timeouts.js', 'content/utils.js', 'content/kiro/desktop-authorize-page.js'];
|
const KIRO_DESKTOP_AUTHORIZE_INJECT_FILES = ['flows/openai/index.js', 'flows/kiro/index.js', 'flows/index.js', 'core/flow-kernel/flow-registry.js', 'core/flow-kernel/source-registry.js', 'shared/kiro-timeouts.js', 'content/utils.js', 'flows/kiro/content/desktop-authorize-page.js'];
|
||||||
const panelBridge = self.MultiPageBackgroundPanelBridge?.createPanelBridge({
|
const panelBridge = self.MultiPageBackgroundPanelBridge?.createPanelBridge({
|
||||||
chrome,
|
chrome,
|
||||||
addLog,
|
addLog,
|
||||||
@@ -13287,7 +13305,7 @@ const signupFlowHelpers = self.MultiPageSignupFlowHelpers?.createSignupFlowHelpe
|
|||||||
setEmailState,
|
setEmailState,
|
||||||
setState,
|
setState,
|
||||||
SIGNUP_ENTRY_URL,
|
SIGNUP_ENTRY_URL,
|
||||||
SIGNUP_PAGE_INJECT_FILES,
|
OPENAI_AUTH_INJECT_FILES,
|
||||||
waitForTabStableComplete,
|
waitForTabStableComplete,
|
||||||
waitForTabUrlMatch,
|
waitForTabUrlMatch,
|
||||||
});
|
});
|
||||||
@@ -13418,7 +13436,7 @@ const step2Executor = self.MultiPageBackgroundStep2?.createStep2Executor({
|
|||||||
resolveSignupMethod,
|
resolveSignupMethod,
|
||||||
resolveSignupEmailForFlow,
|
resolveSignupEmailForFlow,
|
||||||
sendToContentScriptResilient,
|
sendToContentScriptResilient,
|
||||||
SIGNUP_PAGE_INJECT_FILES,
|
OPENAI_AUTH_INJECT_FILES,
|
||||||
waitForTabStableComplete,
|
waitForTabStableComplete,
|
||||||
});
|
});
|
||||||
const step3Executor = self.MultiPageBackgroundStep3?.createStep3Executor({
|
const step3Executor = self.MultiPageBackgroundStep3?.createStep3Executor({
|
||||||
@@ -13432,7 +13450,7 @@ const step3Executor = self.MultiPageBackgroundStep3?.createStep3Executor({
|
|||||||
sendToContentScript,
|
sendToContentScript,
|
||||||
setPasswordState,
|
setPasswordState,
|
||||||
setState,
|
setState,
|
||||||
SIGNUP_PAGE_INJECT_FILES,
|
OPENAI_AUTH_INJECT_FILES,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function ensureIcloudMailSessionForVerification(options = {}) {
|
async function ensureIcloudMailSessionForVerification(options = {}) {
|
||||||
@@ -13917,7 +13935,7 @@ const messageRouter = self.MultiPageBackgroundMessageRouter?.createMessageRouter
|
|||||||
},
|
},
|
||||||
finalizeStep3Completion: async () => {
|
finalizeStep3Completion: async () => {
|
||||||
const currentState = await getState();
|
const currentState = await getState();
|
||||||
const signupTabId = await getTabId('signup-page');
|
const signupTabId = await getTabId('openai-auth');
|
||||||
return signupFlowHelpers.finalizeSignupPasswordSubmitInTab(
|
return signupFlowHelpers.finalizeSignupPasswordSubmitInTab(
|
||||||
signupTabId,
|
signupTabId,
|
||||||
currentState.password || currentState.customPassword || '',
|
currentState.password || currentState.customPassword || '',
|
||||||
@@ -14143,7 +14161,7 @@ async function executeStep2(state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Step 3: Fill Password (via signup-page.js)
|
// Step 3: Fill Password (via openai-auth.js)
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
async function executeStep3(state) {
|
async function executeStep3(state) {
|
||||||
@@ -14151,7 +14169,7 @@ async function executeStep3(state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Step 4: Get Signup Verification Code (qq-mail.js polls, then fills in signup-page.js)
|
// Step 4: Get Signup Verification Code (qq-mail.js polls, then fills in openai-auth.js)
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
function getMailConfig(state) {
|
function getMailConfig(state) {
|
||||||
@@ -14305,7 +14323,7 @@ async function executeStep4(state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Step 5: Fill Name & Birthday (via signup-page.js)
|
// Step 5: Fill Name & Birthday (via openai-auth.js)
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
async function executeStep5(state) {
|
async function executeStep5(state) {
|
||||||
@@ -14659,7 +14677,7 @@ async function getLoginAuthStateFromContent(options = {}) {
|
|||||||
const logStep = visibleStep > 0 ? visibleStep : null;
|
const logStep = visibleStep > 0 ? visibleStep : null;
|
||||||
const { logMessage = '认证页正在切换,等待页面重新就绪后继续确认验证码页状态...' } = options;
|
const { logMessage = '认证页正在切换,等待页面重新就绪后继续确认验证码页状态...' } = options;
|
||||||
const result = await sendToContentScriptResilient(
|
const result = await sendToContentScriptResilient(
|
||||||
'signup-page',
|
'openai-auth',
|
||||||
{
|
{
|
||||||
type: 'GET_LOGIN_AUTH_STATE',
|
type: 'GET_LOGIN_AUTH_STATE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -14684,7 +14702,7 @@ async function getLoginAuthStateFromContent(options = {}) {
|
|||||||
|
|
||||||
async function getStep5SubmitStateFromContent(options = {}) {
|
async function getStep5SubmitStateFromContent(options = {}) {
|
||||||
const result = await sendToContentScriptResilient(
|
const result = await sendToContentScriptResilient(
|
||||||
'signup-page',
|
'openai-auth',
|
||||||
{
|
{
|
||||||
type: 'GET_STEP5_SUBMIT_STATE',
|
type: 'GET_STEP5_SUBMIT_STATE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -14709,7 +14727,7 @@ async function getStep5SubmitStateFromContent(options = {}) {
|
|||||||
|
|
||||||
async function recoverStep5SubmitRetryPageOnTab(options = {}) {
|
async function recoverStep5SubmitRetryPageOnTab(options = {}) {
|
||||||
const result = await sendToContentScriptResilient(
|
const result = await sendToContentScriptResilient(
|
||||||
'signup-page',
|
'openai-auth',
|
||||||
{
|
{
|
||||||
type: 'RECOVER_STEP5_SUBMIT_RETRY_PAGE',
|
type: 'RECOVER_STEP5_SUBMIT_RETRY_PAGE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -14849,7 +14867,7 @@ async function ensureStep8VerificationPageReady(options = {}) {
|
|||||||
const recoverTimeoutMs = 15000;
|
const recoverTimeoutMs = 15000;
|
||||||
if (typeof sendToContentScriptResilient === 'function') {
|
if (typeof sendToContentScriptResilient === 'function') {
|
||||||
recoverResult = await sendToContentScriptResilient(
|
recoverResult = await sendToContentScriptResilient(
|
||||||
'signup-page',
|
'openai-auth',
|
||||||
recoverMessage,
|
recoverMessage,
|
||||||
{
|
{
|
||||||
timeoutMs: recoverTimeoutMs,
|
timeoutMs: recoverTimeoutMs,
|
||||||
@@ -14861,7 +14879,7 @@ async function ensureStep8VerificationPageReady(options = {}) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if (typeof sendToContentScript === 'function') {
|
} else if (typeof sendToContentScript === 'function') {
|
||||||
recoverResult = await sendToContentScript('signup-page', recoverMessage, {
|
recoverResult = await sendToContentScript('openai-auth', recoverMessage, {
|
||||||
responseTimeoutMs: recoverTimeoutMs,
|
responseTimeoutMs: recoverTimeoutMs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -15098,9 +15116,9 @@ async function shouldDeferStep9CallbackTimeout(details = {}) {
|
|||||||
|
|
||||||
async function ensureStep8SignupPageReady(tabId, options = {}) {
|
async function ensureStep8SignupPageReady(tabId, options = {}) {
|
||||||
const visibleStep = Math.floor(Number(options.visibleStep || options.logStep || options.step) || 0);
|
const visibleStep = Math.floor(Number(options.visibleStep || options.logStep || options.step) || 0);
|
||||||
await ensureContentScriptReadyOnTab('signup-page', tabId, {
|
await ensureContentScriptReadyOnTab('openai-auth', tabId, {
|
||||||
inject: SIGNUP_PAGE_INJECT_FILES,
|
inject: OPENAI_AUTH_INJECT_FILES,
|
||||||
injectSource: 'signup-page',
|
injectSource: 'openai-auth',
|
||||||
timeoutMs: options.timeoutMs ?? 15000,
|
timeoutMs: options.timeoutMs ?? 15000,
|
||||||
retryDelayMs: options.retryDelayMs ?? 600,
|
retryDelayMs: options.retryDelayMs ?? 600,
|
||||||
logMessage: options.logMessage || '',
|
logMessage: options.logMessage || '',
|
||||||
@@ -15142,7 +15160,7 @@ async function readAuthTabSnapshot(tabId) {
|
|||||||
|
|
||||||
async function getStep8PageState(tabId, responseTimeoutMs = 1500, visibleStep = 9) {
|
async function getStep8PageState(tabId, responseTimeoutMs = 1500, visibleStep = 9) {
|
||||||
try {
|
try {
|
||||||
const result = await sendTabMessageWithTimeout(tabId, 'signup-page', {
|
const result = await sendTabMessageWithTimeout(tabId, 'openai-auth', {
|
||||||
type: 'STEP8_GET_STATE',
|
type: 'STEP8_GET_STATE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: { visibleStep },
|
payload: { visibleStep },
|
||||||
@@ -15219,7 +15237,7 @@ async function prepareStep8DebuggerClick(tabId, options = {}) {
|
|||||||
logStepKey: 'confirm-oauth',
|
logStepKey: 'confirm-oauth',
|
||||||
logMessage: '认证页内容脚本已失联,正在恢复后继续定位按钮...',
|
logMessage: '认证页内容脚本已失联,正在恢复后继续定位按钮...',
|
||||||
});
|
});
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'STEP8_FIND_AND_CLICK',
|
type: 'STEP8_FIND_AND_CLICK',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: { visibleStep, nodeId: 'confirm-oauth' },
|
payload: { visibleStep, nodeId: 'confirm-oauth' },
|
||||||
@@ -15249,7 +15267,7 @@ async function triggerStep8ContentStrategy(tabId, strategy, options = {}) {
|
|||||||
logStepKey: 'confirm-oauth',
|
logStepKey: 'confirm-oauth',
|
||||||
logMessage: '认证页内容脚本已失联,正在恢复后继续点击“继续”按钮...',
|
logMessage: '认证页内容脚本已失联,正在恢复后继续点击“继续”按钮...',
|
||||||
});
|
});
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'STEP8_TRIGGER_CONTINUE',
|
type: 'STEP8_TRIGGER_CONTINUE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: {
|
payload: {
|
||||||
@@ -15287,7 +15305,7 @@ async function recoverAuthRetryPageOnTab(tabId, payload = {}, options = {}) {
|
|||||||
logStepKey: 'confirm-oauth',
|
logStepKey: 'confirm-oauth',
|
||||||
logMessage: options.readyLogMessage || '认证页内容脚本已失联,正在恢复后继续处理重试页...',
|
logMessage: options.readyLogMessage || '认证页内容脚本已失联,正在恢复后继续处理重试页...',
|
||||||
});
|
});
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'RECOVER_AUTH_RETRY_PAGE',
|
type: 'RECOVER_AUTH_RETRY_PAGE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: { nodeId: 'confirm-oauth', ...(payload || {}) },
|
payload: { nodeId: 'confirm-oauth', ...(payload || {}) },
|
||||||
|
|||||||
@@ -106,8 +106,7 @@
|
|||||||
return {
|
return {
|
||||||
activeFlowId: state.activeFlowId,
|
activeFlowId: state.activeFlowId,
|
||||||
flowId: state.flowId || state.activeFlowId,
|
flowId: state.flowId || state.activeFlowId,
|
||||||
panelMode: state.panelMode,
|
targetId: state.targetId,
|
||||||
kiroTargetId: state.kiroTargetId,
|
|
||||||
vpsUrl: state.vpsUrl,
|
vpsUrl: state.vpsUrl,
|
||||||
vpsPassword: state.vpsPassword,
|
vpsPassword: state.vpsPassword,
|
||||||
customPassword: state.customPassword,
|
customPassword: state.customPassword,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
'openai-auth': '认证页',
|
'openai-auth': '认证页',
|
||||||
'gmail-mail': 'Gmail 邮箱',
|
'gmail-mail': 'Gmail 邮箱',
|
||||||
'sidepanel': '侧边栏',
|
'sidepanel': '侧边栏',
|
||||||
'signup-page': '认证页',
|
|
||||||
'vps-panel': 'CPA 面板',
|
'vps-panel': 'CPA 面板',
|
||||||
'sub2api-panel': 'SUB2API 后台',
|
'sub2api-panel': 'SUB2API 后台',
|
||||||
'codex2api-panel': 'Codex2API 后台',
|
'codex2api-panel': 'Codex2API 后台',
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
}
|
}
|
||||||
return capabilityRegistry.validateAutoRunStart({
|
return capabilityRegistry.validateAutoRunStart({
|
||||||
activeFlowId: options?.activeFlowId ?? validationState?.activeFlowId,
|
activeFlowId: options?.activeFlowId ?? validationState?.activeFlowId,
|
||||||
panelMode: options?.panelMode ?? validationState?.panelMode,
|
targetId: options?.targetId ?? validationState?.targetId,
|
||||||
signupMethod: options?.signupMethod ?? validationState?.signupMethod,
|
signupMethod: options?.signupMethod ?? validationState?.signupMethod,
|
||||||
state: validationState,
|
state: validationState,
|
||||||
});
|
});
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
return capabilityRegistry.validateModeSwitch({
|
return capabilityRegistry.validateModeSwitch({
|
||||||
activeFlowId: options?.activeFlowId ?? validationState?.activeFlowId,
|
activeFlowId: options?.activeFlowId ?? validationState?.activeFlowId,
|
||||||
changedKeys: options?.changedKeys,
|
changedKeys: options?.changedKeys,
|
||||||
panelMode: options?.panelMode ?? validationState?.panelMode,
|
targetId: options?.targetId ?? validationState?.targetId,
|
||||||
signupMethod: options?.signupMethod ?? validationState?.signupMethod,
|
signupMethod: options?.signupMethod ?? validationState?.signupMethod,
|
||||||
state: validationState,
|
state: validationState,
|
||||||
});
|
});
|
||||||
@@ -217,10 +217,6 @@
|
|||||||
return String(targetId || fallbackSourceId).trim().toLowerCase() || fallbackSourceId;
|
return String(targetId || fallbackSourceId).trim().toLowerCase() || fallbackSourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapAutoRunTargetIdToPanelMode(targetId = '', fallback = 'cpa') {
|
|
||||||
return String(targetId || fallback || 'cpa').trim().toLowerCase() || 'cpa';
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildAutoRunFlowStateUpdates(payload = {}) {
|
function buildAutoRunFlowStateUpdates(payload = {}) {
|
||||||
const hasActiveFlowId = Object.prototype.hasOwnProperty.call(payload, 'activeFlowId');
|
const hasActiveFlowId = Object.prototype.hasOwnProperty.call(payload, 'activeFlowId');
|
||||||
const hasTargetId = Object.prototype.hasOwnProperty.call(payload, 'targetId');
|
const hasTargetId = Object.prototype.hasOwnProperty.call(payload, 'targetId');
|
||||||
@@ -233,11 +229,11 @@
|
|||||||
flowId: activeFlowId,
|
flowId: activeFlowId,
|
||||||
};
|
};
|
||||||
if (hasTargetId) {
|
if (hasTargetId) {
|
||||||
if (activeFlowId === 'kiro') {
|
updates.targetId = normalizeMessageTargetId(
|
||||||
updates.kiroTargetId = normalizeMessageTargetId('kiro', payload.targetId, 'kiro-rs');
|
activeFlowId,
|
||||||
} else {
|
payload.targetId,
|
||||||
updates.panelMode = mapAutoRunTargetIdToPanelMode(payload.targetId, 'cpa');
|
activeFlowId === 'kiro' ? 'kiro-rs' : 'cpa'
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
return updates;
|
return updates;
|
||||||
}
|
}
|
||||||
@@ -297,10 +293,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const signupTabId = typeof getTabId === 'function'
|
const signupTabId = typeof getTabId === 'function'
|
||||||
? await getTabId('signup-page')
|
? await getTabId('openai-auth')
|
||||||
: null;
|
: null;
|
||||||
const signupTabAlive = signupTabId && typeof isTabAlive === 'function'
|
const signupTabAlive = signupTabId && typeof isTabAlive === 'function'
|
||||||
? await isTabAlive('signup-page')
|
? await isTabAlive('openai-auth')
|
||||||
: Boolean(signupTabId);
|
: Boolean(signupTabId);
|
||||||
|
|
||||||
if (!signupTabId || !signupTabAlive) {
|
if (!signupTabId || !signupTabAlive) {
|
||||||
@@ -1309,7 +1305,7 @@
|
|||||||
const state = await getState();
|
const state = await getState();
|
||||||
const autoRunStartValidation = validateAutoRunStart(state, {
|
const autoRunStartValidation = validateAutoRunStart(state, {
|
||||||
activeFlowId: autoRunFlowStateUpdates.activeFlowId ?? state?.activeFlowId,
|
activeFlowId: autoRunFlowStateUpdates.activeFlowId ?? state?.activeFlowId,
|
||||||
panelMode: autoRunFlowStateUpdates.panelMode ?? state?.panelMode,
|
targetId: autoRunFlowStateUpdates.targetId ?? state?.targetId,
|
||||||
state,
|
state,
|
||||||
});
|
});
|
||||||
if (autoRunStartValidation?.ok === false) {
|
if (autoRunStartValidation?.ok === false) {
|
||||||
@@ -1352,7 +1348,7 @@
|
|||||||
const state = await getState();
|
const state = await getState();
|
||||||
const autoRunStartValidation = validateAutoRunStart(state, {
|
const autoRunStartValidation = validateAutoRunStart(state, {
|
||||||
activeFlowId: autoRunFlowStateUpdates.activeFlowId ?? state?.activeFlowId,
|
activeFlowId: autoRunFlowStateUpdates.activeFlowId ?? state?.activeFlowId,
|
||||||
panelMode: autoRunFlowStateUpdates.panelMode ?? state?.panelMode,
|
targetId: autoRunFlowStateUpdates.targetId ?? state?.targetId,
|
||||||
state,
|
state,
|
||||||
});
|
});
|
||||||
if (autoRunStartValidation?.ok === false) {
|
if (autoRunStartValidation?.ok === false) {
|
||||||
@@ -1451,7 +1447,7 @@
|
|||||||
Object.prototype.hasOwnProperty.call(updates, 'phoneVerificationEnabled')
|
Object.prototype.hasOwnProperty.call(updates, 'phoneVerificationEnabled')
|
||||||
|| Object.prototype.hasOwnProperty.call(updates, 'plusModeEnabled')
|
|| Object.prototype.hasOwnProperty.call(updates, 'plusModeEnabled')
|
||||||
|| Object.prototype.hasOwnProperty.call(updates, 'signupMethod')
|
|| Object.prototype.hasOwnProperty.call(updates, 'signupMethod')
|
||||||
|| Object.prototype.hasOwnProperty.call(updates, 'panelMode')
|
|| Object.prototype.hasOwnProperty.call(updates, 'targetId')
|
||||||
|| Object.prototype.hasOwnProperty.call(updates, 'activeFlowId')
|
|| Object.prototype.hasOwnProperty.call(updates, 'activeFlowId')
|
||||||
|| Object.prototype.hasOwnProperty.call(updates, 'accountContributionEnabled')
|
|| Object.prototype.hasOwnProperty.call(updates, 'accountContributionEnabled')
|
||||||
) {
|
) {
|
||||||
@@ -1600,10 +1596,8 @@
|
|||||||
);
|
);
|
||||||
const selectedPlusAccountAccessStrategy = getPlusAccountAccessStrategyLabel(
|
const selectedPlusAccountAccessStrategy = getPlusAccountAccessStrategyLabel(
|
||||||
stateUpdates.plusAccountAccessStrategy ?? currentState?.plusAccountAccessStrategy ?? 'oauth',
|
stateUpdates.plusAccountAccessStrategy ?? currentState?.plusAccountAccessStrategy ?? 'oauth',
|
||||||
stateUpdates.panelMode
|
stateUpdates.targetId
|
||||||
?? currentState?.panelMode
|
?? currentState?.targetId
|
||||||
?? stateUpdates.openaiIntegrationTargetId
|
|
||||||
?? currentState?.openaiIntegrationTargetId
|
|
||||||
?? 'cpa'
|
?? 'cpa'
|
||||||
);
|
);
|
||||||
await addLog(
|
await addLog(
|
||||||
@@ -1620,10 +1614,8 @@
|
|||||||
} else if (plusAccountAccessStrategyChanged && nextPlusModeEnabled) {
|
} else if (plusAccountAccessStrategyChanged && nextPlusModeEnabled) {
|
||||||
const selectedPlusAccountAccessStrategy = getPlusAccountAccessStrategyLabel(
|
const selectedPlusAccountAccessStrategy = getPlusAccountAccessStrategyLabel(
|
||||||
stateUpdates.plusAccountAccessStrategy ?? currentState?.plusAccountAccessStrategy ?? 'oauth',
|
stateUpdates.plusAccountAccessStrategy ?? currentState?.plusAccountAccessStrategy ?? 'oauth',
|
||||||
stateUpdates.panelMode
|
stateUpdates.targetId
|
||||||
?? currentState?.panelMode
|
?? currentState?.targetId
|
||||||
?? stateUpdates.openaiIntegrationTargetId
|
|
||||||
?? currentState?.openaiIntegrationTargetId
|
|
||||||
?? 'cpa'
|
?? 'cpa'
|
||||||
);
|
);
|
||||||
await addLog(`Plus 账号接入策略已切换为 ${selectedPlusAccountAccessStrategy},已更新对应的 Plus 尾链。`, 'info');
|
await addLog(`Plus 账号接入策略已切换为 ${selectedPlusAccountAccessStrategy},已更新对应的 Plus 尾链。`, 'info');
|
||||||
@@ -1661,7 +1653,7 @@
|
|||||||
);
|
);
|
||||||
const targetId = normalizeMessageTargetId(
|
const targetId = normalizeMessageTargetId(
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
message.payload?.targetId || currentState?.kiroTargetId || 'kiro-rs',
|
message.payload?.targetId || currentState?.targetId || 'kiro-rs',
|
||||||
'kiro-rs'
|
'kiro-rs'
|
||||||
);
|
);
|
||||||
const nestedTargetConfig = currentState?.settingsState?.flows?.kiro?.targets?.[targetId]
|
const nestedTargetConfig = currentState?.settingsState?.flows?.kiro?.targets?.[targetId]
|
||||||
|
|||||||
@@ -42,10 +42,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getPanelMode(state = {}) {
|
function getPanelMode(state = {}) {
|
||||||
if (state.panelMode === 'sub2api') {
|
if (state.targetId === 'sub2api') {
|
||||||
return 'sub2api';
|
return 'sub2api';
|
||||||
}
|
}
|
||||||
if (state.panelMode === 'codex2api') {
|
if (state.targetId === 'codex2api') {
|
||||||
return 'codex2api';
|
return 'codex2api';
|
||||||
}
|
}
|
||||||
return 'cpa';
|
return 'cpa';
|
||||||
@@ -128,7 +128,6 @@
|
|||||||
|
|
||||||
switch (source) {
|
switch (source) {
|
||||||
case 'openai-auth':
|
case 'openai-auth':
|
||||||
case 'signup-page':
|
|
||||||
return isSignupPageHost(candidate.hostname) || isSignupEntryHost(candidate.hostname);
|
return isSignupPageHost(candidate.hostname) || isSignupEntryHost(candidate.hostname);
|
||||||
case 'duck-mail':
|
case 'duck-mail':
|
||||||
return candidate.hostname === 'duckduckgo.com' && candidate.pathname.startsWith('/email/');
|
return candidate.hostname === 'duckduckgo.com' && candidate.pathname.startsWith('/email/');
|
||||||
|
|||||||
@@ -4585,7 +4585,7 @@
|
|||||||
visibleStep,
|
visibleStep,
|
||||||
logStepKey: 'phone-verification',
|
logStepKey: 'phone-verification',
|
||||||
});
|
});
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'STEP8_GET_STATE',
|
type: 'STEP8_GET_STATE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: { visibleStep },
|
payload: { visibleStep },
|
||||||
@@ -4676,7 +4676,7 @@
|
|||||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||||
? await getOAuthFlowStepTimeoutMs(30000, { step: visibleStep, actionLabel: '提交添加手机号' })
|
? await getOAuthFlowStepTimeoutMs(30000, { step: visibleStep, actionLabel: '提交添加手机号' })
|
||||||
: 30000;
|
: 30000;
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'SUBMIT_PHONE_NUMBER',
|
type: 'SUBMIT_PHONE_NUMBER',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: {
|
payload: {
|
||||||
@@ -4723,7 +4723,7 @@
|
|||||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||||
? await getOAuthFlowStepTimeoutMs(45000, { step: visibleStep, actionLabel: '提交手机验证码' })
|
? await getOAuthFlowStepTimeoutMs(45000, { step: visibleStep, actionLabel: '提交手机验证码' })
|
||||||
: 45000;
|
: 45000;
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'SUBMIT_PHONE_VERIFICATION_CODE',
|
type: 'SUBMIT_PHONE_VERIFICATION_CODE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: {
|
payload: {
|
||||||
@@ -4756,7 +4756,7 @@
|
|||||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||||
? await getOAuthFlowStepTimeoutMs(65000, { step: visibleStep, actionLabel: 'resend phone verification code' })
|
? await getOAuthFlowStepTimeoutMs(65000, { step: visibleStep, actionLabel: 'resend phone verification code' })
|
||||||
: 65000;
|
: 65000;
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'RESEND_PHONE_VERIFICATION_CODE',
|
type: 'RESEND_PHONE_VERIFICATION_CODE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: options || {},
|
payload: options || {},
|
||||||
@@ -4780,7 +4780,7 @@
|
|||||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||||
? await getOAuthFlowStepTimeoutMs(45000, { step: visibleStep, actionLabel: '提交注册手机验证码' })
|
? await getOAuthFlowStepTimeoutMs(45000, { step: visibleStep, actionLabel: '提交注册手机验证码' })
|
||||||
: 45000;
|
: 45000;
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'SUBMIT_PHONE_VERIFICATION_CODE',
|
type: 'SUBMIT_PHONE_VERIFICATION_CODE',
|
||||||
step: visibleStep,
|
step: visibleStep,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -4809,7 +4809,7 @@
|
|||||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||||
? await getOAuthFlowStepTimeoutMs(65000, { step: visibleStep, actionLabel: '重新发送注册手机验证码' })
|
? await getOAuthFlowStepTimeoutMs(65000, { step: visibleStep, actionLabel: '重新发送注册手机验证码' })
|
||||||
: 65000;
|
: 65000;
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'RESEND_VERIFICATION_CODE',
|
type: 'RESEND_VERIFICATION_CODE',
|
||||||
step: visibleStep,
|
step: visibleStep,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -4834,7 +4834,7 @@
|
|||||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||||
? await getOAuthFlowStepTimeoutMs(30000, { step: visibleStep, actionLabel: 'return to add-phone page' })
|
? await getOAuthFlowStepTimeoutMs(30000, { step: visibleStep, actionLabel: 'return to add-phone page' })
|
||||||
: 30000;
|
: 30000;
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'RETURN_TO_ADD_PHONE',
|
type: 'RETURN_TO_ADD_PHONE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: {},
|
payload: {},
|
||||||
@@ -4863,7 +4863,7 @@
|
|||||||
}
|
}
|
||||||
const visibleStep = normalizeLogStep(activePhoneVerificationLogStep) || 9;
|
const visibleStep = normalizeLogStep(activePhoneVerificationLogStep) || 9;
|
||||||
try {
|
try {
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'CHECK_PHONE_RESEND_ERROR',
|
type: 'CHECK_PHONE_RESEND_ERROR',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
payload: { visibleStep },
|
payload: { visibleStep },
|
||||||
@@ -6135,7 +6135,7 @@
|
|||||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||||
? await getOAuthFlowStepTimeoutMs(45000, { step: visibleStep, actionLabel: '提交登录手机验证码' })
|
? await getOAuthFlowStepTimeoutMs(45000, { step: visibleStep, actionLabel: '提交登录手机验证码' })
|
||||||
: 45000;
|
: 45000;
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'SUBMIT_PHONE_VERIFICATION_CODE',
|
type: 'SUBMIT_PHONE_VERIFICATION_CODE',
|
||||||
step: visibleStep,
|
step: visibleStep,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -6164,7 +6164,7 @@
|
|||||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||||
? await getOAuthFlowStepTimeoutMs(65000, { step: visibleStep, actionLabel: '重新发送登录手机验证码' })
|
? await getOAuthFlowStepTimeoutMs(65000, { step: visibleStep, actionLabel: '重新发送登录手机验证码' })
|
||||||
: 65000;
|
: 65000;
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'RESEND_VERIFICATION_CODE',
|
type: 'RESEND_VERIFICATION_CODE',
|
||||||
step: visibleStep,
|
step: visibleStep,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
setEmailState,
|
setEmailState,
|
||||||
setState,
|
setState,
|
||||||
SIGNUP_ENTRY_URL,
|
SIGNUP_ENTRY_URL,
|
||||||
SIGNUP_PAGE_INJECT_FILES,
|
OPENAI_AUTH_INJECT_FILES,
|
||||||
waitForTabStableComplete = null,
|
waitForTabStableComplete = null,
|
||||||
waitForTabUrlMatch,
|
waitForTabUrlMatch,
|
||||||
} = deps;
|
} = deps;
|
||||||
@@ -57,16 +57,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function openSignupEntryTab(step = 1) {
|
async function openSignupEntryTab(step = 1) {
|
||||||
const tabId = await reuseOrCreateTab('signup-page', SIGNUP_ENTRY_URL, {
|
const tabId = await reuseOrCreateTab('openai-auth', SIGNUP_ENTRY_URL, {
|
||||||
inject: SIGNUP_PAGE_INJECT_FILES,
|
inject: OPENAI_AUTH_INJECT_FILES,
|
||||||
injectSource: 'signup-page',
|
injectSource: 'openai-auth',
|
||||||
});
|
});
|
||||||
|
|
||||||
await waitForSignupEntryTabToSettle(tabId, step);
|
await waitForSignupEntryTabToSettle(tabId, step);
|
||||||
|
|
||||||
await ensureContentScriptReadyOnTab('signup-page', tabId, {
|
await ensureContentScriptReadyOnTab('openai-auth', tabId, {
|
||||||
inject: SIGNUP_PAGE_INJECT_FILES,
|
inject: OPENAI_AUTH_INJECT_FILES,
|
||||||
injectSource: 'signup-page',
|
injectSource: 'openai-auth',
|
||||||
timeoutMs: 45000,
|
timeoutMs: 45000,
|
||||||
retryDelayMs: 900,
|
retryDelayMs: 900,
|
||||||
logMessage: `步骤 ${step}:ChatGPT 官网仍在加载,正在重试连接内容脚本...`,
|
logMessage: `步骤 ${step}:ChatGPT 官网仍在加载,正在重试连接内容脚本...`,
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
|
|
||||||
async function ensureSignupEntryPageReady(step = 1) {
|
async function ensureSignupEntryPageReady(step = 1) {
|
||||||
const tabId = await openSignupEntryTab(step);
|
const tabId = await openSignupEntryTab(step);
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'ENSURE_SIGNUP_ENTRY_READY',
|
type: 'ENSURE_SIGNUP_ENTRY_READY',
|
||||||
step,
|
step,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -186,9 +186,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await ensureContentScriptReadyOnTab('signup-page', tabId, {
|
await ensureContentScriptReadyOnTab('openai-auth', tabId, {
|
||||||
inject: SIGNUP_PAGE_INJECT_FILES,
|
inject: OPENAI_AUTH_INJECT_FILES,
|
||||||
injectSource: 'signup-page',
|
injectSource: 'openai-auth',
|
||||||
timeoutMs: 45000,
|
timeoutMs: 45000,
|
||||||
retryDelayMs: 900,
|
retryDelayMs: 900,
|
||||||
logMessage: landingState === 'password_page'
|
logMessage: landingState === 'password_page'
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'ENSURE_SIGNUP_PASSWORD_PAGE_READY',
|
type: 'ENSURE_SIGNUP_PASSWORD_PAGE_READY',
|
||||||
step,
|
step,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -244,9 +244,9 @@
|
|||||||
throw new Error(`认证页面标签页已关闭,无法完成步骤 ${step} 的提交后确认。`);
|
throw new Error(`认证页面标签页已关闭,无法完成步骤 ${step} 的提交后确认。`);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ensureContentScriptReadyOnTab('signup-page', tabId, {
|
await ensureContentScriptReadyOnTab('openai-auth', tabId, {
|
||||||
inject: SIGNUP_PAGE_INJECT_FILES,
|
inject: OPENAI_AUTH_INJECT_FILES,
|
||||||
injectSource: 'signup-page',
|
injectSource: 'openai-auth',
|
||||||
timeoutMs: 45000,
|
timeoutMs: 45000,
|
||||||
retryDelayMs: 900,
|
retryDelayMs: 900,
|
||||||
logMessage: `步骤 ${step}:认证页仍在切换,正在等待页面恢复后继续确认提交流程...`,
|
logMessage: `步骤 ${step}:认证页仍在切换,正在等待页面恢复后继续确认提交流程...`,
|
||||||
@@ -254,7 +254,7 @@
|
|||||||
|
|
||||||
let result;
|
let result;
|
||||||
try {
|
try {
|
||||||
result = await sendToContentScriptResilient('signup-page', {
|
result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'PREPARE_SIGNUP_VERIFICATION',
|
type: 'PREPARE_SIGNUP_VERIFICATION',
|
||||||
step,
|
step,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
|
|||||||
@@ -242,7 +242,7 @@
|
|||||||
const requestTimeoutMs = Math.max(1200, Math.min(5000, timeoutMs));
|
const requestTimeoutMs = Math.max(1200, Math.min(5000, timeoutMs));
|
||||||
const result = typeof sendToContentScriptResilient === 'function'
|
const result = typeof sendToContentScriptResilient === 'function'
|
||||||
? await sendToContentScriptResilient(
|
? await sendToContentScriptResilient(
|
||||||
'signup-page',
|
'openai-auth',
|
||||||
request,
|
request,
|
||||||
{
|
{
|
||||||
timeoutMs: requestTimeoutMs,
|
timeoutMs: requestTimeoutMs,
|
||||||
@@ -251,7 +251,7 @@
|
|||||||
logMessage: `步骤 ${step}:验证码提交后页面正在切换,等待页面恢复并确认授权状态...`,
|
logMessage: `步骤 ${step}:验证码提交后页面正在切换,等待页面恢复并确认授权状态...`,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
: await sendToContentScript('signup-page', request, {
|
: await sendToContentScript('openai-auth', request, {
|
||||||
responseTimeoutMs: requestTimeoutMs,
|
responseTimeoutMs: requestTimeoutMs,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -516,7 +516,7 @@
|
|||||||
|
|
||||||
async function requestVerificationCodeResend(step, options = {}) {
|
async function requestVerificationCodeResend(step, options = {}) {
|
||||||
throwIfStopped();
|
throwIfStopped();
|
||||||
const signupTabId = await getTabId('signup-page');
|
const signupTabId = await getTabId('openai-auth');
|
||||||
if (!signupTabId) {
|
if (!signupTabId) {
|
||||||
throw new Error('认证页面标签页已关闭,无法重新请求验证码。');
|
throw new Error('认证页面标签页已关闭,无法重新请求验证码。');
|
||||||
}
|
}
|
||||||
@@ -525,7 +525,7 @@
|
|||||||
await chrome.tabs.update(signupTabId, { active: true });
|
await chrome.tabs.update(signupTabId, { active: true });
|
||||||
throwIfStopped();
|
throwIfStopped();
|
||||||
|
|
||||||
const result = await sendToContentScript('signup-page', {
|
const result = await sendToContentScript('openai-auth', {
|
||||||
type: 'RESEND_VERIFICATION_CODE',
|
type: 'RESEND_VERIFICATION_CODE',
|
||||||
step,
|
step,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -1111,7 +1111,7 @@
|
|||||||
async function submitVerificationCode(step, code, options = {}) {
|
async function submitVerificationCode(step, code, options = {}) {
|
||||||
const completionStep = getCompletionStep(step, options);
|
const completionStep = getCompletionStep(step, options);
|
||||||
const authLoginStep = completionStep >= 11 ? 10 : 7;
|
const authLoginStep = completionStep >= 11 ? 10 : 7;
|
||||||
const signupTabId = await getTabId('signup-page');
|
const signupTabId = await getTabId('openai-auth');
|
||||||
if (!signupTabId) {
|
if (!signupTabId) {
|
||||||
throw new Error('认证页面标签页已关闭,无法填写验证码。');
|
throw new Error('认证页面标签页已关闭,无法填写验证码。');
|
||||||
}
|
}
|
||||||
@@ -1143,7 +1143,7 @@
|
|||||||
const shouldAvoidReplaySubmit = step === 8;
|
const shouldAvoidReplaySubmit = step === 8;
|
||||||
if (typeof sendToContentScriptResilient === 'function' && !shouldAvoidReplaySubmit) {
|
if (typeof sendToContentScriptResilient === 'function' && !shouldAvoidReplaySubmit) {
|
||||||
try {
|
try {
|
||||||
result = await sendToContentScriptResilient('signup-page', message, {
|
result = await sendToContentScriptResilient('openai-auth', message, {
|
||||||
timeoutMs: Math.max(baseResponseTimeoutMs + 15000, 30000),
|
timeoutMs: Math.max(baseResponseTimeoutMs + 15000, 30000),
|
||||||
retryDelayMs: 700,
|
retryDelayMs: 700,
|
||||||
responseTimeoutMs: baseResponseTimeoutMs,
|
responseTimeoutMs: baseResponseTimeoutMs,
|
||||||
@@ -1206,7 +1206,7 @@
|
|||||||
}
|
}
|
||||||
} else if (shouldAvoidReplaySubmit) {
|
} else if (shouldAvoidReplaySubmit) {
|
||||||
try {
|
try {
|
||||||
result = await sendToContentScript('signup-page', message, {
|
result = await sendToContentScript('openai-auth', message, {
|
||||||
responseTimeoutMs: baseResponseTimeoutMs,
|
responseTimeoutMs: baseResponseTimeoutMs,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -1255,7 +1255,7 @@
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = await sendToContentScript('signup-page', message, {
|
result = await sendToContentScript('openai-auth', message, {
|
||||||
responseTimeoutMs: baseResponseTimeoutMs,
|
responseTimeoutMs: baseResponseTimeoutMs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,11 @@
|
|||||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
||||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
||||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION = 'cpa_codex_session';
|
const PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION = 'cpa_codex_session';
|
||||||
const VALID_OPENAI_TARGET_IDS = Array.isArray(flowRegistryApi.OPENAI_TARGET_IDS)
|
const VALID_OPENAI_TARGET_IDS = typeof flowRegistryApi.getTargetDefinitions === 'function'
|
||||||
? flowRegistryApi.OPENAI_TARGET_IDS.slice()
|
? Object.keys(flowRegistryApi.getTargetDefinitions('openai') || {})
|
||||||
: ['cpa', 'sub2api', 'codex2api'];
|
: (Array.isArray(flowRegistryApi.OPENAI_TARGET_IDS)
|
||||||
|
? flowRegistryApi.OPENAI_TARGET_IDS.slice()
|
||||||
|
: ['cpa', 'sub2api', 'codex2api']);
|
||||||
const REGISTERED_FLOW_IDS = Array.isArray(flowRegistryApi.getRegisteredFlowIds?.())
|
const REGISTERED_FLOW_IDS = Array.isArray(flowRegistryApi.getRegisteredFlowIds?.())
|
||||||
? flowRegistryApi.getRegisteredFlowIds().map((flowId) => String(flowId || '').trim().toLowerCase()).filter(Boolean)
|
? flowRegistryApi.getRegisteredFlowIds().map((flowId) => String(flowId || '').trim().toLowerCase()).filter(Boolean)
|
||||||
: [DEFAULT_FLOW_ID];
|
: [DEFAULT_FLOW_ID];
|
||||||
@@ -63,38 +65,18 @@
|
|||||||
const MODE_SWITCH_RELEVANT_KEYS = Object.freeze([
|
const MODE_SWITCH_RELEVANT_KEYS = Object.freeze([
|
||||||
'activeFlowId',
|
'activeFlowId',
|
||||||
'accountContributionEnabled',
|
'accountContributionEnabled',
|
||||||
'panelMode',
|
|
||||||
'phoneVerificationEnabled',
|
'phoneVerificationEnabled',
|
||||||
'plusModeEnabled',
|
'plusModeEnabled',
|
||||||
'signupMethod',
|
'signupMethod',
|
||||||
'plusAccountAccessStrategy',
|
'plusAccountAccessStrategy',
|
||||||
'openaiIntegrationTargetId',
|
'targetId',
|
||||||
'kiroTargetId',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const OPENAI_TARGET_CAPABILITIES = Object.freeze({
|
const OPENAI_TARGET_CAPABILITIES = Object.freeze(
|
||||||
cpa: Object.freeze({
|
typeof flowRegistryApi.getTargetCapabilityDefinitions === 'function'
|
||||||
supportsPhoneSignup: true,
|
? (flowRegistryApi.getTargetCapabilityDefinitions('openai') || {})
|
||||||
requiresPhoneSignupWarning: true,
|
: {}
|
||||||
supportedPlusAccountAccessStrategies: Object.freeze([
|
);
|
||||||
PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH,
|
|
||||||
PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION,
|
|
||||||
]),
|
|
||||||
}),
|
|
||||||
sub2api: Object.freeze({
|
|
||||||
supportsPhoneSignup: true,
|
|
||||||
requiresPhoneSignupWarning: false,
|
|
||||||
supportedPlusAccountAccessStrategies: Object.freeze([
|
|
||||||
PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH,
|
|
||||||
PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION,
|
|
||||||
]),
|
|
||||||
}),
|
|
||||||
codex2api: Object.freeze({
|
|
||||||
supportsPhoneSignup: true,
|
|
||||||
requiresPhoneSignupWarning: false,
|
|
||||||
supportedPlusAccountAccessStrategies: Object.freeze([PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH]),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
function normalizeFlowId(value = '', fallback = DEFAULT_FLOW_ID) {
|
function normalizeFlowId(value = '', fallback = DEFAULT_FLOW_ID) {
|
||||||
if (typeof flowRegistryApi.normalizeFlowId === 'function') {
|
if (typeof flowRegistryApi.normalizeFlowId === 'function') {
|
||||||
@@ -254,33 +236,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function normalizeRequestedTargetId(activeFlowId, state = {}, options = {}) {
|
function normalizeRequestedTargetId(activeFlowId, state = {}, options = {}) {
|
||||||
if (activeFlowId === 'openai') {
|
const schemaTargetId = settingsSchema?.getSelectedTargetId
|
||||||
return normalizeOpenAiTargetId(
|
? settingsSchema.getSelectedTargetId({
|
||||||
options?.targetId
|
...state,
|
||||||
?? options?.integrationTargetId
|
activeFlowId,
|
||||||
?? options?.panelMode
|
}, activeFlowId)
|
||||||
?? state?.openaiIntegrationTargetId
|
: '';
|
||||||
?? state?.panelMode,
|
const rawTargetId = options?.targetId
|
||||||
DEFAULT_OPENAI_TARGET_ID
|
?? options?.selectedTargetId
|
||||||
);
|
?? state?.targetId
|
||||||
}
|
?? schemaTargetId
|
||||||
|
?? flowRegistryApi.getDefaultTargetId?.(activeFlowId)
|
||||||
const rawTargetId = activeFlowId === 'kiro'
|
?? '';
|
||||||
? (
|
|
||||||
options?.targetId
|
|
||||||
?? state?.kiroTargetId
|
|
||||||
?? flowRegistryApi.getDefaultTargetId?.(activeFlowId)
|
|
||||||
?? ''
|
|
||||||
)
|
|
||||||
: (
|
|
||||||
options?.targetId
|
|
||||||
?? state?.targetId
|
|
||||||
?? state?.openaiIntegrationTargetId
|
|
||||||
?? state?.panelMode
|
|
||||||
?? state?.kiroTargetId
|
|
||||||
?? flowRegistryApi.getDefaultTargetId?.(activeFlowId)
|
|
||||||
?? ''
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isRegisteredFlowId(activeFlowId)
|
isRegisteredFlowId(activeFlowId)
|
||||||
@@ -312,32 +279,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resolveEffectiveTargetId(activeFlowId, state = {}, requestedTargetId = DEFAULT_OPENAI_TARGET_ID) {
|
function resolveEffectiveTargetId(activeFlowId, state = {}, requestedTargetId = DEFAULT_OPENAI_TARGET_ID) {
|
||||||
if (!isRegisteredFlowId(activeFlowId)) {
|
return normalizeRequestedTargetId(activeFlowId, state, {
|
||||||
return normalizeRequestedTargetId(activeFlowId, state, {
|
targetId: requestedTargetId,
|
||||||
targetId: requestedTargetId,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
if (settingsSchema?.getSelectedTargetId) {
|
|
||||||
const targetId = settingsSchema.getSelectedTargetId({
|
|
||||||
...state,
|
|
||||||
activeFlowId,
|
|
||||||
}, activeFlowId);
|
|
||||||
if (targetId) {
|
|
||||||
return targetId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (typeof flowRegistryApi.normalizeTargetId === 'function') {
|
|
||||||
return flowRegistryApi.normalizeTargetId(
|
|
||||||
activeFlowId,
|
|
||||||
activeFlowId === 'openai'
|
|
||||||
? (state?.openaiIntegrationTargetId || state?.panelMode || requestedTargetId)
|
|
||||||
: (state?.kiroTargetId || requestedTargetId),
|
|
||||||
flowRegistryApi.getDefaultTargetId?.(activeFlowId)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return activeFlowId === 'openai'
|
|
||||||
? normalizeOpenAiTargetId(requestedTargetId)
|
|
||||||
: String(requestedTargetId || '').trim().toLowerCase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveSidepanelCapabilities(options = {}) {
|
function resolveSidepanelCapabilities(options = {}) {
|
||||||
@@ -444,13 +388,11 @@
|
|||||||
canUsePhoneSignup: canSelectPhoneSignup,
|
canUsePhoneSignup: canSelectPhoneSignup,
|
||||||
canUseSelectedTarget: targetSupported,
|
canUseSelectedTarget: targetSupported,
|
||||||
effectivePlusAccountAccessStrategy,
|
effectivePlusAccountAccessStrategy,
|
||||||
effectivePanelMode: effectiveTargetId,
|
|
||||||
effectiveSignupMethod,
|
effectiveSignupMethod,
|
||||||
effectiveSignupMethods,
|
effectiveSignupMethods,
|
||||||
effectiveTargetId,
|
effectiveTargetId,
|
||||||
flowCapabilities: flowState,
|
flowCapabilities: flowState,
|
||||||
panelCapabilities: targetState,
|
panelCapabilities: targetState,
|
||||||
panelMode: effectiveTargetId,
|
|
||||||
requestedPlusAccountAccessStrategy,
|
requestedPlusAccountAccessStrategy,
|
||||||
requestedSignupMethod,
|
requestedSignupMethod,
|
||||||
requestedTargetId,
|
requestedTargetId,
|
||||||
@@ -460,8 +402,6 @@
|
|||||||
&& Boolean(targetState.requiresPhoneSignupWarning),
|
&& Boolean(targetState.requiresPhoneSignupWarning),
|
||||||
stepDefinitionOptions: {
|
stepDefinitionOptions: {
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
integrationTargetId: effectiveTargetId,
|
|
||||||
panelMode: effectiveTargetId,
|
|
||||||
targetId: effectiveTargetId,
|
targetId: effectiveTargetId,
|
||||||
plusAccountAccessStrategy: effectivePlusAccountAccessStrategy,
|
plusAccountAccessStrategy: effectivePlusAccountAccessStrategy,
|
||||||
plusModeEnabled: runtimeLocks.plusModeEnabled,
|
plusModeEnabled: runtimeLocks.plusModeEnabled,
|
||||||
@@ -576,14 +516,12 @@
|
|||||||
const shouldReconcileSignupMethod = MODE_SWITCH_RELEVANT_KEYS.some((key) => changedKeySet.has(key));
|
const shouldReconcileSignupMethod = MODE_SWITCH_RELEVANT_KEYS.some((key) => changedKeySet.has(key));
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(changedKeySet.has('panelMode') || changedKeySet.has('openaiIntegrationTargetId') || changedKeySet.has('kiroTargetId'))
|
changedKeySet.has('targetId')
|
||||||
&& Array.isArray(capabilityState.supportedTargetIds)
|
&& Array.isArray(capabilityState.supportedTargetIds)
|
||||||
&& capabilityState.supportedTargetIds.length > 0
|
&& capabilityState.supportedTargetIds.length > 0
|
||||||
&& capabilityState.canUseSelectedTarget === false
|
&& capabilityState.canUseSelectedTarget === false
|
||||||
) {
|
) {
|
||||||
normalizedUpdates.panelMode = capabilityState.effectiveTargetId;
|
normalizedUpdates.targetId = capabilityState.effectiveTargetId;
|
||||||
normalizedUpdates.openaiIntegrationTargetId = capabilityState.effectiveTargetId;
|
|
||||||
normalizedUpdates.kiroTargetId = capabilityState.effectiveTargetId;
|
|
||||||
errors.push({
|
errors.push({
|
||||||
code: 'panel_mode_unsupported',
|
code: 'panel_mode_unsupported',
|
||||||
message: `当前 flow 不支持 ${getTargetLabel(capabilityState.activeFlowId, capabilityState.requestedTargetId)} 来源。`,
|
message: `当前 flow 不支持 ${getTargetLabel(capabilityState.activeFlowId, capabilityState.requestedTargetId)} 来源。`,
|
||||||
@@ -0,0 +1,300 @@
|
|||||||
|
(function attachMultiPageFlowRegistry(root, factory) {
|
||||||
|
root.MultiPageFlowRegistry = factory();
|
||||||
|
})(typeof self !== 'undefined' ? self : globalThis, function createFlowRegistryModule() {
|
||||||
|
const rootScope = typeof self !== 'undefined' ? self : globalThis;
|
||||||
|
const flowsIndexApi = rootScope.MultiPageFlowsIndex || {};
|
||||||
|
|
||||||
|
const DEFAULT_FLOW_ID = 'openai';
|
||||||
|
const SHARED_SERVICE_IDS = Object.freeze(['account', 'email', 'proxy']);
|
||||||
|
|
||||||
|
const DEFAULT_FLOW_CAPABILITIES = Object.freeze({
|
||||||
|
supportsEmailSignup: true,
|
||||||
|
supportsPhoneSignup: false,
|
||||||
|
supportsPhoneVerificationSettings: false,
|
||||||
|
supportsPlusMode: false,
|
||||||
|
supportsContributionMode: false,
|
||||||
|
supportsAccountContribution: false,
|
||||||
|
supportsOpenAiOAuthContribution: false,
|
||||||
|
contributionAdapterIds: [],
|
||||||
|
supportedTargetIds: [],
|
||||||
|
supportsLuckmail: false,
|
||||||
|
supportsOauthTimeoutBudget: false,
|
||||||
|
canSwitchFlow: true,
|
||||||
|
stepDefinitionMode: 'default',
|
||||||
|
targetSelectorLabel: '\u6765\u6e90',
|
||||||
|
});
|
||||||
|
|
||||||
|
function freezeDeep(value) {
|
||||||
|
if (!value || typeof value !== 'object' || Object.isFrozen(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
Object.getOwnPropertyNames(value).forEach((key) => {
|
||||||
|
freezeDeep(value[key]);
|
||||||
|
});
|
||||||
|
return Object.freeze(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHARED_SETTINGS_GROUP_DEFINITIONS = freezeDeep({
|
||||||
|
'service-account': {
|
||||||
|
id: 'service-account',
|
||||||
|
label: '\u8d26\u6237',
|
||||||
|
rowIds: ['row-custom-password'],
|
||||||
|
},
|
||||||
|
'service-email': {
|
||||||
|
id: 'service-email',
|
||||||
|
label: '\u90ae\u7bb1\u670d\u52a1',
|
||||||
|
},
|
||||||
|
'service-proxy': {
|
||||||
|
id: 'service-proxy',
|
||||||
|
label: 'IP \u4ee3\u7406',
|
||||||
|
sectionIds: ['ip-proxy-section'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function buildFlowDefinitions() {
|
||||||
|
if (typeof flowsIndexApi.getFlowDefinitions !== 'function') {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return flowsIndexApi.getFlowDefinitions() || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const FLOW_DEFINITIONS = freezeDeep(buildFlowDefinitions());
|
||||||
|
const REGISTERED_FLOW_IDS = Object.freeze(Object.keys(FLOW_DEFINITIONS));
|
||||||
|
|
||||||
|
function buildSettingsGroupDefinitions() {
|
||||||
|
const next = {
|
||||||
|
...SHARED_SETTINGS_GROUP_DEFINITIONS,
|
||||||
|
};
|
||||||
|
Object.values(FLOW_DEFINITIONS).forEach((flowDefinition) => {
|
||||||
|
Object.assign(next, flowDefinition?.settingsGroups || {});
|
||||||
|
});
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SETTINGS_GROUP_DEFINITIONS = freezeDeep(buildSettingsGroupDefinitions());
|
||||||
|
|
||||||
|
function normalizeFlowId(value = '', fallback = DEFAULT_FLOW_ID) {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
if (normalized && Object.prototype.hasOwnProperty.call(FLOW_DEFINITIONS, normalized)) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
const fallbackValue = String(fallback || '').trim().toLowerCase();
|
||||||
|
if (fallbackValue && Object.prototype.hasOwnProperty.call(FLOW_DEFINITIONS, fallbackValue)) {
|
||||||
|
return fallbackValue;
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(FLOW_DEFINITIONS, DEFAULT_FLOW_ID)) {
|
||||||
|
return DEFAULT_FLOW_ID;
|
||||||
|
}
|
||||||
|
return REGISTERED_FLOW_IDS[0] || DEFAULT_FLOW_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRegisteredFlowIds() {
|
||||||
|
return REGISTERED_FLOW_IDS.slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlowDefinition(flowId) {
|
||||||
|
const normalizedFlowId = normalizeFlowId(flowId);
|
||||||
|
return FLOW_DEFINITIONS[normalizedFlowId] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlowLabel(flowId) {
|
||||||
|
return getFlowDefinition(flowId)?.label || normalizeFlowId(flowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultTargetId(flowId) {
|
||||||
|
const flowDefinition = getFlowDefinition(flowId);
|
||||||
|
return String(flowDefinition?.defaultTargetId || '').trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeTargetId(flowId, targetId = '', fallback = undefined) {
|
||||||
|
const normalizedFlowId = normalizeFlowId(flowId);
|
||||||
|
const targetDefinitions = getFlowDefinition(normalizedFlowId)?.targets || {};
|
||||||
|
const targetKeys = Object.keys(targetDefinitions);
|
||||||
|
if (!targetKeys.length) {
|
||||||
|
return String(targetId || fallback || '').trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedTargetId = String(targetId || '').trim().toLowerCase();
|
||||||
|
if (normalizedTargetId && Object.prototype.hasOwnProperty.call(targetDefinitions, normalizedTargetId)) {
|
||||||
|
return normalizedTargetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fallbackValue = String(fallback || '').trim().toLowerCase();
|
||||||
|
if (fallbackValue && Object.prototype.hasOwnProperty.call(targetDefinitions, fallbackValue)) {
|
||||||
|
return fallbackValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultTargetId = getDefaultTargetId(normalizedFlowId);
|
||||||
|
if (defaultTargetId && Object.prototype.hasOwnProperty.call(targetDefinitions, defaultTargetId)) {
|
||||||
|
return defaultTargetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetKeys[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeOpenAiTargetId(value = '', fallback = undefined) {
|
||||||
|
return normalizeTargetId('openai', value, fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeKiroTargetId(value = '', fallback = undefined) {
|
||||||
|
return normalizeTargetId('kiro', value, fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTargetDefinitions(flowId) {
|
||||||
|
return getFlowDefinition(flowId)?.targets || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTargetDefinition(flowId, targetId) {
|
||||||
|
const normalizedFlowId = normalizeFlowId(flowId);
|
||||||
|
const normalizedTargetId = normalizeTargetId(
|
||||||
|
normalizedFlowId,
|
||||||
|
targetId,
|
||||||
|
getDefaultTargetId(normalizedFlowId)
|
||||||
|
);
|
||||||
|
return getTargetDefinitions(normalizedFlowId)[normalizedTargetId] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTargetOptions(flowId) {
|
||||||
|
return Object.values(getTargetDefinitions(flowId));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTargetLabel(flowId, targetId) {
|
||||||
|
return getTargetDefinition(flowId, targetId)?.label
|
||||||
|
|| normalizeTargetId(flowId, targetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPublicationTargetDefinitions(flowId) {
|
||||||
|
return getFlowDefinition(flowId)?.publicationTargets || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPublicationTargetDefinition(flowId, publicationTargetId) {
|
||||||
|
const normalizedFlowId = normalizeFlowId(flowId);
|
||||||
|
const flowDefinition = getFlowDefinition(normalizedFlowId);
|
||||||
|
const normalizedPublicationTargetId = String(
|
||||||
|
publicationTargetId || flowDefinition?.defaultPublicationTargetId || ''
|
||||||
|
).trim().toLowerCase();
|
||||||
|
return getPublicationTargetDefinitions(normalizedFlowId)[normalizedPublicationTargetId] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlowCapabilities(flowId) {
|
||||||
|
return {
|
||||||
|
...DEFAULT_FLOW_CAPABILITIES,
|
||||||
|
...(getFlowDefinition(flowId)?.capabilities || {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTargetCapabilityDefinitions(flowId) {
|
||||||
|
return getFlowDefinition(flowId)?.targetCapabilities || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTargetCapabilities(flowId, targetId) {
|
||||||
|
const normalizedFlowId = normalizeFlowId(flowId);
|
||||||
|
const normalizedTargetId = normalizeTargetId(
|
||||||
|
normalizedFlowId,
|
||||||
|
targetId,
|
||||||
|
getDefaultTargetId(normalizedFlowId)
|
||||||
|
);
|
||||||
|
return getTargetCapabilityDefinitions(normalizedFlowId)[normalizedTargetId] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVisibleGroupIds(flowId, targetId, options = {}) {
|
||||||
|
const normalizedFlowId = normalizeFlowId(flowId);
|
||||||
|
const flowDefinition = getFlowDefinition(normalizedFlowId);
|
||||||
|
const normalizedTargetId = normalizeTargetId(
|
||||||
|
normalizedFlowId,
|
||||||
|
targetId,
|
||||||
|
getDefaultTargetId(normalizedFlowId)
|
||||||
|
);
|
||||||
|
const targetDefinition = getTargetDefinition(normalizedFlowId, normalizedTargetId);
|
||||||
|
const includeSharedServices = options?.includeSharedServices !== false;
|
||||||
|
const serviceGroups = includeSharedServices
|
||||||
|
? (Array.isArray(flowDefinition?.services)
|
||||||
|
? flowDefinition.services.map((serviceId) => `service-${serviceId}`)
|
||||||
|
: [])
|
||||||
|
: [];
|
||||||
|
return Array.from(new Set([
|
||||||
|
...(Array.isArray(flowDefinition?.baseGroups) ? flowDefinition.baseGroups : []),
|
||||||
|
...(Array.isArray(targetDefinition?.groups) ? targetDefinition.groups : []),
|
||||||
|
...serviceGroups,
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSettingsGroupDefinition(groupId) {
|
||||||
|
const normalizedGroupId = String(groupId || '').trim();
|
||||||
|
return SETTINGS_GROUP_DEFINITIONS[normalizedGroupId] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSettingsGroupDefinitions() {
|
||||||
|
return SETTINGS_GROUP_DEFINITIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRuntimeSourceDefinitions() {
|
||||||
|
const next = {};
|
||||||
|
Object.values(FLOW_DEFINITIONS).forEach((flowDefinition) => {
|
||||||
|
Object.assign(next, flowDefinition?.runtimeSources || {});
|
||||||
|
});
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDriverDefinitions() {
|
||||||
|
const next = {};
|
||||||
|
Object.values(FLOW_DEFINITIONS).forEach((flowDefinition) => {
|
||||||
|
Object.assign(next, flowDefinition?.driverDefinitions || {});
|
||||||
|
});
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSourceAliases() {
|
||||||
|
const next = {};
|
||||||
|
Object.values(FLOW_DEFINITIONS).forEach((flowDefinition) => {
|
||||||
|
Object.assign(next, flowDefinition?.sourceAliases || {});
|
||||||
|
});
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OPENAI_TARGET_IDS = Object.freeze(Object.keys(getTargetDefinitions('openai')));
|
||||||
|
const DEFAULT_OPENAI_TARGET_ID = String(getDefaultTargetId('openai') || OPENAI_TARGET_IDS[0] || 'cpa');
|
||||||
|
const DEFAULT_KIRO_TARGET_ID = String(getDefaultTargetId('kiro') || 'kiro-rs');
|
||||||
|
const DEFAULT_KIRO_PUBLICATION_TARGET_ID = String(
|
||||||
|
getFlowDefinition('kiro')?.defaultPublicationTargetId || DEFAULT_KIRO_TARGET_ID
|
||||||
|
);
|
||||||
|
const DEFAULT_KIRO_RS_URL = String(
|
||||||
|
getFlowDefinition('kiro')?.defaultTargetState?.baseUrl || ''
|
||||||
|
).trim();
|
||||||
|
|
||||||
|
return {
|
||||||
|
DEFAULT_FLOW_CAPABILITIES,
|
||||||
|
DEFAULT_FLOW_ID,
|
||||||
|
DEFAULT_KIRO_PUBLICATION_TARGET_ID,
|
||||||
|
DEFAULT_KIRO_RS_URL,
|
||||||
|
DEFAULT_KIRO_TARGET_ID,
|
||||||
|
DEFAULT_OPENAI_TARGET_ID,
|
||||||
|
FLOW_DEFINITIONS,
|
||||||
|
OPENAI_TARGET_IDS,
|
||||||
|
SETTINGS_GROUP_DEFINITIONS,
|
||||||
|
SHARED_SERVICE_IDS,
|
||||||
|
getDriverDefinitions,
|
||||||
|
getDefaultTargetId,
|
||||||
|
getFlowCapabilities,
|
||||||
|
getFlowDefinition,
|
||||||
|
getFlowLabel,
|
||||||
|
getPublicationTargetDefinition,
|
||||||
|
getPublicationTargetDefinitions,
|
||||||
|
getRegisteredFlowIds,
|
||||||
|
getRuntimeSourceDefinitions,
|
||||||
|
getSettingsGroupDefinition,
|
||||||
|
getSettingsGroupDefinitions,
|
||||||
|
getSourceAliases,
|
||||||
|
getTargetCapabilities,
|
||||||
|
getTargetCapabilityDefinitions,
|
||||||
|
getTargetDefinition,
|
||||||
|
getTargetDefinitions,
|
||||||
|
getTargetLabel,
|
||||||
|
getTargetOptions,
|
||||||
|
getVisibleGroupIds,
|
||||||
|
normalizeFlowId,
|
||||||
|
normalizeKiroTargetId,
|
||||||
|
normalizeOpenAiTargetId,
|
||||||
|
normalizeTargetId,
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
(function attachBackgroundLoggingStatus(root, factory) {
|
||||||
|
root.MultiPageBackgroundLoggingStatus = factory();
|
||||||
|
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundLoggingStatusModule() {
|
||||||
|
function createLoggingStatus(deps = {}) {
|
||||||
|
const {
|
||||||
|
chrome,
|
||||||
|
DEFAULT_STATE,
|
||||||
|
getStepIdByNodeIdForState,
|
||||||
|
getState,
|
||||||
|
isRecoverableStep9AuthFailure,
|
||||||
|
LOG_PREFIX,
|
||||||
|
setState,
|
||||||
|
sourceRegistry = null,
|
||||||
|
STOP_ERROR_MESSAGE,
|
||||||
|
} = deps;
|
||||||
|
|
||||||
|
function getSourceLabel(source) {
|
||||||
|
if (sourceRegistry?.getSourceLabel) {
|
||||||
|
return sourceRegistry.getSourceLabel(source);
|
||||||
|
}
|
||||||
|
const labels = {
|
||||||
|
'openai-auth': '认证页',
|
||||||
|
'gmail-mail': 'Gmail 邮箱',
|
||||||
|
'sidepanel': '侧边栏',
|
||||||
|
'vps-panel': 'CPA 面板',
|
||||||
|
'sub2api-panel': 'SUB2API 后台',
|
||||||
|
'codex2api-panel': 'Codex2API 后台',
|
||||||
|
'qq-mail': 'QQ 邮箱',
|
||||||
|
'mail-163': '163 邮箱',
|
||||||
|
'mail-2925': '2925 邮箱',
|
||||||
|
'inbucket-mail': 'Inbucket 邮箱',
|
||||||
|
'duck-mail': 'Duck 邮箱',
|
||||||
|
'hotmail-api': 'Hotmail(API对接/本地助手)',
|
||||||
|
'luckmail-api': 'LuckMail(API 购邮)',
|
||||||
|
'cloudflare-temp-email': 'Cloudflare Temp Email',
|
||||||
|
'cloudmail': 'Cloud Mail',
|
||||||
|
'plus-checkout': 'Plus Checkout',
|
||||||
|
'paypal-flow': 'PayPal 授权页',
|
||||||
|
'gopay-flow': 'GoPay 授权页',
|
||||||
|
'unknown-source': '未知来源',
|
||||||
|
};
|
||||||
|
return labels[source] || source || '未知来源';
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLogStep(value) {
|
||||||
|
const step = Math.floor(Number(value) || 0);
|
||||||
|
return step > 0 ? step : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildLogEntry(message, level = 'info', options = {}) {
|
||||||
|
const normalizedOptions = options && typeof options === 'object' ? options : {};
|
||||||
|
const step = normalizeLogStep(normalizedOptions.step);
|
||||||
|
const stepKey = String(normalizedOptions.stepKey || '').trim();
|
||||||
|
const nodeId = String(normalizedOptions.nodeId || normalizedOptions.nodeKey || stepKey || '').trim();
|
||||||
|
return {
|
||||||
|
message: String(message || ''),
|
||||||
|
level,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
step,
|
||||||
|
stepKey,
|
||||||
|
nodeId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addLog(message, level = 'info', options = {}) {
|
||||||
|
const state = await getState();
|
||||||
|
const logs = state.logs || [];
|
||||||
|
const entry = buildLogEntry(message, level, options);
|
||||||
|
logs.push(entry);
|
||||||
|
if (logs.length > 500) logs.splice(0, logs.length - 500);
|
||||||
|
await setState({ logs });
|
||||||
|
chrome.runtime.sendMessage({ type: 'LOG_ENTRY', payload: entry }).catch(() => { });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setNodeStatus(nodeId, status) {
|
||||||
|
const normalizedNodeId = String(nodeId || '').trim();
|
||||||
|
if (!normalizedNodeId) {
|
||||||
|
throw new Error('setNodeStatus 缺少 nodeId。');
|
||||||
|
}
|
||||||
|
const state = await getState();
|
||||||
|
const nodeStatuses = { ...(state.nodeStatuses || {}) };
|
||||||
|
nodeStatuses[normalizedNodeId] = status;
|
||||||
|
await setState({
|
||||||
|
nodeStatuses,
|
||||||
|
currentNodeId: normalizedNodeId,
|
||||||
|
});
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
type: 'NODE_STATUS_CHANGED',
|
||||||
|
payload: { nodeId: normalizedNodeId, status },
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
|
|
||||||
|
function getErrorMessage(error) {
|
||||||
|
return String(typeof error === 'string' ? error : error?.message || '')
|
||||||
|
.replace(/^GPC_TASK_ENDED::/i, '')
|
||||||
|
.replace(/^AUTO_RUN_STEP_IDLE_RESTART::/i, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isVerificationMailPollingError(error) {
|
||||||
|
const message = getErrorMessage(error);
|
||||||
|
return /未在 .*邮箱中找到新的匹配邮件|未在 Hotmail 收件箱中找到新的匹配验证码|邮箱轮询结束,但未获取到验证码|无法获取新的(?:注册|登录)验证码|页面未能重新就绪|页面通信异常|内容脚本\s+\d+(?:\.\d+)?\s*秒内未响应|did not respond in \d+s|405\s+method\s+not\s+allowed|route\s+error.*405|did\s+not\s+provide\s+an?\s+[`'"]?action|post\s+request\s+to\s+["']?\/(?:email|phone)-verification/i.test(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAddPhoneAuthFailure(error) {
|
||||||
|
const message = getErrorMessage(error);
|
||||||
|
if (/\u624b\u673a\u53f7\u8f93\u5165\u6a21\u5f0f|phone\s+entry/i.test(message)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return /https:\/\/auth\.openai\.com\/(?:add-phone|phone-verification)(?:[/?#]|$)|\badd-phone\b|phone-verification|\u6dfb\u52a0\u624b\u673a\u53f7|\u624b\u673a\u53f7\u7801|\u624b\u673a\u9a8c\u8bc1\u7801\u9875|\u624b\u673a\u9a8c\u8bc1\u9875|\u8fdb\u5165\u624b\u673a\u53f7\u9875\u9762|\u624b\u673a\u53f7\u9875|\u624b\u673a\u53f7\u9875\u9762|phone\s+number|telephone/i.test(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLoginAuthStateLabel(state) {
|
||||||
|
switch (state) {
|
||||||
|
case 'verification_page':
|
||||||
|
return '登录验证码页';
|
||||||
|
case 'password_page':
|
||||||
|
return '密码页';
|
||||||
|
case 'email_page':
|
||||||
|
return '邮箱输入页';
|
||||||
|
case 'login_timeout_error_page':
|
||||||
|
return '登录超时报错页';
|
||||||
|
case 'oauth_consent_page':
|
||||||
|
return 'OAuth 授权页';
|
||||||
|
case 'add_phone_page':
|
||||||
|
return '手机号页';
|
||||||
|
case 'add_email_page':
|
||||||
|
return '添加邮箱页';
|
||||||
|
case 'phone_verification_page':
|
||||||
|
return '手机验证码页';
|
||||||
|
default:
|
||||||
|
return '未知页面';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRestartCurrentAttemptError(error) {
|
||||||
|
const message = String(typeof error === 'string' ? error : error?.message || '');
|
||||||
|
return /当前邮箱已存在,需要重新开始新一轮|SIGNUP_PHONE_PASSWORD_MISMATCH::/i.test(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSignupUserAlreadyExistsFailure(error) {
|
||||||
|
const message = getErrorMessage(error);
|
||||||
|
return /SIGNUP_USER_ALREADY_EXISTS::|user_already_exists/i.test(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isKiroProxyFailure(error) {
|
||||||
|
const message = getErrorMessage(error);
|
||||||
|
return /Kiro\s*(?:注册页|桌面授权页).*(?:CloudFront\s*拒绝请求|AWS\s*请求异常)|(?:当前代理\s*IP|出口区域异常).*(?:切换代理|更换代理)|AWS\s*风控.*(?:切换代理|更换代理)/i.test(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isStep9RecoverableAuthError(error) {
|
||||||
|
const message = String(typeof error === 'string' ? error : error?.message || '');
|
||||||
|
return /STEP9_OAUTH_RETRY::/i.test(message)
|
||||||
|
|| isRecoverableStep9AuthFailure(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLegacyStep9RecoverableAuthError(error) {
|
||||||
|
const message = String(typeof error === 'string' ? error : error?.message || '');
|
||||||
|
return /STEP9_OAUTH_TIMEOUT::|认证失败:\s*(?:Timeout waiting for OAuth callback|timeout of \d+ms exceeded)/i.test(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isStepDoneStatus(status) {
|
||||||
|
return status === 'completed' || status === 'manual_completed' || status === 'skipped';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFirstUnfinishedStep(statuses = {}) {
|
||||||
|
const nodeStatuses = statuses && typeof statuses === 'object' ? statuses : {};
|
||||||
|
const nodeIds = Object.keys(DEFAULT_STATE.nodeStatuses || {});
|
||||||
|
for (const nodeId of nodeIds) {
|
||||||
|
if (!isStepDoneStatus(nodeStatuses[nodeId] || 'pending')) {
|
||||||
|
return typeof getStepIdByNodeIdForState === 'function'
|
||||||
|
? getStepIdByNodeIdForState(nodeId, {})
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasSavedProgress(statuses = {}) {
|
||||||
|
return Object.values({ ...DEFAULT_STATE.nodeStatuses, ...statuses }).some((status) => status !== 'pending');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRunningSteps(statuses = {}) {
|
||||||
|
return Object.entries({ ...DEFAULT_STATE.nodeStatuses, ...statuses })
|
||||||
|
.filter(([, status]) => status === 'running')
|
||||||
|
.map(([nodeId]) => (typeof getStepIdByNodeIdForState === 'function' ? getStepIdByNodeIdForState(nodeId, {}) : null))
|
||||||
|
.filter((step) => Number.isInteger(step) && step > 0)
|
||||||
|
.sort((a, b) => a - b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFirstUnfinishedNode(statuses = {}) {
|
||||||
|
const nodeIds = Object.keys(DEFAULT_STATE.nodeStatuses || {});
|
||||||
|
for (const nodeId of nodeIds) {
|
||||||
|
if (!isStepDoneStatus(statuses[nodeId] || 'pending')) {
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasSavedNodeProgress(statuses = {}) {
|
||||||
|
return Object.values({ ...DEFAULT_STATE.nodeStatuses, ...statuses }).some((status) => status !== 'pending');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRunningNodes(statuses = {}) {
|
||||||
|
return Object.entries({ ...DEFAULT_STATE.nodeStatuses, ...statuses })
|
||||||
|
.filter(([, status]) => status === 'running')
|
||||||
|
.map(([nodeId]) => nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAutoRunStatusPayload(phase, payload = {}) {
|
||||||
|
return {
|
||||||
|
autoRunning: phase === 'scheduled'
|
||||||
|
|| phase === 'running'
|
||||||
|
|| phase === 'waiting_step'
|
||||||
|
|| phase === 'waiting_email'
|
||||||
|
|| phase === 'retrying'
|
||||||
|
|| phase === 'waiting_interval',
|
||||||
|
autoRunPhase: phase,
|
||||||
|
autoRunCurrentRun: payload.currentRun ?? 0,
|
||||||
|
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 || ''),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
addLog,
|
||||||
|
getAutoRunStatusPayload,
|
||||||
|
getFirstUnfinishedNode,
|
||||||
|
isAddPhoneAuthFailure,
|
||||||
|
getErrorMessage,
|
||||||
|
getFirstUnfinishedStep,
|
||||||
|
getLoginAuthStateLabel,
|
||||||
|
getRunningNodes,
|
||||||
|
getRunningSteps,
|
||||||
|
getSourceLabel,
|
||||||
|
hasSavedNodeProgress,
|
||||||
|
hasSavedProgress,
|
||||||
|
isKiroProxyFailure,
|
||||||
|
isLegacyStep9RecoverableAuthError,
|
||||||
|
isRestartCurrentAttemptError,
|
||||||
|
isSignupUserAlreadyExistsFailure,
|
||||||
|
isStep9RecoverableAuthError,
|
||||||
|
isStepDoneStatus,
|
||||||
|
isVerificationMailPollingError,
|
||||||
|
setNodeStatus,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
createLoggingStatus,
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -140,6 +140,24 @@
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deepMerge(baseValue, patchValue) {
|
||||||
|
if (Array.isArray(patchValue)) {
|
||||||
|
return patchValue.map((item) => cloneValue(item));
|
||||||
|
}
|
||||||
|
if (!isPlainObject(patchValue)) {
|
||||||
|
return patchValue === undefined ? cloneValue(baseValue) : patchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseObject = isPlainObject(baseValue) ? baseValue : {};
|
||||||
|
const next = {
|
||||||
|
...cloneValue(baseObject),
|
||||||
|
};
|
||||||
|
Object.entries(patchValue).forEach(([key, value]) => {
|
||||||
|
next[key] = deepMerge(baseObject[key], value);
|
||||||
|
});
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
function normalizePlainObject(value) {
|
function normalizePlainObject(value) {
|
||||||
return isPlainObject(value) ? value : {};
|
return isPlainObject(value) ? value : {};
|
||||||
}
|
}
|
||||||
@@ -277,6 +295,7 @@
|
|||||||
'activeRunId',
|
'activeRunId',
|
||||||
'currentNodeId',
|
'currentNodeId',
|
||||||
'nodeStatuses',
|
'nodeStatuses',
|
||||||
|
'kiroRuntime',
|
||||||
...RUNTIME_TOP_LEVEL_FIELDS,
|
...RUNTIME_TOP_LEVEL_FIELDS,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -358,6 +377,43 @@
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildRuntimeStateSeed(currentRuntimeState = {}, updates = {}) {
|
||||||
|
const normalizedUpdates = normalizePlainObject(updates);
|
||||||
|
let nextRuntimeState = deepMerge(currentRuntimeState, normalizePlainObject(normalizedUpdates.runtimeState));
|
||||||
|
|
||||||
|
if (Object.prototype.hasOwnProperty.call(normalizedUpdates, 'sharedState')) {
|
||||||
|
nextRuntimeState = deepMerge(nextRuntimeState, {
|
||||||
|
sharedState: normalizePlainObject(normalizedUpdates.sharedState),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(normalizedUpdates, 'shared')) {
|
||||||
|
nextRuntimeState = deepMerge(nextRuntimeState, {
|
||||||
|
sharedState: normalizePlainObject(normalizedUpdates.shared),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(normalizedUpdates, 'serviceState')) {
|
||||||
|
nextRuntimeState = deepMerge(nextRuntimeState, {
|
||||||
|
serviceState: normalizePlainObject(normalizedUpdates.serviceState),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(normalizedUpdates, 'services')) {
|
||||||
|
nextRuntimeState = deepMerge(nextRuntimeState, {
|
||||||
|
serviceState: normalizePlainObject(normalizedUpdates.services),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(normalizedUpdates, 'flowState')) {
|
||||||
|
nextRuntimeState = deepMerge(nextRuntimeState, {
|
||||||
|
flowState: normalizePlainObject(normalizedUpdates.flowState),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(normalizedUpdates, 'flows')) {
|
||||||
|
nextRuntimeState = deepMerge(nextRuntimeState, {
|
||||||
|
flowState: normalizePlainObject(normalizedUpdates.flows),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return nextRuntimeState;
|
||||||
|
}
|
||||||
|
|
||||||
function buildRuntimeStateDefault() {
|
function buildRuntimeStateDefault() {
|
||||||
return {
|
return {
|
||||||
flowId: DEFAULT_ACTIVE_FLOW_ID,
|
flowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
@@ -388,6 +444,19 @@
|
|||||||
...buildRuntimeStateDefault(),
|
...buildRuntimeStateDefault(),
|
||||||
...cloneValue(normalizePlainObject(state.runtimeState)),
|
...cloneValue(normalizePlainObject(state.runtimeState)),
|
||||||
};
|
};
|
||||||
|
const projectedKiroRuntime = isPlainObject(normalizePlainObject(state.flowState).kiro)
|
||||||
|
? normalizePlainObject(state.flowState.kiro)
|
||||||
|
: {};
|
||||||
|
const canonicalKiroRuntime = deepMerge(
|
||||||
|
normalizePlainObject(normalizePlainObject(baseRuntimeState.flowState).kiro),
|
||||||
|
projectedKiroRuntime
|
||||||
|
);
|
||||||
|
if (Object.keys(canonicalKiroRuntime).length > 0) {
|
||||||
|
baseRuntimeState.flowState = {
|
||||||
|
...cloneValue(normalizePlainObject(baseRuntimeState.flowState)),
|
||||||
|
kiro: canonicalKiroRuntime,
|
||||||
|
};
|
||||||
|
}
|
||||||
const activeFlowId = normalizeFlowId(
|
const activeFlowId = normalizeFlowId(
|
||||||
Object.prototype.hasOwnProperty.call(state, 'activeFlowId')
|
Object.prototype.hasOwnProperty.call(state, 'activeFlowId')
|
||||||
? state.activeFlowId
|
? state.activeFlowId
|
||||||
@@ -472,9 +541,10 @@
|
|||||||
|
|
||||||
function buildSessionStatePatch(currentState = {}, updates = {}) {
|
function buildSessionStatePatch(currentState = {}, updates = {}) {
|
||||||
const currentRuntimeState = ensureRuntimeState(currentState);
|
const currentRuntimeState = ensureRuntimeState(currentState);
|
||||||
|
const runtimeStateSeed = buildRuntimeStateSeed(currentRuntimeState, updates);
|
||||||
const runtimeState = ensureRuntimeState({
|
const runtimeState = ensureRuntimeState({
|
||||||
runtimeState: currentRuntimeState,
|
runtimeState: runtimeStateSeed,
|
||||||
...projectRuntimeViewFields(currentRuntimeState),
|
...projectRuntimeViewFields(runtimeStateSeed),
|
||||||
...buildRuntimeInputFromPatch(updates),
|
...buildRuntimeInputFromPatch(updates),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
function buildDefaultSettingsState() {
|
function buildDefaultSettingsState() {
|
||||||
return {
|
return {
|
||||||
schemaVersion: 4,
|
schemaVersion: 5,
|
||||||
activeFlowId: defaultFlowId,
|
activeFlowId: defaultFlowId,
|
||||||
services: {
|
services: {
|
||||||
account: {
|
account: {
|
||||||
@@ -77,8 +77,8 @@
|
|||||||
},
|
},
|
||||||
flows: {
|
flows: {
|
||||||
openai: {
|
openai: {
|
||||||
integrationTargetId: defaultOpenAiTargetId,
|
selectedTargetId: defaultOpenAiTargetId,
|
||||||
integrationTargets: {
|
targets: {
|
||||||
cpa: {
|
cpa: {
|
||||||
vpsUrl: '',
|
vpsUrl: '',
|
||||||
vpsPassword: '',
|
vpsPassword: '',
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
kiro: {
|
kiro: {
|
||||||
targetId: defaultKiroTargetId,
|
selectedTargetId: defaultKiroTargetId,
|
||||||
targets: {
|
targets: {
|
||||||
'kiro-rs': {
|
'kiro-rs': {
|
||||||
baseUrl: defaultKiroRsUrl,
|
baseUrl: defaultKiroRsUrl,
|
||||||
@@ -139,8 +139,12 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIntegrationTargetValue(settingsState, pathGetter, fallback = {}) {
|
function getTargetValue(settingsState, pathGetter, legacyPathGetter = null, fallback = {}) {
|
||||||
return cloneValue(pathGetter(isPlainObject(settingsState) ? settingsState : {}) || fallback);
|
const sourceState = isPlainObject(settingsState) ? settingsState : {};
|
||||||
|
const resolvedValue = pathGetter(sourceState)
|
||||||
|
|| (typeof legacyPathGetter === 'function' ? legacyPathGetter(sourceState) : null)
|
||||||
|
|| fallback;
|
||||||
|
return cloneValue(resolvedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeSettingsState(input = {}, options = {}) {
|
function normalizeSettingsState(input = {}, options = {}) {
|
||||||
@@ -155,20 +159,25 @@
|
|||||||
?? defaults.activeFlowId,
|
?? defaults.activeFlowId,
|
||||||
defaults.activeFlowId
|
defaults.activeFlowId
|
||||||
);
|
);
|
||||||
const openaiIntegrationTargetId = normalizeTargetId(
|
const openaiSelectedTargetId = normalizeTargetId(
|
||||||
'openai',
|
'openai',
|
||||||
nested?.flows?.openai?.integrationTargetId
|
nested?.flows?.openai?.selectedTargetId
|
||||||
?? input?.openaiIntegrationTargetId
|
?? nested?.flows?.openai?.integrationTargetId
|
||||||
?? input?.panelMode
|
?? (activeFlowId === 'openai'
|
||||||
?? defaults.flows.openai.integrationTargetId,
|
? (input?.selectedTargetId ?? input?.targetId)
|
||||||
defaults.flows.openai.integrationTargetId
|
: undefined)
|
||||||
|
?? defaults.flows.openai.selectedTargetId,
|
||||||
|
defaults.flows.openai.selectedTargetId
|
||||||
);
|
);
|
||||||
const kiroTargetId = normalizeTargetId(
|
const kiroSelectedTargetId = normalizeTargetId(
|
||||||
'kiro',
|
'kiro',
|
||||||
nested?.flows?.kiro?.targetId
|
nested?.flows?.kiro?.selectedTargetId
|
||||||
?? input?.kiroTargetId
|
?? nested?.flows?.kiro?.targetId
|
||||||
?? defaults.flows.kiro.targetId,
|
?? (activeFlowId === 'kiro'
|
||||||
defaults.flows.kiro.targetId
|
? (input?.selectedTargetId ?? input?.targetId)
|
||||||
|
: undefined)
|
||||||
|
?? defaults.flows.kiro.selectedTargetId,
|
||||||
|
defaults.flows.kiro.selectedTargetId
|
||||||
);
|
);
|
||||||
const stepExecutionRangeByFlow = isPlainObject(input?.stepExecutionRangeByFlow)
|
const stepExecutionRangeByFlow = isPlainObject(input?.stepExecutionRangeByFlow)
|
||||||
? input.stepExecutionRangeByFlow
|
? input.stepExecutionRangeByFlow
|
||||||
@@ -212,76 +221,101 @@
|
|||||||
},
|
},
|
||||||
flows: {
|
flows: {
|
||||||
openai: {
|
openai: {
|
||||||
integrationTargetId: openaiIntegrationTargetId,
|
selectedTargetId: openaiSelectedTargetId,
|
||||||
integrationTargets: {
|
targets: {
|
||||||
cpa: {
|
cpa: {
|
||||||
...defaults.flows.openai.integrationTargets.cpa,
|
...defaults.flows.openai.targets.cpa,
|
||||||
...getIntegrationTargetValue(nested, (state) => state.flows?.openai?.integrationTargets?.cpa),
|
...getTargetValue(
|
||||||
|
nested,
|
||||||
|
(state) => state.flows?.openai?.targets?.cpa,
|
||||||
|
(state) => state.flows?.openai?.integrationTargets?.cpa
|
||||||
|
),
|
||||||
vpsUrl: String(
|
vpsUrl: String(
|
||||||
input?.vpsUrl
|
input?.vpsUrl
|
||||||
|
?? nested?.flows?.openai?.targets?.cpa?.vpsUrl
|
||||||
?? nested?.flows?.openai?.integrationTargets?.cpa?.vpsUrl
|
?? nested?.flows?.openai?.integrationTargets?.cpa?.vpsUrl
|
||||||
?? ''
|
?? ''
|
||||||
).trim(),
|
).trim(),
|
||||||
vpsPassword: String(
|
vpsPassword: String(
|
||||||
input?.vpsPassword
|
input?.vpsPassword
|
||||||
|
?? nested?.flows?.openai?.targets?.cpa?.vpsPassword
|
||||||
?? nested?.flows?.openai?.integrationTargets?.cpa?.vpsPassword
|
?? nested?.flows?.openai?.integrationTargets?.cpa?.vpsPassword
|
||||||
?? ''
|
?? ''
|
||||||
),
|
),
|
||||||
localCpaStep9Mode: String(
|
localCpaStep9Mode: String(
|
||||||
input?.localCpaStep9Mode
|
input?.localCpaStep9Mode
|
||||||
|
?? nested?.flows?.openai?.targets?.cpa?.localCpaStep9Mode
|
||||||
?? nested?.flows?.openai?.integrationTargets?.cpa?.localCpaStep9Mode
|
?? nested?.flows?.openai?.integrationTargets?.cpa?.localCpaStep9Mode
|
||||||
?? defaults.flows.openai.integrationTargets.cpa.localCpaStep9Mode
|
?? defaults.flows.openai.targets.cpa.localCpaStep9Mode
|
||||||
).trim() || defaults.flows.openai.integrationTargets.cpa.localCpaStep9Mode,
|
).trim() || defaults.flows.openai.targets.cpa.localCpaStep9Mode,
|
||||||
},
|
},
|
||||||
sub2api: {
|
sub2api: {
|
||||||
...defaults.flows.openai.integrationTargets.sub2api,
|
...defaults.flows.openai.targets.sub2api,
|
||||||
...getIntegrationTargetValue(nested, (state) => state.flows?.openai?.integrationTargets?.sub2api),
|
...getTargetValue(
|
||||||
|
nested,
|
||||||
|
(state) => state.flows?.openai?.targets?.sub2api,
|
||||||
|
(state) => state.flows?.openai?.integrationTargets?.sub2api
|
||||||
|
),
|
||||||
sub2apiUrl: String(
|
sub2apiUrl: String(
|
||||||
input?.sub2apiUrl
|
input?.sub2apiUrl
|
||||||
|
?? nested?.flows?.openai?.targets?.sub2api?.sub2apiUrl
|
||||||
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiUrl
|
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiUrl
|
||||||
?? ''
|
?? ''
|
||||||
).trim(),
|
).trim(),
|
||||||
sub2apiEmail: String(
|
sub2apiEmail: String(
|
||||||
input?.sub2apiEmail
|
input?.sub2apiEmail
|
||||||
|
?? nested?.flows?.openai?.targets?.sub2api?.sub2apiEmail
|
||||||
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiEmail
|
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiEmail
|
||||||
?? ''
|
?? ''
|
||||||
).trim(),
|
).trim(),
|
||||||
sub2apiPassword: String(
|
sub2apiPassword: String(
|
||||||
input?.sub2apiPassword
|
input?.sub2apiPassword
|
||||||
|
?? nested?.flows?.openai?.targets?.sub2api?.sub2apiPassword
|
||||||
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiPassword
|
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiPassword
|
||||||
?? ''
|
?? ''
|
||||||
),
|
),
|
||||||
sub2apiGroupName: String(
|
sub2apiGroupName: String(
|
||||||
input?.sub2apiGroupName
|
input?.sub2apiGroupName
|
||||||
|
?? nested?.flows?.openai?.targets?.sub2api?.sub2apiGroupName
|
||||||
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiGroupName
|
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiGroupName
|
||||||
?? defaults.flows.openai.integrationTargets.sub2api.sub2apiGroupName
|
?? defaults.flows.openai.targets.sub2api.sub2apiGroupName
|
||||||
).trim() || defaults.flows.openai.integrationTargets.sub2api.sub2apiGroupName,
|
).trim() || defaults.flows.openai.targets.sub2api.sub2apiGroupName,
|
||||||
sub2apiGroupNames: Array.isArray(input?.sub2apiGroupNames)
|
sub2apiGroupNames: Array.isArray(input?.sub2apiGroupNames)
|
||||||
? input.sub2apiGroupNames.map((entry) => String(entry || '').trim()).filter(Boolean)
|
? input.sub2apiGroupNames.map((entry) => String(entry || '').trim()).filter(Boolean)
|
||||||
: (Array.isArray(nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiGroupNames)
|
: (Array.isArray(nested?.flows?.openai?.targets?.sub2api?.sub2apiGroupNames)
|
||||||
? nested.flows.openai.integrationTargets.sub2api.sub2apiGroupNames.map((entry) => String(entry || '').trim()).filter(Boolean)
|
? nested.flows.openai.targets.sub2api.sub2apiGroupNames.map((entry) => String(entry || '').trim()).filter(Boolean)
|
||||||
: [...defaults.flows.openai.integrationTargets.sub2api.sub2apiGroupNames]),
|
: (Array.isArray(nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiGroupNames)
|
||||||
|
? nested.flows.openai.integrationTargets.sub2api.sub2apiGroupNames.map((entry) => String(entry || '').trim()).filter(Boolean)
|
||||||
|
: [...defaults.flows.openai.targets.sub2api.sub2apiGroupNames])),
|
||||||
sub2apiAccountPriority: Math.max(1, Number(
|
sub2apiAccountPriority: Math.max(1, Number(
|
||||||
input?.sub2apiAccountPriority
|
input?.sub2apiAccountPriority
|
||||||
|
?? nested?.flows?.openai?.targets?.sub2api?.sub2apiAccountPriority
|
||||||
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiAccountPriority
|
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiAccountPriority
|
||||||
?? defaults.flows.openai.integrationTargets.sub2api.sub2apiAccountPriority
|
?? defaults.flows.openai.targets.sub2api.sub2apiAccountPriority
|
||||||
) || defaults.flows.openai.integrationTargets.sub2api.sub2apiAccountPriority),
|
) || defaults.flows.openai.targets.sub2api.sub2apiAccountPriority),
|
||||||
sub2apiDefaultProxyName: String(
|
sub2apiDefaultProxyName: String(
|
||||||
input?.sub2apiDefaultProxyName
|
input?.sub2apiDefaultProxyName
|
||||||
|
?? nested?.flows?.openai?.targets?.sub2api?.sub2apiDefaultProxyName
|
||||||
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiDefaultProxyName
|
?? nested?.flows?.openai?.integrationTargets?.sub2api?.sub2apiDefaultProxyName
|
||||||
?? ''
|
?? ''
|
||||||
).trim(),
|
).trim(),
|
||||||
},
|
},
|
||||||
codex2api: {
|
codex2api: {
|
||||||
...defaults.flows.openai.integrationTargets.codex2api,
|
...defaults.flows.openai.targets.codex2api,
|
||||||
...getIntegrationTargetValue(nested, (state) => state.flows?.openai?.integrationTargets?.codex2api),
|
...getTargetValue(
|
||||||
|
nested,
|
||||||
|
(state) => state.flows?.openai?.targets?.codex2api,
|
||||||
|
(state) => state.flows?.openai?.integrationTargets?.codex2api
|
||||||
|
),
|
||||||
codex2apiUrl: String(
|
codex2apiUrl: String(
|
||||||
input?.codex2apiUrl
|
input?.codex2apiUrl
|
||||||
|
?? nested?.flows?.openai?.targets?.codex2api?.codex2apiUrl
|
||||||
?? nested?.flows?.openai?.integrationTargets?.codex2api?.codex2apiUrl
|
?? nested?.flows?.openai?.integrationTargets?.codex2api?.codex2apiUrl
|
||||||
?? ''
|
?? ''
|
||||||
).trim(),
|
).trim(),
|
||||||
codex2apiAdminKey: String(
|
codex2apiAdminKey: String(
|
||||||
input?.codex2apiAdminKey
|
input?.codex2apiAdminKey
|
||||||
|
?? nested?.flows?.openai?.targets?.codex2api?.codex2apiAdminKey
|
||||||
?? nested?.flows?.openai?.integrationTargets?.codex2api?.codex2apiAdminKey
|
?? nested?.flows?.openai?.integrationTargets?.codex2api?.codex2apiAdminKey
|
||||||
?? ''
|
?? ''
|
||||||
).trim(),
|
).trim(),
|
||||||
@@ -349,11 +383,14 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
kiro: {
|
kiro: {
|
||||||
targetId: kiroTargetId,
|
selectedTargetId: kiroSelectedTargetId,
|
||||||
targets: {
|
targets: {
|
||||||
'kiro-rs': {
|
'kiro-rs': {
|
||||||
...defaults.flows.kiro.targets['kiro-rs'],
|
...defaults.flows.kiro.targets['kiro-rs'],
|
||||||
...getIntegrationTargetValue(nested, (state) => state.flows?.kiro?.targets?.['kiro-rs']),
|
...getTargetValue(
|
||||||
|
nested,
|
||||||
|
(state) => state.flows?.kiro?.targets?.['kiro-rs']
|
||||||
|
),
|
||||||
baseUrl: String(
|
baseUrl: String(
|
||||||
input?.kiroRsUrl
|
input?.kiroRsUrl
|
||||||
?? input?.kiroRsBaseUrl
|
?? input?.kiroRsBaseUrl
|
||||||
@@ -419,20 +456,24 @@
|
|||||||
const normalizedState = normalizeSettingsState(settingsState);
|
const normalizedState = normalizeSettingsState(settingsState);
|
||||||
const normalizedFlowId = normalizeFlowId(flowId, normalizedState.activeFlowId);
|
const normalizedFlowId = normalizeFlowId(flowId, normalizedState.activeFlowId);
|
||||||
const flowSettings = normalizedState?.flows?.[normalizedFlowId] || {};
|
const flowSettings = normalizedState?.flows?.[normalizedFlowId] || {};
|
||||||
if (normalizedFlowId === 'kiro') {
|
|
||||||
return normalizeTargetId(
|
|
||||||
normalizedFlowId,
|
|
||||||
flowSettings?.targetId,
|
|
||||||
defaultKiroTargetId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return normalizeTargetId(
|
return normalizeTargetId(
|
||||||
normalizedFlowId,
|
normalizedFlowId,
|
||||||
flowSettings?.integrationTargetId,
|
flowSettings?.selectedTargetId,
|
||||||
defaultOpenAiTargetId
|
normalizedFlowId === 'kiro' ? defaultKiroTargetId : defaultOpenAiTargetId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTargetSettings(settingsState = {}, flowId, targetId = '') {
|
||||||
|
const normalizedState = normalizeSettingsState(settingsState);
|
||||||
|
const normalizedFlowId = normalizeFlowId(flowId, normalizedState.activeFlowId);
|
||||||
|
const resolvedTargetId = normalizeTargetId(
|
||||||
|
normalizedFlowId,
|
||||||
|
targetId || getSelectedTargetId(normalizedState, normalizedFlowId),
|
||||||
|
getSelectedTargetId(normalizedState, normalizedFlowId)
|
||||||
|
);
|
||||||
|
return cloneValue(normalizedState?.flows?.[normalizedFlowId]?.targets?.[resolvedTargetId] || {});
|
||||||
|
}
|
||||||
|
|
||||||
function buildStepExecutionRangeByFlow(settingsState = {}) {
|
function buildStepExecutionRangeByFlow(settingsState = {}) {
|
||||||
const normalizedState = normalizeSettingsState(settingsState);
|
const normalizedState = normalizeSettingsState(settingsState);
|
||||||
return {
|
return {
|
||||||
@@ -455,21 +496,19 @@
|
|||||||
const openaiState = normalizedState.flows.openai;
|
const openaiState = normalizedState.flows.openai;
|
||||||
const kiroState = normalizedState.flows.kiro;
|
const kiroState = normalizedState.flows.kiro;
|
||||||
next.activeFlowId = normalizedState.activeFlowId;
|
next.activeFlowId = normalizedState.activeFlowId;
|
||||||
next.openaiIntegrationTargetId = getSelectedTargetId(normalizedState, 'openai');
|
next.targetId = getSelectedTargetId(normalizedState, normalizedState.activeFlowId);
|
||||||
next.kiroTargetId = getSelectedTargetId(normalizedState, 'kiro');
|
next.vpsUrl = openaiState.targets.cpa.vpsUrl;
|
||||||
next.panelMode = next.openaiIntegrationTargetId;
|
next.vpsPassword = openaiState.targets.cpa.vpsPassword;
|
||||||
next.vpsUrl = openaiState.integrationTargets.cpa.vpsUrl;
|
next.localCpaStep9Mode = openaiState.targets.cpa.localCpaStep9Mode;
|
||||||
next.vpsPassword = openaiState.integrationTargets.cpa.vpsPassword;
|
next.sub2apiUrl = openaiState.targets.sub2api.sub2apiUrl;
|
||||||
next.localCpaStep9Mode = openaiState.integrationTargets.cpa.localCpaStep9Mode;
|
next.sub2apiEmail = openaiState.targets.sub2api.sub2apiEmail;
|
||||||
next.sub2apiUrl = openaiState.integrationTargets.sub2api.sub2apiUrl;
|
next.sub2apiPassword = openaiState.targets.sub2api.sub2apiPassword;
|
||||||
next.sub2apiEmail = openaiState.integrationTargets.sub2api.sub2apiEmail;
|
next.sub2apiGroupName = openaiState.targets.sub2api.sub2apiGroupName;
|
||||||
next.sub2apiPassword = openaiState.integrationTargets.sub2api.sub2apiPassword;
|
next.sub2apiGroupNames = cloneValue(openaiState.targets.sub2api.sub2apiGroupNames);
|
||||||
next.sub2apiGroupName = openaiState.integrationTargets.sub2api.sub2apiGroupName;
|
next.sub2apiAccountPriority = openaiState.targets.sub2api.sub2apiAccountPriority;
|
||||||
next.sub2apiGroupNames = cloneValue(openaiState.integrationTargets.sub2api.sub2apiGroupNames);
|
next.sub2apiDefaultProxyName = openaiState.targets.sub2api.sub2apiDefaultProxyName;
|
||||||
next.sub2apiAccountPriority = openaiState.integrationTargets.sub2api.sub2apiAccountPriority;
|
next.codex2apiUrl = openaiState.targets.codex2api.codex2apiUrl;
|
||||||
next.sub2apiDefaultProxyName = openaiState.integrationTargets.sub2api.sub2apiDefaultProxyName;
|
next.codex2apiAdminKey = openaiState.targets.codex2api.codex2apiAdminKey;
|
||||||
next.codex2apiUrl = openaiState.integrationTargets.codex2api.codex2apiUrl;
|
|
||||||
next.codex2apiAdminKey = openaiState.integrationTargets.codex2api.codex2apiAdminKey;
|
|
||||||
next.customPassword = normalizedState.services.account.customPassword;
|
next.customPassword = normalizedState.services.account.customPassword;
|
||||||
next.signupMethod = openaiState.signup.signupMethod;
|
next.signupMethod = openaiState.signup.signupMethod;
|
||||||
next.phoneVerificationEnabled = openaiState.signup.phoneVerificationEnabled;
|
next.phoneVerificationEnabled = openaiState.signup.phoneVerificationEnabled;
|
||||||
@@ -497,11 +536,12 @@
|
|||||||
const normalizedFlowId = normalizeFlowId(flowId, normalizedState.activeFlowId);
|
const normalizedFlowId = normalizeFlowId(flowId, normalizedState.activeFlowId);
|
||||||
const targetId = getSelectedTargetId(normalizedState, normalizedFlowId);
|
const targetId = getSelectedTargetId(normalizedState, normalizedFlowId);
|
||||||
if (normalizedFlowId === 'kiro') {
|
if (normalizedFlowId === 'kiro') {
|
||||||
|
const targetSettings = getTargetSettings(normalizedState, normalizedFlowId, targetId);
|
||||||
return {
|
return {
|
||||||
activeFlowId: normalizedFlowId,
|
activeFlowId: normalizedFlowId,
|
||||||
targetId,
|
targetId,
|
||||||
kiroRsUrl: normalizedState.flows.kiro.targets['kiro-rs'].baseUrl,
|
kiroRsUrl: targetSettings.baseUrl || '',
|
||||||
kiroRsKey: normalizedState.flows.kiro.targets['kiro-rs'].apiKey,
|
kiroRsKey: targetSettings.apiKey || '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -517,6 +557,7 @@
|
|||||||
getFlowInputState,
|
getFlowInputState,
|
||||||
getFlowSettings,
|
getFlowSettings,
|
||||||
getSelectedTargetId,
|
getSelectedTargetId,
|
||||||
|
getTargetSettings,
|
||||||
mergeSettingsState,
|
mergeSettingsState,
|
||||||
normalizeSettingsState,
|
normalizeSettingsState,
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,486 @@
|
|||||||
|
(function attachMultiPageSourceRegistry(root, factory) {
|
||||||
|
root.MultiPageSourceRegistry = factory();
|
||||||
|
})(typeof self !== 'undefined' ? self : globalThis, function createSourceRegistryModule() {
|
||||||
|
const rootScope = typeof self !== 'undefined' ? self : globalThis;
|
||||||
|
const flowRegistryApi = rootScope.MultiPageFlowRegistry || {};
|
||||||
|
|
||||||
|
const SHARED_SOURCE_DEFINITIONS = Object.freeze({
|
||||||
|
'qq-mail': {
|
||||||
|
flowId: null,
|
||||||
|
kind: 'mail-provider',
|
||||||
|
label: 'QQ \u90ae\u7bb1',
|
||||||
|
readyPolicy: 'top-frame-only',
|
||||||
|
family: 'qq-mail-family',
|
||||||
|
driverId: 'content/qq-mail',
|
||||||
|
cleanupScopes: [],
|
||||||
|
detectionMatchers: [
|
||||||
|
{ hostnames: ['mail.qq.com', 'wx.mail.qq.com'] },
|
||||||
|
],
|
||||||
|
familyMatchers: [
|
||||||
|
{ hostnames: ['mail.qq.com', 'wx.mail.qq.com'] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'mail-163': {
|
||||||
|
flowId: null,
|
||||||
|
kind: 'mail-provider',
|
||||||
|
label: '163 \u90ae\u7bb1',
|
||||||
|
readyPolicy: 'top-frame-only',
|
||||||
|
family: 'mail-163-family',
|
||||||
|
driverId: 'content/mail-163',
|
||||||
|
cleanupScopes: [],
|
||||||
|
detectionMatchers: [
|
||||||
|
{
|
||||||
|
hostnames: ['mail.163.com', 'mail.126.com', 'webmail.vip.163.com'],
|
||||||
|
hostnameEndsWith: ['.mail.163.com', '.mail.126.com'],
|
||||||
|
matchMode: 'any',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
familyMatchers: [
|
||||||
|
{
|
||||||
|
hostnames: ['mail.163.com', 'mail.126.com', 'webmail.vip.163.com'],
|
||||||
|
hostnameEndsWith: ['.mail.163.com', '.mail.126.com'],
|
||||||
|
matchMode: 'any',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'gmail-mail': {
|
||||||
|
flowId: null,
|
||||||
|
kind: 'mail-provider',
|
||||||
|
label: 'Gmail \u90ae\u7bb1',
|
||||||
|
readyPolicy: 'top-frame-only',
|
||||||
|
family: 'gmail-mail-family',
|
||||||
|
driverId: 'content/gmail-mail',
|
||||||
|
cleanupScopes: [],
|
||||||
|
detectionMatchers: [
|
||||||
|
{ hostnames: ['mail.google.com'] },
|
||||||
|
],
|
||||||
|
familyMatchers: [
|
||||||
|
{ hostnames: ['mail.google.com'] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'icloud-mail': {
|
||||||
|
flowId: null,
|
||||||
|
kind: 'mail-provider',
|
||||||
|
label: 'iCloud \u90ae\u7bb1',
|
||||||
|
readyPolicy: 'allow-child-frame',
|
||||||
|
family: 'icloud-mail-family',
|
||||||
|
driverId: 'content/icloud-mail',
|
||||||
|
cleanupScopes: [],
|
||||||
|
detectionMatchers: [
|
||||||
|
{ hostnames: ['www.icloud.com', 'www.icloud.com.cn'] },
|
||||||
|
],
|
||||||
|
familyMatchers: [
|
||||||
|
{ hostnames: ['www.icloud.com', 'www.icloud.com.cn'] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'inbucket-mail': {
|
||||||
|
flowId: null,
|
||||||
|
kind: 'mail-provider',
|
||||||
|
label: 'Inbucket \u90ae\u7bb1',
|
||||||
|
readyPolicy: 'top-frame-only',
|
||||||
|
family: 'inbucket-mail-family',
|
||||||
|
driverId: 'content/inbucket-mail',
|
||||||
|
cleanupScopes: [],
|
||||||
|
familyMatchers: [
|
||||||
|
{ originEqualsReference: true, pathPrefixes: ['/m/'] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'mail-2925': {
|
||||||
|
flowId: null,
|
||||||
|
kind: 'mail-provider',
|
||||||
|
label: '2925 \u90ae\u7bb1',
|
||||||
|
readyPolicy: 'top-frame-only',
|
||||||
|
family: 'mail-2925-family',
|
||||||
|
driverId: 'content/mail-2925',
|
||||||
|
cleanupScopes: [],
|
||||||
|
detectionMatchers: [
|
||||||
|
{ hostnames: ['2925.com', 'www.2925.com'] },
|
||||||
|
],
|
||||||
|
familyMatchers: [
|
||||||
|
{ hostnames: ['2925.com', 'www.2925.com'] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'duck-mail': {
|
||||||
|
flowId: null,
|
||||||
|
kind: 'mail-provider',
|
||||||
|
label: 'Duck \u90ae\u7bb1',
|
||||||
|
readyPolicy: 'allow-child-frame',
|
||||||
|
family: 'duck-mail-family',
|
||||||
|
driverId: 'content/duck-mail',
|
||||||
|
cleanupScopes: [],
|
||||||
|
detectionMatchers: [
|
||||||
|
{ urlIncludes: 'duckduckgo.com/email/settings/autofill' },
|
||||||
|
],
|
||||||
|
familyMatchers: [
|
||||||
|
{ hostnames: ['duckduckgo.com'], pathPrefixes: ['/email/'] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'unknown-source': {
|
||||||
|
flowId: null,
|
||||||
|
kind: 'unknown',
|
||||||
|
label: '\u672a\u77e5\u6765\u6e90',
|
||||||
|
readyPolicy: 'disabled',
|
||||||
|
family: 'unknown-family',
|
||||||
|
driverId: null,
|
||||||
|
cleanupScopes: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const SHARED_DRIVER_DEFINITIONS = Object.freeze({
|
||||||
|
'content/qq-mail': {
|
||||||
|
sourceId: 'qq-mail',
|
||||||
|
commands: ['POLL_EMAIL'],
|
||||||
|
},
|
||||||
|
'content/mail-163': {
|
||||||
|
sourceId: 'mail-163',
|
||||||
|
commands: ['POLL_EMAIL'],
|
||||||
|
},
|
||||||
|
'content/gmail-mail': {
|
||||||
|
sourceId: 'gmail-mail',
|
||||||
|
commands: ['POLL_EMAIL'],
|
||||||
|
},
|
||||||
|
'content/icloud-mail': {
|
||||||
|
sourceId: 'icloud-mail',
|
||||||
|
commands: ['POLL_EMAIL'],
|
||||||
|
},
|
||||||
|
'content/mail-2925': {
|
||||||
|
sourceId: 'mail-2925',
|
||||||
|
commands: ['POLL_EMAIL'],
|
||||||
|
},
|
||||||
|
'content/duck-mail': {
|
||||||
|
sourceId: 'duck-mail',
|
||||||
|
commands: ['FETCH_ALIAS_EMAIL'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function normalizeHostname(hostname = '') {
|
||||||
|
return String(hostname || '').trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchesNamedHostFamily(hostname = '', family = '') {
|
||||||
|
const normalizedHost = normalizeHostname(hostname);
|
||||||
|
const normalizedFamily = normalizeHostname(family);
|
||||||
|
if (!normalizedHost || !normalizedFamily) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return normalizedHost === normalizedFamily
|
||||||
|
|| normalizedHost.endsWith(`.${normalizedFamily}`)
|
||||||
|
|| normalizedHost.startsWith(`${normalizedFamily}.`)
|
||||||
|
|| normalizedHost.includes(`.${normalizedFamily}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseUrlSafely(rawUrl) {
|
||||||
|
if (!rawUrl) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new URL(rawUrl);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCandidateUrl(url = '', hostname = '') {
|
||||||
|
const candidate = parseUrlSafely(url);
|
||||||
|
if (candidate) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
const normalizedHostname = normalizeHostname(hostname);
|
||||||
|
if (!normalizedHostname) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return parseUrlSafely(`https://${normalizedHostname}/`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeSourceId(source) {
|
||||||
|
return String(source || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeStringArray(values = []) {
|
||||||
|
if (!Array.isArray(values)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
.map((value) => String(value || '').trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hostnameMatchesSuffix(hostname = '', suffix = '') {
|
||||||
|
const normalizedHost = normalizeHostname(hostname);
|
||||||
|
const normalizedSuffix = normalizeHostname(suffix);
|
||||||
|
if (!normalizedHost || !normalizedSuffix) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (normalizedHost === normalizedSuffix) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const dottedSuffix = normalizedSuffix.startsWith('.')
|
||||||
|
? normalizedSuffix
|
||||||
|
: `.${normalizedSuffix}`;
|
||||||
|
return normalizedHost.endsWith(dottedSuffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRuntimeSourceDefinitions() {
|
||||||
|
return {
|
||||||
|
...(typeof flowRegistryApi.getRuntimeSourceDefinitions === 'function'
|
||||||
|
? flowRegistryApi.getRuntimeSourceDefinitions()
|
||||||
|
: {}),
|
||||||
|
...SHARED_SOURCE_DEFINITIONS,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDriverDefinitions() {
|
||||||
|
return {
|
||||||
|
...(typeof flowRegistryApi.getDriverDefinitions === 'function'
|
||||||
|
? flowRegistryApi.getDriverDefinitions()
|
||||||
|
: {}),
|
||||||
|
...SHARED_DRIVER_DEFINITIONS,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSourceAliases() {
|
||||||
|
return {
|
||||||
|
...(typeof flowRegistryApi.getSourceAliases === 'function'
|
||||||
|
? flowRegistryApi.getSourceAliases()
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSourceRegistry() {
|
||||||
|
const SOURCE_DEFINITIONS = getRuntimeSourceDefinitions();
|
||||||
|
const DRIVER_DEFINITIONS = getDriverDefinitions();
|
||||||
|
const SOURCE_ALIASES = getSourceAliases();
|
||||||
|
|
||||||
|
function resolveCanonicalSource(source) {
|
||||||
|
const normalized = normalizeSourceId(source);
|
||||||
|
if (!normalized) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return SOURCE_ALIASES[normalized] || normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAliasKeysForCanonicalSource(source) {
|
||||||
|
const canonical = resolveCanonicalSource(source);
|
||||||
|
return Object.keys(SOURCE_ALIASES).filter((alias) => SOURCE_ALIASES[alias] === canonical);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSourceKeys(source) {
|
||||||
|
const normalized = normalizeSourceId(source);
|
||||||
|
const canonical = resolveCanonicalSource(normalized);
|
||||||
|
return Array.from(new Set([
|
||||||
|
canonical,
|
||||||
|
...getAliasKeysForCanonicalSource(canonical),
|
||||||
|
normalized,
|
||||||
|
].filter(Boolean)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSourceMeta(source) {
|
||||||
|
const canonical = resolveCanonicalSource(source);
|
||||||
|
const definition = SOURCE_DEFINITIONS[canonical];
|
||||||
|
if (!definition) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: canonical,
|
||||||
|
aliases: getAliasKeysForCanonicalSource(canonical),
|
||||||
|
...definition,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSourceLabel(source) {
|
||||||
|
return getSourceMeta(source)?.label || normalizeSourceId(source) || '\u672a\u77e5\u6765\u6e90';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDriverIdForSource(source) {
|
||||||
|
return getSourceMeta(source)?.driverId || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDriverMeta(sourceOrDriverId) {
|
||||||
|
const directDriverId = normalizeSourceId(sourceOrDriverId);
|
||||||
|
const driverId = Object.prototype.hasOwnProperty.call(DRIVER_DEFINITIONS, directDriverId)
|
||||||
|
? directDriverId
|
||||||
|
: getDriverIdForSource(sourceOrDriverId);
|
||||||
|
if (!driverId || !Object.prototype.hasOwnProperty.call(DRIVER_DEFINITIONS, driverId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: driverId,
|
||||||
|
...DRIVER_DEFINITIONS[driverId],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function driverAcceptsCommand(sourceOrDriverId, command) {
|
||||||
|
const normalizedCommand = normalizeSourceId(command);
|
||||||
|
if (!normalizedCommand) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const driver = getDriverMeta(sourceOrDriverId);
|
||||||
|
return Array.isArray(driver?.commands) && driver.commands.includes(normalizedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchesUrlRule(rule = {}, candidate, reference) {
|
||||||
|
if (!candidate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const matchMode = String(rule?.matchMode || 'all').trim().toLowerCase() === 'any'
|
||||||
|
? 'any'
|
||||||
|
: 'all';
|
||||||
|
const conditions = [];
|
||||||
|
|
||||||
|
const hostnames = normalizeStringArray(rule.hostnames);
|
||||||
|
if (hostnames.length) {
|
||||||
|
conditions.push(hostnames.includes(candidate.hostname));
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostnameFamilies = normalizeStringArray(rule.hostnameFamilies);
|
||||||
|
if (hostnameFamilies.length) {
|
||||||
|
conditions.push(hostnameFamilies.some((family) => matchesNamedHostFamily(candidate.hostname, family)));
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostnameEndsWith = normalizeStringArray(rule.hostnameEndsWith);
|
||||||
|
if (hostnameEndsWith.length) {
|
||||||
|
conditions.push(hostnameEndsWith.some((suffix) => hostnameMatchesSuffix(candidate.hostname, suffix)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hostnameRegex) {
|
||||||
|
conditions.push(new RegExp(rule.hostnameRegex, rule.hostnameRegexFlags || '').test(candidate.hostname));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.urlIncludes) {
|
||||||
|
conditions.push(String(candidate.href || '').includes(String(rule.urlIncludes)));
|
||||||
|
}
|
||||||
|
|
||||||
|
const pathPrefixes = normalizeStringArray(rule.pathPrefixes);
|
||||||
|
if (pathPrefixes.length) {
|
||||||
|
conditions.push(pathPrefixes.some((prefix) => candidate.pathname.startsWith(prefix)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.pathEquals) {
|
||||||
|
conditions.push(candidate.pathname === String(rule.pathEquals));
|
||||||
|
}
|
||||||
|
|
||||||
|
const pathEqualsOneOf = normalizeStringArray(rule.pathEqualsOneOf);
|
||||||
|
if (pathEqualsOneOf.length) {
|
||||||
|
conditions.push(pathEqualsOneOf.includes(candidate.pathname));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.originEqualsReference) {
|
||||||
|
conditions.push(Boolean(reference) && candidate.origin === reference.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.pathEqualsReference) {
|
||||||
|
conditions.push(Boolean(reference) && candidate.pathname === reference.pathname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conditions.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchMode === 'any'
|
||||||
|
? conditions.some(Boolean)
|
||||||
|
: conditions.every(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchesSourceDetection(source, url = '', hostname = '') {
|
||||||
|
const candidate = buildCandidateUrl(url, hostname);
|
||||||
|
if (!candidate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const canonical = resolveCanonicalSource(source);
|
||||||
|
const detectionMatchers = getSourceMeta(canonical)?.detectionMatchers || [];
|
||||||
|
return detectionMatchers.some((rule) => matchesUrlRule(rule, candidate, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSignupPageHost(hostname = '') {
|
||||||
|
return matchesSourceDetection('openai-auth', '', hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSignupEntryHost(hostname = '') {
|
||||||
|
return matchesSourceDetection('chatgpt', '', hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
function is163MailHost(hostname = '') {
|
||||||
|
return matchesSourceDetection('mail-163', '', hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchesSourceUrlFamily(source, candidateUrl, referenceUrl) {
|
||||||
|
const candidate = parseUrlSafely(candidateUrl);
|
||||||
|
if (!candidate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const canonical = resolveCanonicalSource(source);
|
||||||
|
const familyMatchers = getSourceMeta(canonical)?.familyMatchers || [];
|
||||||
|
const reference = parseUrlSafely(referenceUrl);
|
||||||
|
return familyMatchers.some((rule) => matchesUrlRule(rule, candidate, reference));
|
||||||
|
}
|
||||||
|
|
||||||
|
function detectSourceFromLocation({
|
||||||
|
injectedSource,
|
||||||
|
url = '',
|
||||||
|
hostname = '',
|
||||||
|
} = {}) {
|
||||||
|
if (injectedSource) {
|
||||||
|
return resolveCanonicalSource(injectedSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
const candidate = buildCandidateUrl(url, hostname);
|
||||||
|
if (!candidate) {
|
||||||
|
return 'unknown-source';
|
||||||
|
}
|
||||||
|
|
||||||
|
const detectionSourceIds = Object.keys(SOURCE_DEFINITIONS).filter((sourceId) => sourceId !== 'unknown-source');
|
||||||
|
for (const sourceId of detectionSourceIds) {
|
||||||
|
if (matchesSourceDetection(sourceId, candidate.href, candidate.hostname)) {
|
||||||
|
return sourceId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'unknown-source';
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldReportReadyForFrame(source, isChildFrame) {
|
||||||
|
const canonical = resolveCanonicalSource(source);
|
||||||
|
const readyPolicy = getSourceMeta(canonical)?.readyPolicy || 'allow-child-frame';
|
||||||
|
if (readyPolicy === 'disabled') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!isChildFrame) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return readyPolicy === 'allow-child-frame';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCleanupOwnerSource(cleanupScope) {
|
||||||
|
const normalizedCleanupScope = String(cleanupScope || '').trim();
|
||||||
|
const owner = Object.keys(SOURCE_DEFINITIONS).find((sourceId) => {
|
||||||
|
const cleanupScopes = Array.isArray(SOURCE_DEFINITIONS[sourceId]?.cleanupScopes)
|
||||||
|
? SOURCE_DEFINITIONS[sourceId].cleanupScopes
|
||||||
|
: [];
|
||||||
|
return cleanupScopes.includes(normalizedCleanupScope);
|
||||||
|
});
|
||||||
|
return resolveCanonicalSource(owner || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
detectSourceFromLocation,
|
||||||
|
driverAcceptsCommand,
|
||||||
|
getCleanupOwnerSource,
|
||||||
|
getDriverIdForSource,
|
||||||
|
getDriverMeta,
|
||||||
|
getSourceKeys,
|
||||||
|
getSourceLabel,
|
||||||
|
getSourceMeta,
|
||||||
|
is163MailHost,
|
||||||
|
isSignupEntryHost,
|
||||||
|
isSignupPageHost,
|
||||||
|
matchesSourceUrlFamily,
|
||||||
|
parseUrlSafely,
|
||||||
|
resolveCanonicalSource,
|
||||||
|
shouldReportReadyForFrame,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
createSourceRegistry,
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
if (sourceRegistry?.getCleanupOwnerSource) {
|
if (sourceRegistry?.getCleanupOwnerSource) {
|
||||||
return sourceRegistry.getCleanupOwnerSource(cleanupScope);
|
return sourceRegistry.getCleanupOwnerSource(cleanupScope);
|
||||||
}
|
}
|
||||||
return cleanupScope === 'oauth-localhost-callback' ? 'signup-page' : '';
|
return cleanupScope === 'oauth-localhost-callback' ? 'openai-auth' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeAutomationWindowId(value) {
|
function normalizeAutomationWindowId(value) {
|
||||||
+73
-585
@@ -1,589 +1,80 @@
|
|||||||
(function attachStepDefinitions(root, factory) {
|
(function attachStepDefinitions(root, factory) {
|
||||||
root.MultiPageStepDefinitions = factory();
|
root.MultiPageStepDefinitions = factory();
|
||||||
})(typeof self !== 'undefined' ? self : globalThis, function createStepDefinitionsModule() {
|
})(typeof self !== 'undefined' ? self : globalThis, function createStepDefinitionsModule() {
|
||||||
|
const rootScope = typeof self !== 'undefined' ? self : globalThis;
|
||||||
|
const flowsIndexApi = rootScope.MultiPageFlowsIndex || {};
|
||||||
|
|
||||||
const DEFAULT_ACTIVE_FLOW_ID = 'openai';
|
const DEFAULT_ACTIVE_FLOW_ID = 'openai';
|
||||||
const PLUS_PAYMENT_METHOD_PAYPAL = 'paypal';
|
|
||||||
const PLUS_PAYMENT_METHOD_PAYPAL_HOSTED = 'paypal-hosted';
|
|
||||||
const PLUS_PAYMENT_METHOD_GOPAY = 'gopay';
|
|
||||||
const PLUS_PAYMENT_METHOD_GPC_HELPER = 'gpc-helper';
|
|
||||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
|
||||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
|
||||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION = 'cpa_codex_session';
|
|
||||||
const PLUS_PAYMENT_STEP_KEY = 'paypal-approve';
|
|
||||||
const SIGNUP_METHOD_EMAIL = 'email';
|
const SIGNUP_METHOD_EMAIL = 'email';
|
||||||
const SIGNUP_METHOD_PHONE = 'phone';
|
const SIGNUP_METHOD_PHONE = 'phone';
|
||||||
|
|
||||||
const NORMAL_PREFIX_STEP_DEFINITIONS = [
|
function normalizeRegisteredFlowIds(values = []) {
|
||||||
{ id: 1, order: 10, key: 'open-chatgpt', title: '打开 ChatGPT 官网', sourceId: 'chatgpt', driverId: null, command: 'open-chatgpt' },
|
if (!Array.isArray(values)) {
|
||||||
{ id: 2, order: 20, key: 'submit-signup-email', title: '注册并输入邮箱', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-signup-email' },
|
return [];
|
||||||
{ id: 3, order: 30, key: 'fill-password', title: '填写密码并继续', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fill-password' },
|
|
||||||
{ id: 4, order: 40, key: 'fetch-signup-code', title: '获取注册验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-verification-code', mailRuleId: 'openai-signup-code' },
|
|
||||||
{ id: 5, order: 50, key: 'fill-profile', title: '填写姓名和生日', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fill-profile' },
|
|
||||||
{ id: 6, order: 60, key: 'wait-registration-success', title: '等待注册成功', sourceId: 'chatgpt', driverId: null, command: 'wait-registration-success' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const PLUS_PAYPAL_PREFIX_STEP_DEFINITIONS = [
|
|
||||||
{ id: 1, order: 10, key: 'open-chatgpt', title: '打开 ChatGPT 官网', sourceId: 'chatgpt', driverId: null, command: 'open-chatgpt' },
|
|
||||||
{ id: 2, order: 20, key: 'submit-signup-email', title: '注册并输入邮箱', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-signup-email' },
|
|
||||||
{ id: 3, order: 30, key: 'fill-password', title: '填写密码并继续', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fill-password' },
|
|
||||||
{ id: 4, order: 40, key: 'fetch-signup-code', title: '获取注册验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-verification-code', mailRuleId: 'openai-signup-code' },
|
|
||||||
{ id: 5, order: 50, key: 'fill-profile', title: '填写姓名和生日', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fill-profile' },
|
|
||||||
{ id: 6, order: 60, key: 'plus-checkout-create', title: '创建 Plus Checkout', sourceId: 'plus-checkout', driverId: 'content/plus-checkout', command: 'plus-checkout-create' },
|
|
||||||
{ id: 7, order: 70, key: 'plus-checkout-billing', title: '填写账单并提交订单', sourceId: 'plus-checkout', driverId: 'content/plus-checkout', command: 'plus-checkout-billing' },
|
|
||||||
{ id: 8, order: 80, key: 'paypal-approve', title: 'PayPal 登录与授权', sourceId: 'paypal-flow', driverId: 'content/paypal-flow', command: 'paypal-approve' },
|
|
||||||
{ id: 9, order: 90, key: 'plus-checkout-return', title: '订阅回跳确认', sourceId: 'plus-checkout', driverId: 'content/plus-checkout', command: 'plus-checkout-return' },
|
|
||||||
];
|
|
||||||
const PLUS_PAYPAL_HOSTED_CHECKOUT_PREFIX_STEP_DEFINITIONS = [
|
|
||||||
...PLUS_PAYPAL_PREFIX_STEP_DEFINITIONS.slice(0, 6),
|
|
||||||
{ id: 7, order: 70, key: 'paypal-hosted-email', title: '无卡直绑填写 PayPal 邮箱', sourceId: 'paypal-flow', driverId: 'content/paypal-flow', command: 'paypal-hosted-email' },
|
|
||||||
{ id: 8, order: 80, key: 'paypal-hosted-card', title: '无卡直绑填写 PayPal 资料', sourceId: 'paypal-flow', driverId: 'content/paypal-flow', command: 'paypal-hosted-card' },
|
|
||||||
{ id: 9, order: 90, key: 'paypal-hosted-create-account', title: '无卡直绑确认创建 PayPal', sourceId: 'paypal-flow', driverId: 'content/paypal-flow', command: 'paypal-hosted-create-account' },
|
|
||||||
{ id: 10, order: 100, key: 'paypal-hosted-review', title: '无卡直绑完成 PayPal 授权', sourceId: 'paypal-flow', driverId: 'content/paypal-flow', command: 'paypal-hosted-review' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const PLUS_GOPAY_PREFIX_STEP_DEFINITIONS = [
|
|
||||||
{ id: 1, order: 10, key: 'open-chatgpt', title: '打开 ChatGPT 官网', sourceId: 'chatgpt', driverId: null, command: 'open-chatgpt' },
|
|
||||||
{ id: 2, order: 20, key: 'submit-signup-email', title: '注册并输入邮箱', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-signup-email' },
|
|
||||||
{ id: 3, order: 30, key: 'fill-password', title: '填写密码并继续', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fill-password' },
|
|
||||||
{ id: 4, order: 40, key: 'fetch-signup-code', title: '获取注册验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-verification-code', mailRuleId: 'openai-signup-code' },
|
|
||||||
{ id: 5, order: 50, key: 'fill-profile', title: '填写姓名和生日', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fill-profile' },
|
|
||||||
{ id: 6, order: 60, key: 'plus-checkout-create', title: '打开 GoPay 订阅页', sourceId: 'plus-checkout', driverId: 'content/plus-checkout', command: 'plus-checkout-create' },
|
|
||||||
{ id: 7, order: 70, key: 'gopay-subscription-confirm', title: '等待 GoPay 订阅确认', sourceId: 'gopay-flow', driverId: 'content/gopay-flow', command: 'gopay-subscription-confirm' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const PLUS_GPC_PREFIX_STEP_DEFINITIONS = [
|
|
||||||
{ id: 1, order: 10, key: 'open-chatgpt', title: '打开 ChatGPT 官网', sourceId: 'chatgpt', driverId: null, command: 'open-chatgpt' },
|
|
||||||
{ id: 2, order: 20, key: 'submit-signup-email', title: '注册并输入邮箱', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-signup-email' },
|
|
||||||
{ id: 3, order: 30, key: 'fill-password', title: '填写密码并继续', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fill-password' },
|
|
||||||
{ id: 4, order: 40, key: 'fetch-signup-code', title: '获取注册验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-verification-code', mailRuleId: 'openai-signup-code' },
|
|
||||||
{ id: 5, order: 50, key: 'fill-profile', title: '填写姓名和生日', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fill-profile' },
|
|
||||||
{ id: 6, order: 60, key: 'plus-checkout-create', title: '创建 GPC 订单', sourceId: 'plus-checkout', driverId: 'content/plus-checkout', command: 'plus-checkout-create' },
|
|
||||||
{ id: 7, order: 70, key: 'plus-checkout-billing', title: '等待 GPC 任务完成', sourceId: 'plus-checkout', driverId: 'content/plus-checkout', command: 'plus-checkout-billing' },
|
|
||||||
];
|
|
||||||
|
|
||||||
function isPhoneSignupReloginAfterBindEmailEnabled(options = {}) {
|
|
||||||
return Boolean(options?.phoneSignupReloginAfterBindEmailEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createOpenAiAuthTail(startId, startOrder, signupMethod = SIGNUP_METHOD_EMAIL, options = {}) {
|
|
||||||
const id = Number(startId) || 7;
|
|
||||||
const order = Number(startOrder) || id * 10;
|
|
||||||
const commonStart = [
|
|
||||||
{ id, order, key: 'oauth-login', title: '刷新 OAuth 并登录', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'oauth-login' },
|
|
||||||
{ id: id + 1, order: order + 10, key: 'fetch-login-code', title: '获取登录验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-verification-code', mailRuleId: 'openai-login-code' },
|
|
||||||
];
|
|
||||||
|
|
||||||
if (signupMethod === SIGNUP_METHOD_PHONE) {
|
|
||||||
if (isPhoneSignupReloginAfterBindEmailEnabled(options)) {
|
|
||||||
return [
|
|
||||||
...commonStart,
|
|
||||||
{ id: id + 2, order: order + 20, key: 'bind-email', title: '绑定邮箱', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'bind-email' },
|
|
||||||
{ id: id + 3, order: order + 30, key: 'fetch-bind-email-code', title: '获取绑定邮箱验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fetch-bind-email-code', mailRuleId: 'openai-login-code' },
|
|
||||||
{ id: id + 4, order: order + 40, key: 'relogin-bound-email', title: '绑定邮箱后刷新 OAuth 并登录(邮箱)', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'oauth-login' },
|
|
||||||
{ id: id + 5, order: order + 50, key: 'fetch-bound-email-login-code', title: '获取登录验证码(邮箱)', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-verification-code', mailRuleId: 'openai-login-code' },
|
|
||||||
{ id: id + 6, order: order + 60, key: 'post-bound-email-phone-verification', title: '手机号验证', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'post-login-phone-verification' },
|
|
||||||
{ id: id + 7, order: order + 70, key: 'confirm-oauth', title: '自动确认 OAuth', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'confirm-oauth' },
|
|
||||||
{ id: id + 8, order: order + 80, key: 'platform-verify', title: '平台回调验证', sourceId: 'platform-panel', driverId: 'content/platform-panel', command: 'platform-verify' },
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
...commonStart,
|
|
||||||
{ id: id + 2, order: order + 20, key: 'bind-email', title: '绑定邮箱', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'bind-email' },
|
|
||||||
{ id: id + 3, order: order + 30, key: 'fetch-bind-email-code', title: '获取绑定邮箱验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fetch-bind-email-code', mailRuleId: 'openai-login-code' },
|
|
||||||
{ id: id + 4, order: order + 40, key: 'confirm-oauth', title: '自动确认 OAuth', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'confirm-oauth' },
|
|
||||||
{ id: id + 5, order: order + 50, key: 'platform-verify', title: '平台回调验证', sourceId: 'platform-panel', driverId: 'content/platform-panel', command: 'platform-verify' },
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
const seen = new Set();
|
||||||
return [
|
return values
|
||||||
...commonStart,
|
.map((value) => String(value || '').trim().toLowerCase())
|
||||||
{ id: id + 2, order: order + 20, key: 'post-login-phone-verification', title: '手机号验证', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'post-login-phone-verification' },
|
.filter((value) => {
|
||||||
{ id: id + 3, order: order + 30, key: 'confirm-oauth', title: '自动确认 OAuth', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'confirm-oauth' },
|
if (!value || seen.has(value)) {
|
||||||
{ id: id + 4, order: order + 40, key: 'platform-verify', title: '平台回调验证', sourceId: 'platform-panel', driverId: 'content/platform-panel', command: 'platform-verify' },
|
return false;
|
||||||
];
|
}
|
||||||
|
seen.add(value);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSub2ApiSessionImportTail(startId, startOrder) {
|
function getRegisteredFlowIds() {
|
||||||
const id = Number(startId) || 10;
|
return normalizeRegisteredFlowIds(
|
||||||
const order = Number(startOrder) || id * 10;
|
typeof flowsIndexApi.getRegisteredFlowIds === 'function'
|
||||||
return [
|
? flowsIndexApi.getRegisteredFlowIds()
|
||||||
{
|
: [DEFAULT_ACTIVE_FLOW_ID]
|
||||||
id,
|
).filter((flowId) => Boolean(getFlowWorkflow(flowId)));
|
||||||
order,
|
|
||||||
key: 'sub2api-session-import',
|
|
||||||
title: '导入当前 ChatGPT 会话到 SUB2API',
|
|
||||||
sourceId: 'sub2api-panel',
|
|
||||||
driverId: 'background/sub2api-session-import',
|
|
||||||
command: 'sub2api-session-import',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createCpaSessionImportTail(startId, startOrder) {
|
function getFlowWorkflow(flowId) {
|
||||||
const id = Number(startId) || 10;
|
return typeof flowsIndexApi.getFlowWorkflow === 'function'
|
||||||
const order = Number(startOrder) || id * 10;
|
? flowsIndexApi.getFlowWorkflow(flowId)
|
||||||
return [
|
: null;
|
||||||
{
|
|
||||||
id,
|
|
||||||
order,
|
|
||||||
key: 'cpa-session-import',
|
|
||||||
title: '导入当前 ChatGPT 会话到 CPA',
|
|
||||||
sourceId: 'vps-panel',
|
|
||||||
driverId: 'background/cpa-session-import',
|
|
||||||
command: 'cpa-session-import',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizePlusAccountAccessStrategy(value = '') {
|
function hasFlow(flowId) {
|
||||||
const normalized = String(value || '').trim().toLowerCase();
|
return Boolean(getFlowWorkflow(flowId));
|
||||||
if (normalized === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION) {
|
|
||||||
return PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION;
|
|
||||||
}
|
|
||||||
if (normalized === PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION) {
|
|
||||||
return PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION;
|
|
||||||
}
|
|
||||||
return PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolvePlusSessionImportTail(options = {}, signupMethod = SIGNUP_METHOD_EMAIL) {
|
|
||||||
if (signupMethod !== SIGNUP_METHOD_EMAIL) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const strategy = normalizePlusAccountAccessStrategy(options?.plusAccountAccessStrategy);
|
|
||||||
if (strategy === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION) {
|
|
||||||
return createSub2ApiSessionImportTail;
|
|
||||||
}
|
|
||||||
if (strategy === PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION) {
|
|
||||||
return createCpaSessionImportTail;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createOpenAiSteps(prefixSteps, startId, startOrder, signupMethod = SIGNUP_METHOD_EMAIL, options = {}) {
|
|
||||||
const sessionTailFactory = resolvePlusSessionImportTail(options, signupMethod);
|
|
||||||
const tailSteps = sessionTailFactory
|
|
||||||
? sessionTailFactory(startId, startOrder)
|
|
||||||
: createOpenAiAuthTail(startId, startOrder, signupMethod, options);
|
|
||||||
return [
|
|
||||||
...prefixSteps,
|
|
||||||
...tailSteps,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
function createHostedCheckoutAuthTail(startId, startOrder, signupMethod = SIGNUP_METHOD_EMAIL, options = {}) {
|
|
||||||
const id = Number(startId) || 7;
|
|
||||||
const order = Number(startOrder) || id * 10;
|
|
||||||
const commonStart = [
|
|
||||||
{ id, order, key: 'oauth-login', title: '刷新 OAuth 并登录', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'oauth-login' },
|
|
||||||
{ id: id + 1, order: order + 10, key: 'fetch-login-code', title: '获取登录验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-verification-code', mailRuleId: 'openai-login-code' },
|
|
||||||
];
|
|
||||||
|
|
||||||
if (signupMethod === SIGNUP_METHOD_PHONE) {
|
|
||||||
if (isPhoneSignupReloginAfterBindEmailEnabled(options)) {
|
|
||||||
return [
|
|
||||||
...commonStart,
|
|
||||||
{ id: id + 2, order: order + 20, key: 'bind-email', title: '绑定邮箱', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'bind-email' },
|
|
||||||
{ id: id + 3, order: order + 30, key: 'fetch-bind-email-code', title: '获取绑定邮箱验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fetch-bind-email-code', mailRuleId: 'openai-login-code' },
|
|
||||||
{ id: id + 4, order: order + 40, key: 'relogin-bound-email', title: '绑定邮箱后刷新 OAuth 并登录(邮箱)', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'oauth-login' },
|
|
||||||
{ id: id + 5, order: order + 50, key: 'fetch-bound-email-login-code', title: '获取登录验证码(邮箱)', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'submit-verification-code', mailRuleId: 'openai-login-code' },
|
|
||||||
{ id: id + 6, order: order + 60, key: 'confirm-oauth', title: '自动确认 OAuth', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'confirm-oauth' },
|
|
||||||
{ id: id + 7, order: order + 70, key: 'platform-verify', title: '平台回调验证', sourceId: 'platform-panel', driverId: 'content/platform-panel', command: 'platform-verify' },
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
...commonStart,
|
|
||||||
{ id: id + 2, order: order + 20, key: 'bind-email', title: '绑定邮箱', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'bind-email' },
|
|
||||||
{ id: id + 3, order: order + 30, key: 'fetch-bind-email-code', title: '获取绑定邮箱验证码', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'fetch-bind-email-code', mailRuleId: 'openai-login-code' },
|
|
||||||
{ id: id + 4, order: order + 40, key: 'confirm-oauth', title: '自动确认 OAuth', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'confirm-oauth' },
|
|
||||||
{ id: id + 5, order: order + 50, key: 'platform-verify', title: '平台回调验证', sourceId: 'platform-panel', driverId: 'content/platform-panel', command: 'platform-verify' },
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
...commonStart,
|
|
||||||
{ id: id + 2, order: order + 20, key: 'confirm-oauth', title: '自动确认 OAuth', sourceId: 'openai-auth', driverId: 'content/signup-page', command: 'confirm-oauth' },
|
|
||||||
{ id: id + 3, order: order + 30, key: 'platform-verify', title: '平台回调验证', sourceId: 'platform-panel', driverId: 'content/platform-panel', command: 'platform-verify' },
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
function createHostedCheckoutSteps(prefixSteps, startId, startOrder, signupMethod = SIGNUP_METHOD_EMAIL, options = {}) {
|
|
||||||
const sessionTailFactory = resolvePlusSessionImportTail(options, signupMethod);
|
|
||||||
const tailSteps = sessionTailFactory
|
|
||||||
? sessionTailFactory(startId, startOrder)
|
|
||||||
: createHostedCheckoutAuthTail(startId, startOrder, signupMethod, options);
|
|
||||||
return [
|
|
||||||
...prefixSteps,
|
|
||||||
...tailSteps,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
const NORMAL_STEP_DEFINITIONS = createOpenAiSteps(NORMAL_PREFIX_STEP_DEFINITIONS, 7, 70, SIGNUP_METHOD_EMAIL);
|
|
||||||
const NORMAL_PHONE_STEP_DEFINITIONS = createOpenAiSteps(NORMAL_PREFIX_STEP_DEFINITIONS, 7, 70, SIGNUP_METHOD_PHONE);
|
|
||||||
const NORMAL_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS = createOpenAiSteps(NORMAL_PREFIX_STEP_DEFINITIONS, 7, 70, SIGNUP_METHOD_PHONE, { phoneSignupReloginAfterBindEmailEnabled: true });
|
|
||||||
const PLUS_PAYPAL_STEP_DEFINITIONS = createOpenAiSteps(PLUS_PAYPAL_PREFIX_STEP_DEFINITIONS, 10, 100, SIGNUP_METHOD_EMAIL);
|
|
||||||
const PLUS_PAYPAL_SUB2API_SESSION_STEP_DEFINITIONS = createOpenAiSteps(
|
|
||||||
PLUS_PAYPAL_PREFIX_STEP_DEFINITIONS,
|
|
||||||
10,
|
|
||||||
100,
|
|
||||||
SIGNUP_METHOD_EMAIL,
|
|
||||||
{ plusAccountAccessStrategy: PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION }
|
|
||||||
);
|
|
||||||
const PLUS_PAYPAL_CPA_SESSION_STEP_DEFINITIONS = createOpenAiSteps(
|
|
||||||
PLUS_PAYPAL_PREFIX_STEP_DEFINITIONS,
|
|
||||||
10,
|
|
||||||
100,
|
|
||||||
SIGNUP_METHOD_EMAIL,
|
|
||||||
{ plusAccountAccessStrategy: PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION }
|
|
||||||
);
|
|
||||||
const PLUS_PAYPAL_PHONE_STEP_DEFINITIONS = createOpenAiSteps(PLUS_PAYPAL_PREFIX_STEP_DEFINITIONS, 10, 100, SIGNUP_METHOD_PHONE);
|
|
||||||
const PLUS_PAYPAL_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS = createOpenAiSteps(PLUS_PAYPAL_PREFIX_STEP_DEFINITIONS, 10, 100, SIGNUP_METHOD_PHONE, { phoneSignupReloginAfterBindEmailEnabled: true });
|
|
||||||
const PLUS_PAYPAL_HOSTED_CHECKOUT_STEP_DEFINITIONS = createHostedCheckoutSteps(PLUS_PAYPAL_HOSTED_CHECKOUT_PREFIX_STEP_DEFINITIONS, 11, 110, SIGNUP_METHOD_EMAIL);
|
|
||||||
const PLUS_PAYPAL_HOSTED_CHECKOUT_SUB2API_SESSION_STEP_DEFINITIONS = createHostedCheckoutSteps(
|
|
||||||
PLUS_PAYPAL_HOSTED_CHECKOUT_PREFIX_STEP_DEFINITIONS,
|
|
||||||
11,
|
|
||||||
110,
|
|
||||||
SIGNUP_METHOD_EMAIL,
|
|
||||||
{ plusAccountAccessStrategy: PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION }
|
|
||||||
);
|
|
||||||
const PLUS_PAYPAL_HOSTED_CHECKOUT_CPA_SESSION_STEP_DEFINITIONS = createHostedCheckoutSteps(
|
|
||||||
PLUS_PAYPAL_HOSTED_CHECKOUT_PREFIX_STEP_DEFINITIONS,
|
|
||||||
11,
|
|
||||||
110,
|
|
||||||
SIGNUP_METHOD_EMAIL,
|
|
||||||
{ plusAccountAccessStrategy: PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION }
|
|
||||||
);
|
|
||||||
const PLUS_PAYPAL_HOSTED_CHECKOUT_PHONE_STEP_DEFINITIONS = createHostedCheckoutSteps(PLUS_PAYPAL_HOSTED_CHECKOUT_PREFIX_STEP_DEFINITIONS, 11, 110, SIGNUP_METHOD_PHONE);
|
|
||||||
const PLUS_PAYPAL_HOSTED_CHECKOUT_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS = createHostedCheckoutSteps(PLUS_PAYPAL_HOSTED_CHECKOUT_PREFIX_STEP_DEFINITIONS, 11, 110, SIGNUP_METHOD_PHONE, { phoneSignupReloginAfterBindEmailEnabled: true });
|
|
||||||
const PLUS_GOPAY_STEP_DEFINITIONS = createOpenAiSteps(PLUS_GOPAY_PREFIX_STEP_DEFINITIONS, 10, 100, SIGNUP_METHOD_EMAIL);
|
|
||||||
const PLUS_GOPAY_SUB2API_SESSION_STEP_DEFINITIONS = createOpenAiSteps(
|
|
||||||
PLUS_GOPAY_PREFIX_STEP_DEFINITIONS,
|
|
||||||
10,
|
|
||||||
100,
|
|
||||||
SIGNUP_METHOD_EMAIL,
|
|
||||||
{ plusAccountAccessStrategy: PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION }
|
|
||||||
);
|
|
||||||
const PLUS_GOPAY_CPA_SESSION_STEP_DEFINITIONS = createOpenAiSteps(
|
|
||||||
PLUS_GOPAY_PREFIX_STEP_DEFINITIONS,
|
|
||||||
10,
|
|
||||||
100,
|
|
||||||
SIGNUP_METHOD_EMAIL,
|
|
||||||
{ plusAccountAccessStrategy: PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION }
|
|
||||||
);
|
|
||||||
const PLUS_GOPAY_PHONE_STEP_DEFINITIONS = createOpenAiSteps(PLUS_GOPAY_PREFIX_STEP_DEFINITIONS, 10, 100, SIGNUP_METHOD_PHONE);
|
|
||||||
const PLUS_GOPAY_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS = createOpenAiSteps(PLUS_GOPAY_PREFIX_STEP_DEFINITIONS, 10, 100, SIGNUP_METHOD_PHONE, { phoneSignupReloginAfterBindEmailEnabled: true });
|
|
||||||
const PLUS_GPC_STEP_DEFINITIONS = createOpenAiSteps(PLUS_GPC_PREFIX_STEP_DEFINITIONS, 10, 100, SIGNUP_METHOD_EMAIL);
|
|
||||||
const PLUS_GPC_SUB2API_SESSION_STEP_DEFINITIONS = createOpenAiSteps(
|
|
||||||
PLUS_GPC_PREFIX_STEP_DEFINITIONS,
|
|
||||||
10,
|
|
||||||
100,
|
|
||||||
SIGNUP_METHOD_EMAIL,
|
|
||||||
{ plusAccountAccessStrategy: PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION }
|
|
||||||
);
|
|
||||||
const PLUS_GPC_CPA_SESSION_STEP_DEFINITIONS = createOpenAiSteps(
|
|
||||||
PLUS_GPC_PREFIX_STEP_DEFINITIONS,
|
|
||||||
10,
|
|
||||||
100,
|
|
||||||
SIGNUP_METHOD_EMAIL,
|
|
||||||
{ plusAccountAccessStrategy: PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION }
|
|
||||||
);
|
|
||||||
const PLUS_GPC_PHONE_STEP_DEFINITIONS = createOpenAiSteps(PLUS_GPC_PREFIX_STEP_DEFINITIONS, 10, 100, SIGNUP_METHOD_PHONE);
|
|
||||||
const PLUS_GPC_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS = createOpenAiSteps(PLUS_GPC_PREFIX_STEP_DEFINITIONS, 10, 100, SIGNUP_METHOD_PHONE, { phoneSignupReloginAfterBindEmailEnabled: true });
|
|
||||||
const KIRO_STEP_DEFINITIONS = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
order: 10,
|
|
||||||
key: 'kiro-open-register-page',
|
|
||||||
title: '打开注册页',
|
|
||||||
sourceId: 'kiro-register-page',
|
|
||||||
driverId: 'background/kiro-register',
|
|
||||||
command: 'kiro-open-register-page',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
order: 20,
|
|
||||||
key: 'kiro-submit-email',
|
|
||||||
title: '获取邮箱并继续',
|
|
||||||
sourceId: 'kiro-register-page',
|
|
||||||
driverId: 'background/kiro-register',
|
|
||||||
command: 'kiro-submit-email',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
order: 30,
|
|
||||||
key: 'kiro-submit-name',
|
|
||||||
title: '填写姓名并继续',
|
|
||||||
sourceId: 'kiro-register-page',
|
|
||||||
driverId: 'background/kiro-register',
|
|
||||||
command: 'kiro-submit-name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
order: 40,
|
|
||||||
key: 'kiro-submit-verification-code',
|
|
||||||
title: '获取验证码并继续',
|
|
||||||
sourceId: 'kiro-register-page',
|
|
||||||
driverId: 'background/kiro-register',
|
|
||||||
command: 'kiro-submit-verification-code',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
order: 50,
|
|
||||||
key: 'kiro-submit-password',
|
|
||||||
title: '设置密码并继续',
|
|
||||||
sourceId: 'kiro-register-page',
|
|
||||||
driverId: 'background/kiro-register',
|
|
||||||
command: 'kiro-submit-password',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
order: 60,
|
|
||||||
key: 'kiro-complete-register-consent',
|
|
||||||
title: '完成注册授权',
|
|
||||||
sourceId: 'kiro-register-page',
|
|
||||||
driverId: 'background/kiro-register',
|
|
||||||
command: 'kiro-complete-register-consent',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
order: 70,
|
|
||||||
key: 'kiro-start-desktop-authorize',
|
|
||||||
title: '启动桌面授权',
|
|
||||||
sourceId: 'kiro-desktop-authorize',
|
|
||||||
driverId: 'background/kiro-desktop-authorize',
|
|
||||||
command: 'kiro-start-desktop-authorize',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
order: 80,
|
|
||||||
key: 'kiro-complete-desktop-authorize',
|
|
||||||
title: '完成桌面授权',
|
|
||||||
sourceId: 'kiro-desktop-authorize',
|
|
||||||
driverId: 'background/kiro-desktop-authorize',
|
|
||||||
command: 'kiro-complete-desktop-authorize',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 9,
|
|
||||||
order: 90,
|
|
||||||
key: 'kiro-upload-credential',
|
|
||||||
title: '上传凭据到 kiro.rs',
|
|
||||||
sourceId: 'kiro-rs-admin',
|
|
||||||
driverId: 'background/kiro-publisher-kiro-rs',
|
|
||||||
command: 'kiro-upload-credential',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const PHONE_SIGNUP_TITLE_OVERRIDES = Object.freeze({
|
|
||||||
'submit-signup-email': '注册并输入手机号',
|
|
||||||
'fetch-signup-code': '获取手机验证码',
|
|
||||||
});
|
|
||||||
const KIRO_CONTRIBUTION_STEP_TITLE = '贡献上传';
|
|
||||||
|
|
||||||
function isPlusModeEnabled(options = {}) {
|
|
||||||
return Boolean(options?.plusModeEnabled || options?.plusMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizePlusPaymentMethod(value = '') {
|
|
||||||
const normalized = String(value || '').trim().toLowerCase();
|
|
||||||
if (normalized === PLUS_PAYMENT_METHOD_PAYPAL_HOSTED || normalized === 'paypal_direct' || normalized === 'paypal-direct') {
|
|
||||||
return PLUS_PAYMENT_METHOD_PAYPAL_HOSTED;
|
|
||||||
}
|
|
||||||
if (normalized === PLUS_PAYMENT_METHOD_GPC_HELPER) {
|
|
||||||
return PLUS_PAYMENT_METHOD_GPC_HELPER;
|
|
||||||
}
|
|
||||||
return normalized === PLUS_PAYMENT_METHOD_GOPAY ? PLUS_PAYMENT_METHOD_GOPAY : PLUS_PAYMENT_METHOD_PAYPAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeSignupMethod(value = '') {
|
|
||||||
return String(value || '').trim().toLowerCase() === SIGNUP_METHOD_PHONE
|
|
||||||
? SIGNUP_METHOD_PHONE
|
|
||||||
: SIGNUP_METHOD_EMAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeActiveFlowId(value = '', fallback = DEFAULT_ACTIVE_FLOW_ID) {
|
function normalizeActiveFlowId(value = '', fallback = DEFAULT_ACTIVE_FLOW_ID) {
|
||||||
const normalized = String(value || '').trim().toLowerCase();
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
if (normalized) {
|
if (hasFlow(normalized)) {
|
||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
const fallbackValue = String(fallback || '').trim().toLowerCase();
|
const fallbackValue = String(fallback || '').trim().toLowerCase();
|
||||||
return fallbackValue || DEFAULT_ACTIVE_FLOW_ID;
|
if (hasFlow(fallbackValue)) {
|
||||||
|
return fallbackValue;
|
||||||
|
}
|
||||||
|
return getRegisteredFlowIds()[0] || DEFAULT_ACTIVE_FLOW_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getResolvedSignupMethod(options = {}) {
|
function hasExplicitActiveFlowId(options = {}) {
|
||||||
return normalizeSignupMethod(options?.resolvedSignupMethod || options?.signupMethod);
|
return Boolean(
|
||||||
}
|
options
|
||||||
|
&& typeof options === 'object'
|
||||||
function getOpenAiModeStepDefinitions(options = {}) {
|
&& Object.prototype.hasOwnProperty.call(options, 'activeFlowId')
|
||||||
const signupMethod = getResolvedSignupMethod(options);
|
&& String(options.activeFlowId || '').trim()
|
||||||
const reloginAfterBindEmail = signupMethod === SIGNUP_METHOD_PHONE
|
);
|
||||||
&& isPhoneSignupReloginAfterBindEmailEnabled(options);
|
|
||||||
if (!isPlusModeEnabled(options)) {
|
|
||||||
if (signupMethod === SIGNUP_METHOD_PHONE) {
|
|
||||||
return reloginAfterBindEmail
|
|
||||||
? NORMAL_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS
|
|
||||||
: NORMAL_PHONE_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
return NORMAL_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
const paymentMethod = normalizePlusPaymentMethod(options?.plusPaymentMethod || options?.paymentMethod);
|
|
||||||
const plusAccountAccessStrategy = normalizePlusAccountAccessStrategy(options?.plusAccountAccessStrategy);
|
|
||||||
if (paymentMethod === PLUS_PAYMENT_METHOD_PAYPAL_HOSTED) {
|
|
||||||
if (signupMethod === SIGNUP_METHOD_PHONE) {
|
|
||||||
return reloginAfterBindEmail
|
|
||||||
? PLUS_PAYPAL_HOSTED_CHECKOUT_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS
|
|
||||||
: PLUS_PAYPAL_HOSTED_CHECKOUT_PHONE_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (plusAccountAccessStrategy === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION) {
|
|
||||||
return PLUS_PAYPAL_HOSTED_CHECKOUT_SUB2API_SESSION_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (plusAccountAccessStrategy === PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION) {
|
|
||||||
return PLUS_PAYPAL_HOSTED_CHECKOUT_CPA_SESSION_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
return PLUS_PAYPAL_HOSTED_CHECKOUT_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (paymentMethod === PLUS_PAYMENT_METHOD_GPC_HELPER) {
|
|
||||||
if (signupMethod === SIGNUP_METHOD_PHONE) {
|
|
||||||
return reloginAfterBindEmail
|
|
||||||
? PLUS_GPC_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS
|
|
||||||
: PLUS_GPC_PHONE_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (plusAccountAccessStrategy === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION) {
|
|
||||||
return PLUS_GPC_SUB2API_SESSION_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (plusAccountAccessStrategy === PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION) {
|
|
||||||
return PLUS_GPC_CPA_SESSION_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
return PLUS_GPC_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (paymentMethod === PLUS_PAYMENT_METHOD_GOPAY) {
|
|
||||||
if (signupMethod === SIGNUP_METHOD_PHONE) {
|
|
||||||
return reloginAfterBindEmail
|
|
||||||
? PLUS_GOPAY_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS
|
|
||||||
: PLUS_GOPAY_PHONE_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (plusAccountAccessStrategy === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION) {
|
|
||||||
return PLUS_GOPAY_SUB2API_SESSION_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (plusAccountAccessStrategy === PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION) {
|
|
||||||
return PLUS_GOPAY_CPA_SESSION_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
return PLUS_GOPAY_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (signupMethod === SIGNUP_METHOD_PHONE) {
|
|
||||||
return reloginAfterBindEmail
|
|
||||||
? PLUS_PAYPAL_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS
|
|
||||||
: PLUS_PAYPAL_PHONE_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (plusAccountAccessStrategy === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION) {
|
|
||||||
return PLUS_PAYPAL_SUB2API_SESSION_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
if (plusAccountAccessStrategy === PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION) {
|
|
||||||
return PLUS_PAYPAL_CPA_SESSION_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
return PLUS_PAYPAL_STEP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOpenAiPlusPaymentStepTitle(options = {}) {
|
|
||||||
if (!isPlusModeEnabled(options)) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
const paymentStep = getOpenAiModeStepDefinitions({
|
|
||||||
...options,
|
|
||||||
plusModeEnabled: true,
|
|
||||||
}).find((step) => step.key === PLUS_PAYMENT_STEP_KEY);
|
|
||||||
return paymentStep?.title || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOpenAiResolvedStepTitle(step = {}, options = {}) {
|
|
||||||
if (isPlusModeEnabled(options) && step.key === PLUS_PAYMENT_STEP_KEY) {
|
|
||||||
return getOpenAiPlusPaymentStepTitle(options) || step.title;
|
|
||||||
}
|
|
||||||
const signupMethod = getResolvedSignupMethod(options);
|
|
||||||
if (signupMethod === SIGNUP_METHOD_PHONE && PHONE_SIGNUP_TITLE_OVERRIDES[step.key]) {
|
|
||||||
return PHONE_SIGNUP_TITLE_OVERRIDES[step.key];
|
|
||||||
}
|
|
||||||
return step.title;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isKiroContributionModeEnabled(options = {}) {
|
|
||||||
return Boolean(options?.accountContributionEnabled || options?.state?.accountContributionEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
const FLOW_DEFINITION_BUILDERS = Object.freeze({
|
|
||||||
openai: {
|
|
||||||
getAllSteps() {
|
|
||||||
const keyed = new Map();
|
|
||||||
for (const step of [
|
|
||||||
...NORMAL_STEP_DEFINITIONS,
|
|
||||||
...NORMAL_PHONE_STEP_DEFINITIONS,
|
|
||||||
...NORMAL_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_SUB2API_SESSION_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_CPA_SESSION_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_PHONE_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_HOSTED_CHECKOUT_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_HOSTED_CHECKOUT_SUB2API_SESSION_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_HOSTED_CHECKOUT_CPA_SESSION_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_HOSTED_CHECKOUT_PHONE_STEP_DEFINITIONS,
|
|
||||||
...PLUS_PAYPAL_HOSTED_CHECKOUT_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GOPAY_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GOPAY_SUB2API_SESSION_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GOPAY_CPA_SESSION_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GOPAY_PHONE_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GOPAY_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GPC_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GPC_SUB2API_SESSION_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GPC_CPA_SESSION_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GPC_PHONE_STEP_DEFINITIONS,
|
|
||||||
...PLUS_GPC_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
]) {
|
|
||||||
keyed.set(`${step.id}:${step.key}`, step);
|
|
||||||
}
|
|
||||||
return Array.from(keyed.values()).sort((left, right) => {
|
|
||||||
const leftOrder = Number.isFinite(left.order) ? left.order : left.id;
|
|
||||||
const rightOrder = Number.isFinite(right.order) ? right.order : right.id;
|
|
||||||
if (leftOrder !== rightOrder) return leftOrder - rightOrder;
|
|
||||||
return left.id - right.id;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getModeStepDefinitions: getOpenAiModeStepDefinitions,
|
|
||||||
getPlusPaymentStepTitle: getOpenAiPlusPaymentStepTitle,
|
|
||||||
resolveStepTitle: getOpenAiResolvedStepTitle,
|
|
||||||
},
|
|
||||||
kiro: {
|
|
||||||
getAllSteps() {
|
|
||||||
return KIRO_STEP_DEFINITIONS;
|
|
||||||
},
|
|
||||||
getModeStepDefinitions() {
|
|
||||||
return KIRO_STEP_DEFINITIONS;
|
|
||||||
},
|
|
||||||
getPlusPaymentStepTitle() {
|
|
||||||
return '';
|
|
||||||
},
|
|
||||||
resolveStepTitle(step, options = {}) {
|
|
||||||
if (step?.key === 'kiro-upload-credential' && isKiroContributionModeEnabled(options)) {
|
|
||||||
return KIRO_CONTRIBUTION_STEP_TITLE;
|
|
||||||
}
|
|
||||||
return step?.title || '';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function hasFlow(flowId) {
|
|
||||||
const normalizedFlowId = normalizeActiveFlowId(flowId, '');
|
|
||||||
return Boolean(normalizedFlowId && FLOW_DEFINITION_BUILDERS[normalizedFlowId]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRegisteredFlowIds() {
|
|
||||||
return Object.keys(FLOW_DEFINITION_BUILDERS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFlowDefinitionBuilder(options = {}) {
|
function getFlowDefinitionBuilder(options = {}) {
|
||||||
const flowId = normalizeActiveFlowId(options?.activeFlowId, DEFAULT_ACTIVE_FLOW_ID);
|
const rawFlowId = String(options?.activeFlowId || '').trim().toLowerCase();
|
||||||
|
if (hasExplicitActiveFlowId(options) && rawFlowId && !hasFlow(rawFlowId)) {
|
||||||
|
return {
|
||||||
|
flowId: rawFlowId,
|
||||||
|
builder: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const flowId = normalizeActiveFlowId(rawFlowId, DEFAULT_ACTIVE_FLOW_ID);
|
||||||
return {
|
return {
|
||||||
flowId,
|
flowId,
|
||||||
builder: FLOW_DEFINITION_BUILDERS[flowId] || null,
|
builder: getFlowWorkflow(flowId),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,7 +147,9 @@
|
|||||||
}
|
}
|
||||||
return cloneNodes(builder.getAllSteps(options), options, flowId)
|
return cloneNodes(builder.getAllSteps(options), options, flowId)
|
||||||
.sort((left, right) => {
|
.sort((left, right) => {
|
||||||
if (left.displayOrder !== right.displayOrder) return left.displayOrder - right.displayOrder;
|
if (left.displayOrder !== right.displayOrder) {
|
||||||
|
return left.displayOrder - right.displayOrder;
|
||||||
|
}
|
||||||
return left.nodeId.localeCompare(right.nodeId);
|
return left.nodeId.localeCompare(right.nodeId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -712,7 +205,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getWorkflow(options = {}) {
|
function getWorkflow(options = {}) {
|
||||||
const flowId = normalizeActiveFlowId(options?.activeFlowId, DEFAULT_ACTIVE_FLOW_ID);
|
const { flowId } = getFlowDefinitionBuilder(options);
|
||||||
const nodes = getNodes(options);
|
const nodes = getNodes(options);
|
||||||
return {
|
return {
|
||||||
flowId,
|
flowId,
|
||||||
@@ -722,34 +215,32 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultWorkflowBuilder = getFlowWorkflow(DEFAULT_ACTIVE_FLOW_ID);
|
||||||
|
const STEP_DEFINITIONS = cloneSteps(
|
||||||
|
defaultWorkflowBuilder?.getVariantStepDefinitions
|
||||||
|
? defaultWorkflowBuilder.getVariantStepDefinitions('normal')
|
||||||
|
: (defaultWorkflowBuilder?.getModeStepDefinitions?.({ activeFlowId: DEFAULT_ACTIVE_FLOW_ID }) || []),
|
||||||
|
{},
|
||||||
|
DEFAULT_ACTIVE_FLOW_ID
|
||||||
|
);
|
||||||
|
const NORMAL_STEP_DEFINITIONS = STEP_DEFINITIONS;
|
||||||
|
const PLUS_STEP_DEFINITIONS = cloneSteps(
|
||||||
|
defaultWorkflowBuilder?.getVariantStepDefinitions
|
||||||
|
? defaultWorkflowBuilder.getVariantStepDefinitions('plusPaypal')
|
||||||
|
: [],
|
||||||
|
{ plusModeEnabled: true },
|
||||||
|
DEFAULT_ACTIVE_FLOW_ID
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
DEFAULT_ACTIVE_FLOW_ID,
|
DEFAULT_ACTIVE_FLOW_ID,
|
||||||
STEP_DEFINITIONS: NORMAL_STEP_DEFINITIONS,
|
|
||||||
NORMAL_STEP_DEFINITIONS,
|
NORMAL_STEP_DEFINITIONS,
|
||||||
NORMAL_PHONE_STEP_DEFINITIONS,
|
PLUS_STEP_DEFINITIONS,
|
||||||
NORMAL_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
PLUS_STEP_DEFINITIONS: PLUS_PAYPAL_STEP_DEFINITIONS,
|
|
||||||
PLUS_PAYPAL_STEP_DEFINITIONS,
|
|
||||||
PLUS_PAYPAL_SUB2API_SESSION_STEP_DEFINITIONS,
|
|
||||||
PLUS_PAYPAL_PHONE_STEP_DEFINITIONS,
|
|
||||||
PLUS_PAYPAL_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
PLUS_PAYPAL_HOSTED_CHECKOUT_STEP_DEFINITIONS,
|
|
||||||
PLUS_PAYPAL_HOSTED_CHECKOUT_SUB2API_SESSION_STEP_DEFINITIONS,
|
|
||||||
PLUS_PAYPAL_HOSTED_CHECKOUT_CPA_SESSION_STEP_DEFINITIONS,
|
|
||||||
PLUS_PAYPAL_HOSTED_CHECKOUT_PHONE_STEP_DEFINITIONS,
|
|
||||||
PLUS_PAYPAL_HOSTED_CHECKOUT_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
PLUS_GOPAY_STEP_DEFINITIONS,
|
|
||||||
PLUS_GOPAY_SUB2API_SESSION_STEP_DEFINITIONS,
|
|
||||||
PLUS_GOPAY_PHONE_STEP_DEFINITIONS,
|
|
||||||
PLUS_GOPAY_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
PLUS_GPC_STEP_DEFINITIONS,
|
|
||||||
PLUS_GPC_SUB2API_SESSION_STEP_DEFINITIONS,
|
|
||||||
PLUS_GPC_PHONE_STEP_DEFINITIONS,
|
|
||||||
PLUS_GPC_PHONE_BOUND_EMAIL_RELOGIN_STEP_DEFINITIONS,
|
|
||||||
SIGNUP_METHOD_EMAIL,
|
SIGNUP_METHOD_EMAIL,
|
||||||
SIGNUP_METHOD_PHONE,
|
SIGNUP_METHOD_PHONE,
|
||||||
getAllSteps,
|
STEP_DEFINITIONS,
|
||||||
getAllNodes,
|
getAllNodes,
|
||||||
|
getAllSteps,
|
||||||
getLastStepId,
|
getLastStepId,
|
||||||
getNodeByDisplayOrder,
|
getNodeByDisplayOrder,
|
||||||
getNodeById,
|
getNodeById,
|
||||||
@@ -762,9 +253,6 @@
|
|||||||
getSteps,
|
getSteps,
|
||||||
getWorkflow,
|
getWorkflow,
|
||||||
hasFlow,
|
hasFlow,
|
||||||
isPlusModeEnabled,
|
|
||||||
normalizeActiveFlowId,
|
normalizeActiveFlowId,
|
||||||
normalizePlusPaymentMethod,
|
|
||||||
normalizeSignupMethod,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# 步骤与Flow节点化重构开发方案
|
# 步骤与Flow节点化重构开发方案
|
||||||
|
|
||||||
## 1. 文档目标
|
## 1. 文档目标
|
||||||
|
|
||||||
@@ -19,17 +19,17 @@
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| 状态 | `background.js` 里仍有 `currentStep`、`stepStatuses` | 数字步骤同时承担状态、顺序和恢复锚点 |
|
| 状态 | `background.js` 里仍有 `currentStep`、`stepStatuses` | 数字步骤同时承担状态、顺序和恢复锚点 |
|
||||||
| 协议 | `EXECUTE_STEP`、`STEP_COMPLETE`、`STEP_ERROR`、`SKIP_STEP` | 消息协议仍以数字 step 为核心 |
|
| 协议 | `EXECUTE_STEP`、`STEP_COMPLETE`、`STEP_ERROR`、`SKIP_STEP` | 消息协议仍以数字 step 为核心 |
|
||||||
| 定义 | `data/step-definitions.js`、`background/steps/registry.js` | 只有 OpenAI 真正注册,且执行仍按数字 id |
|
| 定义 | `data/step-definitions.js`、`core/flow-kernel/step-registry.js` | 只有 OpenAI 真正注册,且执行仍按数字 id |
|
||||||
| UI | `sidepanel/sidepanel.js` 按 step 渲染、发送、跳过 | 侧边栏本质上还是数字步骤面板 |
|
| UI | `sidepanel/sidepanel.js` 按 step 渲染、发送、跳过 | 侧边栏本质上还是数字步骤面板 |
|
||||||
| 内容脚本 | `content/signup-page.js` 按 `message.step` 分支 | 页面驱动逻辑被 step number 绑死 |
|
| 内容脚本 | `flows/openai/content/openai-auth.js` 按 `message.step` 分支 | 页面驱动逻辑被 step number 绑死 |
|
||||||
| 运行态 | `background/runtime-state.js` 已有 `currentNodeId`、`nodeStatuses` | 但仍通过 legacy step 视图回写,双模型并存 |
|
| 运行态 | `core/flow-kernel/runtime-state.js` 已有 `currentNodeId`、`nodeStatuses` | 但仍通过 legacy step 视图回写,双模型并存 |
|
||||||
| 外围能力 | `shared/source-registry.js`、`shared/flow-capabilities.js`、`background/mail-rule-registry.js` | 已有抽象,但都还没成为唯一事实来源 |
|
| 外围能力 | `core/flow-kernel/source-registry.js`、`core/flow-kernel/flow-capabilities.js`、`background/mail-rule-registry.js` | 已有抽象,但都还没成为唯一事实来源 |
|
||||||
|
|
||||||
重点文件里最能说明问题的几个点:
|
重点文件里最能说明问题的几个点:
|
||||||
|
|
||||||
- `background.js`:`DEFAULT_STATE`、`setStepStatus()`、`skipStep()`、`runAutoSequenceFromStep()`、`getStepRegistryForState()` 仍把数字 step 当主流程。
|
- `background.js`:`DEFAULT_STATE`、`setStepStatus()`、`skipStep()`、`runAutoSequenceFromStep()`、`getStepRegistryForState()` 仍把数字 step 当主流程。
|
||||||
- `background/message-router.js`:`STEP_COMPLETE` / `STEP_ERROR` / `EXECUTE_STEP` / `SKIP_STEP` 还在消息层面锁死 step。
|
- `background/message-router.js`:`STEP_COMPLETE` / `STEP_ERROR` / `EXECUTE_STEP` / `SKIP_STEP` 还在消息层面锁死 step。
|
||||||
- `background/runtime-state.js`:已经有 node 相关字段,但还在做 step 兼容派生。
|
- `core/flow-kernel/runtime-state.js`:已经有 node 相关字段,但还在做 step 兼容派生。
|
||||||
- `sidepanel/sidepanel.js`:步骤列表、状态展示、手动执行、跳过、自动运行都还围着 step。
|
- `sidepanel/sidepanel.js`:步骤列表、状态展示、手动执行、跳过、自动运行都还围着 step。
|
||||||
- `flows/openai/mail-rules.js`、`background/mail-rule-registry.js`:已经说明“规则可以 flow 化”,但目前只有 OpenAI 在用。
|
- `flows/openai/mail-rules.js`、`background/mail-rule-registry.js`:已经说明“规则可以 flow 化”,但目前只有 OpenAI 在用。
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ node = {
|
|||||||
type: 'task',
|
type: 'task',
|
||||||
order: 20, // 仅用于展示,不参与身份
|
order: 20, // 仅用于展示,不参与身份
|
||||||
sourceId: 'openai-auth',
|
sourceId: 'openai-auth',
|
||||||
driverId: 'content/signup-page',
|
driverId: 'flows/openai/content/openai-auth',
|
||||||
next: ['fill-password'],
|
next: ['fill-password'],
|
||||||
retryPolicy: { maxAttempts: 3 },
|
retryPolicy: { maxAttempts: 3 },
|
||||||
recoveryPolicy: { onFailure: 'restart-node' },
|
recoveryPolicy: { onFailure: 'restart-node' },
|
||||||
@@ -241,11 +241,11 @@ flows/<flowId>/
|
|||||||
|
|
||||||
### 6.3 content scripts
|
### 6.3 content scripts
|
||||||
|
|
||||||
`content/signup-page.js` 这类脚本要从“按 step 分支”改成“按 node action / command 分支”。
|
`flows/openai/content/openai-auth.js` 这类脚本要从“按 step 分支”改成“按 node action / command 分支”。
|
||||||
|
|
||||||
### 6.4 source / driver
|
### 6.4 source / driver
|
||||||
|
|
||||||
`shared/source-registry.js` 只负责页面来源、标签页生命周期和注入范围。
|
`core/flow-kernel/source-registry.js` 只负责页面来源、标签页生命周期和注入范围。
|
||||||
|
|
||||||
`driverRegistry` 只负责“这个 source 能接什么命令”。
|
`driverRegistry` 只负责“这个 source 能接什么命令”。
|
||||||
|
|
||||||
@@ -378,3 +378,4 @@ flows/<flowId>/
|
|||||||
- 邮件规则是否只从当前 flow definition 派生。
|
- 邮件规则是否只从当前 flow definition 派生。
|
||||||
- sidepanel 是否能仅通过 workflow nodes 渲染,不新增全局步骤 switch。
|
- sidepanel 是否能仅通过 workflow nodes 渲染,不新增全局步骤 switch。
|
||||||
- 自动运行、历史和日志是否都能用 `flowId/runId/nodeId` 定位。
|
- 自动运行、历史和日志是否都能用 `flowId/runId/nodeId` 定位。
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -94,9 +94,9 @@
|
|||||||
|
|
||||||
文件:
|
文件:
|
||||||
|
|
||||||
1. `background/kiro/state.js`
|
1. `flows/kiro/background/state.js`
|
||||||
2. `background/kiro/desktop-authorize-runner.js`
|
2. `flows/kiro/background/desktop-authorize-runner.js`
|
||||||
3. `background/kiro/publisher-kiro-rs.js`
|
3. `flows/kiro/background/publisher-kiro-rs.js`
|
||||||
4. `data/step-definitions.js`
|
4. `data/step-definitions.js`
|
||||||
|
|
||||||
当前事实:
|
当前事实:
|
||||||
@@ -434,7 +434,7 @@ const FLOW_CONTRIBUTION_ADAPTERS = {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4.2 修改 `shared/flow-registry.js`
|
### 4.2 修改 `core/flow-kernel/flow-registry.js`
|
||||||
|
|
||||||
新增 capability:
|
新增 capability:
|
||||||
|
|
||||||
@@ -449,7 +449,7 @@ supportsAccountContribution: true
|
|||||||
3. `supportsContributionMode` 仅作为迁移字段映射到 `supportsAccountContribution`。
|
3. `supportsContributionMode` 仅作为迁移字段映射到 `supportsAccountContribution`。
|
||||||
4. 新增 flow 只有在注册 adapter 后才能设置 `supportsAccountContribution: true`。
|
4. 新增 flow 只有在注册 adapter 后才能设置 `supportsAccountContribution: true`。
|
||||||
|
|
||||||
### 4.3 修改 `shared/flow-capabilities.js`
|
### 4.3 修改 `core/flow-kernel/flow-capabilities.js`
|
||||||
|
|
||||||
处理规则:
|
处理规则:
|
||||||
|
|
||||||
@@ -499,7 +499,7 @@ flowContributionRuntime: {
|
|||||||
新增文件:
|
新增文件:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
background/kiro/credential-artifact.js
|
flows/kiro/background/credential-artifact.js
|
||||||
```
|
```
|
||||||
|
|
||||||
职责:
|
职责:
|
||||||
@@ -515,8 +515,8 @@ background/kiro/credential-artifact.js
|
|||||||
|
|
||||||
修改位置:
|
修改位置:
|
||||||
|
|
||||||
1. `background/kiro/desktop-authorize-runner.js`
|
1. `flows/kiro/background/desktop-authorize-runner.js`
|
||||||
2. `background/kiro/publisher-kiro-rs.js`
|
2. `flows/kiro/background/publisher-kiro-rs.js`
|
||||||
3. Kiro runner 调度处
|
3. Kiro runner 调度处
|
||||||
|
|
||||||
处理规则:
|
处理规则:
|
||||||
@@ -782,7 +782,7 @@ POLL_FLOW_CONTRIBUTION_STATUS
|
|||||||
|
|
||||||
开发内容:
|
开发内容:
|
||||||
|
|
||||||
1. 新增 `background/kiro/credential-artifact.js`。
|
1. 新增 `flows/kiro/background/credential-artifact.js`。
|
||||||
2. 新增 `background/contribution/adapters/kiro-builder-id.js`。
|
2. 新增 `background/contribution/adapters/kiro-builder-id.js`。
|
||||||
3. 复用 Kiro runtime 产物构建 artifact。
|
3. 复用 Kiro runtime 产物构建 artifact。
|
||||||
4. 增加本地校验。
|
4. 增加本地校验。
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# 多注册流程来源与驱动注册设计
|
# 多注册流程来源与驱动注册设计
|
||||||
|
|
||||||
本文解决的是另一个会在第二个 flow 接入时立刻爆炸的问题:当前项目虽然有 `tab-runtime`,但“来源 source 是谁、该注入什么脚本、URL family 怎么判定、localhost callback 应该清谁”仍然带着明显的 OpenAI 单流程假设。
|
本文解决的是另一个会在第二个 flow 接入时立刻爆炸的问题:当前项目虽然有 `tab-runtime`,但“来源 source 是谁、该注入什么脚本、URL family 怎么判定、localhost callback 应该清谁”仍然带着明显的 OpenAI 单流程假设。
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
- `content/utils.js` 的 `detectScriptSource()`
|
- `content/utils.js` 的 `detectScriptSource()`
|
||||||
- `background/navigation-utils.js` 的 `matchesSourceUrlFamily()`
|
- `background/navigation-utils.js` 的 `matchesSourceUrlFamily()`
|
||||||
- `background/tab-runtime.js` 的注册表、冲突清理、callback 清理
|
- `core/flow-kernel/tab-runtime.js` 的注册表、冲突清理、callback 清理
|
||||||
|
|
||||||
这说明当前的 source 体系不是“可扩展的来源注册表”,而是“OpenAI 时代遗留的 source 命名”。
|
这说明当前的 source 体系不是“可扩展的来源注册表”,而是“OpenAI 时代遗留的 source 命名”。
|
||||||
|
|
||||||
@@ -58,10 +58,10 @@ sourceRegistry = {
|
|||||||
'content/activation-utils.js',
|
'content/activation-utils.js',
|
||||||
'content/utils.js',
|
'content/utils.js',
|
||||||
'content/operation-delay.js',
|
'content/operation-delay.js',
|
||||||
'content/auth-page-recovery.js',
|
'flows/openai/content/auth-page-recovery.js',
|
||||||
'content/phone-country-utils.js',
|
'flows/openai/content/phone-country-utils.js',
|
||||||
'content/phone-auth.js',
|
'flows/openai/content/phone-auth.js',
|
||||||
'content/signup-page.js',
|
'flows/openai/content/openai-auth.js',
|
||||||
],
|
],
|
||||||
cleanupScopes: ['oauth-localhost-callback'],
|
cleanupScopes: ['oauth-localhost-callback'],
|
||||||
},
|
},
|
||||||
@@ -81,7 +81,7 @@ sourceRegistry = {
|
|||||||
label: 'SUB2API 后台',
|
label: 'SUB2API 后台',
|
||||||
dynamicOnly: true,
|
dynamicOnly: true,
|
||||||
familyMatcher: 'sub2api-panel-family',
|
familyMatcher: 'sub2api-panel-family',
|
||||||
injectFiles: ['content/utils.js', 'content/sub2api-panel.js'],
|
injectFiles: ['content/utils.js', 'flows/openai/content/sub2api-panel.js'],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@@ -125,7 +125,7 @@ sourceRegistry = {
|
|||||||
driverRegistry = {
|
driverRegistry = {
|
||||||
'openai-auth': {
|
'openai-auth': {
|
||||||
sourceId: 'openai-auth',
|
sourceId: 'openai-auth',
|
||||||
driverId: 'content/signup-page',
|
driverId: 'flows/openai/content/openai-auth',
|
||||||
commands: [
|
commands: [
|
||||||
'OPEN_SIGNUP',
|
'OPEN_SIGNUP',
|
||||||
'SUBMIT_SIGNUP_IDENTIFIER',
|
'SUBMIT_SIGNUP_IDENTIFIER',
|
||||||
@@ -244,3 +244,4 @@ callbackRegistry = {
|
|||||||
- manifest 与动态注入没有统一入口
|
- manifest 与动态注入没有统一入口
|
||||||
- `content/utils.js` 的默认 source 回退会污染未来 flow
|
- `content/utils.js` 的默认 source 回退会污染未来 flow
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -77,8 +77,8 @@ flows/
|
|||||||
- `phone-sms/providers/hero-sms.js`
|
- `phone-sms/providers/hero-sms.js`
|
||||||
- `phone-sms/providers/five-sim.js`
|
- `phone-sms/providers/five-sim.js`
|
||||||
- `phone-sms/providers/registry.js`
|
- `phone-sms/providers/registry.js`
|
||||||
- `content/phone-auth.js`
|
- `flows/openai/content/phone-auth.js`
|
||||||
- `content/phone-country-utils.js`
|
- `flows/openai/content/phone-country-utils.js`
|
||||||
- sidepanel 中的接码配置区
|
- sidepanel 中的接码配置区
|
||||||
- 相关测试:`tests/phone-verification-flow.test.js`、`tests/five-sim-provider.test.js`、`tests/sidepanel-phone-verification-settings.test.js`
|
- 相关测试:`tests/phone-verification-flow.test.js`、`tests/five-sim-provider.test.js`、`tests/sidepanel-phone-verification-settings.test.js`
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -7,8 +7,8 @@
|
|||||||
定义:不离开当前步骤,在当前页面链路内恢复或替换资源。
|
定义:不离开当前步骤,在当前页面链路内恢复或替换资源。
|
||||||
|
|
||||||
典型位置:
|
典型位置:
|
||||||
- `background/steps/fetch-signup-code.js`(步骤 4 页面恢复)
|
- `flows/openai/background/steps/fetch-signup-code.js`(步骤 4 页面恢复)
|
||||||
- `background/steps/fetch-login-code.js` + `background/verification-flow.js`(步骤 8 邮箱轮询与重发)
|
- `flows/openai/background/steps/fetch-login-code.js` + `background/verification-flow.js`(步骤 8 邮箱轮询与重发)
|
||||||
- `background/phone-verification-flow.js`(步骤 9 号码轮换、重发、回到 add-phone)
|
- `background/phone-verification-flow.js`(步骤 9 号码轮换、重发、回到 add-phone)
|
||||||
|
|
||||||
常见动作:
|
常见动作:
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
(function attachMultiPageFlowsIndex(root, factory) {
|
||||||
|
root.MultiPageFlowsIndex = factory();
|
||||||
|
})(typeof self !== 'undefined' ? self : globalThis, function createFlowsIndexModule() {
|
||||||
|
const rootScope = typeof self !== 'undefined' ? self : globalThis;
|
||||||
|
|
||||||
|
const FLOW_ENTRY_DEFINITIONS = Object.freeze({
|
||||||
|
openai: {
|
||||||
|
id: 'openai',
|
||||||
|
path: 'flows/openai/',
|
||||||
|
},
|
||||||
|
kiro: {
|
||||||
|
id: 'kiro',
|
||||||
|
path: 'flows/kiro/',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function normalizeFlowId(value = '') {
|
||||||
|
return String(value || '').trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRegisteredFlowIds() {
|
||||||
|
return Object.keys(FLOW_ENTRY_DEFINITIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlowEntry(flowId) {
|
||||||
|
const normalized = normalizeFlowId(flowId);
|
||||||
|
const baseEntry = FLOW_ENTRY_DEFINITIONS[normalized];
|
||||||
|
if (!baseEntry) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...baseEntry,
|
||||||
|
definition: normalized === 'openai'
|
||||||
|
? (rootScope.MultiPageOpenAiFlowDefinition || null)
|
||||||
|
: (rootScope.MultiPageKiroFlowDefinition || null),
|
||||||
|
workflow: normalized === 'openai'
|
||||||
|
? (rootScope.MultiPageOpenAiWorkflow || null)
|
||||||
|
: (rootScope.MultiPageKiroWorkflow || null),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlowDefinition(flowId) {
|
||||||
|
return getFlowEntry(flowId)?.definition || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlowDefinitions() {
|
||||||
|
const next = {};
|
||||||
|
getRegisteredFlowIds().forEach((flowId) => {
|
||||||
|
const definition = getFlowDefinition(flowId);
|
||||||
|
if (definition) {
|
||||||
|
next[flowId] = definition;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlowWorkflow(flowId) {
|
||||||
|
return getFlowEntry(flowId)?.workflow || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getFlowEntry,
|
||||||
|
getFlowDefinition,
|
||||||
|
getFlowDefinitions,
|
||||||
|
getFlowWorkflow,
|
||||||
|
getRegisteredFlowIds,
|
||||||
|
};
|
||||||
|
});
|
||||||
+5
-5
@@ -20,14 +20,15 @@
|
|||||||
function readKiroRuntime(state = {}) {
|
function readKiroRuntime(state = {}) {
|
||||||
return kiroStateApi?.ensureRuntimeState
|
return kiroStateApi?.ensureRuntimeState
|
||||||
? kiroStateApi.ensureRuntimeState(state)
|
? kiroStateApi.ensureRuntimeState(state)
|
||||||
: (isPlainObject(state?.kiroRuntime) ? state.kiroRuntime : {});
|
: (isPlainObject(state?.runtimeState?.flowState?.kiro)
|
||||||
|
? state.runtimeState.flowState.kiro
|
||||||
|
: (isPlainObject(state?.flowState?.kiro) ? state.flowState.kiro : {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveKiroTargetId(state = {}, runtimeState = readKiroRuntime(state)) {
|
function resolveKiroTargetId(state = {}, runtimeState = readKiroRuntime(state)) {
|
||||||
return cleanString(
|
return cleanString(
|
||||||
state?.settingsState?.flows?.kiro?.targetId
|
state?.settingsState?.flows?.kiro?.selectedTargetId
|
||||||
|| state?.flows?.kiro?.targetId
|
|| state?.targetId
|
||||||
|| state?.kiroTargetId
|
|
||||||
|| runtimeState?.upload?.targetId
|
|| runtimeState?.upload?.targetId
|
||||||
|| DEFAULT_TARGET_ID
|
|| DEFAULT_TARGET_ID
|
||||||
) || DEFAULT_TARGET_ID;
|
) || DEFAULT_TARGET_ID;
|
||||||
@@ -46,7 +47,6 @@
|
|||||||
return cleanString(
|
return cleanString(
|
||||||
runtimeState?.desktopAuth?.region
|
runtimeState?.desktopAuth?.region
|
||||||
|| state?.settingsState?.flows?.kiro?.targets?.[targetId]?.region
|
|| state?.settingsState?.flows?.kiro?.targets?.[targetId]?.region
|
||||||
|| state?.flows?.kiro?.targets?.[targetId]?.region
|
|
||||||
|| DEFAULT_REGION
|
|| DEFAULT_REGION
|
||||||
) || DEFAULT_REGION;
|
) || DEFAULT_REGION;
|
||||||
}
|
}
|
||||||
+27
-3
@@ -97,16 +97,40 @@
|
|||||||
typeof kiroStateApi?.buildDefaultRuntimeState === 'function'
|
typeof kiroStateApi?.buildDefaultRuntimeState === 'function'
|
||||||
? kiroStateApi.buildDefaultRuntimeState()
|
? kiroStateApi.buildDefaultRuntimeState()
|
||||||
: {},
|
: {},
|
||||||
state?.kiroRuntime || {}
|
isPlainObject(state?.runtimeState?.flowState?.kiro)
|
||||||
|
? state.runtimeState.flowState.kiro
|
||||||
|
: (isPlainObject(state?.flowState?.kiro) ? state.flowState.kiro : {})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeRuntimePatch(currentState = {}, patch = {}) {
|
function buildCanonicalRuntimePatch(currentState = {}, nextRuntimeState = {}) {
|
||||||
|
if (typeof kiroStateApi?.buildRuntimeStatePatch === 'function') {
|
||||||
|
return kiroStateApi.buildRuntimeStatePatch(currentState, nextRuntimeState);
|
||||||
|
}
|
||||||
|
const baseRuntimeState = isPlainObject(currentState?.runtimeState)
|
||||||
|
? cloneValue(currentState.runtimeState)
|
||||||
|
: {};
|
||||||
|
const baseFlowState = isPlainObject(baseRuntimeState.flowState)
|
||||||
|
? cloneValue(baseRuntimeState.flowState)
|
||||||
|
: {};
|
||||||
return {
|
return {
|
||||||
kiroRuntime: deepMerge(readKiroRuntime(currentState), patch),
|
runtimeState: {
|
||||||
|
...baseRuntimeState,
|
||||||
|
flowState: {
|
||||||
|
...baseFlowState,
|
||||||
|
kiro: deepMerge(readKiroRuntime(currentState), nextRuntimeState),
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mergeRuntimePatch(currentState = {}, patch = {}) {
|
||||||
|
return buildCanonicalRuntimePatch(
|
||||||
|
currentState,
|
||||||
|
deepMerge(readKiroRuntime(currentState), patch)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function normalizePositiveInteger(value, fallback) {
|
function normalizePositiveInteger(value, fallback) {
|
||||||
const numeric = Math.floor(Number(value));
|
const numeric = Math.floor(Number(value));
|
||||||
if (Number.isInteger(numeric) && numeric > 0) {
|
if (Number.isInteger(numeric) && numeric > 0) {
|
||||||
@@ -108,20 +108,43 @@
|
|||||||
function readKiroRuntime(state = {}) {
|
function readKiroRuntime(state = {}) {
|
||||||
return kiroStateApi?.ensureRuntimeState
|
return kiroStateApi?.ensureRuntimeState
|
||||||
? kiroStateApi.ensureRuntimeState(state)
|
? kiroStateApi.ensureRuntimeState(state)
|
||||||
: (isPlainObject(state?.kiroRuntime) ? state.kiroRuntime : {});
|
: (isPlainObject(state?.runtimeState?.flowState?.kiro)
|
||||||
|
? state.runtimeState.flowState.kiro
|
||||||
|
: (isPlainObject(state?.flowState?.kiro) ? state.flowState.kiro : {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCanonicalRuntimePatch(currentState = {}, nextRuntimeState = {}) {
|
||||||
|
if (typeof kiroStateApi?.buildRuntimeStatePatch === 'function') {
|
||||||
|
return kiroStateApi.buildRuntimeStatePatch(currentState, nextRuntimeState);
|
||||||
|
}
|
||||||
|
const baseRuntimeState = isPlainObject(currentState?.runtimeState)
|
||||||
|
? cloneValue(currentState.runtimeState)
|
||||||
|
: {};
|
||||||
|
const baseFlowState = isPlainObject(baseRuntimeState.flowState)
|
||||||
|
? cloneValue(baseRuntimeState.flowState)
|
||||||
|
: {};
|
||||||
|
return {
|
||||||
|
runtimeState: {
|
||||||
|
...baseRuntimeState,
|
||||||
|
flowState: {
|
||||||
|
...baseFlowState,
|
||||||
|
kiro: deepMerge(readKiroRuntime(currentState), nextRuntimeState),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeRuntimePatch(currentState = {}, patch = {}) {
|
function mergeRuntimePatch(currentState = {}, patch = {}) {
|
||||||
return {
|
return buildCanonicalRuntimePatch(
|
||||||
kiroRuntime: deepMerge(readKiroRuntime(currentState), patch),
|
currentState,
|
||||||
};
|
deepMerge(readKiroRuntime(currentState), patch)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveKiroTargetId(state = {}) {
|
function resolveKiroTargetId(state = {}) {
|
||||||
return cleanString(
|
return cleanString(
|
||||||
state?.settingsState?.flows?.kiro?.targetId
|
state?.settingsState?.flows?.kiro?.selectedTargetId
|
||||||
|| state?.flows?.kiro?.targetId
|
|| state?.targetId
|
||||||
|| state?.kiroTargetId
|
|
||||||
|| readKiroRuntime(state).upload?.targetId
|
|| readKiroRuntime(state).upload?.targetId
|
||||||
|| DEFAULT_TARGET_ID
|
|| DEFAULT_TARGET_ID
|
||||||
) || DEFAULT_TARGET_ID;
|
) || DEFAULT_TARGET_ID;
|
||||||
@@ -131,9 +154,7 @@
|
|||||||
if (targetId !== DEFAULT_TARGET_ID) {
|
if (targetId !== DEFAULT_TARGET_ID) {
|
||||||
throw new Error(`暂不支持 Kiro 发布目标:${targetId}`);
|
throw new Error(`暂不支持 Kiro 发布目标:${targetId}`);
|
||||||
}
|
}
|
||||||
const nestedConfig = state?.settingsState?.flows?.kiro?.targets?.[targetId]
|
const nestedConfig = state?.settingsState?.flows?.kiro?.targets?.[targetId] || {};
|
||||||
|| state?.flows?.kiro?.targets?.[targetId]
|
|
||||||
|| {};
|
|
||||||
return {
|
return {
|
||||||
baseUrl: cleanString(nestedConfig.baseUrl || state?.kiroRsUrl),
|
baseUrl: cleanString(nestedConfig.baseUrl || state?.kiroRsUrl),
|
||||||
apiKey: normalizeKiroRsApiKey(nestedConfig.apiKey ?? state?.kiroRsKey ?? ''),
|
apiKey: normalizeKiroRsApiKey(nestedConfig.apiKey ?? state?.kiroRsKey ?? ''),
|
||||||
@@ -188,7 +209,6 @@
|
|||||||
const region = normalizeRegion(
|
const region = normalizeRegion(
|
||||||
desktopAuth.region
|
desktopAuth.region
|
||||||
|| state?.settingsState?.flows?.kiro?.targets?.[targetId]?.region
|
|| state?.settingsState?.flows?.kiro?.targets?.[targetId]?.region
|
||||||
|| state?.flows?.kiro?.targets?.[targetId]?.region
|
|
||||||
|| DEFAULT_REGION
|
|| DEFAULT_REGION
|
||||||
);
|
);
|
||||||
const email = cleanString(register.email || state?.email);
|
const email = cleanString(register.email || state?.email);
|
||||||
@@ -195,16 +195,40 @@
|
|||||||
typeof kiroStateApi?.buildDefaultRuntimeState === 'function'
|
typeof kiroStateApi?.buildDefaultRuntimeState === 'function'
|
||||||
? kiroStateApi.buildDefaultRuntimeState()
|
? kiroStateApi.buildDefaultRuntimeState()
|
||||||
: {},
|
: {},
|
||||||
state?.kiroRuntime || {}
|
isPlainObject(state?.runtimeState?.flowState?.kiro)
|
||||||
|
? state.runtimeState.flowState.kiro
|
||||||
|
: (isPlainObject(state?.flowState?.kiro) ? state.flowState.kiro : {})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeRuntimePatch(currentState = {}, patch = {}) {
|
function buildCanonicalRuntimePatch(currentState = {}, nextRuntimeState = {}) {
|
||||||
|
if (typeof kiroStateApi?.buildRuntimeStatePatch === 'function') {
|
||||||
|
return kiroStateApi.buildRuntimeStatePatch(currentState, nextRuntimeState);
|
||||||
|
}
|
||||||
|
const baseRuntimeState = isPlainObject(currentState?.runtimeState)
|
||||||
|
? cloneValue(currentState.runtimeState)
|
||||||
|
: {};
|
||||||
|
const baseFlowState = isPlainObject(baseRuntimeState.flowState)
|
||||||
|
? cloneValue(baseRuntimeState.flowState)
|
||||||
|
: {};
|
||||||
return {
|
return {
|
||||||
kiroRuntime: deepMerge(readKiroRuntime(currentState), patch),
|
runtimeState: {
|
||||||
|
...baseRuntimeState,
|
||||||
|
flowState: {
|
||||||
|
...baseFlowState,
|
||||||
|
kiro: deepMerge(readKiroRuntime(currentState), nextRuntimeState),
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mergeRuntimePatch(currentState = {}, patch = {}) {
|
||||||
|
return buildCanonicalRuntimePatch(
|
||||||
|
currentState,
|
||||||
|
deepMerge(readKiroRuntime(currentState), patch)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function getErrorMessage(error) {
|
function getErrorMessage(error) {
|
||||||
return error instanceof Error ? error.message : String(error ?? '未知错误');
|
return error instanceof Error ? error.message : String(error ?? '未知错误');
|
||||||
}
|
}
|
||||||
@@ -1076,7 +1100,7 @@
|
|||||||
tokenSource: 'desktop_authorization_code_pkce',
|
tokenSource: 'desktop_authorization_code_pkce',
|
||||||
},
|
},
|
||||||
upload: {
|
upload: {
|
||||||
targetId: cleanString(currentState?.kiroTargetId || readKiroRuntime(currentState).upload?.targetId) || DEFAULT_TARGET_ID,
|
targetId: cleanString(currentState?.targetId || readKiroRuntime(currentState).upload?.targetId) || DEFAULT_TARGET_ID,
|
||||||
status: 'waiting_register',
|
status: 'waiting_register',
|
||||||
error: '',
|
error: '',
|
||||||
credentialId: null,
|
credentialId: null,
|
||||||
@@ -1361,7 +1385,7 @@
|
|||||||
const pollingState = {
|
const pollingState = {
|
||||||
...currentState,
|
...currentState,
|
||||||
email: currentEmail,
|
email: currentEmail,
|
||||||
kiroRuntime: deepMerge(readKiroRuntime(currentState), {
|
...mergeRuntimePatch(currentState, {
|
||||||
register: {
|
register: {
|
||||||
email: currentEmail,
|
email: currentEmail,
|
||||||
},
|
},
|
||||||
@@ -58,6 +58,24 @@
|
|||||||
return Number.isInteger(numeric) ? numeric : fallback;
|
return Number.isInteger(numeric) ? numeric : fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeNullableIdentifier(value, fallback = null) {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
const numeric = Math.floor(value);
|
||||||
|
return Number.isInteger(numeric) ? numeric : fallback;
|
||||||
|
}
|
||||||
|
const normalized = String(value ?? '').trim();
|
||||||
|
if (!normalized) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
const numeric = Math.floor(Number(normalized));
|
||||||
|
return Number.isInteger(numeric) && String(numeric) === normalized
|
||||||
|
? numeric
|
||||||
|
: normalized;
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeBoolean(value, fallback = false) {
|
function normalizeBoolean(value, fallback = false) {
|
||||||
if (value === true || value === false) {
|
if (value === true || value === false) {
|
||||||
return value;
|
return value;
|
||||||
@@ -174,15 +192,63 @@
|
|||||||
targetId: normalizeString(merged.upload?.targetId, DEFAULT_TARGET_ID),
|
targetId: normalizeString(merged.upload?.targetId, DEFAULT_TARGET_ID),
|
||||||
status: normalizeString(merged.upload?.status),
|
status: normalizeString(merged.upload?.status),
|
||||||
error: normalizeString(merged.upload?.error),
|
error: normalizeString(merged.upload?.error),
|
||||||
credentialId: normalizeNullableInteger(merged.upload?.credentialId),
|
credentialId: normalizeNullableIdentifier(merged.upload?.credentialId),
|
||||||
lastMessage: normalizeString(merged.upload?.lastMessage),
|
lastMessage: normalizeString(merged.upload?.lastMessage),
|
||||||
lastUploadedAt: Math.max(0, normalizeInteger(merged.upload?.lastUploadedAt)),
|
lastUploadedAt: Math.max(0, normalizeInteger(merged.upload?.lastUploadedAt)),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildCanonicalRuntimeStatePatch(state = {}, runtimeState = {}) {
|
||||||
|
const normalizedRuntimeState = normalizeRuntimeState(runtimeState);
|
||||||
|
const baseRuntimeState = isPlainObject(state?.runtimeState)
|
||||||
|
? cloneValue(state.runtimeState)
|
||||||
|
: {};
|
||||||
|
const baseFlowState = isPlainObject(baseRuntimeState.flowState)
|
||||||
|
? cloneValue(baseRuntimeState.flowState)
|
||||||
|
: {};
|
||||||
|
return {
|
||||||
|
...baseRuntimeState,
|
||||||
|
flowState: {
|
||||||
|
...baseFlowState,
|
||||||
|
kiro: normalizedRuntimeState,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildRuntimeStateView(runtimeState = {}) {
|
||||||
|
const normalizedFlowState = isPlainObject(runtimeState?.flowState)
|
||||||
|
? runtimeState.flowState
|
||||||
|
: {};
|
||||||
|
return {
|
||||||
|
flowState: cloneValue(normalizedFlowState),
|
||||||
|
flows: cloneValue(normalizedFlowState),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildRuntimeStatePatch(currentState = {}, patch = {}) {
|
||||||
|
if (!isPlainObject(patch)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const nextRuntimeState = normalizeRuntimeState(
|
||||||
|
deepMerge(ensureRuntimeState(currentState), patch)
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
runtimeState: buildCanonicalRuntimeStatePatch(currentState, nextRuntimeState),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function ensureRuntimeState(state = {}) {
|
function ensureRuntimeState(state = {}) {
|
||||||
return normalizeRuntimeState(isPlainObject(state?.kiroRuntime) ? state.kiroRuntime : {});
|
const runtimeFlowState = isPlainObject(state?.runtimeState?.flowState)
|
||||||
|
? state.runtimeState.flowState
|
||||||
|
: {};
|
||||||
|
if (isPlainObject(runtimeFlowState.kiro)) {
|
||||||
|
return normalizeRuntimeState(runtimeFlowState.kiro);
|
||||||
|
}
|
||||||
|
if (isPlainObject(state?.flowState?.kiro)) {
|
||||||
|
return normalizeRuntimeState(state.flowState.kiro);
|
||||||
|
}
|
||||||
|
return buildDefaultRuntimeState();
|
||||||
}
|
}
|
||||||
|
|
||||||
function projectRuntimeFields() {
|
function projectRuntimeFields() {
|
||||||
@@ -190,31 +256,30 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildStateView(state = {}) {
|
function buildStateView(state = {}) {
|
||||||
|
const nextRuntimeState = ensureRuntimeState(state);
|
||||||
|
const runtimeState = buildCanonicalRuntimeStatePatch(state, nextRuntimeState);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
kiroRuntime: ensureRuntimeState(state),
|
runtimeState,
|
||||||
|
...buildRuntimeStateView(runtimeState),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildSessionStatePatch(currentState = {}, updates = {}) {
|
function buildSessionStatePatch(currentState = {}, updates = {}) {
|
||||||
if (!isPlainObject(updates?.kiroRuntime)) {
|
const runtimePatch = isPlainObject(updates?.runtimeState?.flowState?.kiro)
|
||||||
|
? updates.runtimeState.flowState.kiro
|
||||||
|
: (isPlainObject(updates?.flowState?.kiro)
|
||||||
|
? updates.flowState.kiro
|
||||||
|
: null);
|
||||||
|
if (!runtimePatch) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextRuntimeState = normalizeRuntimeState(
|
return buildRuntimeStatePatch(currentState, runtimePatch);
|
||||||
deepMerge(ensureRuntimeState(currentState), updates.kiroRuntime)
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
kiroRuntime: nextRuntimeState,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildRuntimeResetPatch(currentState = {}, patch = {}) {
|
function buildRuntimeResetPatch(currentState = {}, patch = {}) {
|
||||||
return {
|
return buildRuntimeStatePatch(currentState, patch);
|
||||||
kiroRuntime: normalizeRuntimeState(
|
|
||||||
deepMerge(ensureRuntimeState(currentState), patch)
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildStartRegisterResetPatch(currentState = {}) {
|
function buildStartRegisterResetPatch(currentState = {}) {
|
||||||
@@ -222,7 +287,7 @@
|
|||||||
const nextRuntimeState = buildDefaultRuntimeState();
|
const nextRuntimeState = buildDefaultRuntimeState();
|
||||||
nextRuntimeState.upload.targetId = currentRuntimeState.upload?.targetId || DEFAULT_TARGET_ID;
|
nextRuntimeState.upload.targetId = currentRuntimeState.upload?.targetId || DEFAULT_TARGET_ID;
|
||||||
return {
|
return {
|
||||||
kiroRuntime: nextRuntimeState,
|
runtimeState: buildCanonicalRuntimeStatePatch(currentState, nextRuntimeState),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,43 +316,45 @@
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
kiroRuntime: nextRuntimeState,
|
runtimeState: buildCanonicalRuntimeStatePatch(currentState, nextRuntimeState),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildDesktopResetPatch(currentState = {}) {
|
function buildDesktopResetPatch(currentState = {}) {
|
||||||
const currentRuntimeState = ensureRuntimeState(currentState);
|
const currentRuntimeState = ensureRuntimeState(currentState);
|
||||||
|
const nextRuntimeState = normalizeRuntimeState({
|
||||||
|
...currentRuntimeState,
|
||||||
|
session: {
|
||||||
|
...currentRuntimeState.session,
|
||||||
|
currentStage: 'desktop-authorize',
|
||||||
|
desktopTabId: null,
|
||||||
|
pageState: '',
|
||||||
|
pageUrl: '',
|
||||||
|
lastError: '',
|
||||||
|
lastWarning: '',
|
||||||
|
},
|
||||||
|
desktopAuth: buildDefaultRuntimeState().desktopAuth,
|
||||||
|
upload: {
|
||||||
|
...buildDefaultRuntimeState().upload,
|
||||||
|
targetId: currentRuntimeState.upload?.targetId || DEFAULT_TARGET_ID,
|
||||||
|
},
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
kiroRuntime: normalizeRuntimeState({
|
runtimeState: buildCanonicalRuntimeStatePatch(currentState, nextRuntimeState),
|
||||||
...currentRuntimeState,
|
|
||||||
session: {
|
|
||||||
...currentRuntimeState.session,
|
|
||||||
currentStage: 'desktop-authorize',
|
|
||||||
desktopTabId: null,
|
|
||||||
pageState: '',
|
|
||||||
pageUrl: '',
|
|
||||||
lastError: '',
|
|
||||||
lastWarning: '',
|
|
||||||
},
|
|
||||||
desktopAuth: buildDefaultRuntimeState().desktopAuth,
|
|
||||||
upload: {
|
|
||||||
...buildDefaultRuntimeState().upload,
|
|
||||||
targetId: currentRuntimeState.upload?.targetId || DEFAULT_TARGET_ID,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildUploadResetPatch(currentState = {}) {
|
function buildUploadResetPatch(currentState = {}) {
|
||||||
const currentRuntimeState = ensureRuntimeState(currentState);
|
const currentRuntimeState = ensureRuntimeState(currentState);
|
||||||
|
const nextRuntimeState = normalizeRuntimeState({
|
||||||
|
...currentRuntimeState,
|
||||||
|
upload: {
|
||||||
|
...buildDefaultRuntimeState().upload,
|
||||||
|
targetId: currentRuntimeState.upload?.targetId || DEFAULT_TARGET_ID,
|
||||||
|
},
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
kiroRuntime: normalizeRuntimeState({
|
runtimeState: buildCanonicalRuntimeStatePatch(currentState, nextRuntimeState),
|
||||||
...currentRuntimeState,
|
|
||||||
upload: {
|
|
||||||
...buildDefaultRuntimeState().upload,
|
|
||||||
targetId: currentRuntimeState.upload?.targetId || DEFAULT_TARGET_ID,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,9 +399,9 @@
|
|||||||
const nextRuntimeState = buildDefaultRuntimeState();
|
const nextRuntimeState = buildDefaultRuntimeState();
|
||||||
nextRuntimeState.upload.targetId = currentRuntimeState.upload?.targetId || DEFAULT_TARGET_ID;
|
nextRuntimeState.upload.targetId = currentRuntimeState.upload?.targetId || DEFAULT_TARGET_ID;
|
||||||
return {
|
return {
|
||||||
kiroRuntime: nextRuntimeState,
|
runtimeState: buildCanonicalRuntimeStatePatch(currentState, nextRuntimeState),
|
||||||
...(Object.prototype.hasOwnProperty.call(currentState, 'kiroTargetId')
|
...(Object.prototype.hasOwnProperty.call(currentState, 'targetId')
|
||||||
? { kiroTargetId: normalizeString(currentState.kiroTargetId, DEFAULT_TARGET_ID).toLowerCase() }
|
? { targetId: normalizeString(currentState.targetId, DEFAULT_TARGET_ID).toLowerCase() }
|
||||||
: {}),
|
: {}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -348,6 +415,7 @@
|
|||||||
buildDefaultRuntimeState,
|
buildDefaultRuntimeState,
|
||||||
buildDownstreamResetPatch,
|
buildDownstreamResetPatch,
|
||||||
buildFreshKeepState,
|
buildFreshKeepState,
|
||||||
|
buildRuntimeStatePatch,
|
||||||
buildSessionStatePatch,
|
buildSessionStatePatch,
|
||||||
buildStateView,
|
buildStateView,
|
||||||
ensureRuntimeState,
|
ensureRuntimeState,
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
(function attachMultiPageKiroFlowDefinition(root, factory) {
|
||||||
|
root.MultiPageKiroFlowDefinition = factory();
|
||||||
|
})(typeof self !== 'undefined' ? self : globalThis, function createMultiPageKiroFlowDefinition() {
|
||||||
|
function freezeDeep(entry) {
|
||||||
|
if (!entry || typeof entry !== 'object' || Object.isFrozen(entry)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
Object.getOwnPropertyNames(entry).forEach((key) => {
|
||||||
|
freezeDeep(entry[key]);
|
||||||
|
});
|
||||||
|
return Object.freeze(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
const VALUE = freezeDeep({
|
||||||
|
"id": "kiro",
|
||||||
|
"label": "Kiro",
|
||||||
|
"services": [
|
||||||
|
"account",
|
||||||
|
"email",
|
||||||
|
"proxy"
|
||||||
|
],
|
||||||
|
"capabilities": {
|
||||||
|
"supportsEmailSignup": true,
|
||||||
|
"supportsPhoneSignup": false,
|
||||||
|
"supportsPhoneVerificationSettings": false,
|
||||||
|
"supportsPlusMode": false,
|
||||||
|
"supportsContributionMode": false,
|
||||||
|
"supportsAccountContribution": true,
|
||||||
|
"supportsOpenAiOAuthContribution": false,
|
||||||
|
"contributionAdapterIds": [
|
||||||
|
"kiro-builder-id"
|
||||||
|
],
|
||||||
|
"supportedTargetIds": [
|
||||||
|
"kiro-rs"
|
||||||
|
],
|
||||||
|
"supportsLuckmail": false,
|
||||||
|
"supportsOauthTimeoutBudget": false,
|
||||||
|
"canSwitchFlow": true,
|
||||||
|
"stepDefinitionMode": "kiro",
|
||||||
|
"targetSelectorLabel": "来源"
|
||||||
|
},
|
||||||
|
"baseGroups": [
|
||||||
|
"kiro-runtime-status"
|
||||||
|
],
|
||||||
|
"targets": {
|
||||||
|
"kiro-rs": {
|
||||||
|
"id": "kiro-rs",
|
||||||
|
"label": "kiro.rs",
|
||||||
|
"groups": [
|
||||||
|
"kiro-target-kiro-rs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publicationTargets": {
|
||||||
|
"kiro-rs": {
|
||||||
|
"id": "kiro-rs",
|
||||||
|
"label": "kiro.rs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"runtimeSources": {
|
||||||
|
"kiro-register-page": {
|
||||||
|
"flowId": "kiro",
|
||||||
|
"kind": "flow-page",
|
||||||
|
"label": "Kiro 注册页",
|
||||||
|
"readyPolicy": "top-frame-only",
|
||||||
|
"family": "kiro-register-page-family",
|
||||||
|
"driverId": "flows/kiro/content/register-page",
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"detectionMatchers": [
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"app.kiro.dev",
|
||||||
|
"kiro.dev"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"view.awsapps.com",
|
||||||
|
"login.awsapps.com",
|
||||||
|
"amazonaws.com"
|
||||||
|
],
|
||||||
|
"hostnameFamilies": [
|
||||||
|
"signin.aws",
|
||||||
|
"profile.aws"
|
||||||
|
],
|
||||||
|
"hostnameEndsWith": [
|
||||||
|
".amazonaws.com"
|
||||||
|
],
|
||||||
|
"matchMode": "any"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"app.kiro.dev",
|
||||||
|
"kiro.dev"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"view.awsapps.com",
|
||||||
|
"login.awsapps.com",
|
||||||
|
"amazonaws.com"
|
||||||
|
],
|
||||||
|
"hostnameFamilies": [
|
||||||
|
"signin.aws",
|
||||||
|
"profile.aws"
|
||||||
|
],
|
||||||
|
"hostnameEndsWith": [
|
||||||
|
".amazonaws.com"
|
||||||
|
],
|
||||||
|
"matchMode": "any"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"kiro-desktop-authorize": {
|
||||||
|
"flowId": "kiro",
|
||||||
|
"kind": "flow-page",
|
||||||
|
"label": "Kiro 桌面授权页",
|
||||||
|
"readyPolicy": "top-frame-only",
|
||||||
|
"family": "kiro-desktop-authorize-family",
|
||||||
|
"driverId": "flows/kiro/content/desktop-authorize-page",
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"view.awsapps.com",
|
||||||
|
"login.awsapps.com",
|
||||||
|
"amazonaws.com"
|
||||||
|
],
|
||||||
|
"hostnameFamilies": [
|
||||||
|
"signin.aws",
|
||||||
|
"profile.aws"
|
||||||
|
],
|
||||||
|
"hostnameEndsWith": [
|
||||||
|
".amazonaws.com"
|
||||||
|
],
|
||||||
|
"matchMode": "any"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"kiro-rs-admin": {
|
||||||
|
"flowId": "kiro",
|
||||||
|
"kind": "virtual-page",
|
||||||
|
"label": "kiro.rs Admin",
|
||||||
|
"readyPolicy": "disabled",
|
||||||
|
"family": "kiro-rs-admin-family",
|
||||||
|
"driverId": null,
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"familyMatchers": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"driverDefinitions": {
|
||||||
|
"flows/kiro/content/register-page": {
|
||||||
|
"sourceId": "kiro-register-page",
|
||||||
|
"commands": [
|
||||||
|
"kiro-open-register-page",
|
||||||
|
"kiro-submit-email",
|
||||||
|
"kiro-submit-name",
|
||||||
|
"kiro-submit-verification-code",
|
||||||
|
"kiro-submit-password",
|
||||||
|
"kiro-complete-register-consent"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flows/kiro/content/desktop-authorize-page": {
|
||||||
|
"sourceId": "kiro-desktop-authorize",
|
||||||
|
"commands": [
|
||||||
|
"kiro-complete-desktop-authorize"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flows/kiro/background/register-runner": {
|
||||||
|
"sourceId": "kiro-register-page",
|
||||||
|
"commands": [
|
||||||
|
"kiro-open-register-page",
|
||||||
|
"kiro-submit-email",
|
||||||
|
"kiro-submit-name",
|
||||||
|
"kiro-submit-verification-code",
|
||||||
|
"kiro-submit-password",
|
||||||
|
"kiro-complete-register-consent"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flows/kiro/background/desktop-authorize-runner": {
|
||||||
|
"sourceId": "kiro-desktop-authorize",
|
||||||
|
"commands": [
|
||||||
|
"kiro-start-desktop-authorize",
|
||||||
|
"kiro-complete-desktop-authorize"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flows/kiro/background/publisher-kiro-rs": {
|
||||||
|
"sourceId": "kiro-rs-admin",
|
||||||
|
"commands": [
|
||||||
|
"kiro-upload-credential"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultTargetId": "kiro-rs",
|
||||||
|
"defaultPublicationTargetId": "kiro-rs",
|
||||||
|
"defaultTargetState": {
|
||||||
|
"baseUrl": "",
|
||||||
|
"apiKey": ""
|
||||||
|
},
|
||||||
|
"settingsGroups": {
|
||||||
|
"kiro-target-kiro-rs": {
|
||||||
|
"id": "kiro-target-kiro-rs",
|
||||||
|
"label": "kiro.rs 配置",
|
||||||
|
"rowIds": [
|
||||||
|
"row-kiro-rs-url",
|
||||||
|
"row-kiro-rs-key",
|
||||||
|
"row-kiro-rs-test-status"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"kiro-runtime-status": {
|
||||||
|
"id": "kiro-runtime-status",
|
||||||
|
"label": "Kiro 运行态",
|
||||||
|
"rowIds": [
|
||||||
|
"row-kiro-web-status",
|
||||||
|
"row-kiro-login-url",
|
||||||
|
"row-kiro-upload-status"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceAliases": {}
|
||||||
|
});
|
||||||
|
|
||||||
|
return VALUE;
|
||||||
|
});
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
(function attachMultiPageKiroWorkflow(root, factory) {
|
||||||
|
root.MultiPageKiroWorkflow = factory();
|
||||||
|
})(typeof self !== 'undefined' ? self : globalThis, function createMultiPageKiroWorkflow() {
|
||||||
|
const KIRO_CONTRIBUTION_STEP_TITLE = '\u8d21\u732e\u4e0a\u4f20';
|
||||||
|
|
||||||
|
function freezeDeep(entry) {
|
||||||
|
if (!entry || typeof entry !== 'object' || Object.isFrozen(entry)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
Object.getOwnPropertyNames(entry).forEach((key) => {
|
||||||
|
freezeDeep(entry[key]);
|
||||||
|
});
|
||||||
|
return Object.freeze(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
const STEP_VARIANTS = freezeDeep({
|
||||||
|
"default": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"order": 10,
|
||||||
|
"key": "kiro-open-register-page",
|
||||||
|
"title": "打开注册页",
|
||||||
|
"sourceId": "kiro-register-page",
|
||||||
|
"driverId": "flows/kiro/background/register-runner",
|
||||||
|
"command": "kiro-open-register-page",
|
||||||
|
"flowId": "kiro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"order": 20,
|
||||||
|
"key": "kiro-submit-email",
|
||||||
|
"title": "获取邮箱并继续",
|
||||||
|
"sourceId": "kiro-register-page",
|
||||||
|
"driverId": "flows/kiro/background/register-runner",
|
||||||
|
"command": "kiro-submit-email",
|
||||||
|
"flowId": "kiro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"order": 30,
|
||||||
|
"key": "kiro-submit-name",
|
||||||
|
"title": "填写姓名并继续",
|
||||||
|
"sourceId": "kiro-register-page",
|
||||||
|
"driverId": "flows/kiro/background/register-runner",
|
||||||
|
"command": "kiro-submit-name",
|
||||||
|
"flowId": "kiro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"order": 40,
|
||||||
|
"key": "kiro-submit-verification-code",
|
||||||
|
"title": "获取验证码并继续",
|
||||||
|
"sourceId": "kiro-register-page",
|
||||||
|
"driverId": "flows/kiro/background/register-runner",
|
||||||
|
"command": "kiro-submit-verification-code",
|
||||||
|
"flowId": "kiro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"order": 50,
|
||||||
|
"key": "kiro-submit-password",
|
||||||
|
"title": "设置密码并继续",
|
||||||
|
"sourceId": "kiro-register-page",
|
||||||
|
"driverId": "flows/kiro/background/register-runner",
|
||||||
|
"command": "kiro-submit-password",
|
||||||
|
"flowId": "kiro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"order": 60,
|
||||||
|
"key": "kiro-complete-register-consent",
|
||||||
|
"title": "完成注册授权",
|
||||||
|
"sourceId": "kiro-register-page",
|
||||||
|
"driverId": "flows/kiro/background/register-runner",
|
||||||
|
"command": "kiro-complete-register-consent",
|
||||||
|
"flowId": "kiro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"order": 70,
|
||||||
|
"key": "kiro-start-desktop-authorize",
|
||||||
|
"title": "启动桌面授权",
|
||||||
|
"sourceId": "kiro-desktop-authorize",
|
||||||
|
"driverId": "flows/kiro/background/desktop-authorize-runner",
|
||||||
|
"command": "kiro-start-desktop-authorize",
|
||||||
|
"flowId": "kiro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"order": 80,
|
||||||
|
"key": "kiro-complete-desktop-authorize",
|
||||||
|
"title": "完成桌面授权",
|
||||||
|
"sourceId": "kiro-desktop-authorize",
|
||||||
|
"driverId": "flows/kiro/background/desktop-authorize-runner",
|
||||||
|
"command": "kiro-complete-desktop-authorize",
|
||||||
|
"flowId": "kiro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"order": 90,
|
||||||
|
"key": "kiro-upload-credential",
|
||||||
|
"title": "上传凭据到 kiro.rs",
|
||||||
|
"sourceId": "kiro-rs-admin",
|
||||||
|
"driverId": "flows/kiro/background/publisher-kiro-rs",
|
||||||
|
"command": "kiro-upload-credential",
|
||||||
|
"flowId": "kiro"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
function getVariantStepDefinitions(variantKey = 'default') {
|
||||||
|
return Array.isArray(STEP_VARIANTS[variantKey]) ? STEP_VARIANTS[variantKey] : STEP_VARIANTS.default;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModeStepDefinitions() {
|
||||||
|
return getVariantStepDefinitions('default');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAllSteps() {
|
||||||
|
return getVariantStepDefinitions('default');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPlusPaymentStepTitle() {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveStepTitle(step = {}, options = {}) {
|
||||||
|
if (step?.key === 'kiro-upload-credential' && Boolean(options?.accountContributionEnabled || options?.state?.accountContributionEnabled)) {
|
||||||
|
return KIRO_CONTRIBUTION_STEP_TITLE;
|
||||||
|
}
|
||||||
|
return step?.title || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
flowId: 'kiro',
|
||||||
|
getAllSteps,
|
||||||
|
getModeStepDefinitions,
|
||||||
|
getPlusPaymentStepTitle,
|
||||||
|
getVariantStepDefinitions,
|
||||||
|
resolveStepTitle,
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -221,14 +221,14 @@
|
|||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
throwIfStep8SettledOrStopped(resolved);
|
throwIfStep8SettledOrStopped(resolved);
|
||||||
signupTabId = await getTabId('signup-page');
|
signupTabId = await getTabId('openai-auth');
|
||||||
throwIfStep8SettledOrStopped(resolved);
|
throwIfStep8SettledOrStopped(resolved);
|
||||||
|
|
||||||
if (signupTabId && await isTabAlive('signup-page')) {
|
if (signupTabId && await isTabAlive('openai-auth')) {
|
||||||
await chrome.tabs.update(signupTabId, { active: true });
|
await chrome.tabs.update(signupTabId, { active: true });
|
||||||
await addStepLog(visibleStep, '已切回认证页,正在准备调试器点击...');
|
await addStepLog(visibleStep, '已切回认证页,正在准备调试器点击...');
|
||||||
} else {
|
} else {
|
||||||
signupTabId = await reuseOrCreateTab('signup-page', activeState.oauthUrl);
|
signupTabId = await reuseOrCreateTab('openai-auth', activeState.oauthUrl);
|
||||||
await addStepLog(visibleStep, '已重新打开认证页,正在准备调试器点击...');
|
await addStepLog(visibleStep, '已重新打开认证页,正在准备调试器点击...');
|
||||||
}
|
}
|
||||||
|
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
root.MultiPageBackgroundCpaSessionImport = factory();
|
root.MultiPageBackgroundCpaSessionImport = factory();
|
||||||
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundCpaSessionImportModule() {
|
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundCpaSessionImportModule() {
|
||||||
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
||||||
const PLUS_CHECKOUT_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'content/plus-checkout.js'];
|
const PLUS_CHECKOUT_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'flows/openai/content/plus-checkout.js'];
|
||||||
|
|
||||||
function createCpaSessionImportExecutor(deps = {}) {
|
function createCpaSessionImportExecutor(deps = {}) {
|
||||||
const {
|
const {
|
||||||
+2
-2
@@ -4,8 +4,8 @@
|
|||||||
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
||||||
const PAYPAL_SOURCE = 'paypal-flow';
|
const PAYPAL_SOURCE = 'paypal-flow';
|
||||||
const PLUS_CHECKOUT_ENTRY_URL = 'https://chatgpt.com/';
|
const PLUS_CHECKOUT_ENTRY_URL = 'https://chatgpt.com/';
|
||||||
const PLUS_CHECKOUT_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'content/plus-checkout.js'];
|
const PLUS_CHECKOUT_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'flows/openai/content/plus-checkout.js'];
|
||||||
const PAYPAL_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'content/paypal-flow.js'];
|
const PAYPAL_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'flows/openai/content/paypal-flow.js'];
|
||||||
const PLUS_PAYMENT_METHOD_PAYPAL = 'paypal';
|
const PLUS_PAYMENT_METHOD_PAYPAL = 'paypal';
|
||||||
const PLUS_PAYMENT_METHOD_PAYPAL_HOSTED = 'paypal-hosted';
|
const PLUS_PAYMENT_METHOD_PAYPAL_HOSTED = 'paypal-hosted';
|
||||||
const PLUS_PAYMENT_METHOD_GOPAY = 'gopay';
|
const PLUS_PAYMENT_METHOD_GOPAY = 'gopay';
|
||||||
+8
-8
@@ -158,7 +158,7 @@
|
|||||||
}
|
}
|
||||||
const timeoutMs = Math.max(1000, Number(options.timeoutMs) || 15000);
|
const timeoutMs = Math.max(1000, Number(options.timeoutMs) || 15000);
|
||||||
const result = await sendToContentScriptResilient(
|
const result = await sendToContentScriptResilient(
|
||||||
'signup-page',
|
'openai-auth',
|
||||||
{
|
{
|
||||||
type: 'GET_LOGIN_AUTH_STATE',
|
type: 'GET_LOGIN_AUTH_STATE',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
})
|
})
|
||||||
: 60000;
|
: 60000;
|
||||||
const result = await sendToContentScriptResilient(
|
const result = await sendToContentScriptResilient(
|
||||||
'signup-page',
|
'openai-auth',
|
||||||
{
|
{
|
||||||
type: 'SUBMIT_ADD_EMAIL',
|
type: 'SUBMIT_ADD_EMAIL',
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -439,7 +439,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function ensureAuthTabForPostLoginStep(state, visibleStep) {
|
async function ensureAuthTabForPostLoginStep(state, visibleStep) {
|
||||||
const authTabId = await getTabId('signup-page');
|
const authTabId = await getTabId('openai-auth');
|
||||||
if (authTabId) {
|
if (authTabId) {
|
||||||
await chrome.tabs.update(authTabId, { active: true });
|
await chrome.tabs.update(authTabId, { active: true });
|
||||||
return authTabId;
|
return authTabId;
|
||||||
@@ -447,7 +447,7 @@
|
|||||||
if (!state?.oauthUrl) {
|
if (!state?.oauthUrl) {
|
||||||
throw new Error(`步骤 ${visibleStep}:缺少登录用 OAuth 链接,请先完成刷新 OAuth 并登录。`);
|
throw new Error(`步骤 ${visibleStep}:缺少登录用 OAuth 链接,请先完成刷新 OAuth 并登录。`);
|
||||||
}
|
}
|
||||||
return reuseOrCreateTab('signup-page', state.oauthUrl);
|
return reuseOrCreateTab('openai-auth', state.oauthUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function completePostLoginPhoneVerificationSkippedOnOauth(visibleStep, options = {}) {
|
async function completePostLoginPhoneVerificationSkippedOnOauth(visibleStep, options = {}) {
|
||||||
@@ -708,7 +708,7 @@
|
|||||||
activeFetchLoginCodeStep = visibleStep;
|
activeFetchLoginCodeStep = visibleStep;
|
||||||
activeFetchLoginCodeStepKey = 'fetch-bound-email-login-code';
|
activeFetchLoginCodeStepKey = 'fetch-bound-email-login-code';
|
||||||
const preparedState = buildBoundEmailLoginState(state, visibleStep);
|
const preparedState = buildBoundEmailLoginState(state, visibleStep);
|
||||||
const authTabId = await getTabId('signup-page');
|
const authTabId = await getTabId('openai-auth');
|
||||||
|
|
||||||
if (authTabId) {
|
if (authTabId) {
|
||||||
await chrome.tabs.update(authTabId, { active: true });
|
await chrome.tabs.update(authTabId, { active: true });
|
||||||
@@ -716,7 +716,7 @@
|
|||||||
if (!preparedState.oauthUrl) {
|
if (!preparedState.oauthUrl) {
|
||||||
throw new Error(`步骤 ${visibleStep}:缺少登录用 OAuth 链接,请先完成绑定邮箱后刷新 OAuth 并登录。`);
|
throw new Error(`步骤 ${visibleStep}:缺少登录用 OAuth 链接,请先完成绑定邮箱后刷新 OAuth 并登录。`);
|
||||||
}
|
}
|
||||||
await reuseOrCreateTab('signup-page', preparedState.oauthUrl);
|
await reuseOrCreateTab('openai-auth', preparedState.oauthUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
throwIfStopped();
|
throwIfStopped();
|
||||||
@@ -765,7 +765,7 @@
|
|||||||
const visibleStep = getVisibleStep(state, 8);
|
const visibleStep = getVisibleStep(state, 8);
|
||||||
activeFetchLoginCodeStep = visibleStep;
|
activeFetchLoginCodeStep = visibleStep;
|
||||||
activeFetchLoginCodeStepKey = 'fetch-login-code';
|
activeFetchLoginCodeStepKey = 'fetch-login-code';
|
||||||
const authTabId = await getTabId('signup-page');
|
const authTabId = await getTabId('openai-auth');
|
||||||
|
|
||||||
if (authTabId) {
|
if (authTabId) {
|
||||||
await chrome.tabs.update(authTabId, { active: true });
|
await chrome.tabs.update(authTabId, { active: true });
|
||||||
@@ -773,7 +773,7 @@
|
|||||||
if (!state.oauthUrl) {
|
if (!state.oauthUrl) {
|
||||||
throw new Error(`缺少登录用 OAuth 链接,请先完成步骤 ${getAuthLoginStepForVisibleStep(visibleStep)}。`);
|
throw new Error(`缺少登录用 OAuth 链接,请先完成步骤 ${getAuthLoginStepForVisibleStep(visibleStep)}。`);
|
||||||
}
|
}
|
||||||
await reuseOrCreateTab('signup-page', state.oauthUrl);
|
await reuseOrCreateTab('openai-auth', state.oauthUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
throwIfStopped();
|
throwIfStopped();
|
||||||
+4
-4
@@ -188,7 +188,7 @@
|
|||||||
async function executeStep4(state) {
|
async function executeStep4(state) {
|
||||||
const stepStartedAt = Date.now();
|
const stepStartedAt = Date.now();
|
||||||
const verificationSessionKey = `4:${stepStartedAt}`;
|
const verificationSessionKey = `4:${stepStartedAt}`;
|
||||||
const signupTabId = await getTabId('signup-page');
|
const signupTabId = await getTabId('openai-auth');
|
||||||
|
|
||||||
if (!signupTabId) {
|
if (!signupTabId) {
|
||||||
throw new Error('认证页面标签页已关闭,无法继续步骤 4。请先执行步骤 1 或步骤 2,重新打开认证页后再试。');
|
throw new Error('认证页面标签页已关闭,无法继续步骤 4。请先执行步骤 1 或步骤 2,重新打开认证页后再试。');
|
||||||
@@ -228,10 +228,10 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
prepareResult = typeof sendToContentScript === 'function'
|
prepareResult = typeof sendToContentScript === 'function'
|
||||||
? await sendToContentScript('signup-page', prepareRequest, {
|
? await sendToContentScript('openai-auth', prepareRequest, {
|
||||||
responseTimeoutMs: prepareResponseTimeoutMs,
|
responseTimeoutMs: prepareResponseTimeoutMs,
|
||||||
})
|
})
|
||||||
: await sendToContentScriptResilient('signup-page', prepareRequest, {
|
: await sendToContentScriptResilient('openai-auth', prepareRequest, {
|
||||||
timeoutMs: Math.max(1000, prepareTimeoutMs - (Date.now() - prepareStartAt)),
|
timeoutMs: Math.max(1000, prepareTimeoutMs - (Date.now() - prepareStartAt)),
|
||||||
responseTimeoutMs: prepareResponseTimeoutMs,
|
responseTimeoutMs: prepareResponseTimeoutMs,
|
||||||
retryDelayMs: 700,
|
retryDelayMs: 700,
|
||||||
@@ -248,7 +248,7 @@
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
const recoverResult = await sendToContentScriptResilient('signup-page', {
|
const recoverResult = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'RECOVER_AUTH_RETRY_PAGE',
|
type: 'RECOVER_AUTH_RETRY_PAGE',
|
||||||
step: 4,
|
step: 4,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
sendToContentScript,
|
sendToContentScript,
|
||||||
setPasswordState,
|
setPasswordState,
|
||||||
setState,
|
setState,
|
||||||
SIGNUP_PAGE_INJECT_FILES,
|
OPENAI_AUTH_INJECT_FILES,
|
||||||
} = deps;
|
} = deps;
|
||||||
|
|
||||||
function normalizeSignupMethod(value = '') {
|
function normalizeSignupMethod(value = '') {
|
||||||
@@ -71,8 +71,8 @@
|
|||||||
throw new Error('缺少注册账号,请先完成步骤 2。');
|
throw new Error('缺少注册账号,请先完成步骤 2。');
|
||||||
}
|
}
|
||||||
|
|
||||||
const signupTabId = await getTabId('signup-page');
|
const signupTabId = await getTabId('openai-auth');
|
||||||
if (!signupTabId || !(await isTabAlive('signup-page'))) {
|
if (!signupTabId || !(await isTabAlive('openai-auth'))) {
|
||||||
throw new Error('认证页面标签页已关闭,请先重新完成步骤 2。');
|
throw new Error('认证页面标签页已关闭,请先重新完成步骤 2。');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,9 +90,9 @@
|
|||||||
await setState({ accounts });
|
await setState({ accounts });
|
||||||
|
|
||||||
await chrome.tabs.update(signupTabId, { active: true });
|
await chrome.tabs.update(signupTabId, { active: true });
|
||||||
await ensureContentScriptReadyOnTab('signup-page', signupTabId, {
|
await ensureContentScriptReadyOnTab('openai-auth', signupTabId, {
|
||||||
inject: SIGNUP_PAGE_INJECT_FILES,
|
inject: OPENAI_AUTH_INJECT_FILES,
|
||||||
injectSource: 'signup-page',
|
injectSource: 'openai-auth',
|
||||||
timeoutMs: 45000,
|
timeoutMs: 45000,
|
||||||
retryDelayMs: 900,
|
retryDelayMs: 900,
|
||||||
logMessage: '步骤 3:密码页内容脚本未就绪,正在等待页面恢复...',
|
logMessage: '步骤 3:密码页内容脚本未就绪,正在等待页面恢复...',
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
await addLog(
|
await addLog(
|
||||||
`步骤 3:正在填写密码,${identityLabel},密码为${state.customPassword ? '自定义' : '自动生成'}(${password.length} 位)`
|
`步骤 3:正在填写密码,${identityLabel},密码为${state.customPassword ? '自定义' : '自动生成'}(${password.length} 位)`
|
||||||
);
|
);
|
||||||
await sendToContentScript('signup-page', {
|
await sendToContentScript('openai-auth', {
|
||||||
type: 'EXECUTE_NODE',
|
type: 'EXECUTE_NODE',
|
||||||
nodeId: 'fill-password',
|
nodeId: 'fill-password',
|
||||||
step: 3,
|
step: 3,
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
root.MultiPageBackgroundPlusCheckoutBilling = factory();
|
root.MultiPageBackgroundPlusCheckoutBilling = factory();
|
||||||
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundPlusCheckoutBillingModule() {
|
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundPlusCheckoutBillingModule() {
|
||||||
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
||||||
const PLUS_CHECKOUT_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'content/plus-checkout.js'];
|
const PLUS_CHECKOUT_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'flows/openai/content/plus-checkout.js'];
|
||||||
const PLUS_CHECKOUT_URL_PATTERN = /^https:\/\/chatgpt\.com\/checkout(?:\/|$)/i;
|
const PLUS_CHECKOUT_URL_PATTERN = /^https:\/\/chatgpt\.com\/checkout(?:\/|$)/i;
|
||||||
const PLUS_CHECKOUT_FRAME_READY_DELAY_MS = 500;
|
const PLUS_CHECKOUT_FRAME_READY_DELAY_MS = 500;
|
||||||
const PLUS_CHECKOUT_SUBMIT_MAX_ATTEMPTS = 5;
|
const PLUS_CHECKOUT_SUBMIT_MAX_ATTEMPTS = 5;
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
await addLog(`步骤 5:已生成姓名 ${firstName} ${lastName},生日 ${year}-${month}-${day}`);
|
await addLog(`步骤 5:已生成姓名 ${firstName} ${lastName},生日 ${year}-${month}-${day}`);
|
||||||
|
|
||||||
await sendToContentScript('signup-page', {
|
await sendToContentScript('openai-auth', {
|
||||||
type: 'EXECUTE_NODE',
|
type: 'EXECUTE_NODE',
|
||||||
nodeId: 'fill-profile',
|
nodeId: 'fill-profile',
|
||||||
step: 5,
|
step: 5,
|
||||||
+11
-11
@@ -4,7 +4,7 @@
|
|||||||
const GOPAY_SOURCE = 'gopay-flow';
|
const GOPAY_SOURCE = 'gopay-flow';
|
||||||
const GOPAY_OTP_SOURCE = 'gopay-otp-flow';
|
const GOPAY_OTP_SOURCE = 'gopay-otp-flow';
|
||||||
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
||||||
const GOPAY_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'content/gopay-flow.js'];
|
const GOPAY_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'flows/openai/content/gopay-flow.js'];
|
||||||
const GOPAY_WAIT_TIMEOUT_MS = 120000;
|
const GOPAY_WAIT_TIMEOUT_MS = 120000;
|
||||||
const GOPAY_POLL_INTERVAL_MS = 1000;
|
const GOPAY_POLL_INTERVAL_MS = 1000;
|
||||||
const GOPAY_LINKING_RETRY_WAIT_MS = 15000;
|
const GOPAY_LINKING_RETRY_WAIT_MS = 15000;
|
||||||
@@ -914,16 +914,16 @@
|
|||||||
const target = Number.isInteger(frameId)
|
const target = Number.isInteger(frameId)
|
||||||
? await sendGoPayFrameCommand(tabId, frameId, targetMessageType, {})
|
? await sendGoPayFrameCommand(tabId, frameId, targetMessageType, {})
|
||||||
: await sendGoPayCommand(tabId, targetMessageType, {});
|
: await sendGoPayCommand(tabId, targetMessageType, {});
|
||||||
const rect = target?.rect || null;
|
const rect = target?.rect || null;
|
||||||
if (!target?.found || !rect || !Number.isFinite(rect.centerX) || !Number.isFinite(rect.centerY)) {
|
if (!target?.found || !rect || !Number.isFinite(rect.centerX) || !Number.isFinite(rect.centerY)) {
|
||||||
return { clicked: false, reason: 'target_not_found', clickTarget: target?.target || '' };
|
return { clicked: false, reason: 'target_not_found', clickTarget: target?.target || '' };
|
||||||
}
|
}
|
||||||
if (Number.isInteger(frameId)) {
|
if (Number.isInteger(frameId)) {
|
||||||
return { clicked: false, reason: 'debugger_click_skipped_for_frame_target', clickTarget: target.target || '' };
|
return { clicked: false, reason: 'debugger_click_skipped_for_frame_target', clickTarget: target.target || '' };
|
||||||
}
|
}
|
||||||
await clickWithDebugger(tabId, rect);
|
await clickWithDebugger(tabId, rect);
|
||||||
return { clicked: true, clickTarget: target.target || '' };
|
return { clicked: true, clickTarget: target.target || '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function clickGoPayContinueWithDebugger(tabId, frameId = null) {
|
async function clickGoPayContinueWithDebugger(tabId, frameId = null) {
|
||||||
@@ -301,10 +301,10 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await reuseOrCreateTab('signup-page', oauthUrl, { forceNew: true });
|
await reuseOrCreateTab('openai-auth', oauthUrl, { forceNew: true });
|
||||||
|
|
||||||
const result = await sendToContentScriptResilient(
|
const result = await sendToContentScriptResilient(
|
||||||
'signup-page',
|
'openai-auth',
|
||||||
{
|
{
|
||||||
type: 'EXECUTE_NODE',
|
type: 'EXECUTE_NODE',
|
||||||
nodeId: state?.nodeId || 'oauth-login',
|
nodeId: state?.nodeId || 'oauth-login',
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundPayPalApproveModule() {
|
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundPayPalApproveModule() {
|
||||||
const PAYPAL_SOURCE = 'paypal-flow';
|
const PAYPAL_SOURCE = 'paypal-flow';
|
||||||
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
||||||
const PAYPAL_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'content/paypal-flow.js'];
|
const PAYPAL_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'flows/openai/content/paypal-flow.js'];
|
||||||
const PAYPAL_LOGIN_TRANSITION_TIMEOUT_MS = 30000;
|
const PAYPAL_LOGIN_TRANSITION_TIMEOUT_MS = 30000;
|
||||||
const PAYPAL_LOGIN_TRANSITION_POLL_MS = 500;
|
const PAYPAL_LOGIN_TRANSITION_POLL_MS = 500;
|
||||||
|
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
root.MultiPageBackgroundSub2ApiSessionImport = factory();
|
root.MultiPageBackgroundSub2ApiSessionImport = factory();
|
||||||
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundSub2ApiSessionImportModule() {
|
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundSub2ApiSessionImportModule() {
|
||||||
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
const PLUS_CHECKOUT_SOURCE = 'plus-checkout';
|
||||||
const PLUS_CHECKOUT_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'content/plus-checkout.js'];
|
const PLUS_CHECKOUT_INJECT_FILES = ['content/utils.js', 'content/operation-delay.js', 'flows/openai/content/plus-checkout.js'];
|
||||||
|
|
||||||
function createSub2ApiSessionImportExecutor(deps = {}) {
|
function createSub2ApiSessionImportExecutor(deps = {}) {
|
||||||
const {
|
const {
|
||||||
+10
-10
@@ -17,7 +17,7 @@
|
|||||||
resolveSignupMethod = () => 'email',
|
resolveSignupMethod = () => 'email',
|
||||||
resolveSignupEmailForFlow,
|
resolveSignupEmailForFlow,
|
||||||
sendToContentScriptResilient,
|
sendToContentScriptResilient,
|
||||||
SIGNUP_PAGE_INJECT_FILES,
|
OPENAI_AUTH_INJECT_FILES,
|
||||||
waitForTabStableComplete = null,
|
waitForTabStableComplete = null,
|
||||||
} = deps;
|
} = deps;
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
function isRetryableStep2TransportErrorMessage(errorLike) {
|
function isRetryableStep2TransportErrorMessage(errorLike) {
|
||||||
const message = getErrorMessage(errorLike);
|
const message = getErrorMessage(errorLike);
|
||||||
return /Content script on signup-page did not respond in \d+s|内容脚本\s+\d+(?:\.\d+)?\s*秒内未响应|Receiving end does not exist|message channel closed|A listener indicated an asynchronous response|port closed before a response was received|did not respond in \d+s/i.test(message);
|
return /Content script on [\w-]+ did not respond in \d+s|内容脚本\s+\d+(?:\.\d+)?\s*秒内未响应|Receiving end does not exist|message channel closed|A listener indicated an asynchronous response|port closed before a response was received|did not respond in \d+s/i.test(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLikelyLoggedInChatgptHomeUrl(rawUrl) {
|
function isLikelyLoggedInChatgptHomeUrl(rawUrl) {
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'ENSURE_SIGNUP_ENTRY_READY',
|
type: 'ENSURE_SIGNUP_ENTRY_READY',
|
||||||
step: 2,
|
step: 2,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -151,7 +151,7 @@
|
|||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await sendToContentScriptResilient('signup-page', {
|
return await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'EXECUTE_NODE',
|
type: 'EXECUTE_NODE',
|
||||||
nodeId: 'submit-signup-email',
|
nodeId: 'submit-signup-email',
|
||||||
step: 2,
|
step: 2,
|
||||||
@@ -198,7 +198,7 @@
|
|||||||
throw new Error('步骤 2:未找到可用的注册页标签,无法切换到手机号注册入口。');
|
throw new Error('步骤 2:未找到可用的注册页标签,无法切换到手机号注册入口。');
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await sendToContentScriptResilient('signup-page', {
|
const result = await sendToContentScriptResilient('openai-auth', {
|
||||||
type: 'ENSURE_SIGNUP_PHONE_ENTRY_READY',
|
type: 'ENSURE_SIGNUP_PHONE_ENTRY_READY',
|
||||||
step: 2,
|
step: 2,
|
||||||
source: 'background',
|
source: 'background',
|
||||||
@@ -232,8 +232,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function ensureSignupTabForStep2() {
|
async function ensureSignupTabForStep2() {
|
||||||
let signupTabId = await getTabId('signup-page');
|
let signupTabId = await getTabId('openai-auth');
|
||||||
if (!signupTabId || !(await isTabAlive('signup-page'))) {
|
if (!signupTabId || !(await isTabAlive('openai-auth'))) {
|
||||||
await addLog('步骤 2:未发现可用的注册页标签,正在重新打开 ChatGPT 官网...', 'warn');
|
await addLog('步骤 2:未发现可用的注册页标签,正在重新打开 ChatGPT 官网...', 'warn');
|
||||||
signupTabId = (await ensureSignupEntryPageReady(2)).tabId;
|
signupTabId = (await ensureSignupEntryPageReady(2)).tabId;
|
||||||
} else {
|
} else {
|
||||||
@@ -243,9 +243,9 @@
|
|||||||
signupTabId,
|
signupTabId,
|
||||||
'步骤 2:已切换到注册页标签,正在等待页面加载完成并额外稳定 3 秒...'
|
'步骤 2:已切换到注册页标签,正在等待页面加载完成并额外稳定 3 秒...'
|
||||||
);
|
);
|
||||||
await ensureContentScriptReadyOnTab('signup-page', signupTabId, {
|
await ensureContentScriptReadyOnTab('openai-auth', signupTabId, {
|
||||||
inject: SIGNUP_PAGE_INJECT_FILES,
|
inject: OPENAI_AUTH_INJECT_FILES,
|
||||||
injectSource: 'signup-page',
|
injectSource: 'openai-auth',
|
||||||
timeoutMs: 45000,
|
timeoutMs: 45000,
|
||||||
retryDelayMs: 900,
|
retryDelayMs: 900,
|
||||||
logMessage: '步骤 2:注册入口页内容脚本未就绪,正在等待页面恢复...',
|
logMessage: '步骤 2:注册入口页内容脚本未就绪,正在等待页面恢复...',
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// content/gopay-flow.js — GoPay authorization helper.
|
// flows/openai/content/gopay-flow.js — GoPay authorization helper.
|
||||||
|
|
||||||
console.log('[MultiPage:gopay-flow] Content script loaded on', location.href);
|
console.log('[MultiPage:gopay-flow] Content script loaded on', location.href);
|
||||||
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
// content/signup-page.js — Content script for ChatGPT signup entry + OpenAI auth pages
|
// flows/openai/content/openai-auth.js — Content script for ChatGPT signup entry + OpenAI auth pages
|
||||||
// Injected on: auth0.openai.com, auth.openai.com, accounts.openai.com
|
// Injected on: auth0.openai.com, auth.openai.com, accounts.openai.com
|
||||||
// Dynamically injected on: chatgpt.com
|
// Dynamically injected on: chatgpt.com
|
||||||
|
|
||||||
console.log('[MultiPage:signup-page] Content script loaded on', location.href);
|
console.log('[MultiPage:openai-auth] Content script loaded on', location.href);
|
||||||
|
|
||||||
const SIGNUP_PAGE_LISTENER_SENTINEL = 'data-multipage-signup-page-listener';
|
const OPENAI_AUTH_LISTENER_SENTINEL = 'data-multipage-openai-auth-listener';
|
||||||
|
|
||||||
function getOperationDelayRunner() {
|
function getOperationDelayRunner() {
|
||||||
const rootScope = typeof window !== 'undefined' ? window : globalThis;
|
const rootScope = typeof window !== 'undefined' ? window : globalThis;
|
||||||
@@ -14,8 +14,8 @@ function getOperationDelayRunner() {
|
|||||||
: async (_metadata, operation) => operation();
|
: async (_metadata, operation) => operation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.documentElement.getAttribute(SIGNUP_PAGE_LISTENER_SENTINEL) !== '1') {
|
if (document.documentElement.getAttribute(OPENAI_AUTH_LISTENER_SENTINEL) !== '1') {
|
||||||
document.documentElement.setAttribute(SIGNUP_PAGE_LISTENER_SENTINEL, '1');
|
document.documentElement.setAttribute(OPENAI_AUTH_LISTENER_SENTINEL, '1');
|
||||||
|
|
||||||
// Listen for commands from Background
|
// Listen for commands from Background
|
||||||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
@@ -70,10 +70,10 @@ if (document.documentElement.getAttribute(SIGNUP_PAGE_LISTENER_SENTINEL) !== '1'
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('[MultiPage:signup-page] 消息监听已存在,跳过重复注册');
|
console.log('[MultiPage:openai-auth] 消息监听已存在,跳过重复注册');
|
||||||
}
|
}
|
||||||
|
|
||||||
const SIGNUP_PAGE_NODE_HANDLERS = Object.freeze({
|
const OPENAI_AUTH_NODE_HANDLERS = Object.freeze({
|
||||||
'submit-signup-email': (payload) => step2_clickRegister(payload),
|
'submit-signup-email': (payload) => step2_clickRegister(payload),
|
||||||
'fill-password': (payload) => step3_fillEmailPassword(payload),
|
'fill-password': (payload) => step3_fillEmailPassword(payload),
|
||||||
'fill-profile': (payload) => step5_fillNameBirthday(payload),
|
'fill-profile': (payload) => step5_fillNameBirthday(payload),
|
||||||
@@ -120,9 +120,9 @@ async function handleCommand(message) {
|
|||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'EXECUTE_NODE': {
|
case 'EXECUTE_NODE': {
|
||||||
const nodeId = String(message.nodeId || message.payload?.nodeId || '').trim();
|
const nodeId = String(message.nodeId || message.payload?.nodeId || '').trim();
|
||||||
const handler = SIGNUP_PAGE_NODE_HANDLERS[nodeId];
|
const handler = OPENAI_AUTH_NODE_HANDLERS[nodeId];
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
throw new Error(`signup-page.js 不处理节点 ${nodeId}`);
|
throw new Error(`openai-auth.js 不处理节点 ${nodeId}`);
|
||||||
}
|
}
|
||||||
return await handler(message.payload || {});
|
return await handler(message.payload || {});
|
||||||
}
|
}
|
||||||
@@ -1085,7 +1085,7 @@ function logSignupPasswordDiagnostics(context, level = 'warn') {
|
|||||||
try {
|
try {
|
||||||
log(`${context}:密码页诊断快照:${JSON.stringify(getSignupPasswordDiagnostics())}`, level);
|
log(`${context}:密码页诊断快照:${JSON.stringify(getSignupPasswordDiagnostics())}`, level);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('[MultiPage:signup-page] failed to build signup password diagnostics:', error?.message || error);
|
console.warn('[MultiPage:openai-auth] failed to build signup password diagnostics:', error?.message || error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1310,7 +1310,7 @@ async function fillSignupEmailAndContinue(email, step) {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isStopError(error)) {
|
if (!isStopError(error)) {
|
||||||
console.error('[MultiPage:signup-page] deferred signup email submit failed:', error?.message || error);
|
console.error('[MultiPage:openai-auth] deferred signup email submit failed:', error?.message || error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 120);
|
}, 120);
|
||||||
@@ -2580,7 +2580,7 @@ async function submitSignupPhoneNumberAndContinue(payload = {}) {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isStopError(error)) {
|
if (!isStopError(error)) {
|
||||||
console.error('[MultiPage:signup-page] deferred signup phone submit failed:', error?.message || error);
|
console.error('[MultiPage:openai-auth] deferred signup phone submit failed:', error?.message || error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 120);
|
}, 120);
|
||||||
@@ -2720,7 +2720,7 @@ async function step3_fillEmailPassword(payload) {
|
|||||||
log('步骤 3:表单已提交');
|
log('步骤 3:表单已提交');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isStopError(error)) {
|
if (!isStopError(error)) {
|
||||||
console.error('[MultiPage:signup-page] deferred step 3 submit failed:', error?.message || error);
|
console.error('[MultiPage:openai-auth] deferred step 3 submit failed:', error?.message || error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 120);
|
}, 120);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// content/paypal-flow.js — PayPal login and approval helper.
|
// flows/openai/content/paypal-flow.js — PayPal login and approval helper.
|
||||||
|
|
||||||
console.log('[MultiPage:paypal-flow] Content script loaded on', location.href);
|
console.log('[MultiPage:paypal-flow] Content script loaded on', location.href);
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// content/plus-checkout.js — ChatGPT Plus checkout helper.
|
// flows/openai/content/plus-checkout.js — ChatGPT Plus checkout helper.
|
||||||
|
|
||||||
(function attachPlusCheckoutContentScript() {
|
(function attachPlusCheckoutContentScript() {
|
||||||
console.log('[MultiPage:plus-checkout] Content script loaded on', location.href);
|
console.log('[MultiPage:plus-checkout] Content script loaded on', location.href);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// content/sub2api-panel.js — 页内脚本:SUB2API 后台(OAuth 生成与回调提交)
|
// flows/openai/content/sub2api-panel.js — 页内脚本:SUB2API 后台(OAuth 生成与回调提交)
|
||||||
|
|
||||||
console.log('[MultiPage:sub2api-panel] Content script loaded on', location.href);
|
console.log('[MultiPage:sub2api-panel] Content script loaded on', location.href);
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// content/vps-panel.js — Content script for CPA panel (OAuth URL request / platform verification node)
|
// flows/openai/content/vps-panel.js — Content script for CPA panel (OAuth URL request / platform verification node)
|
||||||
// Injected on: CPA panel (user-configured URL)
|
// Injected on: CPA panel (user-configured URL)
|
||||||
//
|
//
|
||||||
// Actual DOM structure (after login click):
|
// Actual DOM structure (after login click):
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// content/whatsapp-flow.js — WhatsApp Web code reader for GoPay.
|
// flows/openai/content/whatsapp-flow.js — WhatsApp Web code reader for GoPay.
|
||||||
|
|
||||||
console.log('[MultiPage:whatsapp-flow] Content script loaded on', location.href);
|
console.log('[MultiPage:whatsapp-flow] Content script loaded on', location.href);
|
||||||
|
|
||||||
@@ -0,0 +1,425 @@
|
|||||||
|
(function attachMultiPageOpenAiFlowDefinition(root, factory) {
|
||||||
|
root.MultiPageOpenAiFlowDefinition = factory();
|
||||||
|
})(typeof self !== 'undefined' ? self : globalThis, function createMultiPageOpenAiFlowDefinition() {
|
||||||
|
function freezeDeep(entry) {
|
||||||
|
if (!entry || typeof entry !== 'object' || Object.isFrozen(entry)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
Object.getOwnPropertyNames(entry).forEach((key) => {
|
||||||
|
freezeDeep(entry[key]);
|
||||||
|
});
|
||||||
|
return Object.freeze(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
const VALUE = freezeDeep({
|
||||||
|
"id": "openai",
|
||||||
|
"label": "Codex / OpenAI",
|
||||||
|
"services": [
|
||||||
|
"account",
|
||||||
|
"email",
|
||||||
|
"proxy"
|
||||||
|
],
|
||||||
|
"capabilities": {
|
||||||
|
"supportsEmailSignup": true,
|
||||||
|
"supportsPhoneSignup": true,
|
||||||
|
"supportsPhoneVerificationSettings": true,
|
||||||
|
"supportsPlusMode": true,
|
||||||
|
"supportsContributionMode": true,
|
||||||
|
"supportsAccountContribution": true,
|
||||||
|
"supportsOpenAiOAuthContribution": true,
|
||||||
|
"contributionAdapterIds": [
|
||||||
|
"openai-oauth",
|
||||||
|
"openai-codex-file",
|
||||||
|
"openai-sub2api-file"
|
||||||
|
],
|
||||||
|
"supportedTargetIds": [
|
||||||
|
"cpa",
|
||||||
|
"sub2api",
|
||||||
|
"codex2api"
|
||||||
|
],
|
||||||
|
"supportsLuckmail": true,
|
||||||
|
"supportsOauthTimeoutBudget": true,
|
||||||
|
"canSwitchFlow": true,
|
||||||
|
"stepDefinitionMode": "openai-dynamic",
|
||||||
|
"targetSelectorLabel": "来源"
|
||||||
|
},
|
||||||
|
"baseGroups": [
|
||||||
|
"openai-plus",
|
||||||
|
"openai-phone",
|
||||||
|
"openai-oauth",
|
||||||
|
"openai-step6"
|
||||||
|
],
|
||||||
|
"targets": {
|
||||||
|
"cpa": {
|
||||||
|
"id": "cpa",
|
||||||
|
"label": "CPA 面板",
|
||||||
|
"groups": [
|
||||||
|
"openai-target-cpa"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sub2api": {
|
||||||
|
"id": "sub2api",
|
||||||
|
"label": "SUB2API",
|
||||||
|
"groups": [
|
||||||
|
"openai-target-sub2api"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"codex2api": {
|
||||||
|
"id": "codex2api",
|
||||||
|
"label": "Codex2API",
|
||||||
|
"groups": [
|
||||||
|
"openai-target-codex2api"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"runtimeSources": {
|
||||||
|
"openai-auth": {
|
||||||
|
"flowId": "openai",
|
||||||
|
"kind": "flow-page",
|
||||||
|
"label": "认证页",
|
||||||
|
"readyPolicy": "allow-child-frame",
|
||||||
|
"family": "openai-auth-family",
|
||||||
|
"driverId": "flows/openai/content/openai-auth",
|
||||||
|
"cleanupScopes": [
|
||||||
|
"oauth-localhost-callback"
|
||||||
|
],
|
||||||
|
"detectionMatchers": [
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"auth0.openai.com",
|
||||||
|
"auth.openai.com",
|
||||||
|
"accounts.openai.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"auth0.openai.com",
|
||||||
|
"auth.openai.com",
|
||||||
|
"accounts.openai.com"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"chatgpt.com",
|
||||||
|
"www.chatgpt.com",
|
||||||
|
"chat.openai.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"chatgpt": {
|
||||||
|
"flowId": "openai",
|
||||||
|
"kind": "flow-entry",
|
||||||
|
"label": "ChatGPT 首页",
|
||||||
|
"readyPolicy": "allow-child-frame",
|
||||||
|
"family": "chatgpt-entry-family",
|
||||||
|
"driverId": null,
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"detectionMatchers": [
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"chatgpt.com",
|
||||||
|
"www.chatgpt.com",
|
||||||
|
"chat.openai.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"chatgpt.com",
|
||||||
|
"www.chatgpt.com",
|
||||||
|
"chat.openai.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"vps-panel": {
|
||||||
|
"flowId": "openai",
|
||||||
|
"kind": "panel-page",
|
||||||
|
"label": "CPA 面板",
|
||||||
|
"readyPolicy": "allow-child-frame",
|
||||||
|
"family": "vps-panel-family",
|
||||||
|
"driverId": "flows/openai/content/vps-panel",
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"originEqualsReference": true,
|
||||||
|
"pathEqualsReference": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"platform-panel": {
|
||||||
|
"flowId": "openai",
|
||||||
|
"kind": "virtual-page",
|
||||||
|
"label": "平台回调面板",
|
||||||
|
"readyPolicy": "disabled",
|
||||||
|
"family": "platform-panel-family",
|
||||||
|
"driverId": "content/platform-panel",
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"familyMatchers": []
|
||||||
|
},
|
||||||
|
"sub2api-panel": {
|
||||||
|
"flowId": "openai",
|
||||||
|
"kind": "panel-page",
|
||||||
|
"label": "SUB2API 后台",
|
||||||
|
"readyPolicy": "allow-child-frame",
|
||||||
|
"family": "sub2api-panel-family",
|
||||||
|
"driverId": "flows/openai/content/sub2api-panel",
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"originEqualsReference": true,
|
||||||
|
"pathPrefixes": [
|
||||||
|
"/admin/accounts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"originEqualsReference": true,
|
||||||
|
"pathPrefixes": [
|
||||||
|
"/login"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"originEqualsReference": true,
|
||||||
|
"pathEqualsOneOf": [
|
||||||
|
"/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"codex2api-panel": {
|
||||||
|
"flowId": "openai",
|
||||||
|
"kind": "panel-page",
|
||||||
|
"label": "Codex2API 后台",
|
||||||
|
"readyPolicy": "allow-child-frame",
|
||||||
|
"family": "codex2api-panel-family",
|
||||||
|
"driverId": "flows/openai/content/sub2api-panel",
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"originEqualsReference": true,
|
||||||
|
"pathPrefixes": [
|
||||||
|
"/admin/accounts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"originEqualsReference": true,
|
||||||
|
"pathEqualsOneOf": [
|
||||||
|
"/admin",
|
||||||
|
"/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"plus-checkout": {
|
||||||
|
"flowId": "openai",
|
||||||
|
"kind": "flow-page",
|
||||||
|
"label": "Plus Checkout",
|
||||||
|
"readyPolicy": "top-frame-only",
|
||||||
|
"family": "plus-checkout-family",
|
||||||
|
"driverId": "flows/openai/content/plus-checkout",
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"hostnames": [
|
||||||
|
"chatgpt.com"
|
||||||
|
],
|
||||||
|
"pathPrefixes": [
|
||||||
|
"/checkout/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"paypal-flow": {
|
||||||
|
"flowId": "openai",
|
||||||
|
"kind": "flow-page",
|
||||||
|
"label": "PayPal 授权页",
|
||||||
|
"readyPolicy": "allow-child-frame",
|
||||||
|
"family": "paypal-flow-family",
|
||||||
|
"driverId": "flows/openai/content/paypal-flow",
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"hostnameEndsWith": [
|
||||||
|
"paypal.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gopay-flow": {
|
||||||
|
"flowId": "openai",
|
||||||
|
"kind": "flow-page",
|
||||||
|
"label": "GoPay 授权页",
|
||||||
|
"readyPolicy": "allow-child-frame",
|
||||||
|
"family": "gopay-flow-family",
|
||||||
|
"driverId": "flows/openai/content/gopay-flow",
|
||||||
|
"cleanupScopes": [],
|
||||||
|
"familyMatchers": [
|
||||||
|
{
|
||||||
|
"hostnameRegex": "gopay|gojek",
|
||||||
|
"hostnameRegexFlags": "i"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"driverDefinitions": {
|
||||||
|
"flows/openai/content/openai-auth": {
|
||||||
|
"sourceId": "openai-auth",
|
||||||
|
"commands": [
|
||||||
|
"submit-signup-email",
|
||||||
|
"fill-password",
|
||||||
|
"fill-profile",
|
||||||
|
"oauth-login",
|
||||||
|
"submit-verification-code",
|
||||||
|
"post-login-phone-verification",
|
||||||
|
"bind-email",
|
||||||
|
"fetch-bind-email-code",
|
||||||
|
"confirm-oauth",
|
||||||
|
"detect-auth-state"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flows/openai/content/sub2api-panel": {
|
||||||
|
"sourceId": "sub2api-panel",
|
||||||
|
"commands": [
|
||||||
|
"open-panel",
|
||||||
|
"fetch-oauth-url",
|
||||||
|
"platform-verify"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flows/openai/content/vps-panel": {
|
||||||
|
"sourceId": "vps-panel",
|
||||||
|
"commands": [
|
||||||
|
"open-panel",
|
||||||
|
"fetch-oauth-url",
|
||||||
|
"platform-verify"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"content/platform-panel": {
|
||||||
|
"sourceId": "platform-panel",
|
||||||
|
"commands": [
|
||||||
|
"platform-verify",
|
||||||
|
"fetch-oauth-url"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flows/openai/content/plus-checkout": {
|
||||||
|
"sourceId": "plus-checkout",
|
||||||
|
"commands": [
|
||||||
|
"plus-checkout-create",
|
||||||
|
"paypal-hosted-openai-checkout",
|
||||||
|
"plus-checkout-billing",
|
||||||
|
"plus-checkout-return"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flows/openai/content/paypal-flow": {
|
||||||
|
"sourceId": "paypal-flow",
|
||||||
|
"commands": [
|
||||||
|
"paypal-approve",
|
||||||
|
"paypal-hosted-email",
|
||||||
|
"paypal-hosted-card",
|
||||||
|
"paypal-hosted-create-account",
|
||||||
|
"paypal-hosted-review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flows/openai/content/gopay-flow": {
|
||||||
|
"sourceId": "gopay-flow",
|
||||||
|
"commands": [
|
||||||
|
"gopay-subscription-confirm"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultTargetId": "cpa",
|
||||||
|
"settingsGroups": {
|
||||||
|
"openai-target-cpa": {
|
||||||
|
"id": "openai-target-cpa",
|
||||||
|
"label": "CPA 来源",
|
||||||
|
"rowIds": [
|
||||||
|
"row-vps-url",
|
||||||
|
"row-vps-password",
|
||||||
|
"row-local-cpa-step9-mode"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"openai-target-sub2api": {
|
||||||
|
"id": "openai-target-sub2api",
|
||||||
|
"label": "SUB2API 来源",
|
||||||
|
"rowIds": [
|
||||||
|
"row-sub2api-url",
|
||||||
|
"row-sub2api-email",
|
||||||
|
"row-sub2api-password",
|
||||||
|
"row-sub2api-group",
|
||||||
|
"row-sub2api-account-priority",
|
||||||
|
"row-sub2api-default-proxy"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"openai-target-codex2api": {
|
||||||
|
"id": "openai-target-codex2api",
|
||||||
|
"label": "Codex2API 来源",
|
||||||
|
"rowIds": [
|
||||||
|
"row-codex2api-url",
|
||||||
|
"row-codex2api-admin-key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"openai-plus": {
|
||||||
|
"id": "openai-plus",
|
||||||
|
"label": "Plus",
|
||||||
|
"rowIds": [
|
||||||
|
"row-plus-mode",
|
||||||
|
"row-plus-account-access-strategy",
|
||||||
|
"row-plus-payment-method"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"openai-phone": {
|
||||||
|
"id": "openai-phone",
|
||||||
|
"label": "接码设置",
|
||||||
|
"sectionIds": [
|
||||||
|
"phone-verification-section"
|
||||||
|
],
|
||||||
|
"rowIds": []
|
||||||
|
},
|
||||||
|
"openai-oauth": {
|
||||||
|
"id": "openai-oauth",
|
||||||
|
"label": "OAuth",
|
||||||
|
"rowIds": [
|
||||||
|
"row-oauth-flow-timeout",
|
||||||
|
"row-oauth-display"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"openai-step6": {
|
||||||
|
"id": "openai-step6",
|
||||||
|
"label": "第六步",
|
||||||
|
"rowIds": [
|
||||||
|
"row-step6-cookie-settings"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetCapabilities": {
|
||||||
|
"cpa": {
|
||||||
|
"supportsPhoneSignup": true,
|
||||||
|
"requiresPhoneSignupWarning": true,
|
||||||
|
"supportedPlusAccountAccessStrategies": [
|
||||||
|
"oauth",
|
||||||
|
"cpa_codex_session"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sub2api": {
|
||||||
|
"supportsPhoneSignup": true,
|
||||||
|
"requiresPhoneSignupWarning": false,
|
||||||
|
"supportedPlusAccountAccessStrategies": [
|
||||||
|
"oauth",
|
||||||
|
"sub2api_codex_session"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"codex2api": {
|
||||||
|
"supportsPhoneSignup": true,
|
||||||
|
"requiresPhoneSignupWarning": false,
|
||||||
|
"supportedPlusAccountAccessStrategies": [
|
||||||
|
"oauth"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return VALUE;
|
||||||
|
});
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
|||||||
|
(function attachLegacyAccountRecordsImporter(root, factory) {
|
||||||
|
root.MultiPageLegacyAccountRecordsImporter = factory(root);
|
||||||
|
})(typeof self !== 'undefined' ? self : globalThis, function createLegacyAccountRecordsImporterModule(root) {
|
||||||
|
function createAccountRecordsImporter(deps = {}) {
|
||||||
|
const createAccountRunHistoryHelpers = deps.createAccountRunHistoryHelpers
|
||||||
|
|| root.MultiPageBackgroundAccountRunHistory?.createAccountRunHistoryHelpers;
|
||||||
|
|
||||||
|
function importAccountRecords(records = []) {
|
||||||
|
if (!Array.isArray(records)) {
|
||||||
|
throw new Error('账号记录导入内容必须是数组。');
|
||||||
|
}
|
||||||
|
if (typeof createAccountRunHistoryHelpers !== 'function') {
|
||||||
|
return records
|
||||||
|
.filter((record) => Boolean(record) && typeof record === 'object' && !Array.isArray(record))
|
||||||
|
.map((record) => ({ ...record }));
|
||||||
|
}
|
||||||
|
|
||||||
|
const helpers = createAccountRunHistoryHelpers({
|
||||||
|
chrome: deps.chrome || {
|
||||||
|
storage: {
|
||||||
|
local: {
|
||||||
|
get: async () => ({}),
|
||||||
|
set: async () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getState: deps.getState || (async () => ({})),
|
||||||
|
addLog: deps.addLog || (async () => {}),
|
||||||
|
getNodeIdByStepForState: deps.getNodeIdByStepForState || (() => ''),
|
||||||
|
normalizeAccountRunHistoryHelperBaseUrl: deps.normalizeAccountRunHistoryHelperBaseUrl
|
||||||
|
|| ((value) => String(value || '').trim()),
|
||||||
|
});
|
||||||
|
if (typeof helpers?.normalizeAccountRunHistory !== 'function') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return helpers.normalizeAccountRunHistory(records);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
importAccountRecords,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
createAccountRecordsImporter,
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
(function attachLegacySettingsImporter(root, factory) {
|
||||||
|
root.MultiPageLegacySettingsImporter = factory(root);
|
||||||
|
})(typeof self !== 'undefined' ? self : globalThis, function createLegacySettingsImporterModule(root) {
|
||||||
|
const LEGACY_TOP_LEVEL_KEYS = Object.freeze([
|
||||||
|
'panelMode',
|
||||||
|
'openaiIntegrationTargetId',
|
||||||
|
'kiroTargetId',
|
||||||
|
'stepExecutionRangeByFlow',
|
||||||
|
'kiroRuntime',
|
||||||
|
]);
|
||||||
|
|
||||||
|
function isPlainObject(value) {
|
||||||
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneValue(value) {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map((entry) => cloneValue(entry));
|
||||||
|
}
|
||||||
|
if (isPlainObject(value)) {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(value).map(([key, entryValue]) => [key, cloneValue(entryValue)])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectLegacyFieldHits(input = {}) {
|
||||||
|
if (!isPlainObject(input)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const hits = [];
|
||||||
|
LEGACY_TOP_LEVEL_KEYS.forEach((key) => {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(input, key)) {
|
||||||
|
hits.push(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const settingsState = isPlainObject(input.settingsState) ? input.settingsState : {};
|
||||||
|
const openaiSettings = isPlainObject(settingsState?.flows?.openai) ? settingsState.flows.openai : {};
|
||||||
|
const kiroSettings = isPlainObject(settingsState?.flows?.kiro) ? settingsState.flows.kiro : {};
|
||||||
|
if (Object.prototype.hasOwnProperty.call(openaiSettings, 'integrationTargetId')) {
|
||||||
|
hits.push('settingsState.flows.openai.integrationTargetId');
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(openaiSettings, 'integrationTargets')) {
|
||||||
|
hits.push('settingsState.flows.openai.integrationTargets');
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(kiroSettings, 'targetId')) {
|
||||||
|
hits.push('settingsState.flows.kiro.targetId');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(new Set(hits));
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveSettingsSchemaApi(deps = {}) {
|
||||||
|
if (deps.settingsSchemaApi?.normalizeSettingsState && deps.settingsSchemaApi?.buildSettingsView) {
|
||||||
|
return deps.settingsSchemaApi;
|
||||||
|
}
|
||||||
|
const settingsSchemaModule = deps.settingsSchemaModule || root.MultiPageSettingsSchema || null;
|
||||||
|
if (typeof settingsSchemaModule?.createSettingsSchema !== 'function') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return settingsSchemaModule.createSettingsSchema({
|
||||||
|
flowRegistry: deps.flowRegistry || root.MultiPageFlowRegistry || null,
|
||||||
|
defaultFlowId: deps.defaultFlowId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildImportInput(input = {}) {
|
||||||
|
const next = isPlainObject(input) ? cloneValue(input) : {};
|
||||||
|
const settingsState = isPlainObject(next.settingsState) ? next.settingsState : {};
|
||||||
|
const flows = isPlainObject(settingsState.flows) ? settingsState.flows : {};
|
||||||
|
const openaiState = isPlainObject(flows.openai) ? flows.openai : {};
|
||||||
|
const kiroState = isPlainObject(flows.kiro) ? flows.kiro : {};
|
||||||
|
const legacyOpenAiTargetId = String(
|
||||||
|
input?.openaiIntegrationTargetId
|
||||||
|
?? input?.panelMode
|
||||||
|
?? ''
|
||||||
|
).trim();
|
||||||
|
const legacyKiroTargetId = String(input?.kiroTargetId ?? '').trim();
|
||||||
|
const openaiHasCanonicalTarget = Object.prototype.hasOwnProperty.call(openaiState, 'selectedTargetId')
|
||||||
|
|| Object.prototype.hasOwnProperty.call(openaiState, 'integrationTargetId');
|
||||||
|
const kiroHasCanonicalTarget = Object.prototype.hasOwnProperty.call(kiroState, 'selectedTargetId')
|
||||||
|
|| Object.prototype.hasOwnProperty.call(kiroState, 'targetId');
|
||||||
|
|
||||||
|
if (!openaiHasCanonicalTarget && legacyOpenAiTargetId) {
|
||||||
|
next.settingsState = settingsState;
|
||||||
|
next.settingsState.flows = flows;
|
||||||
|
next.settingsState.flows.openai = {
|
||||||
|
...openaiState,
|
||||||
|
selectedTargetId: legacyOpenAiTargetId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kiroHasCanonicalTarget && legacyKiroTargetId) {
|
||||||
|
next.settingsState = next.settingsState || settingsState;
|
||||||
|
next.settingsState.flows = next.settingsState.flows || flows;
|
||||||
|
next.settingsState.flows.kiro = {
|
||||||
|
...kiroState,
|
||||||
|
selectedTargetId: legacyKiroTargetId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSettingsImporter(deps = {}) {
|
||||||
|
const settingsSchemaApi = resolveSettingsSchemaApi(deps);
|
||||||
|
|
||||||
|
function importSettings(input = {}) {
|
||||||
|
if (!isPlainObject(input)) {
|
||||||
|
throw new Error('配置文件中的 settings 内容无效。');
|
||||||
|
}
|
||||||
|
if (!settingsSchemaApi?.normalizeSettingsState) {
|
||||||
|
throw new Error('设置导入器未完成初始化。');
|
||||||
|
}
|
||||||
|
|
||||||
|
const importInput = buildImportInput(input);
|
||||||
|
const normalizedState = settingsSchemaApi.normalizeSettingsState(importInput, {
|
||||||
|
activeFlowId: importInput.activeFlowId || importInput.flowId || deps.defaultFlowId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
settingsSchemaVersion: Number(normalizedState.schemaVersion) || 0,
|
||||||
|
settingsState: cloneValue(normalizedState),
|
||||||
|
legacyFieldHits: collectLegacyFieldHits(input),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
collectLegacyFieldHits,
|
||||||
|
importSettings,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
LEGACY_TOP_LEVEL_KEYS,
|
||||||
|
collectLegacyFieldHits,
|
||||||
|
createSettingsImporter,
|
||||||
|
};
|
||||||
|
});
|
||||||
+29
-9
@@ -49,13 +49,17 @@
|
|||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"content/activation-utils.js",
|
"content/activation-utils.js",
|
||||||
"shared/source-registry.js",
|
"flows/openai/index.js",
|
||||||
|
"flows/kiro/index.js",
|
||||||
|
"flows/index.js",
|
||||||
|
"core/flow-kernel/flow-registry.js",
|
||||||
|
"core/flow-kernel/source-registry.js",
|
||||||
"content/utils.js",
|
"content/utils.js",
|
||||||
"content/operation-delay.js",
|
"content/operation-delay.js",
|
||||||
"content/auth-page-recovery.js",
|
"flows/openai/content/auth-page-recovery.js",
|
||||||
"content/phone-country-utils.js",
|
"flows/openai/content/phone-country-utils.js",
|
||||||
"content/phone-auth.js",
|
"flows/openai/content/phone-auth.js",
|
||||||
"content/signup-page.js"
|
"flows/openai/content/openai-auth.js"
|
||||||
],
|
],
|
||||||
"run_at": "document_idle"
|
"run_at": "document_idle"
|
||||||
},
|
},
|
||||||
@@ -66,7 +70,11 @@
|
|||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"content/activation-utils.js",
|
"content/activation-utils.js",
|
||||||
"shared/source-registry.js",
|
"flows/openai/index.js",
|
||||||
|
"flows/kiro/index.js",
|
||||||
|
"flows/index.js",
|
||||||
|
"core/flow-kernel/flow-registry.js",
|
||||||
|
"core/flow-kernel/source-registry.js",
|
||||||
"content/utils.js",
|
"content/utils.js",
|
||||||
"content/qq-mail.js"
|
"content/qq-mail.js"
|
||||||
],
|
],
|
||||||
@@ -83,7 +91,11 @@
|
|||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"content/activation-utils.js",
|
"content/activation-utils.js",
|
||||||
"shared/source-registry.js",
|
"flows/openai/index.js",
|
||||||
|
"flows/kiro/index.js",
|
||||||
|
"flows/index.js",
|
||||||
|
"core/flow-kernel/flow-registry.js",
|
||||||
|
"core/flow-kernel/source-registry.js",
|
||||||
"content/utils.js",
|
"content/utils.js",
|
||||||
"content/mail-163.js"
|
"content/mail-163.js"
|
||||||
],
|
],
|
||||||
@@ -97,7 +109,11 @@
|
|||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"content/activation-utils.js",
|
"content/activation-utils.js",
|
||||||
"shared/source-registry.js",
|
"flows/openai/index.js",
|
||||||
|
"flows/kiro/index.js",
|
||||||
|
"flows/index.js",
|
||||||
|
"core/flow-kernel/flow-registry.js",
|
||||||
|
"core/flow-kernel/source-registry.js",
|
||||||
"content/utils.js",
|
"content/utils.js",
|
||||||
"content/icloud-mail.js"
|
"content/icloud-mail.js"
|
||||||
],
|
],
|
||||||
@@ -110,7 +126,11 @@
|
|||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"content/activation-utils.js",
|
"content/activation-utils.js",
|
||||||
"shared/source-registry.js",
|
"flows/openai/index.js",
|
||||||
|
"flows/kiro/index.js",
|
||||||
|
"flows/index.js",
|
||||||
|
"core/flow-kernel/flow-registry.js",
|
||||||
|
"core/flow-kernel/source-registry.js",
|
||||||
"content/utils.js",
|
"content/utils.js",
|
||||||
"content/operation-delay.js",
|
"content/operation-delay.js",
|
||||||
"content/duck-mail.js"
|
"content/duck-mail.js"
|
||||||
|
|||||||
@@ -21,21 +21,21 @@
|
|||||||
主仓库 `codex注册扩展` 已重点阅读:
|
主仓库 `codex注册扩展` 已重点阅读:
|
||||||
|
|
||||||
- `data/step-definitions.js`
|
- `data/step-definitions.js`
|
||||||
- `shared/flow-capabilities.js`
|
- `core/flow-kernel/flow-capabilities.js`
|
||||||
- `shared/flow-registry.js`
|
- `core/flow-kernel/flow-registry.js`
|
||||||
- `shared/settings-schema.js`
|
- `core/flow-kernel/settings-schema.js`
|
||||||
- `sidepanel/sidepanel.html`
|
- `sidepanel/sidepanel.html`
|
||||||
- `sidepanel/sidepanel.js`
|
- `sidepanel/sidepanel.js`
|
||||||
- `background.js`
|
- `background.js`
|
||||||
- `background/runtime-state.js`
|
- `core/flow-kernel/runtime-state.js`
|
||||||
- `background/message-router.js`
|
- `background/message-router.js`
|
||||||
- `background/panel-bridge.js`
|
- `background/panel-bridge.js`
|
||||||
- `background/sub2api-api.js`
|
- `background/sub2api-api.js`
|
||||||
- `background/steps/platform-verify.js`
|
- `flows/openai/background/steps/platform-verify.js`
|
||||||
- `background/steps/create-plus-checkout.js`
|
- `flows/openai/background/steps/create-plus-checkout.js`
|
||||||
- `background/steps/fill-plus-checkout.js`
|
- `flows/openai/background/steps/fill-plus-checkout.js`
|
||||||
- `background/steps/plus-return-confirm.js`
|
- `flows/openai/background/steps/plus-return-confirm.js`
|
||||||
- `content/plus-checkout.js`
|
- `flows/openai/content/plus-checkout.js`
|
||||||
- `tests/step-definitions-module.test.js`
|
- `tests/step-definitions-module.test.js`
|
||||||
- `tests/sidepanel-plus-payment-method.test.js`
|
- `tests/sidepanel-plus-payment-method.test.js`
|
||||||
- `tests/flow-capabilities-module.test.js`
|
- `tests/flow-capabilities-module.test.js`
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
1. 通过 `background/panel-bridge.js` 请求 `background/sub2api-api.js` 生成 OAuth URL
|
1. 通过 `background/panel-bridge.js` 请求 `background/sub2api-api.js` 生成 OAuth URL
|
||||||
2. 保存 `oauthUrl / sub2apiSessionId / sub2apiOAuthState`
|
2. 保存 `oauthUrl / sub2apiSessionId / sub2apiOAuthState`
|
||||||
3. 页面完成 OAuth 回调,拿到 `localhostUrl`
|
3. 页面完成 OAuth 回调,拿到 `localhostUrl`
|
||||||
4. `background/steps/platform-verify.js` 调 `submitOpenAiCallback`
|
4. `flows/openai/background/steps/platform-verify.js` 调 `submitOpenAiCallback`
|
||||||
5. SUB2API 用 `exchange-code` 交换 OAuth code,再创建账号
|
5. SUB2API 用 `exchange-code` 交换 OAuth code,再创建账号
|
||||||
|
|
||||||
这条链路是“完整 OAuth 账号创建”,不是导入现有 ChatGPT Web session。
|
这条链路是“完整 OAuth 账号创建”,不是导入现有 ChatGPT Web session。
|
||||||
@@ -140,8 +140,8 @@
|
|||||||
|
|
||||||
现成能力位置:
|
现成能力位置:
|
||||||
|
|
||||||
- `content/plus-checkout.js`
|
- `flows/openai/content/plus-checkout.js`
|
||||||
- `background/steps/create-plus-checkout.js`
|
- `flows/openai/background/steps/create-plus-checkout.js`
|
||||||
|
|
||||||
这意味着新功能不需要再发明“如何拿 session”,只需要把这份能力接到 Plus 尾链上。
|
这意味着新功能不需要再发明“如何拿 session”,只需要把这份能力接到 Plus 尾链上。
|
||||||
|
|
||||||
@@ -258,7 +258,7 @@
|
|||||||
- `select-plus-account-access-strategy`
|
- `select-plus-account-access-strategy`
|
||||||
- `plus-account-access-strategy-caption`
|
- `plus-account-access-strategy-caption`
|
||||||
|
|
||||||
`shared/flow-registry.js` 的 `openai-plus` 设置组应扩展为同时包含:
|
`core/flow-kernel/flow-registry.js` 的 `openai-plus` 设置组应扩展为同时包含:
|
||||||
|
|
||||||
- `row-plus-mode`
|
- `row-plus-mode`
|
||||||
- `row-plus-payment-method`
|
- `row-plus-payment-method`
|
||||||
@@ -364,13 +364,13 @@ Session 导入策略生效时,替换锚点如下:
|
|||||||
|
|
||||||
建议新增后台执行器文件:
|
建议新增后台执行器文件:
|
||||||
|
|
||||||
- `background/steps/sub2api-session-import.js`
|
- `flows/openai/background/steps/sub2api-session-import.js`
|
||||||
|
|
||||||
执行器职责:
|
执行器职责:
|
||||||
|
|
||||||
1. 定位当前 Plus 会话页对应 tab
|
1. 定位当前 Plus 会话页对应 tab
|
||||||
2. 确认当前 tab 已回到 ChatGPT / OpenAI 域名页面,且可访问 `/api/auth/session`
|
2. 确认当前 tab 已回到 ChatGPT / OpenAI 域名页面,且可访问 `/api/auth/session`
|
||||||
3. 通过现有 `content/plus-checkout.js` 能力读取:
|
3. 通过现有 `flows/openai/content/plus-checkout.js` 能力读取:
|
||||||
- `session`
|
- `session`
|
||||||
- `accessToken`
|
- `accessToken`
|
||||||
4. 用现有 `background/sub2api-api.js` 登录 SUB2API
|
4. 用现有 `background/sub2api-api.js` 登录 SUB2API
|
||||||
@@ -477,13 +477,13 @@ Session 导入策略生效时,替换锚点如下:
|
|||||||
|
|
||||||
而不是去复用旧的:
|
而不是去复用旧的:
|
||||||
|
|
||||||
- `content/sub2api-panel.js`
|
- `flows/openai/content/sub2api-panel.js`
|
||||||
|
|
||||||
原因:
|
原因:
|
||||||
|
|
||||||
1. 当前主链路已迁移到 `background/sub2api-api.js`
|
1. 当前主链路已迁移到 `background/sub2api-api.js`
|
||||||
2. session 导入需要登录、查分组、查代理、发导入请求,这些都属于后台 API 编排
|
2. session 导入需要登录、查分组、查代理、发导入请求,这些都属于后台 API 编排
|
||||||
3. 继续往 `content/sub2api-panel.js` 塞逻辑会造成双实现
|
3. 继续往 `flows/openai/content/sub2api-panel.js` 塞逻辑会造成双实现
|
||||||
|
|
||||||
建议新增 API 方法:
|
建议新增 API 方法:
|
||||||
|
|
||||||
@@ -503,7 +503,7 @@ Session 导入策略生效时,替换锚点如下:
|
|||||||
|
|
||||||
- `background/panel-bridge.js` 继续只负责“跨 target 的 OAuth URL 申请桥接”
|
- `background/panel-bridge.js` 继续只负责“跨 target 的 OAuth URL 申请桥接”
|
||||||
- session 导入不要硬塞进 `requestOAuthUrlFromPanel`
|
- session 导入不要硬塞进 `requestOAuthUrlFromPanel`
|
||||||
- `background/steps/platform-verify.js` 继续只处理 callback 型平台验证
|
- `flows/openai/background/steps/platform-verify.js` 继续只处理 callback 型平台验证
|
||||||
- `sub2api-session-import` 走独立后台执行器,不混进 `platform-verify`
|
- `sub2api-session-import` 走独立后台执行器,不混进 `platform-verify`
|
||||||
|
|
||||||
## 5.7 后台总控与运行态设计
|
## 5.7 后台总控与运行态设计
|
||||||
@@ -599,7 +599,7 @@ Session 导入策略生效时,替换锚点如下:
|
|||||||
|
|
||||||
### 5.8.1 settings-schema
|
### 5.8.1 settings-schema
|
||||||
|
|
||||||
`shared/settings-schema.js` 需要在:
|
`core/flow-kernel/settings-schema.js` 需要在:
|
||||||
|
|
||||||
- `flows.openai.plus`
|
- `flows.openai.plus`
|
||||||
|
|
||||||
@@ -647,7 +647,7 @@ Session 导入策略生效时,替换锚点如下:
|
|||||||
|
|
||||||
### 5.9.1 不要把策略可用性写死在 UI
|
### 5.9.1 不要把策略可用性写死在 UI
|
||||||
|
|
||||||
应扩展 `shared/flow-capabilities.js`,让它输出:
|
应扩展 `core/flow-kernel/flow-capabilities.js`,让它输出:
|
||||||
|
|
||||||
- `requestedPlusAccountAccessStrategy`
|
- `requestedPlusAccountAccessStrategy`
|
||||||
- `effectivePlusAccountAccessStrategy`
|
- `effectivePlusAccountAccessStrategy`
|
||||||
@@ -821,9 +821,9 @@ session strategy 下这些逻辑全部不适用。
|
|||||||
|
|
||||||
### 涉及文件
|
### 涉及文件
|
||||||
|
|
||||||
- `shared/settings-schema.js`
|
- `core/flow-kernel/settings-schema.js`
|
||||||
- `shared/flow-capabilities.js`
|
- `core/flow-kernel/flow-capabilities.js`
|
||||||
- `shared/flow-registry.js`
|
- `core/flow-kernel/flow-registry.js`
|
||||||
- `sidepanel/sidepanel.html`
|
- `sidepanel/sidepanel.html`
|
||||||
- `sidepanel/sidepanel.js`
|
- `sidepanel/sidepanel.js`
|
||||||
- `background.js`
|
- `background.js`
|
||||||
@@ -889,10 +889,10 @@ session strategy 下这些逻辑全部不适用。
|
|||||||
### 涉及文件
|
### 涉及文件
|
||||||
|
|
||||||
- `background/sub2api-api.js`
|
- `background/sub2api-api.js`
|
||||||
- `background/steps/sub2api-session-import.js`
|
- `flows/openai/background/steps/sub2api-session-import.js`
|
||||||
- `background/steps/registry.js` 或后台节点注册处
|
- `core/flow-kernel/step-registry.js` 或后台节点注册处
|
||||||
- `content/plus-checkout.js`
|
- `flows/openai/content/plus-checkout.js`
|
||||||
- `background/steps/create-plus-checkout.js`
|
- `flows/openai/background/steps/create-plus-checkout.js`
|
||||||
|
|
||||||
### 完成标准
|
### 完成标准
|
||||||
|
|
||||||
@@ -920,9 +920,9 @@ session strategy 下这些逻辑全部不适用。
|
|||||||
### 涉及文件
|
### 涉及文件
|
||||||
|
|
||||||
- `background.js`
|
- `background.js`
|
||||||
- `background/runtime-state.js`
|
- `core/flow-kernel/runtime-state.js`
|
||||||
- `background/message-router.js`
|
- `background/message-router.js`
|
||||||
- `background/steps/platform-verify.js`
|
- `flows/openai/background/steps/platform-verify.js`
|
||||||
- `background/panel-bridge.js`
|
- `background/panel-bridge.js`
|
||||||
- 自动运行 / auth-chain 相关测试
|
- 自动运行 / auth-chain 相关测试
|
||||||
|
|
||||||
|
|||||||
@@ -1,582 +0,0 @@
|
|||||||
(function attachMultiPageFlowRegistry(root, factory) {
|
|
||||||
root.MultiPageFlowRegistry = factory();
|
|
||||||
})(typeof self !== 'undefined' ? self : globalThis, function createFlowRegistryModule() {
|
|
||||||
const DEFAULT_FLOW_ID = 'openai';
|
|
||||||
const DEFAULT_OPENAI_TARGET_ID = 'cpa';
|
|
||||||
const DEFAULT_KIRO_TARGET_ID = 'kiro-rs';
|
|
||||||
const DEFAULT_KIRO_PUBLICATION_TARGET_ID = 'kiro-rs';
|
|
||||||
const DEFAULT_KIRO_RS_URL = '';
|
|
||||||
const OPENAI_TARGET_IDS = Object.freeze(['cpa', 'sub2api', 'codex2api']);
|
|
||||||
const SHARED_SERVICE_IDS = Object.freeze(['account', 'email', 'proxy']);
|
|
||||||
|
|
||||||
const DEFAULT_FLOW_CAPABILITIES = Object.freeze({
|
|
||||||
supportsEmailSignup: true,
|
|
||||||
supportsPhoneSignup: false,
|
|
||||||
supportsPhoneVerificationSettings: false,
|
|
||||||
supportsPlusMode: false,
|
|
||||||
supportsContributionMode: false,
|
|
||||||
supportsAccountContribution: false,
|
|
||||||
supportsOpenAiOAuthContribution: false,
|
|
||||||
contributionAdapterIds: [],
|
|
||||||
supportedTargetIds: [],
|
|
||||||
supportsLuckmail: false,
|
|
||||||
supportsOauthTimeoutBudget: false,
|
|
||||||
canSwitchFlow: true,
|
|
||||||
stepDefinitionMode: 'default',
|
|
||||||
targetSelectorLabel: '来源',
|
|
||||||
});
|
|
||||||
|
|
||||||
function freezeDeep(value) {
|
|
||||||
if (!value || typeof value !== 'object' || Object.isFrozen(value)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
Object.getOwnPropertyNames(value).forEach((key) => {
|
|
||||||
freezeDeep(value[key]);
|
|
||||||
});
|
|
||||||
return Object.freeze(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const FLOW_DEFINITIONS = freezeDeep({
|
|
||||||
openai: {
|
|
||||||
id: 'openai',
|
|
||||||
label: 'Codex / OpenAI',
|
|
||||||
services: ['account', 'email', 'proxy'],
|
|
||||||
capabilities: {
|
|
||||||
...DEFAULT_FLOW_CAPABILITIES,
|
|
||||||
supportsPhoneSignup: true,
|
|
||||||
supportsPhoneVerificationSettings: true,
|
|
||||||
supportsPlusMode: true,
|
|
||||||
supportsContributionMode: true,
|
|
||||||
supportsAccountContribution: true,
|
|
||||||
supportsOpenAiOAuthContribution: true,
|
|
||||||
contributionAdapterIds: ['openai-oauth', 'openai-codex-file', 'openai-sub2api-file'],
|
|
||||||
supportedTargetIds: [...OPENAI_TARGET_IDS],
|
|
||||||
supportsLuckmail: true,
|
|
||||||
supportsOauthTimeoutBudget: true,
|
|
||||||
stepDefinitionMode: 'openai-dynamic',
|
|
||||||
},
|
|
||||||
baseGroups: [
|
|
||||||
'openai-plus',
|
|
||||||
'openai-phone',
|
|
||||||
'openai-oauth',
|
|
||||||
'openai-step6',
|
|
||||||
],
|
|
||||||
targets: {
|
|
||||||
cpa: {
|
|
||||||
id: 'cpa',
|
|
||||||
label: 'CPA 面板',
|
|
||||||
groups: ['openai-target-cpa'],
|
|
||||||
},
|
|
||||||
sub2api: {
|
|
||||||
id: 'sub2api',
|
|
||||||
label: 'SUB2API',
|
|
||||||
groups: ['openai-target-sub2api'],
|
|
||||||
},
|
|
||||||
codex2api: {
|
|
||||||
id: 'codex2api',
|
|
||||||
label: 'Codex2API',
|
|
||||||
groups: ['openai-target-codex2api'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
runtimeSources: {
|
|
||||||
'openai-auth': {
|
|
||||||
flowId: 'openai',
|
|
||||||
kind: 'flow-page',
|
|
||||||
label: '认证页',
|
|
||||||
readyPolicy: 'allow-child-frame',
|
|
||||||
family: 'openai-auth-family',
|
|
||||||
driverId: 'content/signup-page',
|
|
||||||
cleanupScopes: ['oauth-localhost-callback'],
|
|
||||||
},
|
|
||||||
chatgpt: {
|
|
||||||
flowId: 'openai',
|
|
||||||
kind: 'flow-entry',
|
|
||||||
label: 'ChatGPT 首页',
|
|
||||||
readyPolicy: 'allow-child-frame',
|
|
||||||
family: 'chatgpt-entry-family',
|
|
||||||
driverId: null,
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'vps-panel': {
|
|
||||||
flowId: 'openai',
|
|
||||||
kind: 'panel-page',
|
|
||||||
label: 'CPA 面板',
|
|
||||||
readyPolicy: 'allow-child-frame',
|
|
||||||
family: 'vps-panel-family',
|
|
||||||
driverId: 'content/vps-panel',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'platform-panel': {
|
|
||||||
flowId: 'openai',
|
|
||||||
kind: 'virtual-page',
|
|
||||||
label: '平台回调面板',
|
|
||||||
readyPolicy: 'disabled',
|
|
||||||
family: 'platform-panel-family',
|
|
||||||
driverId: 'content/platform-panel',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'sub2api-panel': {
|
|
||||||
flowId: 'openai',
|
|
||||||
kind: 'panel-page',
|
|
||||||
label: 'SUB2API 后台',
|
|
||||||
readyPolicy: 'allow-child-frame',
|
|
||||||
family: 'sub2api-panel-family',
|
|
||||||
driverId: 'content/sub2api-panel',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'codex2api-panel': {
|
|
||||||
flowId: 'openai',
|
|
||||||
kind: 'panel-page',
|
|
||||||
label: 'Codex2API 后台',
|
|
||||||
readyPolicy: 'allow-child-frame',
|
|
||||||
family: 'codex2api-panel-family',
|
|
||||||
driverId: 'content/sub2api-panel',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'plus-checkout': {
|
|
||||||
flowId: 'openai',
|
|
||||||
kind: 'flow-page',
|
|
||||||
label: 'Plus Checkout',
|
|
||||||
readyPolicy: 'top-frame-only',
|
|
||||||
family: 'plus-checkout-family',
|
|
||||||
driverId: 'content/plus-checkout',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'paypal-flow': {
|
|
||||||
flowId: 'openai',
|
|
||||||
kind: 'flow-page',
|
|
||||||
label: 'PayPal 授权页',
|
|
||||||
readyPolicy: 'allow-child-frame',
|
|
||||||
family: 'paypal-flow-family',
|
|
||||||
driverId: 'content/paypal-flow',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'gopay-flow': {
|
|
||||||
flowId: 'openai',
|
|
||||||
kind: 'flow-page',
|
|
||||||
label: 'GoPay 授权页',
|
|
||||||
readyPolicy: 'allow-child-frame',
|
|
||||||
family: 'gopay-flow-family',
|
|
||||||
driverId: 'content/gopay-flow',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
driverDefinitions: {
|
|
||||||
'content/signup-page': {
|
|
||||||
sourceId: 'openai-auth',
|
|
||||||
commands: [
|
|
||||||
'submit-signup-email',
|
|
||||||
'fill-password',
|
|
||||||
'fill-profile',
|
|
||||||
'oauth-login',
|
|
||||||
'submit-verification-code',
|
|
||||||
'post-login-phone-verification',
|
|
||||||
'bind-email',
|
|
||||||
'fetch-bind-email-code',
|
|
||||||
'confirm-oauth',
|
|
||||||
'detect-auth-state',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'content/sub2api-panel': {
|
|
||||||
sourceId: 'sub2api-panel',
|
|
||||||
commands: ['open-panel', 'fetch-oauth-url', 'platform-verify'],
|
|
||||||
},
|
|
||||||
'content/vps-panel': {
|
|
||||||
sourceId: 'vps-panel',
|
|
||||||
commands: ['open-panel', 'fetch-oauth-url', 'platform-verify'],
|
|
||||||
},
|
|
||||||
'content/platform-panel': {
|
|
||||||
sourceId: 'platform-panel',
|
|
||||||
commands: ['platform-verify', 'fetch-oauth-url'],
|
|
||||||
},
|
|
||||||
'content/plus-checkout': {
|
|
||||||
sourceId: 'plus-checkout',
|
|
||||||
commands: [
|
|
||||||
'plus-checkout-create',
|
|
||||||
'paypal-hosted-openai-checkout',
|
|
||||||
'plus-checkout-billing',
|
|
||||||
'plus-checkout-return',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'content/paypal-flow': {
|
|
||||||
sourceId: 'paypal-flow',
|
|
||||||
commands: [
|
|
||||||
'paypal-approve',
|
|
||||||
'paypal-hosted-email',
|
|
||||||
'paypal-hosted-card',
|
|
||||||
'paypal-hosted-create-account',
|
|
||||||
'paypal-hosted-review',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'content/gopay-flow': {
|
|
||||||
sourceId: 'gopay-flow',
|
|
||||||
commands: ['gopay-subscription-confirm'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
kiro: {
|
|
||||||
id: 'kiro',
|
|
||||||
label: 'Kiro',
|
|
||||||
services: ['account', 'email', 'proxy'],
|
|
||||||
capabilities: {
|
|
||||||
...DEFAULT_FLOW_CAPABILITIES,
|
|
||||||
supportsAccountContribution: true,
|
|
||||||
contributionAdapterIds: ['kiro-builder-id'],
|
|
||||||
supportedTargetIds: [DEFAULT_KIRO_TARGET_ID],
|
|
||||||
stepDefinitionMode: 'kiro',
|
|
||||||
},
|
|
||||||
baseGroups: [
|
|
||||||
'kiro-runtime-status',
|
|
||||||
],
|
|
||||||
targets: {
|
|
||||||
'kiro-rs': {
|
|
||||||
id: 'kiro-rs',
|
|
||||||
label: 'kiro.rs',
|
|
||||||
groups: ['kiro-target-kiro-rs'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
publicationTargets: {
|
|
||||||
'kiro-rs': {
|
|
||||||
id: 'kiro-rs',
|
|
||||||
label: 'kiro.rs',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
runtimeSources: {
|
|
||||||
'kiro-register-page': {
|
|
||||||
flowId: 'kiro',
|
|
||||||
kind: 'flow-page',
|
|
||||||
label: 'Kiro 注册页',
|
|
||||||
readyPolicy: 'top-frame-only',
|
|
||||||
family: 'kiro-register-page-family',
|
|
||||||
driverId: 'content/kiro/register-page',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'kiro-desktop-authorize': {
|
|
||||||
flowId: 'kiro',
|
|
||||||
kind: 'flow-page',
|
|
||||||
label: 'Kiro 桌面授权页',
|
|
||||||
readyPolicy: 'top-frame-only',
|
|
||||||
family: 'kiro-desktop-authorize-family',
|
|
||||||
driverId: 'content/kiro/desktop-authorize-page',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'kiro-rs-admin': {
|
|
||||||
flowId: 'kiro',
|
|
||||||
kind: 'virtual-page',
|
|
||||||
label: 'kiro.rs Admin',
|
|
||||||
readyPolicy: 'disabled',
|
|
||||||
family: 'kiro-rs-admin-family',
|
|
||||||
driverId: null,
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
driverDefinitions: {
|
|
||||||
'content/kiro/register-page': {
|
|
||||||
sourceId: 'kiro-register-page',
|
|
||||||
commands: [
|
|
||||||
'kiro-open-register-page',
|
|
||||||
'kiro-submit-email',
|
|
||||||
'kiro-submit-name',
|
|
||||||
'kiro-submit-verification-code',
|
|
||||||
'kiro-submit-password',
|
|
||||||
'kiro-complete-register-consent',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'content/kiro/desktop-authorize-page': {
|
|
||||||
sourceId: 'kiro-desktop-authorize',
|
|
||||||
commands: [
|
|
||||||
'kiro-complete-desktop-authorize',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'background/kiro-register': {
|
|
||||||
sourceId: 'kiro-register-page',
|
|
||||||
commands: [
|
|
||||||
'kiro-open-register-page',
|
|
||||||
'kiro-submit-email',
|
|
||||||
'kiro-submit-name',
|
|
||||||
'kiro-submit-verification-code',
|
|
||||||
'kiro-submit-password',
|
|
||||||
'kiro-complete-register-consent',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'background/kiro-desktop-authorize': {
|
|
||||||
sourceId: 'kiro-desktop-authorize',
|
|
||||||
commands: [
|
|
||||||
'kiro-start-desktop-authorize',
|
|
||||||
'kiro-complete-desktop-authorize',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'background/kiro-publisher-kiro-rs': {
|
|
||||||
sourceId: 'kiro-rs-admin',
|
|
||||||
commands: [
|
|
||||||
'kiro-upload-credential',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const SETTINGS_GROUP_DEFINITIONS = freezeDeep({
|
|
||||||
'service-account': {
|
|
||||||
id: 'service-account',
|
|
||||||
label: '账户',
|
|
||||||
rowIds: ['row-custom-password'],
|
|
||||||
},
|
|
||||||
'service-email': {
|
|
||||||
id: 'service-email',
|
|
||||||
label: '邮箱服务',
|
|
||||||
},
|
|
||||||
'service-proxy': {
|
|
||||||
id: 'service-proxy',
|
|
||||||
label: 'IP 代理',
|
|
||||||
sectionIds: ['ip-proxy-section'],
|
|
||||||
},
|
|
||||||
'openai-target-cpa': {
|
|
||||||
id: 'openai-target-cpa',
|
|
||||||
label: 'CPA 来源',
|
|
||||||
rowIds: ['row-vps-url', 'row-vps-password', 'row-local-cpa-step9-mode'],
|
|
||||||
},
|
|
||||||
'openai-target-sub2api': {
|
|
||||||
id: 'openai-target-sub2api',
|
|
||||||
label: 'SUB2API 来源',
|
|
||||||
rowIds: [
|
|
||||||
'row-sub2api-url',
|
|
||||||
'row-sub2api-email',
|
|
||||||
'row-sub2api-password',
|
|
||||||
'row-sub2api-group',
|
|
||||||
'row-sub2api-account-priority',
|
|
||||||
'row-sub2api-default-proxy',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'openai-target-codex2api': {
|
|
||||||
id: 'openai-target-codex2api',
|
|
||||||
label: 'Codex2API 来源',
|
|
||||||
rowIds: ['row-codex2api-url', 'row-codex2api-admin-key'],
|
|
||||||
},
|
|
||||||
'openai-plus': {
|
|
||||||
id: 'openai-plus',
|
|
||||||
label: 'Plus',
|
|
||||||
rowIds: ['row-plus-mode', 'row-plus-account-access-strategy', 'row-plus-payment-method'],
|
|
||||||
},
|
|
||||||
'openai-phone': {
|
|
||||||
id: 'openai-phone',
|
|
||||||
label: '接码设置',
|
|
||||||
sectionIds: ['phone-verification-section'],
|
|
||||||
rowIds: [],
|
|
||||||
},
|
|
||||||
'openai-oauth': {
|
|
||||||
id: 'openai-oauth',
|
|
||||||
label: 'OAuth',
|
|
||||||
rowIds: ['row-oauth-flow-timeout', 'row-oauth-display'],
|
|
||||||
},
|
|
||||||
'openai-step6': {
|
|
||||||
id: 'openai-step6',
|
|
||||||
label: '第六步',
|
|
||||||
rowIds: ['row-step6-cookie-settings'],
|
|
||||||
},
|
|
||||||
'kiro-target-kiro-rs': {
|
|
||||||
id: 'kiro-target-kiro-rs',
|
|
||||||
label: 'kiro.rs 配置',
|
|
||||||
rowIds: ['row-kiro-rs-url', 'row-kiro-rs-key', 'row-kiro-rs-test-status'],
|
|
||||||
},
|
|
||||||
'kiro-runtime-status': {
|
|
||||||
id: 'kiro-runtime-status',
|
|
||||||
label: 'Kiro 运行态',
|
|
||||||
rowIds: ['row-kiro-web-status', 'row-kiro-login-url', 'row-kiro-upload-status'],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function normalizeFlowId(value = '', fallback = DEFAULT_FLOW_ID) {
|
|
||||||
const normalized = String(value || '').trim().toLowerCase();
|
|
||||||
if (normalized && Object.prototype.hasOwnProperty.call(FLOW_DEFINITIONS, normalized)) {
|
|
||||||
return normalized;
|
|
||||||
}
|
|
||||||
const fallbackValue = String(fallback || '').trim().toLowerCase();
|
|
||||||
return Object.prototype.hasOwnProperty.call(FLOW_DEFINITIONS, fallbackValue)
|
|
||||||
? fallbackValue
|
|
||||||
: DEFAULT_FLOW_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRegisteredFlowIds() {
|
|
||||||
return Object.keys(FLOW_DEFINITIONS);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFlowDefinition(flowId) {
|
|
||||||
return FLOW_DEFINITIONS[normalizeFlowId(flowId)] || FLOW_DEFINITIONS[DEFAULT_FLOW_ID];
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFlowLabel(flowId) {
|
|
||||||
return getFlowDefinition(flowId)?.label || normalizeFlowId(flowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDefaultTargetId(flowId) {
|
|
||||||
return normalizeFlowId(flowId) === 'kiro'
|
|
||||||
? DEFAULT_KIRO_TARGET_ID
|
|
||||||
: DEFAULT_OPENAI_TARGET_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeOpenAiTargetId(value = '', fallback = DEFAULT_OPENAI_TARGET_ID) {
|
|
||||||
const normalized = String(value || '').trim().toLowerCase();
|
|
||||||
if (OPENAI_TARGET_IDS.includes(normalized)) {
|
|
||||||
return normalized;
|
|
||||||
}
|
|
||||||
const fallbackValue = String(fallback || '').trim().toLowerCase();
|
|
||||||
return OPENAI_TARGET_IDS.includes(fallbackValue)
|
|
||||||
? fallbackValue
|
|
||||||
: DEFAULT_OPENAI_TARGET_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeKiroTargetId(value = '', fallback = DEFAULT_KIRO_TARGET_ID) {
|
|
||||||
const normalized = String(value || '').trim().toLowerCase();
|
|
||||||
if (normalized === DEFAULT_KIRO_TARGET_ID) {
|
|
||||||
return normalized;
|
|
||||||
}
|
|
||||||
const fallbackValue = String(fallback || '').trim().toLowerCase();
|
|
||||||
return fallbackValue === DEFAULT_KIRO_TARGET_ID
|
|
||||||
? fallbackValue
|
|
||||||
: DEFAULT_KIRO_TARGET_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeTargetId(flowId, targetId = '', fallback = undefined) {
|
|
||||||
const normalizedFlowId = normalizeFlowId(flowId);
|
|
||||||
if (normalizedFlowId === 'kiro') {
|
|
||||||
return normalizeKiroTargetId(
|
|
||||||
targetId,
|
|
||||||
fallback || DEFAULT_KIRO_TARGET_ID
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return normalizeOpenAiTargetId(
|
|
||||||
targetId,
|
|
||||||
fallback || DEFAULT_OPENAI_TARGET_ID
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTargetDefinitions(flowId) {
|
|
||||||
return getFlowDefinition(flowId)?.targets || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTargetDefinition(flowId, targetId) {
|
|
||||||
const normalizedFlowId = normalizeFlowId(flowId);
|
|
||||||
const normalizedTargetId = normalizeTargetId(
|
|
||||||
normalizedFlowId,
|
|
||||||
targetId,
|
|
||||||
getDefaultTargetId(normalizedFlowId)
|
|
||||||
);
|
|
||||||
return getTargetDefinitions(normalizedFlowId)[normalizedTargetId] || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTargetOptions(flowId) {
|
|
||||||
return Object.values(getTargetDefinitions(flowId));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTargetLabel(flowId, targetId) {
|
|
||||||
return getTargetDefinition(flowId, targetId)?.label
|
|
||||||
|| normalizeTargetId(flowId, targetId);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPublicationTargetDefinitions(flowId) {
|
|
||||||
return getFlowDefinition(flowId)?.publicationTargets || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPublicationTargetDefinition(flowId, publicationTargetId) {
|
|
||||||
const normalizedFlowId = normalizeFlowId(flowId);
|
|
||||||
const normalizedPublicationTargetId = String(
|
|
||||||
publicationTargetId || (
|
|
||||||
normalizedFlowId === 'kiro'
|
|
||||||
? DEFAULT_KIRO_PUBLICATION_TARGET_ID
|
|
||||||
: ''
|
|
||||||
)
|
|
||||||
).trim().toLowerCase();
|
|
||||||
return getPublicationTargetDefinitions(normalizedFlowId)[normalizedPublicationTargetId] || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFlowCapabilities(flowId) {
|
|
||||||
return {
|
|
||||||
...DEFAULT_FLOW_CAPABILITIES,
|
|
||||||
...(getFlowDefinition(flowId)?.capabilities || {}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVisibleGroupIds(flowId, targetId, options = {}) {
|
|
||||||
const normalizedFlowId = normalizeFlowId(flowId);
|
|
||||||
const flowDefinition = getFlowDefinition(normalizedFlowId);
|
|
||||||
const normalizedTargetId = normalizeTargetId(
|
|
||||||
normalizedFlowId,
|
|
||||||
targetId,
|
|
||||||
getDefaultTargetId(normalizedFlowId)
|
|
||||||
);
|
|
||||||
const targetDefinition = getTargetDefinition(
|
|
||||||
normalizedFlowId,
|
|
||||||
normalizedTargetId
|
|
||||||
);
|
|
||||||
const includeSharedServices = options?.includeSharedServices !== false;
|
|
||||||
const serviceGroups = includeSharedServices
|
|
||||||
? (Array.isArray(flowDefinition?.services)
|
|
||||||
? flowDefinition.services.map((serviceId) => `service-${serviceId}`)
|
|
||||||
: [])
|
|
||||||
: [];
|
|
||||||
return Array.from(new Set([
|
|
||||||
...(Array.isArray(flowDefinition?.baseGroups) ? flowDefinition.baseGroups : []),
|
|
||||||
...(Array.isArray(targetDefinition?.groups) ? targetDefinition.groups : []),
|
|
||||||
...serviceGroups,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSettingsGroupDefinition(groupId) {
|
|
||||||
const normalizedGroupId = String(groupId || '').trim();
|
|
||||||
return SETTINGS_GROUP_DEFINITIONS[normalizedGroupId] || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSettingsGroupDefinitions() {
|
|
||||||
return SETTINGS_GROUP_DEFINITIONS;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRuntimeSourceDefinitions() {
|
|
||||||
const next = {};
|
|
||||||
Object.values(FLOW_DEFINITIONS).forEach((flowDefinition) => {
|
|
||||||
Object.assign(next, flowDefinition.runtimeSources || {});
|
|
||||||
});
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDriverDefinitions() {
|
|
||||||
const next = {};
|
|
||||||
Object.values(FLOW_DEFINITIONS).forEach((flowDefinition) => {
|
|
||||||
Object.assign(next, flowDefinition.driverDefinitions || {});
|
|
||||||
});
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
DEFAULT_FLOW_CAPABILITIES,
|
|
||||||
DEFAULT_FLOW_ID,
|
|
||||||
DEFAULT_KIRO_TARGET_ID,
|
|
||||||
DEFAULT_KIRO_PUBLICATION_TARGET_ID,
|
|
||||||
DEFAULT_KIRO_RS_URL,
|
|
||||||
DEFAULT_OPENAI_TARGET_ID,
|
|
||||||
FLOW_DEFINITIONS,
|
|
||||||
OPENAI_TARGET_IDS,
|
|
||||||
SETTINGS_GROUP_DEFINITIONS,
|
|
||||||
SHARED_SERVICE_IDS,
|
|
||||||
getDriverDefinitions,
|
|
||||||
getDefaultTargetId,
|
|
||||||
getFlowCapabilities,
|
|
||||||
getFlowDefinition,
|
|
||||||
getFlowLabel,
|
|
||||||
getPublicationTargetDefinition,
|
|
||||||
getPublicationTargetDefinitions,
|
|
||||||
getRegisteredFlowIds,
|
|
||||||
getRuntimeSourceDefinitions,
|
|
||||||
getSettingsGroupDefinition,
|
|
||||||
getSettingsGroupDefinitions,
|
|
||||||
getTargetDefinition,
|
|
||||||
getTargetDefinitions,
|
|
||||||
getTargetLabel,
|
|
||||||
getTargetOptions,
|
|
||||||
getVisibleGroupIds,
|
|
||||||
normalizeFlowId,
|
|
||||||
normalizeKiroTargetId,
|
|
||||||
normalizeOpenAiTargetId,
|
|
||||||
normalizeTargetId,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -1,406 +0,0 @@
|
|||||||
(function attachMultiPageSourceRegistry(root, factory) {
|
|
||||||
root.MultiPageSourceRegistry = factory();
|
|
||||||
})(typeof self !== 'undefined' ? self : globalThis, function createSourceRegistryModule() {
|
|
||||||
const rootScope = typeof self !== 'undefined' ? self : globalThis;
|
|
||||||
const flowRegistryApi = rootScope.MultiPageFlowRegistry || {};
|
|
||||||
|
|
||||||
const SOURCE_ALIASES = Object.freeze({
|
|
||||||
'signup-page': 'openai-auth',
|
|
||||||
});
|
|
||||||
|
|
||||||
const SHARED_SOURCE_DEFINITIONS = Object.freeze({
|
|
||||||
'qq-mail': {
|
|
||||||
flowId: null,
|
|
||||||
kind: 'mail-provider',
|
|
||||||
label: 'QQ 邮箱',
|
|
||||||
readyPolicy: 'top-frame-only',
|
|
||||||
family: 'qq-mail-family',
|
|
||||||
driverId: 'content/qq-mail',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'mail-163': {
|
|
||||||
flowId: null,
|
|
||||||
kind: 'mail-provider',
|
|
||||||
label: '163 邮箱',
|
|
||||||
readyPolicy: 'top-frame-only',
|
|
||||||
family: 'mail-163-family',
|
|
||||||
driverId: 'content/mail-163',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'gmail-mail': {
|
|
||||||
flowId: null,
|
|
||||||
kind: 'mail-provider',
|
|
||||||
label: 'Gmail 邮箱',
|
|
||||||
readyPolicy: 'top-frame-only',
|
|
||||||
family: 'gmail-mail-family',
|
|
||||||
driverId: 'content/gmail-mail',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'icloud-mail': {
|
|
||||||
flowId: null,
|
|
||||||
kind: 'mail-provider',
|
|
||||||
label: 'iCloud 邮箱',
|
|
||||||
readyPolicy: 'allow-child-frame',
|
|
||||||
family: 'icloud-mail-family',
|
|
||||||
driverId: 'content/icloud-mail',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'inbucket-mail': {
|
|
||||||
flowId: null,
|
|
||||||
kind: 'mail-provider',
|
|
||||||
label: 'Inbucket 邮箱',
|
|
||||||
readyPolicy: 'top-frame-only',
|
|
||||||
family: 'inbucket-mail-family',
|
|
||||||
driverId: 'content/inbucket-mail',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'mail-2925': {
|
|
||||||
flowId: null,
|
|
||||||
kind: 'mail-provider',
|
|
||||||
label: '2925 邮箱',
|
|
||||||
readyPolicy: 'top-frame-only',
|
|
||||||
family: 'mail-2925-family',
|
|
||||||
driverId: 'content/mail-2925',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'duck-mail': {
|
|
||||||
flowId: null,
|
|
||||||
kind: 'mail-provider',
|
|
||||||
label: 'Duck 邮箱',
|
|
||||||
readyPolicy: 'allow-child-frame',
|
|
||||||
family: 'duck-mail-family',
|
|
||||||
driverId: 'content/duck-mail',
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
'unknown-source': {
|
|
||||||
flowId: null,
|
|
||||||
kind: 'unknown',
|
|
||||||
label: '未知来源',
|
|
||||||
readyPolicy: 'disabled',
|
|
||||||
family: 'unknown-family',
|
|
||||||
driverId: null,
|
|
||||||
cleanupScopes: [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const SHARED_DRIVER_DEFINITIONS = Object.freeze({
|
|
||||||
'content/qq-mail': {
|
|
||||||
sourceId: 'qq-mail',
|
|
||||||
commands: ['POLL_EMAIL'],
|
|
||||||
},
|
|
||||||
'content/mail-163': {
|
|
||||||
sourceId: 'mail-163',
|
|
||||||
commands: ['POLL_EMAIL'],
|
|
||||||
},
|
|
||||||
'content/gmail-mail': {
|
|
||||||
sourceId: 'gmail-mail',
|
|
||||||
commands: ['POLL_EMAIL'],
|
|
||||||
},
|
|
||||||
'content/icloud-mail': {
|
|
||||||
sourceId: 'icloud-mail',
|
|
||||||
commands: ['POLL_EMAIL'],
|
|
||||||
},
|
|
||||||
'content/mail-2925': {
|
|
||||||
sourceId: 'mail-2925',
|
|
||||||
commands: ['POLL_EMAIL'],
|
|
||||||
},
|
|
||||||
'content/duck-mail': {
|
|
||||||
sourceId: 'duck-mail',
|
|
||||||
commands: ['FETCH_ALIAS_EMAIL'],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const CLEANUP_SCOPE_OWNERS = Object.freeze({
|
|
||||||
'oauth-localhost-callback': 'openai-auth',
|
|
||||||
});
|
|
||||||
|
|
||||||
const AUTH_PAGE_HOSTS = new Set(['auth0.openai.com', 'auth.openai.com', 'accounts.openai.com']);
|
|
||||||
const ENTRY_PAGE_HOSTS = new Set(['chatgpt.com', 'www.chatgpt.com', 'chat.openai.com']);
|
|
||||||
const CHILD_FRAME_BLOCKED_SOURCES = new Set([
|
|
||||||
'qq-mail',
|
|
||||||
'mail-163',
|
|
||||||
'gmail-mail',
|
|
||||||
'mail-2925',
|
|
||||||
'inbucket-mail',
|
|
||||||
'plus-checkout',
|
|
||||||
'kiro-register-page',
|
|
||||||
'kiro-desktop-authorize',
|
|
||||||
]);
|
|
||||||
|
|
||||||
function normalizeHostname(hostname = '') {
|
|
||||||
return String(hostname || '').trim().toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
function matchesNamedHostFamily(hostname = '', family = '') {
|
|
||||||
const normalizedHost = normalizeHostname(hostname);
|
|
||||||
const normalizedFamily = normalizeHostname(family);
|
|
||||||
if (!normalizedHost || !normalizedFamily) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return normalizedHost === normalizedFamily
|
|
||||||
|| normalizedHost.endsWith(`.${normalizedFamily}`)
|
|
||||||
|| normalizedHost.startsWith(`${normalizedFamily}.`)
|
|
||||||
|| normalizedHost.includes(`.${normalizedFamily}.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isKiroWebHost(hostname = '') {
|
|
||||||
const normalized = normalizeHostname(hostname);
|
|
||||||
return normalized === 'app.kiro.dev'
|
|
||||||
|| normalized === 'kiro.dev';
|
|
||||||
}
|
|
||||||
|
|
||||||
function isKiroAwsAuthHost(hostname = '') {
|
|
||||||
const normalized = normalizeHostname(hostname);
|
|
||||||
return normalized === 'view.awsapps.com'
|
|
||||||
|| normalized === 'login.awsapps.com'
|
|
||||||
|| matchesNamedHostFamily(normalized, 'signin.aws')
|
|
||||||
|| matchesNamedHostFamily(normalized, 'profile.aws')
|
|
||||||
|| normalized === 'amazonaws.com'
|
|
||||||
|| normalized.endsWith('.amazonaws.com');
|
|
||||||
}
|
|
||||||
|
|
||||||
function isKiroRegisterHost(hostname = '') {
|
|
||||||
return isKiroWebHost(hostname) || isKiroAwsAuthHost(hostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRuntimeSourceDefinitions() {
|
|
||||||
return {
|
|
||||||
...(typeof flowRegistryApi.getRuntimeSourceDefinitions === 'function'
|
|
||||||
? flowRegistryApi.getRuntimeSourceDefinitions()
|
|
||||||
: {}),
|
|
||||||
...SHARED_SOURCE_DEFINITIONS,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDriverDefinitions() {
|
|
||||||
return {
|
|
||||||
...(typeof flowRegistryApi.getDriverDefinitions === 'function'
|
|
||||||
? flowRegistryApi.getDriverDefinitions()
|
|
||||||
: {}),
|
|
||||||
...SHARED_DRIVER_DEFINITIONS,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createSourceRegistry() {
|
|
||||||
const SOURCE_DEFINITIONS = getRuntimeSourceDefinitions();
|
|
||||||
const DRIVER_DEFINITIONS = getDriverDefinitions();
|
|
||||||
|
|
||||||
function parseUrlSafely(rawUrl) {
|
|
||||||
if (!rawUrl) return null;
|
|
||||||
try {
|
|
||||||
return new URL(rawUrl);
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeSourceId(source) {
|
|
||||||
return String(source || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveCanonicalSource(source) {
|
|
||||||
const normalized = normalizeSourceId(source);
|
|
||||||
if (!normalized) return '';
|
|
||||||
return SOURCE_ALIASES[normalized] || normalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAliasKeysForCanonicalSource(source) {
|
|
||||||
const canonical = resolveCanonicalSource(source);
|
|
||||||
return Object.keys(SOURCE_ALIASES).filter((alias) => SOURCE_ALIASES[alias] === canonical);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSourceKeys(source) {
|
|
||||||
const normalized = normalizeSourceId(source);
|
|
||||||
const canonical = resolveCanonicalSource(normalized);
|
|
||||||
return Array.from(new Set([
|
|
||||||
canonical,
|
|
||||||
...getAliasKeysForCanonicalSource(canonical),
|
|
||||||
normalized,
|
|
||||||
].filter(Boolean)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSourceMeta(source) {
|
|
||||||
const canonical = resolveCanonicalSource(source);
|
|
||||||
const definition = SOURCE_DEFINITIONS[canonical];
|
|
||||||
if (!definition) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
id: canonical,
|
|
||||||
aliases: getAliasKeysForCanonicalSource(canonical),
|
|
||||||
...definition,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSourceLabel(source) {
|
|
||||||
return getSourceMeta(source)?.label || normalizeSourceId(source) || '未知来源';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDriverIdForSource(source) {
|
|
||||||
return getSourceMeta(source)?.driverId || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDriverMeta(sourceOrDriverId) {
|
|
||||||
const directDriverId = normalizeSourceId(sourceOrDriverId);
|
|
||||||
const driverId = Object.prototype.hasOwnProperty.call(DRIVER_DEFINITIONS, directDriverId)
|
|
||||||
? directDriverId
|
|
||||||
: getDriverIdForSource(sourceOrDriverId);
|
|
||||||
if (!driverId || !Object.prototype.hasOwnProperty.call(DRIVER_DEFINITIONS, driverId)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
id: driverId,
|
|
||||||
...DRIVER_DEFINITIONS[driverId],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function driverAcceptsCommand(sourceOrDriverId, command) {
|
|
||||||
const normalizedCommand = normalizeSourceId(command);
|
|
||||||
if (!normalizedCommand) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const driver = getDriverMeta(sourceOrDriverId);
|
|
||||||
return Array.isArray(driver?.commands) && driver.commands.includes(normalizedCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isSignupPageHost(hostname = '') {
|
|
||||||
return AUTH_PAGE_HOSTS.has(normalizeHostname(hostname));
|
|
||||||
}
|
|
||||||
|
|
||||||
function isSignupEntryHost(hostname = '') {
|
|
||||||
return ENTRY_PAGE_HOSTS.has(normalizeHostname(hostname));
|
|
||||||
}
|
|
||||||
|
|
||||||
function is163MailHost(hostname = '') {
|
|
||||||
const normalized = normalizeHostname(hostname);
|
|
||||||
return normalized === 'mail.163.com'
|
|
||||||
|| normalized.endsWith('.mail.163.com')
|
|
||||||
|| normalized === 'mail.126.com'
|
|
||||||
|| normalized.endsWith('.mail.126.com')
|
|
||||||
|| normalized === 'webmail.vip.163.com';
|
|
||||||
}
|
|
||||||
|
|
||||||
function matchesSourceUrlFamily(source, candidateUrl, referenceUrl) {
|
|
||||||
const candidate = parseUrlSafely(candidateUrl);
|
|
||||||
if (!candidate) return false;
|
|
||||||
|
|
||||||
const canonical = resolveCanonicalSource(source);
|
|
||||||
const reference = parseUrlSafely(referenceUrl);
|
|
||||||
|
|
||||||
switch (canonical) {
|
|
||||||
case 'openai-auth':
|
|
||||||
return isSignupPageHost(candidate.hostname) || isSignupEntryHost(candidate.hostname);
|
|
||||||
case 'chatgpt':
|
|
||||||
return isSignupEntryHost(candidate.hostname);
|
|
||||||
case 'duck-mail':
|
|
||||||
return candidate.hostname === 'duckduckgo.com' && candidate.pathname.startsWith('/email/');
|
|
||||||
case 'qq-mail':
|
|
||||||
return candidate.hostname === 'mail.qq.com' || candidate.hostname === 'wx.mail.qq.com';
|
|
||||||
case 'mail-163':
|
|
||||||
return is163MailHost(candidate.hostname);
|
|
||||||
case 'gmail-mail':
|
|
||||||
return candidate.hostname === 'mail.google.com';
|
|
||||||
case 'icloud-mail':
|
|
||||||
return candidate.hostname === 'www.icloud.com'
|
|
||||||
|| candidate.hostname === 'www.icloud.com.cn';
|
|
||||||
case 'inbucket-mail':
|
|
||||||
return Boolean(reference)
|
|
||||||
&& candidate.origin === reference.origin
|
|
||||||
&& candidate.pathname.startsWith('/m/');
|
|
||||||
case 'mail-2925':
|
|
||||||
return candidate.hostname === '2925.com' || candidate.hostname === 'www.2925.com';
|
|
||||||
case 'vps-panel':
|
|
||||||
return Boolean(reference)
|
|
||||||
&& candidate.origin === reference.origin
|
|
||||||
&& candidate.pathname === reference.pathname;
|
|
||||||
case 'sub2api-panel':
|
|
||||||
return Boolean(reference)
|
|
||||||
&& candidate.origin === reference.origin
|
|
||||||
&& (
|
|
||||||
candidate.pathname.startsWith('/admin/accounts')
|
|
||||||
|| candidate.pathname.startsWith('/login')
|
|
||||||
|| candidate.pathname === '/'
|
|
||||||
);
|
|
||||||
case 'codex2api-panel':
|
|
||||||
return Boolean(reference)
|
|
||||||
&& candidate.origin === reference.origin
|
|
||||||
&& (
|
|
||||||
candidate.pathname.startsWith('/admin/accounts')
|
|
||||||
|| candidate.pathname === '/admin'
|
|
||||||
|| candidate.pathname === '/'
|
|
||||||
);
|
|
||||||
case 'plus-checkout':
|
|
||||||
return candidate.hostname === 'chatgpt.com'
|
|
||||||
&& candidate.pathname.startsWith('/checkout/');
|
|
||||||
case 'paypal-flow':
|
|
||||||
return candidate.hostname.endsWith('paypal.com');
|
|
||||||
case 'gopay-flow':
|
|
||||||
return /gopay|gojek/i.test(candidate.hostname);
|
|
||||||
case 'kiro-register-page':
|
|
||||||
return isKiroRegisterHost(candidate.hostname);
|
|
||||||
case 'kiro-desktop-authorize':
|
|
||||||
return isKiroAwsAuthHost(candidate.hostname);
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function detectSourceFromLocation({
|
|
||||||
injectedSource,
|
|
||||||
url = '',
|
|
||||||
hostname = '',
|
|
||||||
} = {}) {
|
|
||||||
if (injectedSource) return resolveCanonicalSource(injectedSource);
|
|
||||||
|
|
||||||
const normalizedHostname = String(hostname || '').toLowerCase();
|
|
||||||
const normalizedUrl = String(url || '');
|
|
||||||
|
|
||||||
if (isSignupPageHost(normalizedHostname)) return 'openai-auth';
|
|
||||||
if (normalizedHostname === 'mail.qq.com' || normalizedHostname === 'wx.mail.qq.com') return 'qq-mail';
|
|
||||||
if (is163MailHost(normalizedHostname)) return 'mail-163';
|
|
||||||
if (normalizedHostname === 'mail.google.com') return 'gmail-mail';
|
|
||||||
if (normalizedHostname === 'www.icloud.com' || normalizedHostname === 'www.icloud.com.cn') return 'icloud-mail';
|
|
||||||
if (normalizedUrl.includes('duckduckgo.com/email/settings/autofill')) return 'duck-mail';
|
|
||||||
if (normalizedUrl.includes('2925.com')) return 'mail-2925';
|
|
||||||
if (isKiroRegisterHost(normalizedHostname)) return 'kiro-register-page';
|
|
||||||
if (isSignupEntryHost(normalizedHostname)) return 'chatgpt';
|
|
||||||
return 'unknown-source';
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldReportReadyForFrame(source, isChildFrame) {
|
|
||||||
const canonical = resolveCanonicalSource(source);
|
|
||||||
const readyPolicy = getSourceMeta(canonical)?.readyPolicy || 'allow-child-frame';
|
|
||||||
if (readyPolicy === 'disabled') return false;
|
|
||||||
if (!isChildFrame) return true;
|
|
||||||
if (readyPolicy === 'top-frame-only') return false;
|
|
||||||
if (CHILD_FRAME_BLOCKED_SOURCES.has(canonical)) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCleanupOwnerSource(cleanupScope) {
|
|
||||||
return resolveCanonicalSource(CLEANUP_SCOPE_OWNERS[String(cleanupScope || '').trim()] || '');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
detectSourceFromLocation,
|
|
||||||
driverAcceptsCommand,
|
|
||||||
getCleanupOwnerSource,
|
|
||||||
getDriverIdForSource,
|
|
||||||
getDriverMeta,
|
|
||||||
getSourceKeys,
|
|
||||||
getSourceLabel,
|
|
||||||
getSourceMeta,
|
|
||||||
is163MailHost,
|
|
||||||
isSignupEntryHost,
|
|
||||||
isSignupPageHost,
|
|
||||||
matchesSourceUrlFamily,
|
|
||||||
parseUrlSafely,
|
|
||||||
resolveCanonicalSource,
|
|
||||||
shouldReportReadyForFrame,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
createSourceRegistry,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getContributionSource(currentState = getLatestState()) {
|
function getContributionSource(currentState = getLatestState()) {
|
||||||
return normalizeContributionSource(currentState.contributionSource || currentState.panelMode);
|
return normalizeContributionSource(currentState.contributionSource || getActiveTargetId(currentState));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getContributionSourceLabel(currentState = getLatestState()) {
|
function getContributionSourceLabel(currentState = getLatestState()) {
|
||||||
@@ -107,10 +107,8 @@
|
|||||||
if (selectedTargetId) {
|
if (selectedTargetId) {
|
||||||
return selectedTargetId;
|
return selectedTargetId;
|
||||||
}
|
}
|
||||||
if (activeFlowId === 'kiro') {
|
return normalizeString(currentState.targetId).toLowerCase()
|
||||||
return normalizeString(currentState.kiroTargetId || currentState.targetId || 'kiro-rs').toLowerCase() || 'kiro-rs';
|
|| (activeFlowId === 'kiro' ? 'kiro-rs' : 'cpa');
|
||||||
}
|
|
||||||
return normalizeString(currentState.openaiIntegrationTargetId || currentState.panelMode || currentState.targetId || 'cpa').toLowerCase() || 'cpa';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function applySelectedFlowToState(nextState = {}, flowId = 'openai', targetId = '') {
|
function applySelectedFlowToState(nextState = {}, flowId = 'openai', targetId = '') {
|
||||||
@@ -122,14 +120,14 @@
|
|||||||
...baseState,
|
...baseState,
|
||||||
activeFlowId: selectedFlowId,
|
activeFlowId: selectedFlowId,
|
||||||
flowId: selectedFlowId,
|
flowId: selectedFlowId,
|
||||||
panelMode: selectedTargetId || normalizeString(baseState.panelMode).toLowerCase() || 'cpa',
|
targetId: selectedTargetId || normalizeString(baseState.targetId).toLowerCase() || 'cpa',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...baseState,
|
...baseState,
|
||||||
activeFlowId: selectedFlowId,
|
activeFlowId: selectedFlowId,
|
||||||
flowId: selectedFlowId,
|
flowId: selectedFlowId,
|
||||||
kiroTargetId: selectedTargetId || normalizeString(baseState.kiroTargetId || baseState.targetId).toLowerCase() || 'kiro-rs',
|
targetId: selectedTargetId || normalizeString(baseState.targetId).toLowerCase() || 'kiro-rs',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +162,7 @@
|
|||||||
if (registry?.resolveSidepanelCapabilities) {
|
if (registry?.resolveSidepanelCapabilities) {
|
||||||
return Boolean(registry.resolveSidepanelCapabilities({
|
return Boolean(registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId: getActiveFlowId(currentState),
|
activeFlowId: getActiveFlowId(currentState),
|
||||||
panelMode: currentState?.panelMode,
|
targetId: getActiveTargetId(currentState),
|
||||||
state: currentState,
|
state: currentState,
|
||||||
})?.canShowContributionMode);
|
})?.canShowContributionMode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
@@ -1876,10 +1876,15 @@
|
|||||||
<script src="../hotmail-utils.js"></script>
|
<script src="../hotmail-utils.js"></script>
|
||||||
<script src="../luckmail-utils.js"></script>
|
<script src="../luckmail-utils.js"></script>
|
||||||
<script src="../yyds-mail-utils.js"></script>
|
<script src="../yyds-mail-utils.js"></script>
|
||||||
<script src="../shared/flow-registry.js"></script>
|
<script src="../flows/openai/index.js"></script>
|
||||||
|
<script src="../flows/openai/workflow.js"></script>
|
||||||
|
<script src="../flows/kiro/index.js"></script>
|
||||||
|
<script src="../flows/kiro/workflow.js"></script>
|
||||||
|
<script src="../flows/index.js"></script>
|
||||||
|
<script src="../core/flow-kernel/flow-registry.js"></script>
|
||||||
<script src="../shared/contribution-registry.js"></script>
|
<script src="../shared/contribution-registry.js"></script>
|
||||||
<script src="../shared/settings-schema.js"></script>
|
<script src="../core/flow-kernel/settings-schema.js"></script>
|
||||||
<script src="../shared/flow-capabilities.js"></script>
|
<script src="../core/flow-kernel/flow-capabilities.js"></script>
|
||||||
<script src="../data/step-definitions.js"></script>
|
<script src="../data/step-definitions.js"></script>
|
||||||
<script src="update-service.js"></script>
|
<script src="update-service.js"></script>
|
||||||
<script src="contribution-content-update-service.js"></script>
|
<script src="contribution-content-update-service.js"></script>
|
||||||
|
|||||||
+432
-149
@@ -2002,13 +2002,44 @@ async function openConfirmModalWithOption({
|
|||||||
async function openPlusManualConfirmationDialog(options = {}) {
|
async function openPlusManualConfirmationDialog(options = {}) {
|
||||||
const method = String(options.method || '').trim().toLowerCase();
|
const method = String(options.method || '').trim().toLowerCase();
|
||||||
const activeFlowId = String(latestState?.activeFlowId || latestState?.flowId || 'openai').trim().toLowerCase();
|
const activeFlowId = String(latestState?.activeFlowId || latestState?.flowId || 'openai').trim().toLowerCase();
|
||||||
const panelMode = String(latestState?.panelMode || latestState?.openaiIntegrationTargetId || '').trim().toLowerCase();
|
const normalizeTargetIdForFlowSafe = typeof normalizeTargetIdForFlow === 'function'
|
||||||
|
? normalizeTargetIdForFlow
|
||||||
|
: ((flowId, targetId = '', fallback = '') => {
|
||||||
|
const normalizedFlowId = String(flowId || '').trim().toLowerCase() || 'openai';
|
||||||
|
if (normalizedFlowId === 'openai') {
|
||||||
|
const normalizedTargetId = String(targetId || fallback || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId === 'sub2api' || normalizedTargetId === 'codex2api' ? normalizedTargetId : 'cpa';
|
||||||
|
}
|
||||||
|
const normalizedTargetId = String(targetId || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId || String(fallback || '').trim().toLowerCase() || 'kiro-rs';
|
||||||
|
});
|
||||||
|
const getDefaultTargetIdForFlowSafe = typeof getDefaultTargetIdForFlow === 'function'
|
||||||
|
? getDefaultTargetIdForFlow
|
||||||
|
: ((flowId = 'openai') => (String(flowId || '').trim().toLowerCase() === 'openai' ? 'cpa' : 'kiro-rs'));
|
||||||
|
const normalizePlusStrategyTargetIdSafe = typeof normalizePlusStrategyTargetId === 'function'
|
||||||
|
? normalizePlusStrategyTargetId
|
||||||
|
: ((value = '') => {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
if (normalized === 'sub2api' || normalized === 'codex2api') {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return 'cpa';
|
||||||
|
});
|
||||||
|
const targetId = normalizePlusStrategyTargetIdSafe(
|
||||||
|
typeof getSelectedTargetIdForState === 'function'
|
||||||
|
? getSelectedTargetIdForState(latestState, activeFlowId)
|
||||||
|
: normalizeTargetIdForFlowSafe(
|
||||||
|
activeFlowId,
|
||||||
|
latestState?.targetId || '',
|
||||||
|
getDefaultTargetIdForFlowSafe(activeFlowId)
|
||||||
|
)
|
||||||
|
);
|
||||||
const signupMethod = String(latestState?.resolvedSignupMethod || latestState?.signupMethod || 'email').trim().toLowerCase();
|
const signupMethod = String(latestState?.resolvedSignupMethod || latestState?.signupMethod || 'email').trim().toLowerCase();
|
||||||
const plusModeEnabled = latestState?.plusModeEnabled === undefined ? true : Boolean(latestState.plusModeEnabled);
|
const plusModeEnabled = latestState?.plusModeEnabled === undefined ? true : Boolean(latestState.plusModeEnabled);
|
||||||
const plusAccountAccessStrategy = String(latestState?.plusAccountAccessStrategy || 'oauth').trim().toLowerCase();
|
const plusAccountAccessStrategy = String(latestState?.plusAccountAccessStrategy || 'oauth').trim().toLowerCase();
|
||||||
const useSub2ApiSessionImport = plusModeEnabled
|
const useSub2ApiSessionImport = plusModeEnabled
|
||||||
&& activeFlowId === 'openai'
|
&& activeFlowId === 'openai'
|
||||||
&& panelMode === 'sub2api'
|
&& targetId === 'sub2api'
|
||||||
&& signupMethod === 'email'
|
&& signupMethod === 'email'
|
||||||
&& plusAccountAccessStrategy === 'sub2api_codex_session';
|
&& plusAccountAccessStrategy === 'sub2api_codex_session';
|
||||||
const continuationActionLabel = useSub2ApiSessionImport
|
const continuationActionLabel = useSub2ApiSessionImport
|
||||||
@@ -2042,13 +2073,44 @@ async function syncPlusManualConfirmationDialog() {
|
|||||||
const step = Number(latestState?.plusManualConfirmationStep) || 0;
|
const step = Number(latestState?.plusManualConfirmationStep) || 0;
|
||||||
const method = String(latestState?.plusManualConfirmationMethod || '').trim().toLowerCase();
|
const method = String(latestState?.plusManualConfirmationMethod || '').trim().toLowerCase();
|
||||||
const activeFlowId = String(latestState?.activeFlowId || latestState?.flowId || 'openai').trim().toLowerCase();
|
const activeFlowId = String(latestState?.activeFlowId || latestState?.flowId || 'openai').trim().toLowerCase();
|
||||||
const panelMode = String(latestState?.panelMode || latestState?.openaiIntegrationTargetId || '').trim().toLowerCase();
|
const normalizeTargetIdForFlowSafe = typeof normalizeTargetIdForFlow === 'function'
|
||||||
|
? normalizeTargetIdForFlow
|
||||||
|
: ((flowId, targetId = '', fallback = '') => {
|
||||||
|
const normalizedFlowId = String(flowId || '').trim().toLowerCase() || 'openai';
|
||||||
|
if (normalizedFlowId === 'openai') {
|
||||||
|
const normalizedTargetId = String(targetId || fallback || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId === 'sub2api' || normalizedTargetId === 'codex2api' ? normalizedTargetId : 'cpa';
|
||||||
|
}
|
||||||
|
const normalizedTargetId = String(targetId || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId || String(fallback || '').trim().toLowerCase() || 'kiro-rs';
|
||||||
|
});
|
||||||
|
const getDefaultTargetIdForFlowSafe = typeof getDefaultTargetIdForFlow === 'function'
|
||||||
|
? getDefaultTargetIdForFlow
|
||||||
|
: ((flowId = 'openai') => (String(flowId || '').trim().toLowerCase() === 'openai' ? 'cpa' : 'kiro-rs'));
|
||||||
|
const normalizePlusStrategyTargetIdSafe = typeof normalizePlusStrategyTargetId === 'function'
|
||||||
|
? normalizePlusStrategyTargetId
|
||||||
|
: ((value = '') => {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
if (normalized === 'sub2api' || normalized === 'codex2api') {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return 'cpa';
|
||||||
|
});
|
||||||
|
const targetId = normalizePlusStrategyTargetIdSafe(
|
||||||
|
typeof getSelectedTargetIdForState === 'function'
|
||||||
|
? getSelectedTargetIdForState(latestState, activeFlowId)
|
||||||
|
: normalizeTargetIdForFlowSafe(
|
||||||
|
activeFlowId,
|
||||||
|
latestState?.targetId || '',
|
||||||
|
getDefaultTargetIdForFlowSafe(activeFlowId)
|
||||||
|
)
|
||||||
|
);
|
||||||
const signupMethod = String(latestState?.resolvedSignupMethod || latestState?.signupMethod || 'email').trim().toLowerCase();
|
const signupMethod = String(latestState?.resolvedSignupMethod || latestState?.signupMethod || 'email').trim().toLowerCase();
|
||||||
const plusModeEnabled = latestState?.plusModeEnabled === undefined ? true : Boolean(latestState.plusModeEnabled);
|
const plusModeEnabled = latestState?.plusModeEnabled === undefined ? true : Boolean(latestState.plusModeEnabled);
|
||||||
const plusAccountAccessStrategy = String(latestState?.plusAccountAccessStrategy || 'oauth').trim().toLowerCase();
|
const plusAccountAccessStrategy = String(latestState?.plusAccountAccessStrategy || 'oauth').trim().toLowerCase();
|
||||||
const useSub2ApiSessionImport = plusModeEnabled
|
const useSub2ApiSessionImport = plusModeEnabled
|
||||||
&& activeFlowId === 'openai'
|
&& activeFlowId === 'openai'
|
||||||
&& panelMode === 'sub2api'
|
&& targetId === 'sub2api'
|
||||||
&& signupMethod === 'email'
|
&& signupMethod === 'email'
|
||||||
&& plusAccountAccessStrategy === 'sub2api_codex_session';
|
&& plusAccountAccessStrategy === 'sub2api_codex_session';
|
||||||
const continuationActionLabel = useSub2ApiSessionImport
|
const continuationActionLabel = useSub2ApiSessionImport
|
||||||
@@ -2159,10 +2221,10 @@ function getContributionContentFlowId(state = latestState) {
|
|||||||
|
|
||||||
function getContributionContentTargetId(state = latestState) {
|
function getContributionContentTargetId(state = latestState) {
|
||||||
const flowId = getContributionContentFlowId(state);
|
const flowId = getContributionContentFlowId(state);
|
||||||
if (flowId === 'kiro') {
|
if (typeof getSelectedTargetIdForState === 'function') {
|
||||||
return String(state?.kiroTargetId || state?.targetId || 'kiro-rs').trim().toLowerCase() || 'kiro-rs';
|
return getSelectedTargetIdForState(state, flowId);
|
||||||
}
|
}
|
||||||
return String(state?.openaiIntegrationTargetId || state?.panelMode || state?.targetId || 'cpa').trim().toLowerCase() || 'cpa';
|
return normalizeTargetIdForFlow(flowId, state?.targetId || '', getDefaultTargetIdForFlow(flowId));
|
||||||
}
|
}
|
||||||
|
|
||||||
function openNewUserGuidePrompt() {
|
function openNewUserGuidePrompt() {
|
||||||
@@ -2255,29 +2317,54 @@ function shouldWarnAutoRunFallbackRisk(totalRuns, autoRunSkipFailures) {
|
|||||||
return totalRuns >= AUTO_RUN_FALLBACK_RISK_WARNING_MIN_RUNS;
|
return totalRuns >= AUTO_RUN_FALLBACK_RISK_WARNING_MIN_RUNS;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldWarnCpaPhoneSignup(signupMethod = null, panelMode = null) {
|
function shouldWarnCpaPhoneSignup(signupMethod = null, targetId = null) {
|
||||||
|
const defaultFlowId = typeof DEFAULT_ACTIVE_FLOW_ID === 'string' ? DEFAULT_ACTIVE_FLOW_ID : 'openai';
|
||||||
const resolvedSignupMethod = normalizeSignupMethod(
|
const resolvedSignupMethod = normalizeSignupMethod(
|
||||||
signupMethod ?? (
|
signupMethod ?? (
|
||||||
typeof getSelectedSignupMethod === 'function'
|
typeof getSelectedSignupMethod === 'function'
|
||||||
? getSelectedSignupMethod()
|
? getSelectedSignupMethod()
|
||||||
: DEFAULT_SIGNUP_METHOD
|
: DEFAULT_SIGNUP_METHOD
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
const resolvedPanelMode = normalizePanelMode(
|
const activeFlowId = typeof getSelectedFlowId === 'function'
|
||||||
panelMode ?? (
|
? getSelectedFlowId(latestState)
|
||||||
typeof getSelectedPanelMode === 'function'
|
: (
|
||||||
? getSelectedPanelMode()
|
typeof normalizeFlowId === 'function'
|
||||||
: 'cpa'
|
? normalizeFlowId(latestState?.activeFlowId || latestState?.flowId || defaultFlowId)
|
||||||
)
|
: (String(latestState?.activeFlowId || latestState?.flowId || defaultFlowId).trim().toLowerCase() || defaultFlowId)
|
||||||
|
);
|
||||||
|
const normalizeTargetIdForFlowSafe = typeof normalizeTargetIdForFlow === 'function'
|
||||||
|
? normalizeTargetIdForFlow
|
||||||
|
: ((flowId, value = '', fallback = '') => {
|
||||||
|
const normalizedFlowId = String(flowId || '').trim().toLowerCase() || defaultFlowId;
|
||||||
|
if (normalizedFlowId === defaultFlowId) {
|
||||||
|
return normalizePanelMode(value || fallback);
|
||||||
|
}
|
||||||
|
const normalizedValue = String(value || '').trim().toLowerCase();
|
||||||
|
return normalizedValue || String(fallback || '').trim().toLowerCase() || 'kiro-rs';
|
||||||
|
});
|
||||||
|
const resolvedTargetId = normalizeTargetIdForFlowSafe(
|
||||||
|
activeFlowId,
|
||||||
|
targetId ?? (
|
||||||
|
typeof getSelectedTargetId === 'function'
|
||||||
|
? getSelectedTargetId(activeFlowId)
|
||||||
|
: getSelectedTargetIdForState(latestState, activeFlowId)
|
||||||
|
),
|
||||||
|
typeof getDefaultTargetIdForFlow === 'function'
|
||||||
|
? getDefaultTargetIdForFlow(activeFlowId)
|
||||||
|
: (activeFlowId === defaultFlowId ? 'cpa' : 'kiro-rs')
|
||||||
);
|
);
|
||||||
|
|
||||||
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
||||||
? resolveCurrentSidepanelCapabilities({
|
? resolveCurrentSidepanelCapabilities({
|
||||||
panelMode: resolvedPanelMode,
|
activeFlowId,
|
||||||
|
targetId: resolvedTargetId,
|
||||||
signupMethod: resolvedSignupMethod,
|
signupMethod: resolvedSignupMethod,
|
||||||
state: {
|
state: {
|
||||||
...(typeof latestState !== 'undefined' ? latestState : {}),
|
...(typeof latestState !== 'undefined' ? latestState : {}),
|
||||||
panelMode: resolvedPanelMode,
|
activeFlowId,
|
||||||
|
flowId: activeFlowId,
|
||||||
|
targetId: resolvedTargetId,
|
||||||
signupMethod: resolvedSignupMethod,
|
signupMethod: resolvedSignupMethod,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -2288,12 +2375,14 @@ function shouldWarnCpaPhoneSignup(signupMethod = null, panelMode = null) {
|
|||||||
}) || null;
|
}) || null;
|
||||||
return registry?.resolveSidepanelCapabilities
|
return registry?.resolveSidepanelCapabilities
|
||||||
? registry.resolveSidepanelCapabilities({
|
? registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId: typeof latestState !== 'undefined' ? latestState?.activeFlowId : '',
|
activeFlowId,
|
||||||
panelMode: resolvedPanelMode,
|
targetId: resolvedTargetId,
|
||||||
signupMethod: resolvedSignupMethod,
|
signupMethod: resolvedSignupMethod,
|
||||||
state: {
|
state: {
|
||||||
...(typeof latestState !== 'undefined' ? latestState : {}),
|
...(typeof latestState !== 'undefined' ? latestState : {}),
|
||||||
panelMode: resolvedPanelMode,
|
activeFlowId,
|
||||||
|
flowId: activeFlowId,
|
||||||
|
targetId: resolvedTargetId,
|
||||||
signupMethod: resolvedSignupMethod,
|
signupMethod: resolvedSignupMethod,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -2305,7 +2394,7 @@ function shouldWarnCpaPhoneSignup(signupMethod = null, panelMode = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return resolvedSignupMethod === SIGNUP_METHOD_PHONE
|
return resolvedSignupMethod === SIGNUP_METHOD_PHONE
|
||||||
&& resolvedPanelMode === 'cpa'
|
&& resolvedTargetId === 'cpa'
|
||||||
&& !isCpaPhoneSignupPromptDismissed();
|
&& !isCpaPhoneSignupPromptDismissed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2327,11 +2416,11 @@ async function confirmCpaPhoneSignupIfNeeded(options = {}) {
|
|||||||
const signupMethod = Object.prototype.hasOwnProperty.call(options, 'signupMethod')
|
const signupMethod = Object.prototype.hasOwnProperty.call(options, 'signupMethod')
|
||||||
? options.signupMethod
|
? options.signupMethod
|
||||||
: null;
|
: null;
|
||||||
const panelMode = Object.prototype.hasOwnProperty.call(options, 'panelMode')
|
const targetId = Object.prototype.hasOwnProperty.call(options, 'targetId')
|
||||||
? options.panelMode
|
? options.targetId
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!shouldWarnCpaPhoneSignup(signupMethod, panelMode)) {
|
if (!shouldWarnCpaPhoneSignup(signupMethod, targetId)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2559,6 +2648,18 @@ function getKiroUploadStatusLabel(value = '') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getKiroRuntimeState(state = {}) {
|
||||||
|
const runtimeState = state?.runtimeState?.flowState?.kiro;
|
||||||
|
if (runtimeState && typeof runtimeState === 'object' && !Array.isArray(runtimeState)) {
|
||||||
|
return runtimeState;
|
||||||
|
}
|
||||||
|
const flowState = state?.flowState?.kiro;
|
||||||
|
if (flowState && typeof flowState === 'object' && !Array.isArray(flowState)) {
|
||||||
|
return flowState;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
function setKiroRsConnectionTestStatus(message = '') {
|
function setKiroRsConnectionTestStatus(message = '') {
|
||||||
const nextText = String(message || '').trim() || '未测试';
|
const nextText = String(message || '').trim() || '未测试';
|
||||||
kiroRsConnectionTestStatusText = nextText;
|
kiroRsConnectionTestStatusText = nextText;
|
||||||
@@ -2873,6 +2974,18 @@ function syncLatestState(nextState) {
|
|||||||
nodeStatuses: mergedNodeStatuses,
|
nodeStatuses: mergedNodeStatuses,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const activeFlowId = typeof normalizeFlowId === 'function'
|
||||||
|
? normalizeFlowId(latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID, DEFAULT_ACTIVE_FLOW_ID)
|
||||||
|
: (String(latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase() || DEFAULT_ACTIVE_FLOW_ID);
|
||||||
|
const schema = typeof getSettingsSchema === 'function' ? getSettingsSchema() : null;
|
||||||
|
const selectedTargetId = schema?.getSelectedTargetId
|
||||||
|
? schema.getSelectedTargetId(latestState, activeFlowId)
|
||||||
|
: (String(latestState?.targetId || '').trim().toLowerCase()
|
||||||
|
|| (activeFlowId === 'kiro' ? 'kiro-rs' : 'cpa'));
|
||||||
|
latestState.targetId = typeof normalizeTargetIdForFlow === 'function'
|
||||||
|
? normalizeTargetIdForFlow(activeFlowId, selectedTargetId)
|
||||||
|
: selectedTargetId;
|
||||||
|
|
||||||
renderAccountRecords(latestState);
|
renderAccountRecords(latestState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3053,7 +3166,12 @@ function getRequestedPlusAccountAccessStrategy(state = latestState) {
|
|||||||
if (typeof selectPanelMode !== 'undefined' && selectPanelMode?.value) {
|
if (typeof selectPanelMode !== 'undefined' && selectPanelMode?.value) {
|
||||||
return selectPanelMode.value;
|
return selectPanelMode.value;
|
||||||
}
|
}
|
||||||
return state?.panelMode || state?.openaiIntegrationTargetId || 'cpa';
|
return getSelectedTargetIdForState({
|
||||||
|
...(latestState || {}),
|
||||||
|
...(state || {}),
|
||||||
|
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
|
flowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
|
}, DEFAULT_ACTIVE_FLOW_ID);
|
||||||
};
|
};
|
||||||
const resolveStrategyForTarget = typeof resolvePlusAccountAccessStrategyForTarget === 'function'
|
const resolveStrategyForTarget = typeof resolvePlusAccountAccessStrategyForTarget === 'function'
|
||||||
? resolvePlusAccountAccessStrategyForTarget
|
? resolvePlusAccountAccessStrategyForTarget
|
||||||
@@ -3136,7 +3254,38 @@ function resolvePlusManualContinuationActionLabelFromState(state = latestState)
|
|||||||
const activeFlowId = String(state?.activeFlowId || state?.flowId || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase();
|
const activeFlowId = String(state?.activeFlowId || state?.flowId || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase();
|
||||||
const signupMethod = normalizeSignupMethod(state?.resolvedSignupMethod || state?.signupMethod || DEFAULT_SIGNUP_METHOD);
|
const signupMethod = normalizeSignupMethod(state?.resolvedSignupMethod || state?.signupMethod || DEFAULT_SIGNUP_METHOD);
|
||||||
const plusModeEnabled = state?.plusModeEnabled === undefined ? true : Boolean(state?.plusModeEnabled);
|
const plusModeEnabled = state?.plusModeEnabled === undefined ? true : Boolean(state?.plusModeEnabled);
|
||||||
const targetId = normalizePlusStrategyTargetId(state?.panelMode || state?.openaiIntegrationTargetId || 'cpa');
|
const normalizeTargetIdForFlowSafe = typeof normalizeTargetIdForFlow === 'function'
|
||||||
|
? normalizeTargetIdForFlow
|
||||||
|
: ((flowId, targetId = '', fallback = '') => {
|
||||||
|
const normalizedFlowId = String(flowId || '').trim().toLowerCase() || DEFAULT_ACTIVE_FLOW_ID;
|
||||||
|
if (normalizedFlowId === DEFAULT_ACTIVE_FLOW_ID) {
|
||||||
|
const normalizedTargetId = String(targetId || fallback || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId === 'sub2api' || normalizedTargetId === 'codex2api' ? normalizedTargetId : 'cpa';
|
||||||
|
}
|
||||||
|
const normalizedTargetId = String(targetId || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId || String(fallback || '').trim().toLowerCase() || 'kiro-rs';
|
||||||
|
});
|
||||||
|
const getDefaultTargetIdForFlowSafe = typeof getDefaultTargetIdForFlow === 'function'
|
||||||
|
? getDefaultTargetIdForFlow
|
||||||
|
: ((flowId = DEFAULT_ACTIVE_FLOW_ID) => (String(flowId || '').trim().toLowerCase() === DEFAULT_ACTIVE_FLOW_ID ? 'cpa' : 'kiro-rs'));
|
||||||
|
const normalizePlusStrategyTargetIdSafe = typeof normalizePlusStrategyTargetId === 'function'
|
||||||
|
? normalizePlusStrategyTargetId
|
||||||
|
: ((value = '') => {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
if (normalized === 'sub2api' || normalized === 'codex2api') {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return 'cpa';
|
||||||
|
});
|
||||||
|
const targetId = normalizePlusStrategyTargetIdSafe(
|
||||||
|
typeof getSelectedTargetIdForState === 'function'
|
||||||
|
? getSelectedTargetIdForState(state, activeFlowId)
|
||||||
|
: normalizeTargetIdForFlowSafe(
|
||||||
|
activeFlowId,
|
||||||
|
state?.targetId || '',
|
||||||
|
getDefaultTargetIdForFlowSafe(activeFlowId)
|
||||||
|
)
|
||||||
|
);
|
||||||
const strategy = normalizePlusAccountAccessStrategy(state?.plusAccountAccessStrategy || DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY);
|
const strategy = normalizePlusAccountAccessStrategy(state?.plusAccountAccessStrategy || DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY);
|
||||||
const effectiveStrategy = plusModeEnabled && activeFlowId === DEFAULT_ACTIVE_FLOW_ID && signupMethod === SIGNUP_METHOD_EMAIL
|
const effectiveStrategy = plusModeEnabled && activeFlowId === DEFAULT_ACTIVE_FLOW_ID && signupMethod === SIGNUP_METHOD_EMAIL
|
||||||
? strategy
|
? strategy
|
||||||
@@ -4478,12 +4627,63 @@ function collectSettingsPayload() {
|
|||||||
const normalized = String(value || '').trim().toLowerCase();
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
return normalized === 'sub2api' || normalized === 'codex2api' ? normalized : 'cpa';
|
return normalized === 'sub2api' || normalized === 'codex2api' ? normalized : 'cpa';
|
||||||
});
|
});
|
||||||
const rawPanelMode = normalizePanelModeSafe(selectPanelMode?.value || latestState?.panelMode || 'cpa');
|
const normalizeTargetIdForFlowSafe = typeof normalizeTargetIdForFlow === 'function'
|
||||||
|
? normalizeTargetIdForFlow
|
||||||
|
: ((flowId, targetId = '', fallback = '') => {
|
||||||
|
const normalizedFlowId = String(flowId || '').trim().toLowerCase() || defaultFlowId;
|
||||||
|
if (normalizedFlowId === defaultFlowId) {
|
||||||
|
return normalizePanelModeSafe(targetId || fallback);
|
||||||
|
}
|
||||||
|
const normalizedTargetId = String(targetId || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId || String(fallback || '').trim().toLowerCase() || 'kiro-rs';
|
||||||
|
});
|
||||||
|
const resolvePlusAccountAccessStrategyForTargetSafe = typeof resolvePlusAccountAccessStrategyForTarget === 'function'
|
||||||
|
? resolvePlusAccountAccessStrategyForTarget
|
||||||
|
: ((value = '', targetId = '') => {
|
||||||
|
const oauthStrategyValue = typeof PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH !== 'undefined'
|
||||||
|
? PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH
|
||||||
|
: 'oauth';
|
||||||
|
const sub2apiSessionStrategyValue = typeof PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION !== 'undefined'
|
||||||
|
? PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION
|
||||||
|
: 'sub2api_codex_session';
|
||||||
|
const cpaSessionStrategyValue = typeof PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION !== 'undefined'
|
||||||
|
? PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION
|
||||||
|
: 'cpa_codex_session';
|
||||||
|
const sessionUiValue = typeof PLUS_ACCOUNT_ACCESS_STRATEGY_CODEX_SESSION_UI !== 'undefined'
|
||||||
|
? PLUS_ACCOUNT_ACCESS_STRATEGY_CODEX_SESSION_UI
|
||||||
|
: 'codex_session';
|
||||||
|
const normalizedValue = String(value || '').trim().toLowerCase();
|
||||||
|
const isSessionImport = normalizedValue === sessionUiValue
|
||||||
|
|| normalizedValue === sub2apiSessionStrategyValue
|
||||||
|
|| normalizedValue === cpaSessionStrategyValue;
|
||||||
|
if (!isSessionImport) {
|
||||||
|
return oauthStrategyValue;
|
||||||
|
}
|
||||||
|
const normalizedTargetId = typeof normalizePlusStrategyTargetId === 'function'
|
||||||
|
? normalizePlusStrategyTargetId(targetId)
|
||||||
|
: normalizePanelModeSafe(targetId || '');
|
||||||
|
if (normalizedTargetId === 'sub2api') {
|
||||||
|
return sub2apiSessionStrategyValue;
|
||||||
|
}
|
||||||
|
if (normalizedTargetId === 'cpa') {
|
||||||
|
return cpaSessionStrategyValue;
|
||||||
|
}
|
||||||
|
return oauthStrategyValue;
|
||||||
|
});
|
||||||
const selectedTargetId = typeof getSelectedTargetId === 'function'
|
const selectedTargetId = typeof getSelectedTargetId === 'function'
|
||||||
? getSelectedTargetId(activeFlowId)
|
? getSelectedTargetId(activeFlowId)
|
||||||
: (activeFlowId === defaultFlowId
|
: normalizeTargetIdForFlowSafe(
|
||||||
? rawPanelMode
|
activeFlowId,
|
||||||
: String(selectPanelMode?.value || latestState?.kiroTargetId || 'kiro-rs').trim().toLowerCase() || 'kiro-rs');
|
selectPanelMode?.value || latestState?.targetId || '',
|
||||||
|
typeof getDefaultTargetIdForFlow === 'function'
|
||||||
|
? getDefaultTargetIdForFlow(activeFlowId)
|
||||||
|
: (activeFlowId === defaultFlowId ? 'cpa' : 'kiro-rs')
|
||||||
|
);
|
||||||
|
const openAiTargetId = normalizePanelModeSafe(
|
||||||
|
activeFlowId === defaultFlowId
|
||||||
|
? selectedTargetId
|
||||||
|
: getSelectedPanelMode(latestState)
|
||||||
|
);
|
||||||
const rawPlusModeEnabled = typeof inputPlusModeEnabled !== 'undefined' && inputPlusModeEnabled
|
const rawPlusModeEnabled = typeof inputPlusModeEnabled !== 'undefined' && inputPlusModeEnabled
|
||||||
? Boolean(inputPlusModeEnabled.checked)
|
? Boolean(inputPlusModeEnabled.checked)
|
||||||
: Boolean(latestState?.plusModeEnabled);
|
: Boolean(latestState?.plusModeEnabled);
|
||||||
@@ -4495,14 +4695,12 @@ function collectSettingsPayload() {
|
|||||||
? resolveCurrentSidepanelCapabilities({
|
? resolveCurrentSidepanelCapabilities({
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
targetId: selectedTargetId,
|
targetId: selectedTargetId,
|
||||||
panelMode: rawPanelMode,
|
|
||||||
signupMethod: selectedSignupMethod,
|
signupMethod: selectedSignupMethod,
|
||||||
state: {
|
state: {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
...(activeFlowId === defaultFlowId
|
flowId: activeFlowId,
|
||||||
? { panelMode: rawPanelMode }
|
targetId: selectedTargetId,
|
||||||
: { kiroTargetId: selectedTargetId }),
|
|
||||||
plusModeEnabled: rawPlusModeEnabled,
|
plusModeEnabled: rawPlusModeEnabled,
|
||||||
plusAccountAccessStrategy: requestedPlusAccountAccessStrategy,
|
plusAccountAccessStrategy: requestedPlusAccountAccessStrategy,
|
||||||
phoneVerificationEnabled: rawPhoneVerificationEnabled,
|
phoneVerificationEnabled: rawPhoneVerificationEnabled,
|
||||||
@@ -4517,15 +4715,13 @@ function collectSettingsPayload() {
|
|||||||
return registry?.resolveSidepanelCapabilities
|
return registry?.resolveSidepanelCapabilities
|
||||||
? registry.resolveSidepanelCapabilities({
|
? registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
panelMode: rawPanelMode,
|
|
||||||
targetId: selectedTargetId,
|
targetId: selectedTargetId,
|
||||||
signupMethod: selectedSignupMethod,
|
signupMethod: selectedSignupMethod,
|
||||||
state: {
|
state: {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
...(activeFlowId === defaultFlowId
|
flowId: activeFlowId,
|
||||||
? { panelMode: rawPanelMode }
|
targetId: selectedTargetId,
|
||||||
: { kiroTargetId: selectedTargetId }),
|
|
||||||
plusModeEnabled: rawPlusModeEnabled,
|
plusModeEnabled: rawPlusModeEnabled,
|
||||||
plusAccountAccessStrategy: requestedPlusAccountAccessStrategy,
|
plusAccountAccessStrategy: requestedPlusAccountAccessStrategy,
|
||||||
phoneVerificationEnabled: rawPhoneVerificationEnabled,
|
phoneVerificationEnabled: rawPhoneVerificationEnabled,
|
||||||
@@ -4534,8 +4730,12 @@ function collectSettingsPayload() {
|
|||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
})();
|
})();
|
||||||
const effectivePanelMode = capabilityState?.effectivePanelMode || capabilityState?.panelMode || rawPanelMode;
|
|
||||||
const effectiveTargetId = capabilityState?.effectiveTargetId || selectedTargetId;
|
const effectiveTargetId = capabilityState?.effectiveTargetId || selectedTargetId;
|
||||||
|
const effectiveOpenAiTargetId = normalizePanelModeSafe(
|
||||||
|
activeFlowId === defaultFlowId
|
||||||
|
? effectiveTargetId
|
||||||
|
: openAiTargetId
|
||||||
|
);
|
||||||
const effectivePlusModeEnabled = capabilityState
|
const effectivePlusModeEnabled = capabilityState
|
||||||
? Boolean(capabilityState.runtimeLocks?.plusModeEnabled)
|
? Boolean(capabilityState.runtimeLocks?.plusModeEnabled)
|
||||||
: rawPlusModeEnabled;
|
: rawPlusModeEnabled;
|
||||||
@@ -4623,16 +4823,7 @@ function collectSettingsPayload() {
|
|||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
...(accountContributionEnabled ? {} : {
|
targetId: effectiveTargetId,
|
||||||
...(activeFlowId === defaultFlowId ? { panelMode: effectivePanelMode } : {}),
|
|
||||||
}),
|
|
||||||
kiroTargetId: normalizeKiroTargetIdSafe(
|
|
||||||
'kiro',
|
|
||||||
activeFlowId === 'kiro'
|
|
||||||
? effectiveTargetId
|
|
||||||
: (latestState?.kiroTargetId || 'kiro-rs'),
|
|
||||||
'kiro-rs'
|
|
||||||
),
|
|
||||||
kiroRsUrl: currentKiroRsUrlValue !== null
|
kiroRsUrl: currentKiroRsUrlValue !== null
|
||||||
? (currentKiroRsUrlValue || defaultKiroRsUrl)
|
? (currentKiroRsUrlValue || defaultKiroRsUrl)
|
||||||
: (String(latestState?.kiroRsUrl || defaultKiroRsUrl).trim() || defaultKiroRsUrl),
|
: (String(latestState?.kiroRsUrl || defaultKiroRsUrl).trim() || defaultKiroRsUrl),
|
||||||
@@ -4677,7 +4868,9 @@ function collectSettingsPayload() {
|
|||||||
codex2apiAdminKey: inputCodex2ApiAdminKey.value.trim(),
|
codex2apiAdminKey: inputCodex2ApiAdminKey.value.trim(),
|
||||||
plusModeEnabled: effectivePlusModeEnabled,
|
plusModeEnabled: effectivePlusModeEnabled,
|
||||||
plusPaymentMethod,
|
plusPaymentMethod,
|
||||||
plusAccountAccessStrategy: requestedPlusAccountAccessStrategy,
|
plusAccountAccessStrategy: activeFlowId === defaultFlowId
|
||||||
|
? resolvePlusAccountAccessStrategyForTargetSafe(requestedPlusAccountAccessStrategy, effectiveOpenAiTargetId)
|
||||||
|
: requestedPlusAccountAccessStrategy,
|
||||||
hostedCheckoutVerificationUrl: typeof inputHostedCheckoutVerificationUrl !== 'undefined' && inputHostedCheckoutVerificationUrl
|
hostedCheckoutVerificationUrl: typeof inputHostedCheckoutVerificationUrl !== 'undefined' && inputHostedCheckoutVerificationUrl
|
||||||
? String(inputHostedCheckoutVerificationUrl.value || '').trim()
|
? String(inputHostedCheckoutVerificationUrl.value || '').trim()
|
||||||
: String(latestState?.hostedCheckoutVerificationUrl || '').trim(),
|
: String(latestState?.hostedCheckoutVerificationUrl || '').trim(),
|
||||||
@@ -8683,12 +8876,9 @@ function getSelectedTargetIdForState(state = latestState, flowId = getSelectedFl
|
|||||||
if (schema?.getSelectedTargetId) {
|
if (schema?.getSelectedTargetId) {
|
||||||
return schema.getSelectedTargetId(state || {}, normalizedFlowId);
|
return schema.getSelectedTargetId(state || {}, normalizedFlowId);
|
||||||
}
|
}
|
||||||
if (normalizedFlowId === DEFAULT_ACTIVE_FLOW_ID) {
|
|
||||||
return normalizePanelMode(state?.panelMode || getDefaultTargetIdForFlow(normalizedFlowId));
|
|
||||||
}
|
|
||||||
return normalizeTargetIdForFlow(
|
return normalizeTargetIdForFlow(
|
||||||
normalizedFlowId,
|
normalizedFlowId,
|
||||||
state?.kiroTargetId || '',
|
state?.targetId || '',
|
||||||
getDefaultTargetIdForFlow(normalizedFlowId)
|
getDefaultTargetIdForFlow(normalizedFlowId)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -8698,14 +8888,9 @@ function getSelectedTargetId(flowId = getSelectedFlowId()) {
|
|||||||
const selectedValue = typeof selectPanelMode !== 'undefined' && selectPanelMode
|
const selectedValue = typeof selectPanelMode !== 'undefined' && selectPanelMode
|
||||||
? selectPanelMode.value
|
? selectPanelMode.value
|
||||||
: '';
|
: '';
|
||||||
if (normalizedFlowId === DEFAULT_ACTIVE_FLOW_ID) {
|
|
||||||
return normalizePanelMode(
|
|
||||||
selectedValue || latestState?.panelMode || getDefaultTargetIdForFlow(normalizedFlowId)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return normalizeTargetIdForFlow(
|
return normalizeTargetIdForFlow(
|
||||||
normalizedFlowId,
|
normalizedFlowId,
|
||||||
selectedValue || latestState?.kiroTargetId || '',
|
selectedValue || latestState?.targetId || '',
|
||||||
getDefaultTargetIdForFlow(normalizedFlowId)
|
getDefaultTargetIdForFlow(normalizedFlowId)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -8857,24 +9042,15 @@ function resolveCurrentSidepanelCapabilities(options = {}) {
|
|||||||
};
|
};
|
||||||
const targetId = options?.targetId !== undefined
|
const targetId = options?.targetId !== undefined
|
||||||
? options.targetId
|
? options.targetId
|
||||||
: (activeFlowId === DEFAULT_ACTIVE_FLOW_ID
|
: (state?.targetId ?? getSelectedTargetIdForState(state, activeFlowId));
|
||||||
? (options?.panelMode ?? state?.panelMode)
|
state.targetId = normalizeTargetIdForFlow(
|
||||||
: (options?.kiroTargetId ?? state?.kiroTargetId));
|
activeFlowId,
|
||||||
if (activeFlowId === DEFAULT_ACTIVE_FLOW_ID) {
|
targetId || state?.targetId || '',
|
||||||
state.panelMode = normalizePanelMode(
|
getDefaultTargetIdForFlow(activeFlowId)
|
||||||
targetId || state?.panelMode || getDefaultTargetIdForFlow(activeFlowId)
|
);
|
||||||
);
|
|
||||||
} else {
|
|
||||||
state.kiroTargetId = normalizeTargetIdForFlow(
|
|
||||||
activeFlowId,
|
|
||||||
targetId || state?.kiroTargetId || '',
|
|
||||||
getDefaultTargetIdForFlow(activeFlowId)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return registry.resolveSidepanelCapabilities({
|
return registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
panelMode: state?.panelMode,
|
targetId: state.targetId,
|
||||||
targetId: activeFlowId === DEFAULT_ACTIVE_FLOW_ID ? state?.panelMode : state?.kiroTargetId,
|
|
||||||
signupMethod: options?.signupMethod ?? state?.signupMethod,
|
signupMethod: options?.signupMethod ?? state?.signupMethod,
|
||||||
state,
|
state,
|
||||||
});
|
});
|
||||||
@@ -8887,7 +9063,7 @@ function resolveStepDefinitionCapabilityState(state = latestState, options = {})
|
|||||||
};
|
};
|
||||||
const capabilityState = resolveCurrentSidepanelCapabilities({
|
const capabilityState = resolveCurrentSidepanelCapabilities({
|
||||||
activeFlowId: options?.activeFlowId ?? nextState?.activeFlowId,
|
activeFlowId: options?.activeFlowId ?? nextState?.activeFlowId,
|
||||||
panelMode: options?.panelMode ?? nextState?.panelMode,
|
targetId: options?.targetId ?? nextState?.targetId,
|
||||||
signupMethod: options?.signupMethod ?? nextState?.signupMethod,
|
signupMethod: options?.signupMethod ?? nextState?.signupMethod,
|
||||||
state: nextState,
|
state: nextState,
|
||||||
});
|
});
|
||||||
@@ -8905,16 +9081,35 @@ function resolveStepDefinitionCapabilityState(state = latestState, options = {})
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectedPanelMode() {
|
function getSelectedPanelMode(state = latestState) {
|
||||||
const resolvedPanelMode = normalizePanelMode(
|
const resolvedPanelMode = normalizePanelMode(
|
||||||
typeof selectPanelMode !== 'undefined' && selectPanelMode
|
typeof getSelectedTargetIdForState === 'function'
|
||||||
? selectPanelMode.value
|
? getSelectedTargetIdForState({
|
||||||
: (typeof latestState !== 'undefined' ? latestState?.panelMode : '')
|
...(typeof latestState !== 'undefined' ? latestState : {}),
|
||||||
|
...(state || {}),
|
||||||
|
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
|
flowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
|
}, DEFAULT_ACTIVE_FLOW_ID)
|
||||||
|
: (
|
||||||
|
typeof selectPanelMode !== 'undefined' && selectPanelMode
|
||||||
|
? selectPanelMode.value
|
||||||
|
: (typeof state !== 'undefined' ? state?.targetId : '')
|
||||||
|
)
|
||||||
);
|
);
|
||||||
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
||||||
? resolveCurrentSidepanelCapabilities({ panelMode: resolvedPanelMode })
|
? resolveCurrentSidepanelCapabilities({
|
||||||
|
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
|
targetId: resolvedPanelMode,
|
||||||
|
state: {
|
||||||
|
...(typeof latestState !== 'undefined' ? latestState : {}),
|
||||||
|
...(state || {}),
|
||||||
|
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
|
flowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
|
targetId: resolvedPanelMode,
|
||||||
|
},
|
||||||
|
})
|
||||||
: null;
|
: null;
|
||||||
return capabilityState?.effectivePanelMode || capabilityState?.panelMode || resolvedPanelMode;
|
return normalizePanelMode(capabilityState?.effectiveTargetId || resolvedPanelMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectedSignupMethod() {
|
function getSelectedSignupMethod() {
|
||||||
@@ -8943,7 +9138,9 @@ function canSelectPhoneSignupMethod() {
|
|||||||
: Boolean(latestState?.accountContributionEnabled);
|
: Boolean(latestState?.accountContributionEnabled);
|
||||||
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
||||||
? resolveCurrentSidepanelCapabilities({
|
? resolveCurrentSidepanelCapabilities({
|
||||||
panelMode: typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : latestState?.panelMode,
|
targetId: typeof getSelectedTargetId === 'function'
|
||||||
|
? getSelectedTargetId(getSelectedFlowId(latestState))
|
||||||
|
: latestState?.targetId,
|
||||||
state: {
|
state: {
|
||||||
...(typeof latestState !== 'undefined' ? latestState : {}),
|
...(typeof latestState !== 'undefined' ? latestState : {}),
|
||||||
phoneVerificationEnabled: phoneEnabled,
|
phoneVerificationEnabled: phoneEnabled,
|
||||||
@@ -8959,7 +9156,9 @@ function canSelectPhoneSignupMethod() {
|
|||||||
return registry?.resolveSidepanelCapabilities
|
return registry?.resolveSidepanelCapabilities
|
||||||
? registry.resolveSidepanelCapabilities({
|
? registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId: typeof latestState !== 'undefined' ? latestState?.activeFlowId : '',
|
activeFlowId: typeof latestState !== 'undefined' ? latestState?.activeFlowId : '',
|
||||||
panelMode: typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : (latestState?.panelMode || 'cpa'),
|
targetId: typeof getSelectedTargetId === 'function'
|
||||||
|
? getSelectedTargetId(getSelectedFlowId(latestState))
|
||||||
|
: latestState?.targetId,
|
||||||
state: {
|
state: {
|
||||||
...(typeof latestState !== 'undefined' ? latestState : {}),
|
...(typeof latestState !== 'undefined' ? latestState : {}),
|
||||||
phoneVerificationEnabled: phoneEnabled,
|
phoneVerificationEnabled: phoneEnabled,
|
||||||
@@ -9061,7 +9260,9 @@ function updatePhoneVerificationSettingsUI() {
|
|||||||
: Boolean(latestState?.plusModeEnabled);
|
: Boolean(latestState?.plusModeEnabled);
|
||||||
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
||||||
? resolveCurrentSidepanelCapabilities({
|
? resolveCurrentSidepanelCapabilities({
|
||||||
panelMode: typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : latestState?.panelMode,
|
targetId: typeof getSelectedTargetId === 'function'
|
||||||
|
? getSelectedTargetId(getSelectedFlowId(latestState))
|
||||||
|
: latestState?.targetId,
|
||||||
signupMethod: typeof getSelectedSignupMethod === 'function' ? getSelectedSignupMethod() : latestState?.signupMethod,
|
signupMethod: typeof getSelectedSignupMethod === 'function' ? getSelectedSignupMethod() : latestState?.signupMethod,
|
||||||
state: {
|
state: {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
@@ -9077,7 +9278,9 @@ function updatePhoneVerificationSettingsUI() {
|
|||||||
return registry?.resolveSidepanelCapabilities
|
return registry?.resolveSidepanelCapabilities
|
||||||
? registry.resolveSidepanelCapabilities({
|
? registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId: latestState?.activeFlowId,
|
activeFlowId: latestState?.activeFlowId,
|
||||||
panelMode: typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : (latestState?.panelMode || 'cpa'),
|
targetId: typeof getSelectedTargetId === 'function'
|
||||||
|
? getSelectedTargetId(getSelectedFlowId(latestState))
|
||||||
|
: latestState?.targetId,
|
||||||
signupMethod: typeof getSelectedSignupMethod === 'function' ? getSelectedSignupMethod() : latestState?.signupMethod,
|
signupMethod: typeof getSelectedSignupMethod === 'function' ? getSelectedSignupMethod() : latestState?.signupMethod,
|
||||||
state: {
|
state: {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
@@ -9366,7 +9569,9 @@ function updatePlusModeUI() {
|
|||||||
: false;
|
: false;
|
||||||
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
||||||
? resolveCurrentSidepanelCapabilities({
|
? resolveCurrentSidepanelCapabilities({
|
||||||
panelMode: typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : latestState?.panelMode,
|
targetId: typeof getSelectedTargetId === 'function'
|
||||||
|
? getSelectedTargetId(getSelectedFlowId(latestState))
|
||||||
|
: latestState?.targetId,
|
||||||
state: {
|
state: {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
plusModeEnabled: rawEnabled,
|
plusModeEnabled: rawEnabled,
|
||||||
@@ -9381,7 +9586,9 @@ function updatePlusModeUI() {
|
|||||||
return registry?.resolveSidepanelCapabilities
|
return registry?.resolveSidepanelCapabilities
|
||||||
? registry.resolveSidepanelCapabilities({
|
? registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId: latestState?.activeFlowId,
|
activeFlowId: latestState?.activeFlowId,
|
||||||
panelMode: typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : (latestState?.panelMode || 'cpa'),
|
targetId: typeof getSelectedTargetId === 'function'
|
||||||
|
? getSelectedTargetId(getSelectedFlowId(latestState))
|
||||||
|
: latestState?.targetId,
|
||||||
state: {
|
state: {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
plusModeEnabled: rawEnabled,
|
plusModeEnabled: rawEnabled,
|
||||||
@@ -9403,10 +9610,8 @@ function updatePlusModeUI() {
|
|||||||
|| requestedPlusAccountAccessStrategy
|
|| requestedPlusAccountAccessStrategy
|
||||||
|| oauthStrategyValue;
|
|| oauthStrategyValue;
|
||||||
const effectiveTargetId = resolveStrategyTargetId(
|
const effectiveTargetId = resolveStrategyTargetId(
|
||||||
capabilityState?.effectivePanelMode
|
capabilityState?.effectiveTargetId
|
||||||
|| capabilityState?.effectiveTargetId
|
|| (typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode(latestState) : latestState?.targetId)
|
||||||
|| capabilityState?.panelMode
|
|
||||||
|| (typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : latestState?.panelMode)
|
|
||||||
|| 'cpa'
|
|| 'cpa'
|
||||||
);
|
);
|
||||||
const method = enabled ? getSelectedPlusPaymentMethod() : defaultMethod;
|
const method = enabled ? getSelectedPlusPaymentMethod() : defaultMethod;
|
||||||
@@ -9711,7 +9916,12 @@ function syncSignupPhoneInputFromState(state = latestState) {
|
|||||||
: (String(rawSignupMethod || '').trim().toLowerCase() === 'phone' ? 'phone' : 'email');
|
: (String(rawSignupMethod || '').trim().toLowerCase() === 'phone' ? 'phone' : 'email');
|
||||||
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
||||||
? resolveCurrentSidepanelCapabilities({
|
? resolveCurrentSidepanelCapabilities({
|
||||||
panelMode: state?.panelMode || latestState?.panelMode,
|
targetId: typeof getSelectedTargetIdForState === 'function'
|
||||||
|
? getSelectedTargetIdForState({
|
||||||
|
...(latestState || {}),
|
||||||
|
...(state || {}),
|
||||||
|
}, state?.activeFlowId || latestState?.activeFlowId || DEFAULT_ACTIVE_FLOW_ID)
|
||||||
|
: (state?.targetId || latestState?.targetId),
|
||||||
signupMethod: selectedMethod,
|
signupMethod: selectedMethod,
|
||||||
state: {
|
state: {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
@@ -9727,7 +9937,12 @@ function syncSignupPhoneInputFromState(state = latestState) {
|
|||||||
return registry?.resolveSidepanelCapabilities
|
return registry?.resolveSidepanelCapabilities
|
||||||
? registry.resolveSidepanelCapabilities({
|
? registry.resolveSidepanelCapabilities({
|
||||||
activeFlowId: state?.activeFlowId || latestState?.activeFlowId,
|
activeFlowId: state?.activeFlowId || latestState?.activeFlowId,
|
||||||
panelMode: state?.panelMode || latestState?.panelMode,
|
targetId: typeof getSelectedTargetIdForState === 'function'
|
||||||
|
? getSelectedTargetIdForState({
|
||||||
|
...(latestState || {}),
|
||||||
|
...(state || {}),
|
||||||
|
}, state?.activeFlowId || latestState?.activeFlowId || DEFAULT_ACTIVE_FLOW_ID)
|
||||||
|
: (state?.targetId || latestState?.targetId),
|
||||||
signupMethod: selectedMethod,
|
signupMethod: selectedMethod,
|
||||||
state: {
|
state: {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
@@ -9925,13 +10140,44 @@ async function openPlusManualConfirmationDialog(options = {}) {
|
|||||||
const method = String(options.method || '').trim().toLowerCase();
|
const method = String(options.method || '').trim().toLowerCase();
|
||||||
const gopayValue = typeof PLUS_PAYMENT_METHOD_GOPAY !== 'undefined' ? PLUS_PAYMENT_METHOD_GOPAY : 'gopay';
|
const gopayValue = typeof PLUS_PAYMENT_METHOD_GOPAY !== 'undefined' ? PLUS_PAYMENT_METHOD_GOPAY : 'gopay';
|
||||||
const activeFlowId = String(latestState?.activeFlowId || latestState?.flowId || 'openai').trim().toLowerCase();
|
const activeFlowId = String(latestState?.activeFlowId || latestState?.flowId || 'openai').trim().toLowerCase();
|
||||||
const panelMode = String(latestState?.panelMode || latestState?.openaiIntegrationTargetId || '').trim().toLowerCase();
|
const normalizeTargetIdForFlowSafe = typeof normalizeTargetIdForFlow === 'function'
|
||||||
|
? normalizeTargetIdForFlow
|
||||||
|
: ((flowId, targetId = '', fallback = '') => {
|
||||||
|
const normalizedFlowId = String(flowId || '').trim().toLowerCase() || 'openai';
|
||||||
|
if (normalizedFlowId === 'openai') {
|
||||||
|
const normalizedTargetId = String(targetId || fallback || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId === 'sub2api' || normalizedTargetId === 'codex2api' ? normalizedTargetId : 'cpa';
|
||||||
|
}
|
||||||
|
const normalizedTargetId = String(targetId || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId || String(fallback || '').trim().toLowerCase() || 'kiro-rs';
|
||||||
|
});
|
||||||
|
const getDefaultTargetIdForFlowSafe = typeof getDefaultTargetIdForFlow === 'function'
|
||||||
|
? getDefaultTargetIdForFlow
|
||||||
|
: ((flowId = 'openai') => (String(flowId || '').trim().toLowerCase() === 'openai' ? 'cpa' : 'kiro-rs'));
|
||||||
|
const normalizePlusStrategyTargetIdSafe = typeof normalizePlusStrategyTargetId === 'function'
|
||||||
|
? normalizePlusStrategyTargetId
|
||||||
|
: ((value = '') => {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
if (normalized === 'sub2api' || normalized === 'codex2api') {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return 'cpa';
|
||||||
|
});
|
||||||
|
const targetId = normalizePlusStrategyTargetIdSafe(
|
||||||
|
typeof getSelectedTargetIdForState === 'function'
|
||||||
|
? getSelectedTargetIdForState(latestState, activeFlowId)
|
||||||
|
: normalizeTargetIdForFlowSafe(
|
||||||
|
activeFlowId,
|
||||||
|
latestState?.targetId || '',
|
||||||
|
getDefaultTargetIdForFlowSafe(activeFlowId)
|
||||||
|
)
|
||||||
|
);
|
||||||
const signupMethod = String(latestState?.resolvedSignupMethod || latestState?.signupMethod || 'email').trim().toLowerCase();
|
const signupMethod = String(latestState?.resolvedSignupMethod || latestState?.signupMethod || 'email').trim().toLowerCase();
|
||||||
const plusModeEnabled = latestState?.plusModeEnabled === undefined ? true : Boolean(latestState.plusModeEnabled);
|
const plusModeEnabled = latestState?.plusModeEnabled === undefined ? true : Boolean(latestState.plusModeEnabled);
|
||||||
const plusAccountAccessStrategy = String(latestState?.plusAccountAccessStrategy || 'oauth').trim().toLowerCase();
|
const plusAccountAccessStrategy = String(latestState?.plusAccountAccessStrategy || 'oauth').trim().toLowerCase();
|
||||||
const useSub2ApiSessionImport = plusModeEnabled
|
const useSub2ApiSessionImport = plusModeEnabled
|
||||||
&& activeFlowId === 'openai'
|
&& activeFlowId === 'openai'
|
||||||
&& panelMode === 'sub2api'
|
&& targetId === 'sub2api'
|
||||||
&& signupMethod === 'email'
|
&& signupMethod === 'email'
|
||||||
&& plusAccountAccessStrategy === 'sub2api_codex_session';
|
&& plusAccountAccessStrategy === 'sub2api_codex_session';
|
||||||
const continuationActionLabel = useSub2ApiSessionImport
|
const continuationActionLabel = useSub2ApiSessionImport
|
||||||
@@ -9996,13 +10242,44 @@ async function syncPlusManualConfirmationDialog() {
|
|||||||
const step = Number(latestState?.plusManualConfirmationStep) || 0;
|
const step = Number(latestState?.plusManualConfirmationStep) || 0;
|
||||||
const method = String(latestState?.plusManualConfirmationMethod || '').trim().toLowerCase();
|
const method = String(latestState?.plusManualConfirmationMethod || '').trim().toLowerCase();
|
||||||
const activeFlowId = String(latestState?.activeFlowId || latestState?.flowId || 'openai').trim().toLowerCase();
|
const activeFlowId = String(latestState?.activeFlowId || latestState?.flowId || 'openai').trim().toLowerCase();
|
||||||
const panelMode = String(latestState?.panelMode || latestState?.openaiIntegrationTargetId || '').trim().toLowerCase();
|
const normalizeTargetIdForFlowSafe = typeof normalizeTargetIdForFlow === 'function'
|
||||||
|
? normalizeTargetIdForFlow
|
||||||
|
: ((flowId, targetId = '', fallback = '') => {
|
||||||
|
const normalizedFlowId = String(flowId || '').trim().toLowerCase() || 'openai';
|
||||||
|
if (normalizedFlowId === 'openai') {
|
||||||
|
const normalizedTargetId = String(targetId || fallback || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId === 'sub2api' || normalizedTargetId === 'codex2api' ? normalizedTargetId : 'cpa';
|
||||||
|
}
|
||||||
|
const normalizedTargetId = String(targetId || '').trim().toLowerCase();
|
||||||
|
return normalizedTargetId || String(fallback || '').trim().toLowerCase() || 'kiro-rs';
|
||||||
|
});
|
||||||
|
const getDefaultTargetIdForFlowSafe = typeof getDefaultTargetIdForFlow === 'function'
|
||||||
|
? getDefaultTargetIdForFlow
|
||||||
|
: ((flowId = 'openai') => (String(flowId || '').trim().toLowerCase() === 'openai' ? 'cpa' : 'kiro-rs'));
|
||||||
|
const normalizePlusStrategyTargetIdSafe = typeof normalizePlusStrategyTargetId === 'function'
|
||||||
|
? normalizePlusStrategyTargetId
|
||||||
|
: ((value = '') => {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
if (normalized === 'sub2api' || normalized === 'codex2api') {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return 'cpa';
|
||||||
|
});
|
||||||
|
const targetId = normalizePlusStrategyTargetIdSafe(
|
||||||
|
typeof getSelectedTargetIdForState === 'function'
|
||||||
|
? getSelectedTargetIdForState(latestState, activeFlowId)
|
||||||
|
: normalizeTargetIdForFlowSafe(
|
||||||
|
activeFlowId,
|
||||||
|
latestState?.targetId || '',
|
||||||
|
getDefaultTargetIdForFlowSafe(activeFlowId)
|
||||||
|
)
|
||||||
|
);
|
||||||
const signupMethod = String(latestState?.resolvedSignupMethod || latestState?.signupMethod || 'email').trim().toLowerCase();
|
const signupMethod = String(latestState?.resolvedSignupMethod || latestState?.signupMethod || 'email').trim().toLowerCase();
|
||||||
const plusModeEnabled = latestState?.plusModeEnabled === undefined ? true : Boolean(latestState.plusModeEnabled);
|
const plusModeEnabled = latestState?.plusModeEnabled === undefined ? true : Boolean(latestState.plusModeEnabled);
|
||||||
const plusAccountAccessStrategy = String(latestState?.plusAccountAccessStrategy || 'oauth').trim().toLowerCase();
|
const plusAccountAccessStrategy = String(latestState?.plusAccountAccessStrategy || 'oauth').trim().toLowerCase();
|
||||||
const useSub2ApiSessionImport = plusModeEnabled
|
const useSub2ApiSessionImport = plusModeEnabled
|
||||||
&& activeFlowId === 'openai'
|
&& activeFlowId === 'openai'
|
||||||
&& panelMode === 'sub2api'
|
&& targetId === 'sub2api'
|
||||||
&& signupMethod === 'email'
|
&& signupMethod === 'email'
|
||||||
&& plusAccountAccessStrategy === 'sub2api_codex_session';
|
&& plusAccountAccessStrategy === 'sub2api_codex_session';
|
||||||
const continuationActionLabel = useSub2ApiSessionImport
|
const continuationActionLabel = useSub2ApiSessionImport
|
||||||
@@ -10523,7 +10800,7 @@ function syncStepDefinitionsFromUiState(stateOverrides = {}) {
|
|||||||
const stepDefinitionState = typeof resolveStepDefinitionCapabilityState === 'function'
|
const stepDefinitionState = typeof resolveStepDefinitionCapabilityState === 'function'
|
||||||
? resolveStepDefinitionCapabilityState(nextState, {
|
? resolveStepDefinitionCapabilityState(nextState, {
|
||||||
activeFlowId: nextState?.activeFlowId,
|
activeFlowId: nextState?.activeFlowId,
|
||||||
panelMode: nextState?.panelMode,
|
targetId: nextState?.targetId,
|
||||||
signupMethod: nextState?.signupMethod,
|
signupMethod: nextState?.signupMethod,
|
||||||
state: nextState,
|
state: nextState,
|
||||||
})
|
})
|
||||||
@@ -10616,7 +10893,7 @@ function applySettingsState(state) {
|
|||||||
? syncFlowSelectorsFromState(state)
|
? syncFlowSelectorsFromState(state)
|
||||||
: {
|
: {
|
||||||
activeFlowId: String(state?.activeFlowId || state?.flowId || defaultActiveFlowId).trim().toLowerCase() || defaultActiveFlowId,
|
activeFlowId: String(state?.activeFlowId || state?.flowId || defaultActiveFlowId).trim().toLowerCase() || defaultActiveFlowId,
|
||||||
targetId: String(state?.panelMode || 'cpa').trim().toLowerCase() || 'cpa',
|
targetId: String(state?.targetId || 'cpa').trim().toLowerCase() || 'cpa',
|
||||||
};
|
};
|
||||||
if (typeof applyOperationDelayState === 'function') {
|
if (typeof applyOperationDelayState === 'function') {
|
||||||
applyOperationDelayState(state);
|
applyOperationDelayState(state);
|
||||||
@@ -10748,24 +11025,38 @@ function applySettingsState(state) {
|
|||||||
if (typeof displayKiroRsTestStatus !== 'undefined' && displayKiroRsTestStatus) {
|
if (typeof displayKiroRsTestStatus !== 'undefined' && displayKiroRsTestStatus) {
|
||||||
displayKiroRsTestStatus.textContent = kiroRsConnectionTestStatusText;
|
displayKiroRsTestStatus.textContent = kiroRsConnectionTestStatusText;
|
||||||
}
|
}
|
||||||
|
const resolveKiroRuntimeState = typeof getKiroRuntimeState === 'function'
|
||||||
|
? getKiroRuntimeState
|
||||||
|
: ((value = {}) => {
|
||||||
|
const runtimeState = value?.runtimeState?.flowState?.kiro;
|
||||||
|
if (runtimeState && typeof runtimeState === 'object' && !Array.isArray(runtimeState)) {
|
||||||
|
return runtimeState;
|
||||||
|
}
|
||||||
|
const flowState = value?.flowState?.kiro;
|
||||||
|
if (flowState && typeof flowState === 'object' && !Array.isArray(flowState)) {
|
||||||
|
return flowState;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
const kiroRuntimeState = resolveKiroRuntimeState(state);
|
||||||
if (typeof displayKiroWebStatus !== 'undefined' && displayKiroWebStatus) {
|
if (typeof displayKiroWebStatus !== 'undefined' && displayKiroWebStatus) {
|
||||||
const kiroWebStatus = String(
|
const kiroWebStatus = String(
|
||||||
state?.kiroRuntime?.webAuth?.status
|
kiroRuntimeState?.webAuth?.status
|
||||||
|| state?.kiroRuntime?.register?.status
|
|| kiroRuntimeState?.register?.status
|
||||||
|| ''
|
|| ''
|
||||||
).trim();
|
).trim();
|
||||||
displayKiroWebStatus.textContent = kiroWebStatus || '未开始';
|
displayKiroWebStatus.textContent = kiroWebStatus || '未开始';
|
||||||
}
|
}
|
||||||
if (typeof displayKiroLoginUrl !== 'undefined' && displayKiroLoginUrl) {
|
if (typeof displayKiroLoginUrl !== 'undefined' && displayKiroLoginUrl) {
|
||||||
const kiroLoginUrl = String(
|
const kiroLoginUrl = String(
|
||||||
state?.kiroRuntime?.register?.loginUrl
|
kiroRuntimeState?.register?.loginUrl
|
||||||
|| ''
|
|| ''
|
||||||
).trim();
|
).trim();
|
||||||
displayKiroLoginUrl.textContent = kiroLoginUrl || '未打开';
|
displayKiroLoginUrl.textContent = kiroLoginUrl || '未打开';
|
||||||
}
|
}
|
||||||
if (typeof displayKiroUploadStatus !== 'undefined' && displayKiroUploadStatus) {
|
if (typeof displayKiroUploadStatus !== 'undefined' && displayKiroUploadStatus) {
|
||||||
const kiroUploadStatus = String(
|
const kiroUploadStatus = String(
|
||||||
state?.kiroRuntime?.upload?.status
|
kiroRuntimeState?.upload?.status
|
||||||
|| ''
|
|| ''
|
||||||
).trim();
|
).trim();
|
||||||
displayKiroUploadStatus.textContent = getKiroUploadStatusLabel(kiroUploadStatus);
|
displayKiroUploadStatus.textContent = getKiroUploadStatusLabel(kiroUploadStatus);
|
||||||
@@ -12404,7 +12695,9 @@ function updateMailProviderUI() {
|
|||||||
: latestState?.icloudHostPreference;
|
: latestState?.icloudHostPreference;
|
||||||
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
||||||
? resolveCurrentSidepanelCapabilities({
|
? resolveCurrentSidepanelCapabilities({
|
||||||
panelMode: typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : latestState?.panelMode,
|
targetId: typeof getSelectedTargetId === 'function'
|
||||||
|
? getSelectedTargetId(getSelectedFlowId(latestState))
|
||||||
|
: latestState?.targetId,
|
||||||
state: latestState || {},
|
state: latestState || {},
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
@@ -13048,23 +13341,16 @@ function updatePanelModeUI() {
|
|||||||
: normalizeFlowId(latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID);
|
: normalizeFlowId(latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID);
|
||||||
const targetId = typeof getSelectedTargetId === 'function'
|
const targetId = typeof getSelectedTargetId === 'function'
|
||||||
? getSelectedTargetId(activeFlowId)
|
? getSelectedTargetId(activeFlowId)
|
||||||
: (activeFlowId === DEFAULT_ACTIVE_FLOW_ID
|
: normalizeTargetIdForFlow(activeFlowId, selectPanelMode?.value || latestState?.targetId || '', getDefaultTargetIdForFlow(activeFlowId));
|
||||||
? normalizePanelMode(selectPanelMode?.value || latestState?.panelMode || 'cpa')
|
|
||||||
: String(selectPanelMode?.value || latestState?.kiroTargetId || 'kiro-rs').trim().toLowerCase() || 'kiro-rs');
|
|
||||||
const rawPanelMode = activeFlowId === DEFAULT_ACTIVE_FLOW_ID
|
|
||||||
? normalizePanelMode(targetId || latestState?.panelMode || 'cpa')
|
|
||||||
: normalizePanelMode(latestState?.panelMode || 'cpa');
|
|
||||||
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
const capabilityState = typeof resolveCurrentSidepanelCapabilities === 'function'
|
||||||
? resolveCurrentSidepanelCapabilities({
|
? resolveCurrentSidepanelCapabilities({
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
targetId,
|
targetId,
|
||||||
panelMode: rawPanelMode,
|
|
||||||
state: {
|
state: {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
...(activeFlowId === DEFAULT_ACTIVE_FLOW_ID
|
flowId: activeFlowId,
|
||||||
? { panelMode: rawPanelMode }
|
targetId,
|
||||||
: { kiroTargetId: targetId }),
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
@@ -13089,12 +13375,16 @@ function updatePanelModeUI() {
|
|||||||
if (typeof updatePhoneVerificationSettingsUI === 'function') {
|
if (typeof updatePhoneVerificationSettingsUI === 'function') {
|
||||||
updatePhoneVerificationSettingsUI();
|
updatePhoneVerificationSettingsUI();
|
||||||
}
|
}
|
||||||
const panelMode = capabilityState?.effectivePanelMode || capabilityState?.panelMode || rawPanelMode;
|
const displayTargetId = normalizePanelMode(
|
||||||
|
activeFlowId === DEFAULT_ACTIVE_FLOW_ID
|
||||||
|
? (capabilityState?.effectiveTargetId || targetId)
|
||||||
|
: getSelectedPanelMode(latestState)
|
||||||
|
);
|
||||||
|
|
||||||
const useCodex2Api = panelMode === 'codex2api';
|
const useCodex2Api = displayTargetId === 'codex2api';
|
||||||
const step9Btn = document.querySelector('.step-btn[data-step-key="platform-verify"]');
|
const step9Btn = document.querySelector('.step-btn[data-step-key="platform-verify"]');
|
||||||
if (step9Btn && activeFlowId === DEFAULT_ACTIVE_FLOW_ID) {
|
if (step9Btn && activeFlowId === DEFAULT_ACTIVE_FLOW_ID) {
|
||||||
step9Btn.textContent = panelMode === 'sub2api'
|
step9Btn.textContent = displayTargetId === 'sub2api'
|
||||||
? 'SUB2API 回调验证'
|
? 'SUB2API 回调验证'
|
||||||
: (useCodex2Api ? 'Codex2API 回调验证' : 'CPA 回调验证');
|
: (useCodex2Api ? 'Codex2API 回调验证' : 'CPA 回调验证');
|
||||||
}
|
}
|
||||||
@@ -14042,7 +14332,7 @@ const accountContributionManager = window.SidepanelContributionMode?.createContr
|
|||||||
: String(latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase() || DEFAULT_ACTIVE_FLOW_ID),
|
: String(latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase() || DEFAULT_ACTIVE_FLOW_ID),
|
||||||
getSelectedTargetId: (flowId, state = latestState) => (typeof getSelectedTargetIdForState === 'function'
|
getSelectedTargetId: (flowId, state = latestState) => (typeof getSelectedTargetIdForState === 'function'
|
||||||
? getSelectedTargetIdForState(state, flowId)
|
? getSelectedTargetIdForState(state, flowId)
|
||||||
: (String(state?.panelMode || state?.kiroTargetId || 'cpa').trim().toLowerCase() || 'cpa')),
|
: normalizeTargetIdForFlow(flowId, state?.targetId || '', getDefaultTargetIdForFlow(flowId))),
|
||||||
isModeSwitchBlocked: isContributionModeSwitchBlocked,
|
isModeSwitchBlocked: isContributionModeSwitchBlocked,
|
||||||
openConfirmModal,
|
openConfirmModal,
|
||||||
openExternalUrl,
|
openExternalUrl,
|
||||||
@@ -14570,7 +14860,9 @@ async function startAutoRunFromCurrentSettings() {
|
|||||||
}
|
}
|
||||||
const validationState = {
|
const validationState = {
|
||||||
...(latestState || {}),
|
...(latestState || {}),
|
||||||
panelMode: typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : latestState?.panelMode,
|
targetId: typeof getSelectedTargetId === 'function'
|
||||||
|
? getSelectedTargetId(getSelectedFlowId(latestState))
|
||||||
|
: latestState?.targetId,
|
||||||
signupMethod: typeof getSelectedSignupMethod === 'function' ? getSelectedSignupMethod() : latestState?.signupMethod,
|
signupMethod: typeof getSelectedSignupMethod === 'function' ? getSelectedSignupMethod() : latestState?.signupMethod,
|
||||||
phoneVerificationEnabled: typeof inputPhoneVerificationEnabled !== 'undefined' && inputPhoneVerificationEnabled
|
phoneVerificationEnabled: typeof inputPhoneVerificationEnabled !== 'undefined' && inputPhoneVerificationEnabled
|
||||||
? Boolean(inputPhoneVerificationEnabled.checked)
|
? Boolean(inputPhoneVerificationEnabled.checked)
|
||||||
@@ -14582,7 +14874,7 @@ async function startAutoRunFromCurrentSettings() {
|
|||||||
};
|
};
|
||||||
return registry.validateAutoRunStart({
|
return registry.validateAutoRunStart({
|
||||||
activeFlowId: validationState.activeFlowId,
|
activeFlowId: validationState.activeFlowId,
|
||||||
panelMode: validationState.panelMode,
|
targetId: validationState.targetId,
|
||||||
signupMethod: validationState.signupMethod,
|
signupMethod: validationState.signupMethod,
|
||||||
state: validationState,
|
state: validationState,
|
||||||
});
|
});
|
||||||
@@ -14650,11 +14942,7 @@ async function startAutoRunFromCurrentSettings() {
|
|||||||
: (String(latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase() || DEFAULT_ACTIVE_FLOW_ID);
|
: (String(latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase() || DEFAULT_ACTIVE_FLOW_ID);
|
||||||
const targetId = typeof getSelectedTargetId === 'function'
|
const targetId = typeof getSelectedTargetId === 'function'
|
||||||
? getSelectedTargetId(activeFlowId)
|
? getSelectedTargetId(activeFlowId)
|
||||||
: (
|
: normalizeTargetIdForFlow(activeFlowId, latestState?.targetId || '', getDefaultTargetIdForFlow(activeFlowId));
|
||||||
activeFlowId === DEFAULT_ACTIVE_FLOW_ID
|
|
||||||
? normalizePanelMode(latestState?.panelMode || 'cpa')
|
|
||||||
: (String(latestState?.kiroTargetId || 'kiro-rs').trim().toLowerCase() || 'kiro-rs')
|
|
||||||
);
|
|
||||||
inputAutoDelayMinutes.value = String(delayMinutes);
|
inputAutoDelayMinutes.value = String(delayMinutes);
|
||||||
btnAutoRun.innerHTML = delayEnabled
|
btnAutoRun.innerHTML = delayEnabled
|
||||||
? '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg> 计划中...'
|
? '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg> 计划中...'
|
||||||
@@ -15230,9 +15518,7 @@ selectPanelMode.addEventListener('change', async () => {
|
|||||||
: (activeFlowId === DEFAULT_ACTIVE_FLOW_ID ? 'cpa' : 'kiro-rs');
|
: (activeFlowId === DEFAULT_ACTIVE_FLOW_ID ? 'cpa' : 'kiro-rs');
|
||||||
const previousTargetId = typeof getSelectedTargetIdForState === 'function'
|
const previousTargetId = typeof getSelectedTargetIdForState === 'function'
|
||||||
? getSelectedTargetIdForState(latestState, activeFlowId)
|
? getSelectedTargetIdForState(latestState, activeFlowId)
|
||||||
: (activeFlowId === DEFAULT_ACTIVE_FLOW_ID
|
: normalizeTargetIdForFlow(activeFlowId, latestState?.targetId || '', defaultTargetId);
|
||||||
? normalizePanelMode(latestState?.panelMode || defaultTargetId)
|
|
||||||
: String(latestState?.kiroTargetId || defaultTargetId).trim().toLowerCase() || defaultTargetId);
|
|
||||||
let nextTargetId = typeof normalizeTargetIdForFlow === 'function'
|
let nextTargetId = typeof normalizeTargetIdForFlow === 'function'
|
||||||
? normalizeTargetIdForFlow(activeFlowId, selectPanelMode.value, defaultTargetId)
|
? normalizeTargetIdForFlow(activeFlowId, selectPanelMode.value, defaultTargetId)
|
||||||
: (activeFlowId === DEFAULT_ACTIVE_FLOW_ID
|
: (activeFlowId === DEFAULT_ACTIVE_FLOW_ID
|
||||||
@@ -15243,7 +15529,7 @@ selectPanelMode.addEventListener('change', async () => {
|
|||||||
selectPanelMode.value = nextPanelMode;
|
selectPanelMode.value = nextPanelMode;
|
||||||
const confirmed = await confirmCpaPhoneSignupIfNeeded({
|
const confirmed = await confirmCpaPhoneSignupIfNeeded({
|
||||||
signupMethod: getSelectedSignupMethod(),
|
signupMethod: getSelectedSignupMethod(),
|
||||||
panelMode: nextPanelMode,
|
targetId: nextPanelMode,
|
||||||
});
|
});
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
selectPanelMode.value = previousTargetId;
|
selectPanelMode.value = previousTargetId;
|
||||||
@@ -15254,7 +15540,7 @@ selectPanelMode.addEventListener('change', async () => {
|
|||||||
syncLatestState({
|
syncLatestState({
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
flowId: activeFlowId,
|
flowId: activeFlowId,
|
||||||
panelMode: nextPanelMode,
|
targetId: nextPanelMode,
|
||||||
});
|
});
|
||||||
if (
|
if (
|
||||||
typeof selectPlusAccountAccessStrategy !== 'undefined'
|
typeof selectPlusAccountAccessStrategy !== 'undefined'
|
||||||
@@ -15278,7 +15564,7 @@ selectPanelMode.addEventListener('change', async () => {
|
|||||||
syncLatestState({
|
syncLatestState({
|
||||||
activeFlowId,
|
activeFlowId,
|
||||||
flowId: activeFlowId,
|
flowId: activeFlowId,
|
||||||
kiroTargetId: nextTargetId,
|
targetId: nextTargetId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
updatePanelModeUI();
|
updatePanelModeUI();
|
||||||
@@ -15305,7 +15591,7 @@ selectPlusAccountAccessStrategy?.addEventListener('change', () => {
|
|||||||
selectPlusAccountAccessStrategy.value = nextUiValue;
|
selectPlusAccountAccessStrategy.value = nextUiValue;
|
||||||
selectPlusAccountAccessStrategy.dataset.requestedValue = resolvePlusAccountAccessStrategyForTarget(
|
selectPlusAccountAccessStrategy.dataset.requestedValue = resolvePlusAccountAccessStrategyForTarget(
|
||||||
nextUiValue,
|
nextUiValue,
|
||||||
typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode() : latestState?.panelMode
|
typeof getSelectedPanelMode === 'function' ? getSelectedPanelMode(latestState) : latestState?.targetId
|
||||||
);
|
);
|
||||||
updatePlusModeUI();
|
updatePlusModeUI();
|
||||||
markSettingsDirty(true);
|
markSettingsDirty(true);
|
||||||
@@ -16100,19 +16386,13 @@ selectFlow?.addEventListener('change', () => {
|
|||||||
: (nextActiveFlowId === DEFAULT_ACTIVE_FLOW_ID ? 'cpa' : 'kiro-rs');
|
: (nextActiveFlowId === DEFAULT_ACTIVE_FLOW_ID ? 'cpa' : 'kiro-rs');
|
||||||
const nextTargetId = typeof getSelectedTargetIdForState === 'function'
|
const nextTargetId = typeof getSelectedTargetIdForState === 'function'
|
||||||
? getSelectedTargetIdForState(nextStateBase, nextActiveFlowId)
|
? getSelectedTargetIdForState(nextStateBase, nextActiveFlowId)
|
||||||
: (nextActiveFlowId === DEFAULT_ACTIVE_FLOW_ID
|
: normalizeTargetIdForFlow(nextActiveFlowId, nextStateBase?.targetId || '', defaultTargetId);
|
||||||
? normalizePanelMode(nextStateBase?.panelMode || defaultTargetId)
|
|
||||||
: String(nextStateBase?.kiroTargetId || defaultTargetId).trim().toLowerCase() || defaultTargetId);
|
|
||||||
syncLatestState({
|
syncLatestState({
|
||||||
activeFlowId: nextActiveFlowId,
|
activeFlowId: nextActiveFlowId,
|
||||||
flowId: nextActiveFlowId,
|
flowId: nextActiveFlowId,
|
||||||
...(nextActiveFlowId === DEFAULT_ACTIVE_FLOW_ID
|
targetId: typeof normalizeTargetIdForFlow === 'function'
|
||||||
? { panelMode: normalizePanelMode(nextTargetId || defaultTargetId) }
|
? normalizeTargetIdForFlow(nextActiveFlowId, nextTargetId, defaultTargetId)
|
||||||
: {
|
: (String(nextTargetId || defaultTargetId).trim().toLowerCase() || defaultTargetId),
|
||||||
kiroTargetId: typeof normalizeTargetIdForFlow === 'function'
|
|
||||||
? normalizeTargetIdForFlow(nextActiveFlowId, nextTargetId, defaultTargetId)
|
|
||||||
: (String(nextTargetId || defaultTargetId).trim().toLowerCase() || defaultTargetId),
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
updatePanelModeUI();
|
updatePanelModeUI();
|
||||||
if (typeof syncStepDefinitionsFromUiState === 'function') {
|
if (typeof syncStepDefinitionsFromUiState === 'function') {
|
||||||
@@ -16320,7 +16600,7 @@ signupMethodButtons.forEach((button) => {
|
|||||||
const nextSignupMethod = normalizeSignupMethod(button.dataset.signupMethod);
|
const nextSignupMethod = normalizeSignupMethod(button.dataset.signupMethod);
|
||||||
const confirmed = await confirmCpaPhoneSignupIfNeeded({
|
const confirmed = await confirmCpaPhoneSignupIfNeeded({
|
||||||
signupMethod: nextSignupMethod,
|
signupMethod: nextSignupMethod,
|
||||||
panelMode: getSelectedPanelMode(),
|
targetId: getSelectedPanelMode(latestState),
|
||||||
});
|
});
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
updateSignupMethodUI();
|
updateSignupMethodUI();
|
||||||
@@ -17047,15 +17327,18 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|||||||
setLocalCpaStep9Mode(message.payload.localCpaStep9Mode);
|
setLocalCpaStep9Mode(message.payload.localCpaStep9Mode);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
message.payload.panelMode !== undefined
|
message.payload.targetId !== undefined
|
||||||
|| message.payload.activeFlowId !== undefined
|
|| message.payload.activeFlowId !== undefined
|
||||||
|| message.payload.flowId !== undefined
|
|| message.payload.flowId !== undefined
|
||||||
|| message.payload.kiroTargetId !== undefined
|
|
||||||
) {
|
) {
|
||||||
if (typeof syncFlowSelectorsFromState === 'function') {
|
if (typeof syncFlowSelectorsFromState === 'function') {
|
||||||
syncFlowSelectorsFromState(latestState);
|
syncFlowSelectorsFromState(latestState);
|
||||||
} else if (message.payload.panelMode !== undefined) {
|
} else if (message.payload.targetId !== undefined) {
|
||||||
selectPanelMode.value = normalizePanelMode(message.payload.panelMode || 'cpa');
|
selectPanelMode.value = normalizeTargetIdForFlow(
|
||||||
|
latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID,
|
||||||
|
message.payload.targetId || '',
|
||||||
|
getDefaultTargetIdForFlow(latestState?.activeFlowId || latestState?.flowId || DEFAULT_ACTIVE_FLOW_ID)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
updatePanelModeUI();
|
updatePanelModeUI();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const test = require('node:test');
|
|||||||
const assert = require('node:assert/strict');
|
const assert = require('node:assert/strict');
|
||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
const source = fs.readFileSync('content/signup-page.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/content/openai-auth.js', 'utf8');
|
||||||
|
|
||||||
function extractFunction(name) {
|
function extractFunction(name) {
|
||||||
const markers = [`async function ${name}(`, `function ${name}(`];
|
const markers = [`async function ${name}(`, `function ${name}(`];
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ const test = require('node:test');
|
|||||||
const assert = require('node:assert/strict');
|
const assert = require('node:assert/strict');
|
||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
const { createAuthPageRecovery } = require('../content/auth-page-recovery.js');
|
const { createAuthPageRecovery } = require('../flows/openai/content/auth-page-recovery.js');
|
||||||
const source = fs.readFileSync('content/auth-page-recovery.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/content/auth-page-recovery.js', 'utf8');
|
||||||
|
|
||||||
function extractFunction(sourceText, name) {
|
function extractFunction(sourceText, name) {
|
||||||
const start = sourceText.indexOf(`function ${name}(`);
|
const start = sourceText.indexOf(`function ${name}(`);
|
||||||
|
|||||||
@@ -311,10 +311,10 @@ async function runAutoSequenceFromStep() {
|
|||||||
10: 'completed',
|
10: 'completed',
|
||||||
}),
|
}),
|
||||||
tabRegistry: {
|
tabRegistry: {
|
||||||
'signup-page': { tabId: 88, ready: true },
|
'openai-auth': { tabId: 88, ready: true },
|
||||||
},
|
},
|
||||||
sourceLastUrls: {
|
sourceLastUrls: {
|
||||||
'signup-page': 'https://auth.openai.com/authorize',
|
'openai-auth': 'https://auth.openai.com/authorize',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ return {
|
|||||||
assert.equal(api.normalizePersistentSettingValue('signupMethod', 'unknown'), 'email');
|
assert.equal(api.normalizePersistentSettingValue('signupMethod', 'unknown'), 'email');
|
||||||
assert.equal(api.normalizePersistentSettingValue('activeFlowId', 'codex'), 'openai');
|
assert.equal(api.normalizePersistentSettingValue('activeFlowId', 'codex'), 'openai');
|
||||||
assert.equal(api.normalizePersistentSettingValue('activeFlowId', 'kiro'), 'kiro');
|
assert.equal(api.normalizePersistentSettingValue('activeFlowId', 'kiro'), 'kiro');
|
||||||
assert.equal(api.normalizePersistentSettingValue('kiroTargetId', 'unknown'), 'kiro-rs');
|
assert.equal(api.normalizePersistentSettingValue('targetId', 'sub2api'), 'sub2api');
|
||||||
assert.equal(api.normalizePersistentSettingValue('kiroRsUrl', ''), '');
|
assert.equal(api.normalizePersistentSettingValue('kiroRsUrl', ''), '');
|
||||||
assert.equal(api.normalizePersistentSettingValue('kiroRsKey', ' key-1 '), 'key-1');
|
assert.equal(api.normalizePersistentSettingValue('kiroRsKey', ' key-1 '), 'key-1');
|
||||||
assert.equal(api.normalizePersistentSettingValue('phoneSmsProvider', '5SIM'), '5sim');
|
assert.equal(api.normalizePersistentSettingValue('phoneSmsProvider', '5SIM'), '5sim');
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ const self = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const DEFAULT_STATE = { panelMode: 'cpa' };
|
const DEFAULT_STATE = { targetId: 'cpa' };
|
||||||
const CONTRIBUTION_RUNTIME_DEFAULTS = {
|
const CONTRIBUTION_RUNTIME_DEFAULTS = {
|
||||||
accountContributionEnabled: false,
|
accountContributionEnabled: false,
|
||||||
accountContributionExpected: false,
|
accountContributionExpected: false,
|
||||||
@@ -150,7 +150,7 @@ return { buildAccountContributionState };
|
|||||||
`)();
|
`)();
|
||||||
|
|
||||||
const enabledState = api.buildAccountContributionState(true, {
|
const enabledState = api.buildAccountContributionState(true, {
|
||||||
panelMode: 'sub2api',
|
targetId: 'sub2api',
|
||||||
customPassword: 'Secret123!',
|
customPassword: 'Secret123!',
|
||||||
accountRunHistoryTextEnabled: true,
|
accountRunHistoryTextEnabled: true,
|
||||||
}, {
|
}, {
|
||||||
@@ -166,12 +166,12 @@ return { buildAccountContributionState };
|
|||||||
openai: { enabled: true, adapterId: 'openai-oauth' },
|
openai: { enabled: true, adapterId: 'openai-oauth' },
|
||||||
});
|
});
|
||||||
assert.equal(enabledState.contributionSessionId, 'session-001');
|
assert.equal(enabledState.contributionSessionId, 'session-001');
|
||||||
assert.equal(enabledState.panelMode, 'sub2api');
|
assert.equal(enabledState.targetId, 'sub2api');
|
||||||
assert.equal(enabledState.customPassword, '');
|
assert.equal(enabledState.customPassword, '');
|
||||||
assert.equal(enabledState.accountRunHistoryTextEnabled, false);
|
assert.equal(enabledState.accountRunHistoryTextEnabled, false);
|
||||||
|
|
||||||
const disabledState = api.buildAccountContributionState(false, {
|
const disabledState = api.buildAccountContributionState(false, {
|
||||||
panelMode: 'sub2api',
|
targetId: 'sub2api',
|
||||||
customPassword: 'Secret123!',
|
customPassword: 'Secret123!',
|
||||||
accountRunHistoryTextEnabled: true,
|
accountRunHistoryTextEnabled: true,
|
||||||
}, {
|
}, {
|
||||||
@@ -184,17 +184,17 @@ return { buildAccountContributionState };
|
|||||||
assert.equal(disabledState.contributionAdapterId, '');
|
assert.equal(disabledState.contributionAdapterId, '');
|
||||||
assert.deepStrictEqual(disabledState.flowContributionRuntime, {});
|
assert.deepStrictEqual(disabledState.flowContributionRuntime, {});
|
||||||
assert.equal(disabledState.contributionSessionId, '');
|
assert.equal(disabledState.contributionSessionId, '');
|
||||||
assert.equal(disabledState.panelMode, 'sub2api');
|
assert.equal(disabledState.targetId, 'sub2api');
|
||||||
assert.equal(disabledState.customPassword, 'Secret123!');
|
assert.equal(disabledState.customPassword, 'Secret123!');
|
||||||
|
|
||||||
const plusContributionState = api.buildAccountContributionState(true, {
|
const plusContributionState = api.buildAccountContributionState(true, {
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
plusModeEnabled: true,
|
plusModeEnabled: true,
|
||||||
customPassword: 'Secret123!',
|
customPassword: 'Secret123!',
|
||||||
accountRunHistoryTextEnabled: true,
|
accountRunHistoryTextEnabled: true,
|
||||||
}, {});
|
}, {});
|
||||||
assert.equal(plusContributionState.contributionTargetGroupName, 'openai-plus');
|
assert.equal(plusContributionState.contributionTargetGroupName, 'openai-plus');
|
||||||
assert.equal(plusContributionState.panelMode, 'sub2api');
|
assert.equal(plusContributionState.targetId, 'sub2api');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('resetState preserves contribution runtime across reset', () => {
|
test('resetState preserves contribution runtime across reset', () => {
|
||||||
@@ -289,7 +289,7 @@ test('message router handles contribution mode, start flow, and status polling m
|
|||||||
calls.push({ type: 'toggle', enabled });
|
calls.push({ type: 'toggle', enabled });
|
||||||
return {
|
return {
|
||||||
accountContributionEnabled: Boolean(enabled),
|
accountContributionEnabled: Boolean(enabled),
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
startFlowContribution: async (options) => {
|
startFlowContribution: async (options) => {
|
||||||
@@ -383,7 +383,7 @@ test('message router blocks AUTO_RUN and SCHEDULE_AUTO_RUN when shared auto-run
|
|||||||
getPendingAutoRunTimerPlan: () => null,
|
getPendingAutoRunTimerPlan: () => null,
|
||||||
getState: async () => ({
|
getState: async () => ({
|
||||||
activeFlowId: 'site-a',
|
activeFlowId: 'site-a',
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
signupMethod: 'phone',
|
signupMethod: 'phone',
|
||||||
stepStatuses: {},
|
stepStatuses: {},
|
||||||
}),
|
}),
|
||||||
@@ -947,7 +947,7 @@ return { refreshOAuthUrlBeforeStep6 };
|
|||||||
|
|
||||||
const oauthUrl = await api.refreshOAuthUrlBeforeStep6({
|
const oauthUrl = await api.refreshOAuthUrlBeforeStep6({
|
||||||
accountContributionEnabled: false,
|
accountContributionEnabled: false,
|
||||||
panelMode: 'sub2api',
|
targetId: 'sub2api',
|
||||||
email: 'user@example.com',
|
email: 'user@example.com',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const fs = require('node:fs');
|
|||||||
const test = require('node:test');
|
const test = require('node:test');
|
||||||
|
|
||||||
function loadCpaSessionImportModule() {
|
function loadCpaSessionImportModule() {
|
||||||
const source = fs.readFileSync('background/steps/cpa-session-import.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/cpa-session-import.js', 'utf8');
|
||||||
return new Function('self', `${source}; return self.MultiPageBackgroundCpaSessionImport;`)({});
|
return new Function('self', `${source}; return self.MultiPageBackgroundCpaSessionImport;`)({});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ test('CPA session import step reads current ChatGPT session and completes node',
|
|||||||
assert.deepStrictEqual(ensureCalls[0].options.inject, [
|
assert.deepStrictEqual(ensureCalls[0].options.inject, [
|
||||||
'content/utils.js',
|
'content/utils.js',
|
||||||
'content/operation-delay.js',
|
'content/operation-delay.js',
|
||||||
'content/plus-checkout.js',
|
'flows/openai/content/plus-checkout.js',
|
||||||
]);
|
]);
|
||||||
assert.deepStrictEqual(sentMessages, [{
|
assert.deepStrictEqual(sentMessages, [{
|
||||||
tabId: 91,
|
tabId: 91,
|
||||||
|
|||||||
@@ -120,20 +120,20 @@ function isPlusModeState(state = {}) {
|
|||||||
return Boolean(state?.plusModeEnabled);
|
return Boolean(state?.plusModeEnabled);
|
||||||
}
|
}
|
||||||
function resolveCurrentFlowCapabilities(state = {}, options = {}) {
|
function resolveCurrentFlowCapabilities(state = {}, options = {}) {
|
||||||
const normalizedPanelMode = String(options.panelMode || '').trim().toLowerCase();
|
const normalizedTargetId = String(options.targetId || '').trim().toLowerCase();
|
||||||
const requestedStrategy = normalizePlusAccountAccessStrategy(state.plusAccountAccessStrategy);
|
const requestedStrategy = normalizePlusAccountAccessStrategy(state.plusAccountAccessStrategy);
|
||||||
const effectiveStrategy = normalizedPanelMode === 'sub2api'
|
const effectiveStrategy = normalizedTargetId === 'sub2api'
|
||||||
? (requestedStrategy === 'sub2api_codex_session' ? 'sub2api_codex_session' : 'oauth')
|
? (requestedStrategy === 'sub2api_codex_session' ? 'sub2api_codex_session' : 'oauth')
|
||||||
: (normalizedPanelMode === 'cpa'
|
: (normalizedTargetId === 'cpa'
|
||||||
? (requestedStrategy === 'cpa_codex_session' ? 'cpa_codex_session' : 'oauth')
|
? (requestedStrategy === 'cpa_codex_session' ? 'cpa_codex_session' : 'oauth')
|
||||||
: 'oauth');
|
: 'oauth');
|
||||||
return {
|
return {
|
||||||
effectivePanelMode: options.panelMode,
|
effectiveTargetId: options.targetId,
|
||||||
effectivePlusAccountAccessStrategy: effectiveStrategy,
|
effectivePlusAccountAccessStrategy: effectiveStrategy,
|
||||||
effectiveSignupMethod: 'email',
|
effectiveSignupMethod: 'email',
|
||||||
stepDefinitionOptions: {
|
stepDefinitionOptions: {
|
||||||
activeFlowId: 'openai',
|
activeFlowId: 'openai',
|
||||||
panelMode: options.panelMode,
|
targetId: options.targetId,
|
||||||
plusModeEnabled: Boolean(state.plusModeEnabled),
|
plusModeEnabled: Boolean(state.plusModeEnabled),
|
||||||
plusPaymentMethod: normalizePlusPaymentMethod(state.plusPaymentMethod),
|
plusPaymentMethod: normalizePlusPaymentMethod(state.plusPaymentMethod),
|
||||||
plusAccountAccessStrategy: effectiveStrategy,
|
plusAccountAccessStrategy: effectiveStrategy,
|
||||||
@@ -158,7 +158,7 @@ test('background step resolution keeps SUB2API session tail only when the effect
|
|||||||
const state = {
|
const state = {
|
||||||
activeFlowId: 'openai',
|
activeFlowId: 'openai',
|
||||||
flowId: 'openai',
|
flowId: 'openai',
|
||||||
panelMode: 'sub2api',
|
targetId: 'sub2api',
|
||||||
plusModeEnabled: true,
|
plusModeEnabled: true,
|
||||||
plusPaymentMethod: 'paypal',
|
plusPaymentMethod: 'paypal',
|
||||||
plusAccountAccessStrategy: 'sub2api_codex_session',
|
plusAccountAccessStrategy: 'sub2api_codex_session',
|
||||||
@@ -184,7 +184,7 @@ test('background step resolution keeps CPA session tail when the effective Plus
|
|||||||
const state = {
|
const state = {
|
||||||
activeFlowId: 'openai',
|
activeFlowId: 'openai',
|
||||||
flowId: 'openai',
|
flowId: 'openai',
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
plusModeEnabled: true,
|
plusModeEnabled: true,
|
||||||
plusPaymentMethod: 'paypal',
|
plusPaymentMethod: 'paypal',
|
||||||
plusAccountAccessStrategy: 'cpa_codex_session',
|
plusAccountAccessStrategy: 'cpa_codex_session',
|
||||||
@@ -210,7 +210,7 @@ test('background step resolution falls back to OAuth tail when the requested ses
|
|||||||
const state = {
|
const state = {
|
||||||
activeFlowId: 'openai',
|
activeFlowId: 'openai',
|
||||||
flowId: 'openai',
|
flowId: 'openai',
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
plusModeEnabled: true,
|
plusModeEnabled: true,
|
||||||
plusPaymentMethod: 'paypal',
|
plusPaymentMethod: 'paypal',
|
||||||
plusAccountAccessStrategy: 'sub2api_codex_session',
|
plusAccountAccessStrategy: 'sub2api_codex_session',
|
||||||
|
|||||||
@@ -3,34 +3,42 @@ const assert = require('node:assert/strict');
|
|||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
function loadDesktopAuthorizeRunnerApi() {
|
function loadDesktopAuthorizeRunnerApi() {
|
||||||
const stateSource = fs.readFileSync('background/kiro/state.js', 'utf8');
|
const stateSource = fs.readFileSync('flows/kiro/background/state.js', 'utf8');
|
||||||
const clientSource = fs.readFileSync('background/kiro/desktop-client.js', 'utf8');
|
const clientSource = fs.readFileSync('flows/kiro/background/desktop-client.js', 'utf8');
|
||||||
const runnerSource = fs.readFileSync('background/kiro/desktop-authorize-runner.js', 'utf8');
|
const runnerSource = fs.readFileSync('flows/kiro/background/desktop-authorize-runner.js', 'utf8');
|
||||||
const globalScope = {};
|
const globalScope = {};
|
||||||
new Function('self', `${stateSource}; ${clientSource}; ${runnerSource}; return self;`)(globalScope);
|
new Function('self', `${stateSource}; ${clientSource}; ${runnerSource}; return self;`)(globalScope);
|
||||||
return globalScope.MultiPageBackgroundKiroDesktopAuthorizeRunner;
|
return globalScope.MultiPageBackgroundKiroDesktopAuthorizeRunner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getKiroRuntime(state = {}) {
|
||||||
|
return state?.runtimeState?.flowState?.kiro || {};
|
||||||
|
}
|
||||||
|
|
||||||
function createDesktopAuthorizeState(overrides = {}) {
|
function createDesktopAuthorizeState(overrides = {}) {
|
||||||
return {
|
return {
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
session: {
|
flowState: {
|
||||||
desktopTabId: 91,
|
kiro: {
|
||||||
|
session: {
|
||||||
|
desktopTabId: 91,
|
||||||
|
},
|
||||||
|
register: {
|
||||||
|
email: 'kiro-user@example.com',
|
||||||
|
},
|
||||||
|
desktopAuth: {
|
||||||
|
region: 'us-east-1',
|
||||||
|
clientId: 'desktop-client-id',
|
||||||
|
clientSecret: 'desktop-client-secret',
|
||||||
|
state: 'desktop-state-001',
|
||||||
|
codeVerifier: 'desktop-code-verifier',
|
||||||
|
redirectUri: 'http://127.0.0.1:43121/oauth/callback',
|
||||||
|
redirectPort: 43121,
|
||||||
|
authorizeUrl: 'https://example.com/authorize',
|
||||||
|
},
|
||||||
|
upload: {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
register: {
|
|
||||||
email: 'kiro-user@example.com',
|
|
||||||
},
|
|
||||||
desktopAuth: {
|
|
||||||
region: 'us-east-1',
|
|
||||||
clientId: 'desktop-client-id',
|
|
||||||
clientSecret: 'desktop-client-secret',
|
|
||||||
state: 'desktop-state-001',
|
|
||||||
codeVerifier: 'desktop-code-verifier',
|
|
||||||
redirectUri: 'http://127.0.0.1:43121/oauth/callback',
|
|
||||||
redirectPort: 43121,
|
|
||||||
authorizeUrl: 'https://example.com/authorize',
|
|
||||||
},
|
|
||||||
upload: {},
|
|
||||||
},
|
},
|
||||||
...overrides,
|
...overrides,
|
||||||
};
|
};
|
||||||
@@ -73,7 +81,7 @@ test('parseDesktopCallbackUrl validates state and redirect port', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('kiro desktop authorize runner uses a shared 3-minute page-load timeout budget', () => {
|
test('kiro desktop authorize runner uses a shared 3-minute page-load timeout budget', () => {
|
||||||
const source = fs.readFileSync('background/kiro/desktop-authorize-runner.js', 'utf8');
|
const source = fs.readFileSync('flows/kiro/background/desktop-authorize-runner.js', 'utf8');
|
||||||
assert.match(source, /DEFAULT_KIRO_PAGE_LOAD_TIMEOUT_MS/);
|
assert.match(source, /DEFAULT_KIRO_PAGE_LOAD_TIMEOUT_MS/);
|
||||||
assert.match(source, /createTimeoutBudget/);
|
assert.match(source, /createTimeoutBudget/);
|
||||||
assert.match(source, /resolveTimeoutBudget/);
|
assert.match(source, /resolveTimeoutBudget/);
|
||||||
@@ -95,14 +103,14 @@ test('background wires the Kiro register injector into desktop authorization run
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('kiro desktop authorization opens account page when no web session tab is tracked', () => {
|
test('kiro desktop authorization opens account page when no web session tab is tracked', () => {
|
||||||
const source = fs.readFileSync('background/kiro/desktop-authorize-runner.js', 'utf8');
|
const source = fs.readFileSync('flows/kiro/background/desktop-authorize-runner.js', 'utf8');
|
||||||
assert.match(source, /KIRO_WEB_ACCOUNT_URL = 'https:\/\/app\.kiro\.dev\/settings\/account'/);
|
assert.match(source, /KIRO_WEB_ACCOUNT_URL = 'https:\/\/app\.kiro\.dev\/settings\/account'/);
|
||||||
assert.match(source, /chrome\.tabs\.create\(\{\s*url: KIRO_WEB_ACCOUNT_URL,\s*active: true,/);
|
assert.match(source, /chrome\.tabs\.create\(\{\s*url: KIRO_WEB_ACCOUNT_URL,\s*active: true,/);
|
||||||
assert.match(source, /未能从已打开页面确认 Kiro Web 登录态,正在打开 Kiro 账号页重新确认/);
|
assert.match(source, /未能从已打开页面确认 Kiro Web 登录态,正在打开 Kiro 账号页重新确认/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('kiro desktop authorization is gated by completed Kiro Web sign-in', () => {
|
test('kiro desktop authorization is gated by completed Kiro Web sign-in', () => {
|
||||||
const source = fs.readFileSync('background/kiro/desktop-authorize-runner.js', 'utf8');
|
const source = fs.readFileSync('flows/kiro/background/desktop-authorize-runner.js', 'utf8');
|
||||||
assert.match(source, /restoreKiroWebSessionFromOpenTabs/);
|
assert.match(source, /restoreKiroWebSessionFromOpenTabs/);
|
||||||
assert.match(source, /GET_KIRO_REGISTER_PAGE_STATE/);
|
assert.match(source, /GET_KIRO_REGISTER_PAGE_STATE/);
|
||||||
assert.match(source, /Kiro Web 登录态尚未建立/);
|
assert.match(source, /Kiro Web 登录态尚未建立/);
|
||||||
@@ -112,12 +120,16 @@ test('kiro desktop authorization is gated by completed Kiro Web sign-in', () =>
|
|||||||
test('executeKiroStartDesktopAuthorize restores existing Kiro Web session before desktop auth', async () => {
|
test('executeKiroStartDesktopAuthorize restores existing Kiro Web session before desktop auth', async () => {
|
||||||
const api = loadDesktopAuthorizeRunnerApi();
|
const api = loadDesktopAuthorizeRunnerApi();
|
||||||
let currentState = {
|
let currentState = {
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
session: {},
|
flowState: {
|
||||||
register: {},
|
kiro: {
|
||||||
webAuth: {},
|
session: {},
|
||||||
desktopAuth: {},
|
register: {},
|
||||||
upload: {},
|
webAuth: {},
|
||||||
|
desktopAuth: {},
|
||||||
|
upload: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const setStateCalls = [];
|
const setStateCalls = [];
|
||||||
@@ -178,7 +190,7 @@ test('executeKiroStartDesktopAuthorize restores existing Kiro Web session before
|
|||||||
getState: async () => currentState,
|
getState: async () => currentState,
|
||||||
getTabId: async () => null,
|
getTabId: async () => null,
|
||||||
isTabAlive: async () => false,
|
isTabAlive: async () => false,
|
||||||
KIRO_REGISTER_INJECT_FILES: ['content/kiro/register-page.js'],
|
KIRO_REGISTER_INJECT_FILES: ['flows/kiro/content/register-page.js'],
|
||||||
registerTab: async (source, tabId) => {
|
registerTab: async (source, tabId) => {
|
||||||
if (source === 'kiro-desktop-authorize') {
|
if (source === 'kiro-desktop-authorize') {
|
||||||
desktopRegisteredTabId = tabId;
|
desktopRegisteredTabId = tabId;
|
||||||
@@ -213,10 +225,10 @@ test('executeKiroStartDesktopAuthorize restores existing Kiro Web session before
|
|||||||
assert.equal(desktopRegisteredTabId, 88);
|
assert.equal(desktopRegisteredTabId, 88);
|
||||||
assert.match(openedAuthorizeUrl, /client_id=restored-client-id/);
|
assert.match(openedAuthorizeUrl, /client_id=restored-client-id/);
|
||||||
assert.equal(currentState.email, 'restored@duck.com');
|
assert.equal(currentState.email, 'restored@duck.com');
|
||||||
assert.equal(currentState.kiroRuntime.register.email, 'restored@duck.com');
|
assert.equal(getKiroRuntime(currentState).register.email, 'restored@duck.com');
|
||||||
assert.equal(currentState.kiroRuntime.register.status, 'completed');
|
assert.equal(getKiroRuntime(currentState).register.status, 'completed');
|
||||||
assert.equal(currentState.kiroRuntime.webAuth.status, 'signed_in');
|
assert.equal(getKiroRuntime(currentState).webAuth.status, 'signed_in');
|
||||||
assert.equal(completedPayload?.kiroRuntime?.desktopAuth?.clientId, 'restored-client-id');
|
assert.equal(getKiroRuntime(completedPayload).desktopAuth?.clientId, 'restored-client-id');
|
||||||
assert.equal(
|
assert.equal(
|
||||||
logs.some(({ message }) => message.includes('检测到已有 Kiro Web 登录态,已恢复账号 restored@duck.com')),
|
logs.some(({ message }) => message.includes('检测到已有 Kiro Web 登录态,已恢复账号 restored@duck.com')),
|
||||||
true
|
true
|
||||||
@@ -227,12 +239,16 @@ test('executeKiroStartDesktopAuthorize restores existing Kiro Web session before
|
|||||||
test('executeKiroStartDesktopAuthorize opens Kiro account page to restore login state', async () => {
|
test('executeKiroStartDesktopAuthorize opens Kiro account page to restore login state', async () => {
|
||||||
const api = loadDesktopAuthorizeRunnerApi();
|
const api = loadDesktopAuthorizeRunnerApi();
|
||||||
let currentState = {
|
let currentState = {
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
session: {},
|
flowState: {
|
||||||
register: {},
|
kiro: {
|
||||||
webAuth: {},
|
session: {},
|
||||||
desktopAuth: {},
|
register: {},
|
||||||
upload: {},
|
webAuth: {},
|
||||||
|
desktopAuth: {},
|
||||||
|
upload: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const logs = [];
|
const logs = [];
|
||||||
@@ -278,7 +294,7 @@ test('executeKiroStartDesktopAuthorize opens Kiro account page to restore login
|
|||||||
ensureContentScriptReadyOnTab: async (source, tabId, options = {}) => {
|
ensureContentScriptReadyOnTab: async (source, tabId, options = {}) => {
|
||||||
assert.equal(source, 'kiro-register-page');
|
assert.equal(source, 'kiro-register-page');
|
||||||
assert.equal(tabId, 91);
|
assert.equal(tabId, 91);
|
||||||
assert.deepEqual(options.inject, ['content/kiro/register-page.js']);
|
assert.deepEqual(options.inject, ['flows/kiro/content/register-page.js']);
|
||||||
assert.equal(options.injectSource, 'kiro-register-page');
|
assert.equal(options.injectSource, 'kiro-register-page');
|
||||||
},
|
},
|
||||||
fetchImpl: async () => ({
|
fetchImpl: async () => ({
|
||||||
@@ -291,7 +307,7 @@ test('executeKiroStartDesktopAuthorize opens Kiro account page to restore login
|
|||||||
getState: async () => currentState,
|
getState: async () => currentState,
|
||||||
getTabId: async () => null,
|
getTabId: async () => null,
|
||||||
isTabAlive: async () => false,
|
isTabAlive: async () => false,
|
||||||
KIRO_REGISTER_INJECT_FILES: ['content/kiro/register-page.js'],
|
KIRO_REGISTER_INJECT_FILES: ['flows/kiro/content/register-page.js'],
|
||||||
registerTab: async (source, tabId) => {
|
registerTab: async (source, tabId) => {
|
||||||
registeredTabs.push({ source, tabId });
|
registeredTabs.push({ source, tabId });
|
||||||
},
|
},
|
||||||
@@ -320,8 +336,8 @@ test('executeKiroStartDesktopAuthorize opens Kiro account page to restore login
|
|||||||
await runner.executeKiroStartDesktopAuthorize(currentState);
|
await runner.executeKiroStartDesktopAuthorize(currentState);
|
||||||
|
|
||||||
assert.equal(createdTabUrl, 'https://app.kiro.dev/settings/account');
|
assert.equal(createdTabUrl, 'https://app.kiro.dev/settings/account');
|
||||||
assert.equal(currentState.kiroRuntime.register.email, 'opened@duck.com');
|
assert.equal(getKiroRuntime(currentState).register.email, 'opened@duck.com');
|
||||||
assert.equal(completedPayload?.kiroRuntime?.desktopAuth?.clientId, 'opened-client-id');
|
assert.equal(getKiroRuntime(completedPayload).desktopAuth?.clientId, 'opened-client-id');
|
||||||
assert.deepEqual(registeredTabs, [
|
assert.deepEqual(registeredTabs, [
|
||||||
{ source: 'kiro-register-page', tabId: 91 },
|
{ source: 'kiro-register-page', tabId: 91 },
|
||||||
{ source: 'kiro-desktop-authorize', tabId: 92 },
|
{ source: 'kiro-desktop-authorize', tabId: 92 },
|
||||||
@@ -391,31 +407,35 @@ test('executeKiroCompleteDesktopAuthorize finishes from callback page without wa
|
|||||||
|
|
||||||
await runner.executeKiroCompleteDesktopAuthorize(currentState);
|
await runner.executeKiroCompleteDesktopAuthorize(currentState);
|
||||||
|
|
||||||
assert.equal(completedPayload?.kiroRuntime?.desktopAuth?.authorizationCode, 'auth-code-001');
|
assert.equal(getKiroRuntime(completedPayload).desktopAuth?.authorizationCode, 'auth-code-001');
|
||||||
assert.equal(completedPayload?.kiroRuntime?.desktopAuth?.refreshToken, 'refresh-token-001');
|
assert.equal(getKiroRuntime(completedPayload).desktopAuth?.refreshToken, 'refresh-token-001');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('executeKiroCompleteDesktopAuthorize waits for callback after consent even if original tab disappears', async () => {
|
test('executeKiroCompleteDesktopAuthorize waits for callback after consent even if original tab disappears', async () => {
|
||||||
const api = loadDesktopAuthorizeRunnerApi();
|
const api = loadDesktopAuthorizeRunnerApi();
|
||||||
let currentState = createDesktopAuthorizeState({
|
let currentState = createDesktopAuthorizeState({
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
session: {
|
flowState: {
|
||||||
desktopTabId: 91,
|
kiro: {
|
||||||
|
session: {
|
||||||
|
desktopTabId: 91,
|
||||||
|
},
|
||||||
|
register: {
|
||||||
|
email: 'kiro-user@example.com',
|
||||||
|
},
|
||||||
|
desktopAuth: {
|
||||||
|
region: 'us-east-1',
|
||||||
|
clientId: 'desktop-client-id',
|
||||||
|
clientSecret: 'desktop-client-secret',
|
||||||
|
state: 'desktop-state-002',
|
||||||
|
codeVerifier: 'desktop-code-verifier',
|
||||||
|
redirectUri: 'http://127.0.0.1:43121/oauth/callback',
|
||||||
|
redirectPort: 43121,
|
||||||
|
authorizeUrl: 'https://example.com/authorize',
|
||||||
|
},
|
||||||
|
upload: {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
register: {
|
|
||||||
email: 'kiro-user@example.com',
|
|
||||||
},
|
|
||||||
desktopAuth: {
|
|
||||||
region: 'us-east-1',
|
|
||||||
clientId: 'desktop-client-id',
|
|
||||||
clientSecret: 'desktop-client-secret',
|
|
||||||
state: 'desktop-state-002',
|
|
||||||
codeVerifier: 'desktop-code-verifier',
|
|
||||||
redirectUri: 'http://127.0.0.1:43121/oauth/callback',
|
|
||||||
redirectPort: 43121,
|
|
||||||
authorizeUrl: 'https://example.com/authorize',
|
|
||||||
},
|
|
||||||
upload: {},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
let completedPayload = null;
|
let completedPayload = null;
|
||||||
@@ -505,6 +525,6 @@ test('executeKiroCompleteDesktopAuthorize waits for callback after consent even
|
|||||||
|
|
||||||
await runner.executeKiroCompleteDesktopAuthorize(currentState);
|
await runner.executeKiroCompleteDesktopAuthorize(currentState);
|
||||||
|
|
||||||
assert.equal(completedPayload?.kiroRuntime?.desktopAuth?.authorizationCode, 'auth-code-002');
|
assert.equal(getKiroRuntime(completedPayload).desktopAuth?.authorizationCode, 'auth-code-002');
|
||||||
assert.equal(completedPayload?.kiroRuntime?.desktopAuth?.refreshToken, 'refresh-token-002');
|
assert.equal(getKiroRuntime(completedPayload).desktopAuth?.refreshToken, 'refresh-token-002');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ const assert = require('node:assert/strict');
|
|||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
function loadPublisherApi() {
|
function loadPublisherApi() {
|
||||||
const stateSource = fs.readFileSync('background/kiro/state.js', 'utf8');
|
const stateSource = fs.readFileSync('flows/kiro/background/state.js', 'utf8');
|
||||||
const publisherSource = fs.readFileSync('background/kiro/publisher-kiro-rs.js', 'utf8');
|
const publisherSource = fs.readFileSync('flows/kiro/background/publisher-kiro-rs.js', 'utf8');
|
||||||
const globalScope = {};
|
const globalScope = {};
|
||||||
new Function('self', `${stateSource}; ${publisherSource}; return self;`)(globalScope);
|
new Function('self', `${stateSource}; ${publisherSource}; return self;`)(globalScope);
|
||||||
return globalScope.MultiPageBackgroundKiroPublisherKiroRs;
|
return globalScope.MultiPageBackgroundKiroPublisherKiroRs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getKiroRuntime(state = {}) {
|
||||||
|
return state?.runtimeState?.flowState?.kiro || {};
|
||||||
|
}
|
||||||
|
|
||||||
test('kiro publisher exposes a factory and upload payload helpers', () => {
|
test('kiro publisher exposes a factory and upload payload helpers', () => {
|
||||||
const api = loadPublisherApi();
|
const api = loadPublisherApi();
|
||||||
assert.equal(typeof api?.createKiroRsPublisher, 'function');
|
assert.equal(typeof api?.createKiroRsPublisher, 'function');
|
||||||
@@ -20,7 +24,7 @@ test('kiro publisher exposes a factory and upload payload helpers', () => {
|
|||||||
test('kiro publisher builds kiro.rs payload from desktop auth runtime with BuilderId profileArn', async () => {
|
test('kiro publisher builds kiro.rs payload from desktop auth runtime with BuilderId profileArn', async () => {
|
||||||
const api = loadPublisherApi();
|
const api = loadPublisherApi();
|
||||||
const payload = api.buildKiroRsPayload({
|
const payload = api.buildKiroRsPayload({
|
||||||
kiroTargetId: 'kiro-rs',
|
targetId: 'kiro-rs',
|
||||||
kiroRsUrl: 'https://kiro.example.com/admin',
|
kiroRsUrl: 'https://kiro.example.com/admin',
|
||||||
kiroRsKey: 'demo-key',
|
kiroRsKey: 'demo-key',
|
||||||
ipProxyEnabled: true,
|
ipProxyEnabled: true,
|
||||||
@@ -29,18 +33,22 @@ test('kiro publisher builds kiro.rs payload from desktop auth runtime with Build
|
|||||||
ipProxyProtocol: 'http',
|
ipProxyProtocol: 'http',
|
||||||
ipProxyUsername: 'proxy-user',
|
ipProxyUsername: 'proxy-user',
|
||||||
ipProxyPassword: 'proxy-pass',
|
ipProxyPassword: 'proxy-pass',
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
register: {
|
flowState: {
|
||||||
email: 'aws-user@example.com',
|
kiro: {
|
||||||
},
|
register: {
|
||||||
desktopAuth: {
|
email: 'aws-user@example.com',
|
||||||
region: 'us-east-1',
|
},
|
||||||
clientId: 'client-001',
|
desktopAuth: {
|
||||||
clientSecret: 'secret-001',
|
region: 'us-east-1',
|
||||||
refreshToken: 'refresh-token-001',
|
clientId: 'client-001',
|
||||||
},
|
clientSecret: 'secret-001',
|
||||||
upload: {
|
refreshToken: 'refresh-token-001',
|
||||||
targetId: 'kiro-rs',
|
},
|
||||||
|
upload: {
|
||||||
|
targetId: 'kiro-rs',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -69,22 +77,26 @@ test('kiro publisher reads latest kiro.rs key from background state instead of s
|
|||||||
const api = loadPublisherApi();
|
const api = loadPublisherApi();
|
||||||
const requests = [];
|
const requests = [];
|
||||||
let liveState = {
|
let liveState = {
|
||||||
kiroTargetId: 'kiro-rs',
|
targetId: 'kiro-rs',
|
||||||
kiroRsUrl: 'https://kiro.example.com/admin',
|
kiroRsUrl: 'https://kiro.example.com/admin',
|
||||||
kiroRsKey: 'live-key',
|
kiroRsKey: 'live-key',
|
||||||
email: 'aws-user@example.com',
|
email: 'aws-user@example.com',
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
register: {
|
flowState: {
|
||||||
email: 'aws-user@example.com',
|
kiro: {
|
||||||
},
|
register: {
|
||||||
desktopAuth: {
|
email: 'aws-user@example.com',
|
||||||
region: 'us-east-1',
|
},
|
||||||
clientId: 'client-001',
|
desktopAuth: {
|
||||||
clientSecret: 'secret-001',
|
region: 'us-east-1',
|
||||||
refreshToken: 'refresh-token-001',
|
clientId: 'client-001',
|
||||||
},
|
clientSecret: 'secret-001',
|
||||||
upload: {
|
refreshToken: 'refresh-token-001',
|
||||||
targetId: 'kiro-rs',
|
},
|
||||||
|
upload: {
|
||||||
|
targetId: 'kiro-rs',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
settingsState: {
|
settingsState: {
|
||||||
@@ -180,19 +192,23 @@ test('kiro publisher routes step 9 through public contribution upload when contr
|
|||||||
flowId: 'kiro',
|
flowId: 'kiro',
|
||||||
accountContributionEnabled: true,
|
accountContributionEnabled: true,
|
||||||
contributionAdapterId: 'kiro-builder-id',
|
contributionAdapterId: 'kiro-builder-id',
|
||||||
kiroTargetId: 'kiro-rs',
|
targetId: 'kiro-rs',
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
register: {
|
flowState: {
|
||||||
email: 'aws-user@example.com',
|
kiro: {
|
||||||
},
|
register: {
|
||||||
desktopAuth: {
|
email: 'aws-user@example.com',
|
||||||
region: 'us-east-1',
|
},
|
||||||
clientId: 'client-001',
|
desktopAuth: {
|
||||||
clientSecret: 'secret-001',
|
region: 'us-east-1',
|
||||||
refreshToken: 'refresh-token-001',
|
clientId: 'client-001',
|
||||||
},
|
clientSecret: 'secret-001',
|
||||||
upload: {
|
refreshToken: 'refresh-token-001',
|
||||||
targetId: 'kiro-rs',
|
},
|
||||||
|
upload: {
|
||||||
|
targetId: 'kiro-rs',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -224,10 +240,10 @@ test('kiro publisher routes step 9 through public contribution upload when contr
|
|||||||
assert.equal(requests.length, 0);
|
assert.equal(requests.length, 0);
|
||||||
assert.equal(completed.length, 1);
|
assert.equal(completed.length, 1);
|
||||||
assert.equal(completed[0].nodeId, 'kiro-upload-credential');
|
assert.equal(completed[0].nodeId, 'kiro-upload-credential');
|
||||||
assert.equal(completed[0].payload.kiroRuntime.upload.targetId, 'contribution');
|
assert.equal(getKiroRuntime(completed[0].payload).upload.targetId, 'contribution');
|
||||||
assert.equal(completed[0].payload.kiroRuntime.upload.status, 'uploaded');
|
assert.equal(getKiroRuntime(completed[0].payload).upload.status, 'uploaded');
|
||||||
assert.equal(completed[0].payload.kiroRuntime.upload.credentialId, 'kiro-contribution-009');
|
assert.equal(getKiroRuntime(completed[0].payload).upload.credentialId, 'kiro-contribution-009');
|
||||||
assert.equal(completed[0].payload.kiroRuntime.upload.lastMessage, '贡献链路成功:kiro-step-9');
|
assert.equal(getKiroRuntime(completed[0].payload).upload.lastMessage, '贡献链路成功:kiro-step-9');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('kiro publisher trims api key and includes fallback Authorization header during connection check', async () => {
|
test('kiro publisher trims api key and includes fallback Authorization header during connection check', async () => {
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ const assert = require('node:assert/strict');
|
|||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
function loadRegisterRunnerApi() {
|
function loadRegisterRunnerApi() {
|
||||||
const stateSource = fs.readFileSync('background/kiro/state.js', 'utf8');
|
const stateSource = fs.readFileSync('flows/kiro/background/state.js', 'utf8');
|
||||||
const runnerSource = fs.readFileSync('background/kiro/register-runner.js', 'utf8');
|
const runnerSource = fs.readFileSync('flows/kiro/background/register-runner.js', 'utf8');
|
||||||
const globalScope = {};
|
const globalScope = {};
|
||||||
new Function('self', `${stateSource}; ${runnerSource}; return self;`)(globalScope);
|
new Function('self', `${stateSource}; ${runnerSource}; return self;`)(globalScope);
|
||||||
return globalScope.MultiPageBackgroundKiroRegisterRunner;
|
return globalScope.MultiPageBackgroundKiroRegisterRunner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getKiroRuntime(state = {}) {
|
||||||
|
return state?.runtimeState?.flowState?.kiro || {};
|
||||||
|
}
|
||||||
|
|
||||||
test('kiro register runner module exposes a factory and Kiro official sign-in entry', () => {
|
test('kiro register runner module exposes a factory and Kiro official sign-in entry', () => {
|
||||||
const api = loadRegisterRunnerApi();
|
const api = loadRegisterRunnerApi();
|
||||||
assert.equal(typeof api?.createKiroRegisterRunner, 'function');
|
assert.equal(typeof api?.createKiroRegisterRunner, 'function');
|
||||||
@@ -17,7 +21,7 @@ test('kiro register runner module exposes a factory and Kiro official sign-in en
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('kiro register runner removed the old AWS device authorization bootstrap', () => {
|
test('kiro register runner removed the old AWS device authorization bootstrap', () => {
|
||||||
const source = fs.readFileSync('background/kiro/register-runner.js', 'utf8');
|
const source = fs.readFileSync('flows/kiro/background/register-runner.js', 'utf8');
|
||||||
assert.doesNotMatch(source, /startBuilderIdDeviceLogin/);
|
assert.doesNotMatch(source, /startBuilderIdDeviceLogin/);
|
||||||
assert.doesNotMatch(source, /device_authorization/);
|
assert.doesNotMatch(source, /device_authorization/);
|
||||||
assert.doesNotMatch(source, /verificationUriComplete/);
|
assert.doesNotMatch(source, /verificationUriComplete/);
|
||||||
@@ -25,7 +29,7 @@ test('kiro register runner removed the old AWS device authorization bootstrap',
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('kiro register runner uses a shared 3-minute page-load timeout budget', () => {
|
test('kiro register runner uses a shared 3-minute page-load timeout budget', () => {
|
||||||
const source = fs.readFileSync('background/kiro/register-runner.js', 'utf8');
|
const source = fs.readFileSync('flows/kiro/background/register-runner.js', 'utf8');
|
||||||
assert.match(source, /DEFAULT_KIRO_PAGE_LOAD_TIMEOUT_MS/);
|
assert.match(source, /DEFAULT_KIRO_PAGE_LOAD_TIMEOUT_MS/);
|
||||||
assert.match(source, /createTimeoutBudget/);
|
assert.match(source, /createTimeoutBudget/);
|
||||||
assert.match(source, /resolveTimeoutBudget/);
|
assert.match(source, /resolveTimeoutBudget/);
|
||||||
@@ -34,7 +38,7 @@ test('kiro register runner uses a shared 3-minute page-load timeout budget', ()
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('kiro register consent step treats Kiro Web signed-in page as completion', () => {
|
test('kiro register consent step treats Kiro Web signed-in page as completion', () => {
|
||||||
const source = fs.readFileSync('background/kiro/register-runner.js', 'utf8');
|
const source = fs.readFileSync('flows/kiro/background/register-runner.js', 'utf8');
|
||||||
assert.match(source, /readKiroRegisterPageState\(tabId, \{/);
|
assert.match(source, /readKiroRegisterPageState\(tabId, \{/);
|
||||||
assert.match(source, /\['authorization_page', 'success_page', 'kiro_web_signed_in'\]\.includes\(landingResult\?\.state\)/);
|
assert.match(source, /\['authorization_page', 'success_page', 'kiro_web_signed_in'\]\.includes\(landingResult\?\.state\)/);
|
||||||
assert.match(source, /landingResult\?\.state === 'authorization_page'/);
|
assert.match(source, /landingResult\?\.state === 'authorization_page'/);
|
||||||
@@ -42,7 +46,7 @@ test('kiro register consent step treats Kiro Web signed-in page as completion',
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('kiro register runner uses registration-only page states instead of shared OpenAI names', () => {
|
test('kiro register runner uses registration-only page states instead of shared OpenAI names', () => {
|
||||||
const source = fs.readFileSync('background/kiro/register-runner.js', 'utf8');
|
const source = fs.readFileSync('flows/kiro/background/register-runner.js', 'utf8');
|
||||||
assert.match(source, /KIRO_REGISTER_PAGE_STATES/);
|
assert.match(source, /KIRO_REGISTER_PAGE_STATES/);
|
||||||
assert.match(source, /'register_otp_page'/);
|
assert.match(source, /'register_otp_page'/);
|
||||||
assert.match(source, /'create_password_page'/);
|
assert.match(source, /'create_password_page'/);
|
||||||
@@ -54,7 +58,7 @@ test('kiro register runner uses registration-only page states instead of shared
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('kiro register runner fails existing-account login branches during registration', () => {
|
test('kiro register runner fails existing-account login branches during registration', () => {
|
||||||
const source = fs.readFileSync('background/kiro/register-runner.js', 'utf8');
|
const source = fs.readFileSync('flows/kiro/background/register-runner.js', 'utf8');
|
||||||
assert.match(source, /KIRO_REGISTER_EXISTING_ACCOUNT_STATES/);
|
assert.match(source, /KIRO_REGISTER_EXISTING_ACCOUNT_STATES/);
|
||||||
assert.match(source, /assertKiroRegistrationOnlyState\(landingResult, currentState, 2, resolvedEmail\)/);
|
assert.match(source, /assertKiroRegistrationOnlyState\(landingResult, currentState, 2, resolvedEmail\)/);
|
||||||
assert.match(source, /邮箱.*已进入 AWS Builder ID 登录页/);
|
assert.match(source, /邮箱.*已进入 AWS Builder ID 登录页/);
|
||||||
@@ -64,12 +68,16 @@ test('kiro register runner fails existing-account login branches during registra
|
|||||||
test('kiro submit-email stops immediately when AWS routes the email to login', async () => {
|
test('kiro submit-email stops immediately when AWS routes the email to login', async () => {
|
||||||
const api = loadRegisterRunnerApi();
|
const api = loadRegisterRunnerApi();
|
||||||
const currentState = {
|
const currentState = {
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
session: {
|
flowState: {
|
||||||
registerTabId: 101,
|
kiro: {
|
||||||
},
|
session: {
|
||||||
register: {
|
registerTabId: 101,
|
||||||
loginUrl: 'https://app.kiro.dev/signin',
|
},
|
||||||
|
register: {
|
||||||
|
loginUrl: 'https://app.kiro.dev/signin',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -119,18 +127,22 @@ test('kiro submit-email stops immediately when AWS routes the email to login', a
|
|||||||
|
|
||||||
assert.equal(completed, false);
|
assert.equal(completed, false);
|
||||||
assert.equal(sentMessages.some((message) => message.type === 'EXECUTE_NODE'), true);
|
assert.equal(sentMessages.some((message) => message.type === 'EXECUTE_NODE'), true);
|
||||||
assert.equal(statePatches.some((patch) => /已进入 AWS Builder ID 登录页/.test(patch.kiroRuntime?.session?.lastError || '')), true);
|
assert.equal(statePatches.some((patch) => /已进入 AWS Builder ID 登录页/.test(getKiroRuntime(patch).session?.lastError || '')), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('kiro submit-email can adopt an already-open registration OTP page without allocating a new mailbox', async () => {
|
test('kiro submit-email can adopt an already-open registration OTP page without allocating a new mailbox', async () => {
|
||||||
const api = loadRegisterRunnerApi();
|
const api = loadRegisterRunnerApi();
|
||||||
const currentState = {
|
const currentState = {
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
session: {
|
flowState: {
|
||||||
registerTabId: 102,
|
kiro: {
|
||||||
},
|
session: {
|
||||||
register: {
|
registerTabId: 102,
|
||||||
loginUrl: 'https://app.kiro.dev/signin',
|
},
|
||||||
|
register: {
|
||||||
|
loginUrl: 'https://app.kiro.dev/signin',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -163,8 +175,8 @@ test('kiro submit-email can adopt an already-open registration OTP page without
|
|||||||
|
|
||||||
await runner.executeKiroSubmitEmail({ nodeId: 'kiro-submit-email', ...currentState });
|
await runner.executeKiroSubmitEmail({ nodeId: 'kiro-submit-email', ...currentState });
|
||||||
|
|
||||||
assert.equal(completedPayload?.kiroRuntime?.register?.email, 'manual-user@duck.com');
|
assert.equal(getKiroRuntime(completedPayload).register?.email, 'manual-user@duck.com');
|
||||||
assert.equal(completedPayload?.kiroRuntime?.register?.status, 'waiting_otp');
|
assert.equal(getKiroRuntime(completedPayload).register?.status, 'waiting_otp');
|
||||||
assert.equal(completedPayload?.kiroRuntime?.register?.verificationRequestedAt, 0);
|
assert.equal(getKiroRuntime(completedPayload).register?.verificationRequestedAt, 0);
|
||||||
assert.equal(sentMessages.some((message) => message.type === 'EXECUTE_NODE'), false);
|
assert.equal(sentMessages.some((message) => message.type === 'EXECUTE_NODE'), false);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,109 +3,128 @@ const assert = require('node:assert/strict');
|
|||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
function loadKiroStateApi() {
|
function loadKiroStateApi() {
|
||||||
const source = fs.readFileSync('background/kiro/state.js', 'utf8');
|
const source = fs.readFileSync('flows/kiro/background/state.js', 'utf8');
|
||||||
const globalScope = {};
|
const globalScope = {};
|
||||||
return new Function('self', `${source}; return self.MultiPageBackgroundKiroState;`)(globalScope);
|
return new Function('self', `${source}; return self.MultiPageBackgroundKiroState;`)(globalScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
test('background imports kiro state module and routes Kiro runtime through dedicated helpers', () => {
|
function getKiroRuntime(state = {}) {
|
||||||
|
return state?.runtimeState?.flowState?.kiro || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('background imports kiro state module for Kiro runtime projection and reset helpers', () => {
|
||||||
const source = fs.readFileSync('background.js', 'utf8');
|
const source = fs.readFileSync('background.js', 'utf8');
|
||||||
assert.match(source, /background\/kiro\/state\.js/);
|
assert.match(source, /flows\/kiro\/background\/state\.js/);
|
||||||
assert.match(source, /const kiroStateHelpers = self\.MultiPageBackgroundKiroState/);
|
assert.match(source, /const kiroStateHelpers = self\.MultiPageBackgroundKiroState/);
|
||||||
assert.match(source, /kiroStateHelpers\?\.buildStateView/);
|
assert.match(source, /kiroStateHelpers\?\.buildStateView/);
|
||||||
assert.match(source, /kiroStateHelpers\?\.buildSessionStatePatch/);
|
|
||||||
assert.match(source, /kiroStateHelpers\?\.buildDownstreamResetPatch/);
|
assert.match(source, /kiroStateHelpers\?\.buildDownstreamResetPatch/);
|
||||||
assert.match(source, /kiroStateHelpers\?\.applyNodeCompletionPayload/);
|
assert.match(source, /kiroStateHelpers\?\.applyNodeCompletionPayload/);
|
||||||
|
assert.doesNotMatch(source, /migrateLegacyKiroRuntimeState/);
|
||||||
|
assert.equal(/kiroStateHelpers\?\.buildSessionStatePatch/.test(source), false);
|
||||||
|
assert.equal(/kiroRuntime:\s*kiroStateHelpers\?\.buildDefaultRuntimeState/.test(source), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('kiro state module exposes canonical nested kiroRuntime view', () => {
|
test('kiro state module exposes canonical nested runtimeState view', () => {
|
||||||
const api = loadKiroStateApi();
|
const api = loadKiroStateApi();
|
||||||
const view = api.buildStateView({
|
const runtimeState = api.buildRuntimeStatePatch({}, {
|
||||||
kiroTargetId: 'kiro-rs',
|
session: {
|
||||||
kiroRuntime: {
|
currentStage: 'desktop-authorize',
|
||||||
session: {
|
registerTabId: 88,
|
||||||
currentStage: 'desktop-authorize',
|
pageState: 'name_entry',
|
||||||
registerTabId: 88,
|
pageUrl: 'https://view.awsapps.com/start',
|
||||||
pageState: 'name_entry',
|
|
||||||
pageUrl: 'https://view.awsapps.com/start',
|
|
||||||
},
|
|
||||||
register: {
|
|
||||||
email: 'aws-user@example.com',
|
|
||||||
fullName: 'Ada Lovelace',
|
|
||||||
loginUrl: 'https://app.kiro.dev/signin',
|
|
||||||
status: 'waiting_name',
|
|
||||||
},
|
|
||||||
webAuth: {
|
|
||||||
status: 'signin_started',
|
|
||||||
hasAccessToken: false,
|
|
||||||
hasSessionToken: false,
|
|
||||||
},
|
|
||||||
desktopAuth: {
|
|
||||||
clientId: 'client-001',
|
|
||||||
clientSecret: 'secret-001',
|
|
||||||
refreshToken: 'refresh-001',
|
|
||||||
status: 'authorized',
|
|
||||||
},
|
|
||||||
upload: {
|
|
||||||
targetId: 'kiro-rs',
|
|
||||||
status: 'ready_to_upload',
|
|
||||||
credentialId: 321,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
register: {
|
||||||
|
email: 'aws-user@example.com',
|
||||||
|
fullName: 'Ada Lovelace',
|
||||||
|
loginUrl: 'https://app.kiro.dev/signin',
|
||||||
|
status: 'waiting_name',
|
||||||
|
},
|
||||||
|
webAuth: {
|
||||||
|
status: 'signin_started',
|
||||||
|
hasAccessToken: false,
|
||||||
|
hasSessionToken: false,
|
||||||
|
},
|
||||||
|
desktopAuth: {
|
||||||
|
clientId: 'client-001',
|
||||||
|
clientSecret: 'secret-001',
|
||||||
|
refreshToken: 'refresh-001',
|
||||||
|
status: 'authorized',
|
||||||
|
},
|
||||||
|
upload: {
|
||||||
|
targetId: 'kiro-rs',
|
||||||
|
status: 'ready_to_upload',
|
||||||
|
credentialId: 321,
|
||||||
|
},
|
||||||
|
}).runtimeState;
|
||||||
|
const view = api.buildStateView({
|
||||||
|
targetId: 'kiro-rs',
|
||||||
|
runtimeState,
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.equal(view.kiroTargetId, 'kiro-rs');
|
assert.equal(view.targetId, 'kiro-rs');
|
||||||
assert.equal(view.kiroRuntime.session.currentStage, 'desktop-authorize');
|
assert.equal(Object.prototype.hasOwnProperty.call(view, 'kiroRuntime'), false);
|
||||||
assert.equal(view.kiroRuntime.session.registerTabId, 88);
|
assert.equal(getKiroRuntime(view).session.currentStage, 'desktop-authorize');
|
||||||
assert.equal(view.kiroRuntime.register.email, 'aws-user@example.com');
|
assert.equal(getKiroRuntime(view).session.registerTabId, 88);
|
||||||
assert.equal(view.kiroRuntime.register.loginUrl, 'https://app.kiro.dev/signin');
|
assert.equal(getKiroRuntime(view).register.email, 'aws-user@example.com');
|
||||||
assert.equal(view.kiroRuntime.webAuth.status, 'signin_started');
|
assert.equal(getKiroRuntime(view).register.loginUrl, 'https://app.kiro.dev/signin');
|
||||||
assert.equal(view.kiroRuntime.desktopAuth.clientId, 'client-001');
|
assert.equal(getKiroRuntime(view).webAuth.status, 'signin_started');
|
||||||
assert.equal(view.kiroRuntime.desktopAuth.refreshToken, 'refresh-001');
|
assert.equal(getKiroRuntime(view).desktopAuth.clientId, 'client-001');
|
||||||
assert.equal(view.kiroRuntime.upload.status, 'ready_to_upload');
|
assert.equal(getKiroRuntime(view).desktopAuth.refreshToken, 'refresh-001');
|
||||||
assert.equal(view.kiroRuntime.upload.credentialId, 321);
|
assert.equal(getKiroRuntime(view).upload.status, 'ready_to_upload');
|
||||||
|
assert.equal(getKiroRuntime(view).upload.credentialId, 321);
|
||||||
|
assert.equal(view.runtimeState.flowState.kiro.session.currentStage, 'desktop-authorize');
|
||||||
|
assert.equal(view.runtimeState.flowState.kiro.register.email, 'aws-user@example.com');
|
||||||
|
assert.equal(view.runtimeState.flowState.kiro.upload.credentialId, 321);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('kiro state session patch accepts canonical nested runtime updates', () => {
|
test('kiro state session patch accepts canonical nested runtime updates', () => {
|
||||||
const api = loadKiroStateApi();
|
const api = loadKiroStateApi();
|
||||||
const patch = api.buildSessionStatePatch({
|
const patch = api.buildSessionStatePatch({
|
||||||
kiroRuntime: api.buildDefaultRuntimeState(),
|
runtimeState: api.buildRuntimeStatePatch({}, api.buildDefaultRuntimeState()).runtimeState,
|
||||||
}, {
|
}, {
|
||||||
kiroRuntime: {
|
runtimeState: {
|
||||||
session: {
|
flowState: {
|
||||||
currentStage: 'register',
|
kiro: {
|
||||||
pageState: 'register_otp_page',
|
session: {
|
||||||
pageUrl: 'https://signin.aws/register',
|
currentStage: 'register',
|
||||||
},
|
pageState: 'register_otp_page',
|
||||||
register: {
|
pageUrl: 'https://signin.aws/register',
|
||||||
email: 'aws-user@example.com',
|
},
|
||||||
fullName: 'Ada Lovelace',
|
register: {
|
||||||
verificationRequestedAt: 1700000000000,
|
email: 'aws-user@example.com',
|
||||||
},
|
fullName: 'Ada Lovelace',
|
||||||
desktopAuth: {
|
verificationRequestedAt: 1700000000000,
|
||||||
status: 'waiting_callback',
|
},
|
||||||
},
|
desktopAuth: {
|
||||||
upload: {
|
status: 'waiting_callback',
|
||||||
status: 'waiting_register',
|
},
|
||||||
|
upload: {
|
||||||
|
status: 'waiting_register',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.equal(patch.kiroRuntime.session.currentStage, 'register');
|
assert.equal(Object.prototype.hasOwnProperty.call(patch, 'kiroRuntime'), false);
|
||||||
assert.equal(patch.kiroRuntime.session.pageState, 'register_otp_page');
|
assert.equal(getKiroRuntime(patch).session.currentStage, 'register');
|
||||||
assert.equal(patch.kiroRuntime.session.pageUrl, 'https://signin.aws/register');
|
assert.equal(getKiroRuntime(patch).session.pageState, 'register_otp_page');
|
||||||
assert.equal(patch.kiroRuntime.register.email, 'aws-user@example.com');
|
assert.equal(getKiroRuntime(patch).session.pageUrl, 'https://signin.aws/register');
|
||||||
assert.equal(patch.kiroRuntime.register.fullName, 'Ada Lovelace');
|
assert.equal(getKiroRuntime(patch).register.email, 'aws-user@example.com');
|
||||||
assert.equal(patch.kiroRuntime.register.verificationRequestedAt, 1700000000000);
|
assert.equal(getKiroRuntime(patch).register.fullName, 'Ada Lovelace');
|
||||||
assert.equal(patch.kiroRuntime.desktopAuth.status, 'waiting_callback');
|
assert.equal(getKiroRuntime(patch).register.verificationRequestedAt, 1700000000000);
|
||||||
assert.equal(patch.kiroRuntime.upload.status, 'waiting_register');
|
assert.equal(getKiroRuntime(patch).desktopAuth.status, 'waiting_callback');
|
||||||
|
assert.equal(getKiroRuntime(patch).upload.status, 'waiting_register');
|
||||||
|
assert.equal(patch.runtimeState.flowState.kiro.session.currentStage, 'register');
|
||||||
|
assert.equal(patch.runtimeState.flowState.kiro.register.email, 'aws-user@example.com');
|
||||||
|
assert.equal(patch.runtimeState.flowState.kiro.desktopAuth.status, 'waiting_callback');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('kiro state reset helpers clear downstream runtime and fresh keep-state preserves only target selection', () => {
|
test('kiro state reset helpers clear downstream runtime and fresh keep-state preserves only target selection', () => {
|
||||||
const api = loadKiroStateApi();
|
const api = loadKiroStateApi();
|
||||||
const currentState = {
|
const currentState = {
|
||||||
kiroTargetId: 'kiro-rs',
|
targetId: 'kiro-rs',
|
||||||
kiroRuntime: {
|
runtimeState: api.buildRuntimeStatePatch({}, {
|
||||||
session: {
|
session: {
|
||||||
currentStage: 'upload',
|
currentStage: 'upload',
|
||||||
registerTabId: 88,
|
registerTabId: 88,
|
||||||
@@ -126,21 +145,26 @@ test('kiro state reset helpers clear downstream runtime and fresh keep-state pre
|
|||||||
status: 'uploaded',
|
status: 'uploaded',
|
||||||
credentialId: 321,
|
credentialId: 321,
|
||||||
},
|
},
|
||||||
},
|
}).runtimeState,
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetPatch = api.buildDownstreamResetPatch('kiro-submit-email', currentState);
|
const resetPatch = api.buildDownstreamResetPatch('kiro-submit-email', currentState);
|
||||||
assert.equal(resetPatch.kiroRuntime.session.currentStage, 'register');
|
assert.equal(Object.prototype.hasOwnProperty.call(resetPatch, 'kiroRuntime'), false);
|
||||||
assert.equal(resetPatch.kiroRuntime.register.email, '');
|
assert.equal(getKiroRuntime(resetPatch).session.currentStage, 'register');
|
||||||
assert.equal(resetPatch.kiroRuntime.register.fullName, '');
|
assert.equal(getKiroRuntime(resetPatch).register.email, '');
|
||||||
assert.equal(resetPatch.kiroRuntime.desktopAuth.refreshToken, '');
|
assert.equal(getKiroRuntime(resetPatch).register.fullName, '');
|
||||||
assert.equal(resetPatch.kiroRuntime.upload.status, '');
|
assert.equal(getKiroRuntime(resetPatch).desktopAuth.refreshToken, '');
|
||||||
assert.equal(resetPatch.kiroRuntime.upload.credentialId, null);
|
assert.equal(getKiroRuntime(resetPatch).upload.status, '');
|
||||||
|
assert.equal(getKiroRuntime(resetPatch).upload.credentialId, null);
|
||||||
|
assert.equal(resetPatch.runtimeState.flowState.kiro.register.email, '');
|
||||||
|
assert.equal(resetPatch.runtimeState.flowState.kiro.desktopAuth.refreshToken, '');
|
||||||
|
|
||||||
const keepState = api.buildFreshKeepState(currentState);
|
const keepState = api.buildFreshKeepState(currentState);
|
||||||
assert.equal(keepState.kiroTargetId, 'kiro-rs');
|
assert.equal(keepState.targetId, 'kiro-rs');
|
||||||
assert.equal(keepState.kiroRuntime.register.email, '');
|
assert.equal(Object.prototype.hasOwnProperty.call(keepState, 'kiroRuntime'), false);
|
||||||
assert.equal(keepState.kiroRuntime.desktopAuth.refreshToken, '');
|
assert.equal(getKiroRuntime(keepState).register.email, '');
|
||||||
assert.equal(keepState.kiroRuntime.upload.status, '');
|
assert.equal(getKiroRuntime(keepState).desktopAuth.refreshToken, '');
|
||||||
assert.equal(keepState.kiroRuntime.upload.targetId, 'kiro-rs');
|
assert.equal(getKiroRuntime(keepState).upload.status, '');
|
||||||
|
assert.equal(getKiroRuntime(keepState).upload.targetId, 'kiro-rs');
|
||||||
|
assert.equal(keepState.runtimeState.flowState.kiro.upload.targetId, 'kiro-rs');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ const fs = require('node:fs');
|
|||||||
|
|
||||||
test('background imports logging/status module', () => {
|
test('background imports logging/status module', () => {
|
||||||
const source = fs.readFileSync('background.js', 'utf8');
|
const source = fs.readFileSync('background.js', 'utf8');
|
||||||
assert.match(source, /background\/logging-status\.js/);
|
assert.match(source, /core\/flow-kernel\/logging-status\.js/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('logging/status module exposes a factory', () => {
|
test('logging/status module exposes a factory', () => {
|
||||||
const source = fs.readFileSync('background/logging-status.js', 'utf8');
|
const source = fs.readFileSync('core/flow-kernel/logging-status.js', 'utf8');
|
||||||
const globalScope = {};
|
const globalScope = {};
|
||||||
|
|
||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundLoggingStatus;`)(globalScope);
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundLoggingStatus;`)(globalScope);
|
||||||
@@ -17,7 +17,7 @@ test('logging/status module exposes a factory', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('logging/status add-phone detection ignores step 2 phone-entry switch failures', () => {
|
test('logging/status add-phone detection ignores step 2 phone-entry switch failures', () => {
|
||||||
const source = fs.readFileSync('background/logging-status.js', 'utf8');
|
const source = fs.readFileSync('core/flow-kernel/logging-status.js', 'utf8');
|
||||||
const globalScope = {};
|
const globalScope = {};
|
||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundLoggingStatus;`)(globalScope);
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundLoggingStatus;`)(globalScope);
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ test('signup flow helper allocates mail2925 account before generating alias emai
|
|||||||
calls.setEmail.push(email);
|
calls.setEmail.push(email);
|
||||||
},
|
},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
waitForTabUrlMatch: async () => null,
|
waitForTabUrlMatch: async () => null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ test('signup flow helper skips mail2925 account allocation when account pool swi
|
|||||||
sendToContentScriptResilient: async () => ({}),
|
sendToContentScriptResilient: async () => ({}),
|
||||||
setEmailState: async () => {},
|
setEmailState: async () => {},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
waitForTabUrlMatch: async () => null,
|
waitForTabUrlMatch: async () => null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ test('SAVE_SETTING rebuilds Plus node statuses when panel mode forces the effect
|
|||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope);
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope);
|
||||||
const broadcasts = [];
|
const broadcasts = [];
|
||||||
let state = {
|
let state = {
|
||||||
panelMode: 'sub2api',
|
targetId: 'sub2api',
|
||||||
plusModeEnabled: true,
|
plusModeEnabled: true,
|
||||||
plusPaymentMethod: 'paypal',
|
plusPaymentMethod: 'paypal',
|
||||||
plusAccountAccessStrategy: 'sub2api_codex_session',
|
plusAccountAccessStrategy: 'sub2api_codex_session',
|
||||||
@@ -486,12 +486,12 @@ test('SAVE_SETTING rebuilds Plus node statuses when panel mode forces the effect
|
|||||||
const router = api.createMessageRouter({
|
const router = api.createMessageRouter({
|
||||||
addLog: async () => {},
|
addLog: async () => {},
|
||||||
buildLuckmailSessionSettingsPayload: () => ({}),
|
buildLuckmailSessionSettingsPayload: () => ({}),
|
||||||
buildPersistentSettingsPayload: (input = {}) => Object.prototype.hasOwnProperty.call(input, 'panelMode')
|
buildPersistentSettingsPayload: (input = {}) => Object.prototype.hasOwnProperty.call(input, 'targetId')
|
||||||
? { panelMode: input.panelMode }
|
? { targetId: input.targetId }
|
||||||
: {},
|
: {},
|
||||||
broadcastDataUpdate: (payload) => broadcasts.push(payload),
|
broadcastDataUpdate: (payload) => broadcasts.push(payload),
|
||||||
getNodeIdsForState: (nextState = {}) => (
|
getNodeIdsForState: (nextState = {}) => (
|
||||||
String(nextState.panelMode || '').trim() === 'sub2api'
|
String(nextState.targetId || '').trim() === 'sub2api'
|
||||||
&& String(nextState.plusAccountAccessStrategy || '').trim() === 'sub2api_codex_session'
|
&& String(nextState.plusAccountAccessStrategy || '').trim() === 'sub2api_codex_session'
|
||||||
? [
|
? [
|
||||||
'open-chatgpt',
|
'open-chatgpt',
|
||||||
@@ -525,12 +525,12 @@ test('SAVE_SETTING rebuilds Plus node statuses when panel mode forces the effect
|
|||||||
const response = await router.handleMessage({
|
const response = await router.handleMessage({
|
||||||
type: 'SAVE_SETTING',
|
type: 'SAVE_SETTING',
|
||||||
payload: {
|
payload: {
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.equal(response.ok, true);
|
assert.equal(response.ok, true);
|
||||||
assert.equal(state.panelMode, 'cpa');
|
assert.equal(state.targetId, 'cpa');
|
||||||
assert.equal(state.plusAccountAccessStrategy, 'sub2api_codex_session');
|
assert.equal(state.plusAccountAccessStrategy, 'sub2api_codex_session');
|
||||||
assert.equal(state.currentNodeId, '');
|
assert.equal(state.currentNodeId, '');
|
||||||
assert.equal(state.oauthUrl, null);
|
assert.equal(state.oauthUrl, null);
|
||||||
@@ -552,7 +552,7 @@ test('SAVE_SETTING rebuilds Plus node statuses when panel mode forces the effect
|
|||||||
});
|
});
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(state.nodeStatuses, 'sub2api-session-import'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(state.nodeStatuses, 'sub2api-session-import'), false);
|
||||||
assert.deepStrictEqual(broadcasts.at(-1), {
|
assert.deepStrictEqual(broadcasts.at(-1), {
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
signupMethod: 'email',
|
signupMethod: 'email',
|
||||||
oauthUrl: null,
|
oauthUrl: null,
|
||||||
localhostUrl: null,
|
localhostUrl: null,
|
||||||
@@ -595,7 +595,7 @@ test('SAVE_SETTING mirrors activeFlowId into flowId when switching to kiro flow'
|
|||||||
const globalScope = { console };
|
const globalScope = { console };
|
||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope);
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope);
|
||||||
const broadcasts = [];
|
const broadcasts = [];
|
||||||
let state = { activeFlowId: 'openai', flowId: 'openai', panelMode: 'cpa', plusModeEnabled: false, plusPaymentMethod: 'paypal' };
|
let state = { activeFlowId: 'openai', flowId: 'openai', targetId: 'cpa', plusModeEnabled: false, plusPaymentMethod: 'paypal' };
|
||||||
|
|
||||||
const router = api.createMessageRouter({
|
const router = api.createMessageRouter({
|
||||||
addLog: async () => {},
|
addLog: async () => {},
|
||||||
@@ -683,7 +683,7 @@ test('SAVE_SETTING syncs canonical kiro settingsState back into session state',
|
|||||||
let state = {
|
let state = {
|
||||||
activeFlowId: 'kiro',
|
activeFlowId: 'kiro',
|
||||||
flowId: 'kiro',
|
flowId: 'kiro',
|
||||||
kiroTargetId: 'kiro-rs',
|
targetId: 'kiro-rs',
|
||||||
kiroRsUrl: 'https://kiro.example.com/admin',
|
kiroRsUrl: 'https://kiro.example.com/admin',
|
||||||
kiroRsKey: '',
|
kiroRsKey: '',
|
||||||
settingsSchemaVersion: 4,
|
settingsSchemaVersion: 4,
|
||||||
@@ -718,7 +718,7 @@ test('SAVE_SETTING syncs canonical kiro settingsState back into session state',
|
|||||||
setPersistentSettings: async () => ({
|
setPersistentSettings: async () => ({
|
||||||
activeFlowId: 'kiro',
|
activeFlowId: 'kiro',
|
||||||
flowId: 'kiro',
|
flowId: 'kiro',
|
||||||
kiroTargetId: 'kiro-rs',
|
targetId: 'kiro-rs',
|
||||||
kiroRsUrl: 'https://kiro.example.com/admin',
|
kiroRsUrl: 'https://kiro.example.com/admin',
|
||||||
kiroRsKey: 'live-key',
|
kiroRsKey: 'live-key',
|
||||||
settingsSchemaVersion: 4,
|
settingsSchemaVersion: 4,
|
||||||
@@ -751,7 +751,7 @@ test('CHECK_KIRO_RS_CONNECTION prefers current sidepanel payload over stale save
|
|||||||
getState: async () => ({
|
getState: async () => ({
|
||||||
activeFlowId: 'kiro',
|
activeFlowId: 'kiro',
|
||||||
flowId: 'kiro',
|
flowId: 'kiro',
|
||||||
kiroTargetId: 'kiro-rs',
|
targetId: 'kiro-rs',
|
||||||
kiroRsUrl: 'https://old.example.com/admin',
|
kiroRsUrl: 'https://old.example.com/admin',
|
||||||
kiroRsKey: 'old-key',
|
kiroRsKey: 'old-key',
|
||||||
settingsState: {
|
settingsState: {
|
||||||
@@ -808,7 +808,7 @@ test('AUTO_RUN applies current flow selection from payload before starting loop'
|
|||||||
let state = {
|
let state = {
|
||||||
activeFlowId: 'openai',
|
activeFlowId: 'openai',
|
||||||
flowId: 'openai',
|
flowId: 'openai',
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
plusModeEnabled: false,
|
plusModeEnabled: false,
|
||||||
plusPaymentMethod: 'paypal',
|
plusPaymentMethod: 'paypal',
|
||||||
};
|
};
|
||||||
@@ -829,7 +829,7 @@ test('AUTO_RUN applies current flow selection from payload before starting loop'
|
|||||||
validations.push({
|
validations.push({
|
||||||
activeFlowId: validationState?.activeFlowId,
|
activeFlowId: validationState?.activeFlowId,
|
||||||
flowId: validationState?.flowId,
|
flowId: validationState?.flowId,
|
||||||
kiroTargetId: validationState?.kiroTargetId,
|
targetId: validationState?.targetId,
|
||||||
optionActiveFlowId: options?.activeFlowId,
|
optionActiveFlowId: options?.activeFlowId,
|
||||||
});
|
});
|
||||||
return { ok: true, errors: [] };
|
return { ok: true, errors: [] };
|
||||||
@@ -848,14 +848,14 @@ test('AUTO_RUN applies current flow selection from payload before starting loop'
|
|||||||
assert.equal(response.ok, true);
|
assert.equal(response.ok, true);
|
||||||
assert.equal(state.activeFlowId, 'kiro');
|
assert.equal(state.activeFlowId, 'kiro');
|
||||||
assert.equal(state.flowId, 'kiro');
|
assert.equal(state.flowId, 'kiro');
|
||||||
assert.equal(state.kiroTargetId, 'kiro-rs');
|
assert.equal(state.targetId, 'kiro-rs');
|
||||||
assert.deepStrictEqual(calls, [
|
assert.deepStrictEqual(calls, [
|
||||||
{
|
{
|
||||||
type: 'setState',
|
type: 'setState',
|
||||||
updates: {
|
updates: {
|
||||||
activeFlowId: 'kiro',
|
activeFlowId: 'kiro',
|
||||||
flowId: 'kiro',
|
flowId: 'kiro',
|
||||||
kiroTargetId: 'kiro-rs',
|
targetId: 'kiro-rs',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -877,7 +877,7 @@ test('AUTO_RUN applies current flow selection from payload before starting loop'
|
|||||||
{
|
{
|
||||||
activeFlowId: 'kiro',
|
activeFlowId: 'kiro',
|
||||||
flowId: 'kiro',
|
flowId: 'kiro',
|
||||||
kiroTargetId: 'kiro-rs',
|
targetId: 'kiro-rs',
|
||||||
optionActiveFlowId: 'kiro',
|
optionActiveFlowId: 'kiro',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@@ -891,18 +891,18 @@ test('SAVE_SETTING re-resolves signup method when panel mode changes', async ()
|
|||||||
signupMethod: 'phone',
|
signupMethod: 'phone',
|
||||||
phoneVerificationEnabled: true,
|
phoneVerificationEnabled: true,
|
||||||
plusModeEnabled: false,
|
plusModeEnabled: false,
|
||||||
panelMode: 'sub2api',
|
targetId: 'sub2api',
|
||||||
};
|
};
|
||||||
|
|
||||||
const router = api.createMessageRouter({
|
const router = api.createMessageRouter({
|
||||||
addLog: async () => {},
|
addLog: async () => {},
|
||||||
buildLuckmailSessionSettingsPayload: () => ({}),
|
buildLuckmailSessionSettingsPayload: () => ({}),
|
||||||
buildPersistentSettingsPayload: (input = {}) => Object.prototype.hasOwnProperty.call(input, 'panelMode')
|
buildPersistentSettingsPayload: (input = {}) => Object.prototype.hasOwnProperty.call(input, 'targetId')
|
||||||
? { panelMode: input.panelMode }
|
? { targetId: input.targetId }
|
||||||
: {},
|
: {},
|
||||||
broadcastDataUpdate: () => {},
|
broadcastDataUpdate: () => {},
|
||||||
getState: async () => ({ ...state }),
|
getState: async () => ({ ...state }),
|
||||||
resolveSignupMethod: (nextState = {}) => nextState.panelMode === 'cpa' ? 'email' : 'phone',
|
resolveSignupMethod: (nextState = {}) => nextState.targetId === 'cpa' ? 'email' : 'phone',
|
||||||
setPersistentSettings: async (updates) => ({ ...updates }),
|
setPersistentSettings: async (updates) => ({ ...updates }),
|
||||||
setState: async (updates) => {
|
setState: async (updates) => {
|
||||||
state = { ...state, ...updates };
|
state = { ...state, ...updates };
|
||||||
@@ -911,11 +911,11 @@ test('SAVE_SETTING re-resolves signup method when panel mode changes', async ()
|
|||||||
|
|
||||||
const response = await router.handleMessage({
|
const response = await router.handleMessage({
|
||||||
type: 'SAVE_SETTING',
|
type: 'SAVE_SETTING',
|
||||||
payload: { panelMode: 'cpa' },
|
payload: { targetId: 'cpa' },
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.equal(response.ok, true);
|
assert.equal(response.ok, true);
|
||||||
assert.equal(state.panelMode, 'cpa');
|
assert.equal(state.targetId, 'cpa');
|
||||||
assert.equal(state.signupMethod, 'email');
|
assert.equal(state.signupMethod, 'email');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -929,7 +929,7 @@ test('SAVE_SETTING applies shared mode-switch normalization before persisting in
|
|||||||
signupMethod: 'email',
|
signupMethod: 'email',
|
||||||
phoneVerificationEnabled: false,
|
phoneVerificationEnabled: false,
|
||||||
plusModeEnabled: false,
|
plusModeEnabled: false,
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
};
|
};
|
||||||
|
|
||||||
const router = api.createMessageRouter({
|
const router = api.createMessageRouter({
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ test('message router finalizes step 3 before marking it completed', async () =>
|
|||||||
const response = await router.handleMessage({
|
const response = await router.handleMessage({
|
||||||
type: 'NODE_COMPLETE',
|
type: 'NODE_COMPLETE',
|
||||||
nodeId: 'fill-password',
|
nodeId: 'fill-password',
|
||||||
source: 'signup-page',
|
source: 'openai-auth',
|
||||||
payload: {
|
payload: {
|
||||||
nodeId: 'fill-password',
|
nodeId: 'fill-password',
|
||||||
email: 'user@example.com',
|
email: 'user@example.com',
|
||||||
@@ -548,7 +548,7 @@ test('message router marks step 3 failed when post-submit finalize fails', async
|
|||||||
const response = await router.handleMessage({
|
const response = await router.handleMessage({
|
||||||
type: 'NODE_COMPLETE',
|
type: 'NODE_COMPLETE',
|
||||||
nodeId: 'fill-password',
|
nodeId: 'fill-password',
|
||||||
source: 'signup-page',
|
source: 'openai-auth',
|
||||||
payload: {
|
payload: {
|
||||||
nodeId: 'fill-password',
|
nodeId: 'fill-password',
|
||||||
email: 'user@example.com',
|
email: 'user@example.com',
|
||||||
@@ -581,7 +581,7 @@ test('message router does not duplicate step 3 mismatch failure log after finali
|
|||||||
const response = await router.handleMessage({
|
const response = await router.handleMessage({
|
||||||
type: 'NODE_ERROR',
|
type: 'NODE_ERROR',
|
||||||
nodeId: 'fill-password',
|
nodeId: 'fill-password',
|
||||||
source: 'signup-page',
|
source: 'openai-auth',
|
||||||
payload: { nodeId: 'fill-password' },
|
payload: { nodeId: 'fill-password' },
|
||||||
error: mismatchError,
|
error: mismatchError,
|
||||||
}, {});
|
}, {});
|
||||||
@@ -604,7 +604,7 @@ test('message router stops the flow and surfaces cloudflare security block error
|
|||||||
const response = await router.handleMessage({
|
const response = await router.handleMessage({
|
||||||
type: 'NODE_ERROR',
|
type: 'NODE_ERROR',
|
||||||
nodeId: 'oauth-login',
|
nodeId: 'oauth-login',
|
||||||
source: 'signup-page',
|
source: 'openai-auth',
|
||||||
payload: { nodeId: 'oauth-login' },
|
payload: { nodeId: 'oauth-login' },
|
||||||
error: 'CF_SECURITY_BLOCKED::您已触发Cloudflare 安全防护系统',
|
error: 'CF_SECURITY_BLOCKED::您已触发Cloudflare 安全防护系统',
|
||||||
}, {});
|
}, {});
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ test('navigation utils support codex2api mode and url normalization', () => {
|
|||||||
utils.normalizeCodex2ApiUrl('https://codex-admin.example.com/'),
|
utils.normalizeCodex2ApiUrl('https://codex-admin.example.com/'),
|
||||||
'https://codex-admin.example.com/admin/accounts'
|
'https://codex-admin.example.com/admin/accounts'
|
||||||
);
|
);
|
||||||
assert.equal(utils.getPanelMode({ panelMode: 'codex2api' }), 'codex2api');
|
assert.equal(utils.getPanelMode({ targetId: 'codex2api' }), 'codex2api');
|
||||||
assert.equal(utils.getPanelModeLabel('codex2api'), 'Codex2API');
|
assert.equal(utils.getPanelModeLabel('codex2api'), 'Codex2API');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ const fs = require('node:fs');
|
|||||||
|
|
||||||
test('confirm-oauth and platform-verify stay free of operation delay gate calls', () => {
|
test('confirm-oauth and platform-verify stay free of operation delay gate calls', () => {
|
||||||
for (const file of [
|
for (const file of [
|
||||||
'background/steps/confirm-oauth.js',
|
'flows/openai/background/steps/confirm-oauth.js',
|
||||||
'background/steps/platform-verify.js',
|
'flows/openai/background/steps/platform-verify.js',
|
||||||
'background/panel-bridge.js',
|
'background/panel-bridge.js',
|
||||||
'content/sub2api-panel.js',
|
'flows/openai/content/sub2api-panel.js',
|
||||||
]) {
|
]) {
|
||||||
const source = fs.readFileSync(file, 'utf8');
|
const source = fs.readFileSync(file, 'utf8');
|
||||||
assert.doesNotMatch(source, /performOperationWithDelay\(/, `${file} must not call the operation delay gate`);
|
assert.doesNotMatch(source, /performOperationWithDelay\(/, `${file} must not call the operation delay gate`);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const fs = require('node:fs');
|
|||||||
const test = require('node:test');
|
const test = require('node:test');
|
||||||
|
|
||||||
test('platform verify module supports codex2api protocol callback exchange', async () => {
|
test('platform verify module supports codex2api protocol callback exchange', async () => {
|
||||||
const source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/platform-verify.js', 'utf8');
|
||||||
const originalFetch = globalThis.fetch;
|
const originalFetch = globalThis.fetch;
|
||||||
globalThis.fetch = async (url, options = {}) => {
|
globalThis.fetch = async (url, options = {}) => {
|
||||||
assert.equal(url, 'http://localhost:8080/api/admin/oauth/exchange-code');
|
assert.equal(url, 'http://localhost:8080/api/admin/oauth/exchange-code');
|
||||||
@@ -81,7 +81,7 @@ test('platform verify module supports codex2api protocol callback exchange', asy
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('platform verify retries transient SUB2API oauth/token exchange errors before succeeding', async () => {
|
test('platform verify retries transient SUB2API oauth/token exchange errors before succeeding', async () => {
|
||||||
const source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/platform-verify.js', 'utf8');
|
||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundStep10;`)({});
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundStep10;`)({});
|
||||||
|
|
||||||
const logs = [];
|
const logs = [];
|
||||||
@@ -150,7 +150,7 @@ test('platform verify retries transient SUB2API oauth/token exchange errors befo
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('platform verify retries transient SUB2API token_exchange_user_error before succeeding', async () => {
|
test('platform verify retries transient SUB2API token_exchange_user_error before succeeding', async () => {
|
||||||
const source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/platform-verify.js', 'utf8');
|
||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundStep10;`)({});
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundStep10;`)({});
|
||||||
|
|
||||||
const logs = [];
|
const logs = [];
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ function createDeps(overrides = {}) {
|
|||||||
|
|
||||||
function loadStep10WithSub2Api() {
|
function loadStep10WithSub2Api() {
|
||||||
const sub2apiSource = fs.readFileSync('background/sub2api-api.js', 'utf8');
|
const sub2apiSource = fs.readFileSync('background/sub2api-api.js', 'utf8');
|
||||||
const step10Source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
|
const step10Source = fs.readFileSync('flows/openai/background/steps/platform-verify.js', 'utf8');
|
||||||
return new Function('self', `${sub2apiSource}\n${step10Source}; return self.MultiPageBackgroundStep10;`)({});
|
return new Function('self', `${sub2apiSource}\n${step10Source}; return self.MultiPageBackgroundStep10;`)({});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ function createSub2ApiResponse(payload, status = 200) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test('platform verify module submits CPA callback via management API first', async () => {
|
test('platform verify module submits CPA callback via management API first', async () => {
|
||||||
const source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/platform-verify.js', 'utf8');
|
||||||
const originalFetch = globalThis.fetch;
|
const originalFetch = globalThis.fetch;
|
||||||
let uiCalled = false;
|
let uiCalled = false;
|
||||||
globalThis.fetch = async (url, options = {}) => {
|
globalThis.fetch = async (url, options = {}) => {
|
||||||
@@ -114,7 +114,7 @@ test('platform verify module submits CPA callback via management API first', asy
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('platform verify module prefers cpaManagementOrigin when provided', async () => {
|
test('platform verify module prefers cpaManagementOrigin when provided', async () => {
|
||||||
const source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/platform-verify.js', 'utf8');
|
||||||
const originalFetch = globalThis.fetch;
|
const originalFetch = globalThis.fetch;
|
||||||
globalThis.fetch = async (url, options = {}) => {
|
globalThis.fetch = async (url, options = {}) => {
|
||||||
assert.equal(url, 'http://localhost:9999/v0/management/oauth-callback');
|
assert.equal(url, 'http://localhost:9999/v0/management/oauth-callback');
|
||||||
@@ -149,7 +149,7 @@ test('platform verify module prefers cpaManagementOrigin when provided', async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('platform verify module fails fast when CPA API submit fails', async () => {
|
test('platform verify module fails fast when CPA API submit fails', async () => {
|
||||||
const source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/platform-verify.js', 'utf8');
|
||||||
const originalFetch = globalThis.fetch;
|
const originalFetch = globalThis.fetch;
|
||||||
globalThis.fetch = async () => ({
|
globalThis.fetch = async () => ({
|
||||||
ok: false,
|
ok: false,
|
||||||
@@ -185,7 +185,7 @@ test('platform verify module fails fast when CPA API submit fails', async () =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('platform verify module requires management key for CPA API-only flow', async () => {
|
test('platform verify module requires management key for CPA API-only flow', async () => {
|
||||||
const source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/platform-verify.js', 'utf8');
|
||||||
const originalFetch = globalThis.fetch;
|
const originalFetch = globalThis.fetch;
|
||||||
let fetchCalled = false;
|
let fetchCalled = false;
|
||||||
globalThis.fetch = async () => {
|
globalThis.fetch = async () => {
|
||||||
@@ -221,7 +221,7 @@ test('platform verify module requires management key for CPA API-only flow', asy
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('platform verify module rejects callback when cpa oauth state mismatches', async () => {
|
test('platform verify module rejects callback when cpa oauth state mismatches', async () => {
|
||||||
const source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/platform-verify.js', 'utf8');
|
||||||
const originalFetch = globalThis.fetch;
|
const originalFetch = globalThis.fetch;
|
||||||
let fetchCalled = false;
|
let fetchCalled = false;
|
||||||
globalThis.fetch = async () => {
|
globalThis.fetch = async () => {
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ const assert = require('node:assert/strict');
|
|||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
function loadRuntimeStateApi() {
|
function loadRuntimeStateApi() {
|
||||||
const source = fs.readFileSync('background/runtime-state.js', 'utf8');
|
const source = fs.readFileSync('core/flow-kernel/runtime-state.js', 'utf8');
|
||||||
const globalScope = {};
|
const globalScope = {};
|
||||||
return new Function('self', `${source}; return self.MultiPageBackgroundRuntimeState;`)(globalScope);
|
return new Function('self', `${source}; return self.MultiPageBackgroundRuntimeState;`)(globalScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
test('background imports runtime-state module and wires state view helpers', () => {
|
test('background imports runtime-state module and wires state view helpers', () => {
|
||||||
const source = fs.readFileSync('background.js', 'utf8');
|
const source = fs.readFileSync('background.js', 'utf8');
|
||||||
assert.match(source, /background\/runtime-state\.js/);
|
assert.match(source, /core\/flow-kernel\/runtime-state\.js/);
|
||||||
assert.match(source, /createRuntimeStateHelpers/);
|
assert.match(source, /createRuntimeStateHelpers/);
|
||||||
assert.match(source, /buildStateViewWithRuntimeState/);
|
assert.match(source, /buildStateViewWithRuntimeState/);
|
||||||
assert.match(source, /buildStatePatchWithRuntimeState/);
|
assert.match(source, /buildStatePatchWithRuntimeState/);
|
||||||
@@ -46,10 +46,10 @@ test('runtime-state view preserves canonical flow metadata from node state', ()
|
|||||||
phoneNumber: '+447700900123',
|
phoneNumber: '+447700900123',
|
||||||
},
|
},
|
||||||
tabRegistry: {
|
tabRegistry: {
|
||||||
'signup-page': { tabId: 12 },
|
'openai-auth': { tabId: 12 },
|
||||||
},
|
},
|
||||||
sourceLastUrls: {
|
sourceLastUrls: {
|
||||||
'signup-page': 'https://auth.example.com/start',
|
'openai-auth': 'https://auth.example.com/start',
|
||||||
},
|
},
|
||||||
flowStartTime: 12345,
|
flowStartTime: 12345,
|
||||||
});
|
});
|
||||||
@@ -72,10 +72,10 @@ test('runtime-state view preserves canonical flow metadata from node state', ()
|
|||||||
});
|
});
|
||||||
assert.deepStrictEqual(view.sharedState, {
|
assert.deepStrictEqual(view.sharedState, {
|
||||||
tabRegistry: {
|
tabRegistry: {
|
||||||
'signup-page': { tabId: 12 },
|
'openai-auth': { tabId: 12 },
|
||||||
},
|
},
|
||||||
sourceLastUrls: {
|
sourceLastUrls: {
|
||||||
'signup-page': 'https://auth.example.com/start',
|
'openai-auth': 'https://auth.example.com/start',
|
||||||
},
|
},
|
||||||
flowStartTime: 12345,
|
flowStartTime: 12345,
|
||||||
});
|
});
|
||||||
@@ -171,3 +171,53 @@ test('runtime-state patch prefers explicit activeFlowId over stale legacy flowId
|
|||||||
'kiro-open-register-page': 'running',
|
'kiro-open-register-page': 'running',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('runtime-state patch preserves canonical nested kiro flow state without projecting a top-level alias', () => {
|
||||||
|
const api = loadRuntimeStateApi();
|
||||||
|
const helpers = api.createRuntimeStateHelpers({
|
||||||
|
DEFAULT_ACTIVE_FLOW_ID: 'openai',
|
||||||
|
defaultNodeStatuses: {
|
||||||
|
'open-chatgpt': 'pending',
|
||||||
|
'kiro-open-register-page': 'pending',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const patch = helpers.buildSessionStatePatch({
|
||||||
|
runtimeState: {
|
||||||
|
activeFlowId: 'kiro',
|
||||||
|
flowState: {
|
||||||
|
kiro: {
|
||||||
|
session: {
|
||||||
|
currentStage: 'register',
|
||||||
|
},
|
||||||
|
register: {
|
||||||
|
email: 'old-user@example.com',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
runtimeState: {
|
||||||
|
flowState: {
|
||||||
|
kiro: {
|
||||||
|
register: {
|
||||||
|
email: 'aws-user@example.com',
|
||||||
|
},
|
||||||
|
upload: {
|
||||||
|
status: 'uploaded',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(Object.prototype.hasOwnProperty.call(patch, 'kiroRuntime'), false);
|
||||||
|
assert.equal(patch.runtimeState.flowState.kiro.session.currentStage, 'register');
|
||||||
|
assert.equal(patch.runtimeState.flowState.kiro.register.email, 'aws-user@example.com');
|
||||||
|
assert.equal(patch.runtimeState.flowState.kiro.upload.status, 'uploaded');
|
||||||
|
|
||||||
|
const view = helpers.buildStateView(patch);
|
||||||
|
assert.equal(Object.prototype.hasOwnProperty.call(view, 'kiroRuntime'), false);
|
||||||
|
assert.equal(view.flowState.kiro.register.email, 'aws-user@example.com');
|
||||||
|
assert.equal(view.flowState.kiro.upload.status, 'uploaded');
|
||||||
|
});
|
||||||
|
|||||||
@@ -52,12 +52,24 @@ test('importSettingsBundle normalizes unsupported capability flags before persis
|
|||||||
const api = new Function(`
|
const api = new Function(`
|
||||||
const SETTINGS_EXPORT_SCHEMA_VERSION = 1;
|
const SETTINGS_EXPORT_SCHEMA_VERSION = 1;
|
||||||
const DEFAULT_REGISTRATION_EMAIL_STATE = { emailHistory: [] };
|
const DEFAULT_REGISTRATION_EMAIL_STATE = { emailHistory: [] };
|
||||||
|
const DEFAULT_ACTIVE_FLOW_ID = 'openai';
|
||||||
|
const self = {
|
||||||
|
MultiPageLegacySettingsImporter: {
|
||||||
|
createSettingsImporter() {
|
||||||
|
return {
|
||||||
|
importSettings(settings = {}) {
|
||||||
|
return { ...settings };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
let persistedUpdates = null;
|
let persistedUpdates = null;
|
||||||
let stateUpdates = null;
|
let stateUpdates = null;
|
||||||
let broadcastPayload = null;
|
let broadcastPayload = null;
|
||||||
let currentState = {
|
let currentState = {
|
||||||
activeFlowId: 'site-a',
|
activeFlowId: 'site-a',
|
||||||
panelMode: 'sub2api',
|
targetId: 'sub2api',
|
||||||
signupMethod: 'phone',
|
signupMethod: 'phone',
|
||||||
plusModeEnabled: false,
|
plusModeEnabled: false,
|
||||||
phoneVerificationEnabled: false,
|
phoneVerificationEnabled: false,
|
||||||
@@ -74,7 +86,7 @@ function validateModeSwitchState() {
|
|||||||
ok: false,
|
ok: false,
|
||||||
errors: [{ code: 'panel_mode_unsupported', message: '当前 flow 不支持 SUB2API 面板模式。' }],
|
errors: [{ code: 'panel_mode_unsupported', message: '当前 flow 不支持 SUB2API 面板模式。' }],
|
||||||
normalizedUpdates: {
|
normalizedUpdates: {
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
plusModeEnabled: false,
|
plusModeEnabled: false,
|
||||||
phoneVerificationEnabled: false,
|
phoneVerificationEnabled: false,
|
||||||
signupMethod: 'email',
|
signupMethod: 'email',
|
||||||
@@ -84,6 +96,9 @@ function validateModeSwitchState() {
|
|||||||
function resolveSignupMethod(state = {}) {
|
function resolveSignupMethod(state = {}) {
|
||||||
return String(state?.signupMethod || '').trim().toLowerCase() === 'phone' ? 'phone' : 'email';
|
return String(state?.signupMethod || '').trim().toLowerCase() === 'phone' ? 'phone' : 'email';
|
||||||
}
|
}
|
||||||
|
function getSettingsSchemaApi() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
async function setPersistentSettings(updates) {
|
async function setPersistentSettings(updates) {
|
||||||
persistedUpdates = { ...updates };
|
persistedUpdates = { ...updates };
|
||||||
}
|
}
|
||||||
@@ -109,7 +124,7 @@ return {
|
|||||||
const result = await api.importSettingsBundle({
|
const result = await api.importSettingsBundle({
|
||||||
schemaVersion: 1,
|
schemaVersion: 1,
|
||||||
settings: {
|
settings: {
|
||||||
panelMode: 'sub2api',
|
targetId: 'sub2api',
|
||||||
plusModeEnabled: true,
|
plusModeEnabled: true,
|
||||||
phoneVerificationEnabled: true,
|
phoneVerificationEnabled: true,
|
||||||
signupMethod: 'phone',
|
signupMethod: 'phone',
|
||||||
@@ -117,16 +132,164 @@ return {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assert.deepEqual(api.getPersistedUpdates(), {
|
assert.deepEqual(api.getPersistedUpdates(), {
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
plusModeEnabled: false,
|
plusModeEnabled: false,
|
||||||
phoneVerificationEnabled: false,
|
phoneVerificationEnabled: false,
|
||||||
signupMethod: 'email',
|
signupMethod: 'email',
|
||||||
});
|
});
|
||||||
assert.equal(api.getStateUpdates().panelMode, 'cpa');
|
assert.equal(api.getStateUpdates().targetId, 'cpa');
|
||||||
assert.equal(api.getStateUpdates().plusModeEnabled, false);
|
assert.equal(api.getStateUpdates().plusModeEnabled, false);
|
||||||
assert.equal(api.getStateUpdates().phoneVerificationEnabled, false);
|
assert.equal(api.getStateUpdates().phoneVerificationEnabled, false);
|
||||||
assert.equal(api.getStateUpdates().signupMethod, 'email');
|
assert.equal(api.getStateUpdates().signupMethod, 'email');
|
||||||
assert.equal(api.getBroadcastPayload().panelMode, 'cpa');
|
assert.equal(api.getBroadcastPayload().targetId, 'cpa');
|
||||||
assert.equal(api.getBroadcastPayload().signupMethod, 'email');
|
assert.equal(api.getBroadcastPayload().signupMethod, 'email');
|
||||||
assert.equal(result.signupMethod, 'email');
|
assert.equal(result.signupMethod, 'email');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('importSettingsBundle routes legacy settings through the legacy importer before persisting', async () => {
|
||||||
|
const api = new Function(`
|
||||||
|
const SETTINGS_EXPORT_SCHEMA_VERSION = 1;
|
||||||
|
const DEFAULT_REGISTRATION_EMAIL_STATE = { emailHistory: [] };
|
||||||
|
const DEFAULT_ACTIVE_FLOW_ID = 'openai';
|
||||||
|
let importerInput = null;
|
||||||
|
let persistedUpdates = null;
|
||||||
|
let currentState = {
|
||||||
|
activeFlowId: 'openai',
|
||||||
|
nodeStatuses: {},
|
||||||
|
};
|
||||||
|
const self = {
|
||||||
|
MultiPageFlowRegistry: {
|
||||||
|
DEFAULT_FLOW_ID: 'openai',
|
||||||
|
},
|
||||||
|
MultiPageLegacySettingsImporter: {
|
||||||
|
createSettingsImporter() {
|
||||||
|
return {
|
||||||
|
importSettings(settings = {}) {
|
||||||
|
importerInput = JSON.parse(JSON.stringify(settings));
|
||||||
|
return {
|
||||||
|
settingsSchemaVersion: 5,
|
||||||
|
settingsState: {
|
||||||
|
schemaVersion: 5,
|
||||||
|
activeFlowId: 'kiro',
|
||||||
|
services: {
|
||||||
|
account: { customPassword: '' },
|
||||||
|
email: { provider: '163' },
|
||||||
|
proxy: { enabled: false, provider: '711proxy', mode: 'account' },
|
||||||
|
},
|
||||||
|
flows: {
|
||||||
|
openai: {
|
||||||
|
selectedTargetId: 'cpa',
|
||||||
|
targets: {
|
||||||
|
cpa: { vpsUrl: '', vpsPassword: '', localCpaStep9Mode: 'submit' },
|
||||||
|
sub2api: {
|
||||||
|
sub2apiUrl: '',
|
||||||
|
sub2apiEmail: '',
|
||||||
|
sub2apiPassword: '',
|
||||||
|
sub2apiGroupName: 'codex',
|
||||||
|
sub2apiGroupNames: ['codex', 'openai-plus'],
|
||||||
|
sub2apiAccountPriority: 1,
|
||||||
|
sub2apiDefaultProxyName: '',
|
||||||
|
},
|
||||||
|
codex2api: { codex2apiUrl: '', codex2apiAdminKey: '' },
|
||||||
|
},
|
||||||
|
signup: {
|
||||||
|
signupMethod: 'email',
|
||||||
|
phoneVerificationEnabled: false,
|
||||||
|
phoneSignupReloginAfterBindEmailEnabled: false,
|
||||||
|
},
|
||||||
|
plus: {
|
||||||
|
plusModeEnabled: false,
|
||||||
|
plusPaymentMethod: 'paypal',
|
||||||
|
plusAccountAccessStrategy: 'oauth',
|
||||||
|
},
|
||||||
|
autoRun: {
|
||||||
|
stepExecutionRange: { enabled: false, fromStep: 1, toStep: 11 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
kiro: {
|
||||||
|
selectedTargetId: 'kiro-rs',
|
||||||
|
targets: {
|
||||||
|
'kiro-rs': {
|
||||||
|
baseUrl: 'https://kiro.example.com/admin',
|
||||||
|
apiKey: 'imported-key',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
autoRun: {
|
||||||
|
stepExecutionRange: { enabled: false, fromStep: 1, toStep: 9 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
async function ensureManualInteractionAllowed() {
|
||||||
|
return currentState;
|
||||||
|
}
|
||||||
|
function buildPersistentSettingsPayload(settings = {}) {
|
||||||
|
return {
|
||||||
|
activeFlowId: settings.settingsState.activeFlowId,
|
||||||
|
targetId: 'cpa',
|
||||||
|
signupMethod: 'email',
|
||||||
|
targetId: 'kiro-rs',
|
||||||
|
kiroRsUrl: settings.settingsState.flows.kiro.targets['kiro-rs'].baseUrl,
|
||||||
|
kiroRsKey: settings.settingsState.flows.kiro.targets['kiro-rs'].apiKey,
|
||||||
|
settingsSchemaVersion: settings.settingsSchemaVersion,
|
||||||
|
settingsState: settings.settingsState,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function validateModeSwitchState() {
|
||||||
|
return { normalizedUpdates: {} };
|
||||||
|
}
|
||||||
|
function resolveSignupMethod() {
|
||||||
|
return 'email';
|
||||||
|
}
|
||||||
|
function getSettingsSchemaApi() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
async function setPersistentSettings(updates) {
|
||||||
|
persistedUpdates = { ...updates };
|
||||||
|
return updates;
|
||||||
|
}
|
||||||
|
async function setState(updates) {
|
||||||
|
currentState = { ...currentState, ...updates };
|
||||||
|
}
|
||||||
|
function broadcastDataUpdate() {}
|
||||||
|
async function getState() {
|
||||||
|
return currentState;
|
||||||
|
}
|
||||||
|
${extractFunction('importSettingsBundle')}
|
||||||
|
return {
|
||||||
|
importSettingsBundle,
|
||||||
|
getImporterInput: () => importerInput,
|
||||||
|
getPersistedUpdates: () => persistedUpdates,
|
||||||
|
};
|
||||||
|
`)();
|
||||||
|
|
||||||
|
await api.importSettingsBundle({
|
||||||
|
schemaVersion: 1,
|
||||||
|
settings: {
|
||||||
|
targetId: 'sub2api',
|
||||||
|
kiroRuntime: {
|
||||||
|
upload: {
|
||||||
|
status: 'uploaded',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(api.getImporterInput(), {
|
||||||
|
targetId: 'sub2api',
|
||||||
|
kiroRuntime: {
|
||||||
|
upload: {
|
||||||
|
status: 'uploaded',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
assert.equal(api.getPersistedUpdates().activeFlowId, 'kiro');
|
||||||
|
assert.equal(api.getPersistedUpdates().settingsSchemaVersion, 5);
|
||||||
|
assert.equal(api.getPersistedUpdates().settingsState.flows.kiro.targets['kiro-rs'].apiKey, 'imported-key');
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
const test = require('node:test');
|
const test = require('node:test');
|
||||||
const assert = require('node:assert/strict');
|
const assert = require('node:assert/strict');
|
||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
const { readFlowRegistryBundle } = require('./helpers/script-bundles.js');
|
||||||
|
|
||||||
const flowRegistrySource = fs.readFileSync('shared/flow-registry.js', 'utf8');
|
const flowRegistrySource = readFlowRegistryBundle();
|
||||||
const settingsSchemaSource = fs.readFileSync('shared/settings-schema.js', 'utf8');
|
const settingsSchemaSource = fs.readFileSync('core/flow-kernel/settings-schema.js', 'utf8');
|
||||||
const backgroundSource = fs.readFileSync('background.js', 'utf8');
|
const backgroundSource = fs.readFileSync('background.js', 'utf8');
|
||||||
|
|
||||||
function extractFunction(name) {
|
function extractFunction(name) {
|
||||||
@@ -59,9 +60,7 @@ const DEFAULT_ACTIVE_FLOW_ID = 'openai';
|
|||||||
const DEFAULT_SUB2API_GROUP_NAMES = ['codex', 'openai-plus'];
|
const DEFAULT_SUB2API_GROUP_NAMES = ['codex', 'openai-plus'];
|
||||||
const SETTINGS_SCHEMA_VIEW_KEYS = Object.freeze([
|
const SETTINGS_SCHEMA_VIEW_KEYS = Object.freeze([
|
||||||
'activeFlowId',
|
'activeFlowId',
|
||||||
'openaiIntegrationTargetId',
|
'targetId',
|
||||||
'panelMode',
|
|
||||||
'kiroTargetId',
|
|
||||||
'vpsUrl',
|
'vpsUrl',
|
||||||
'vpsPassword',
|
'vpsPassword',
|
||||||
'localCpaStep9Mode',
|
'localCpaStep9Mode',
|
||||||
@@ -92,7 +91,7 @@ const SETTINGS_SCHEMA_VIEW_KEYS = Object.freeze([
|
|||||||
const SETTINGS_SCHEMA_VIEW_KEY_SET = new Set(SETTINGS_SCHEMA_VIEW_KEYS);
|
const SETTINGS_SCHEMA_VIEW_KEY_SET = new Set(SETTINGS_SCHEMA_VIEW_KEYS);
|
||||||
const PERSISTED_SETTING_DEFAULTS = {
|
const PERSISTED_SETTING_DEFAULTS = {
|
||||||
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
|
activeFlowId: DEFAULT_ACTIVE_FLOW_ID,
|
||||||
panelMode: 'cpa',
|
targetId: 'cpa',
|
||||||
signupMethod: 'email',
|
signupMethod: 'email',
|
||||||
plusModeEnabled: false,
|
plusModeEnabled: false,
|
||||||
plusPaymentMethod: 'paypal',
|
plusPaymentMethod: 'paypal',
|
||||||
@@ -102,7 +101,6 @@ const PERSISTED_SETTING_DEFAULTS = {
|
|||||||
ipProxyEnabled: false,
|
ipProxyEnabled: false,
|
||||||
ipProxyService: '711proxy',
|
ipProxyService: '711proxy',
|
||||||
ipProxyMode: 'account',
|
ipProxyMode: 'account',
|
||||||
kiroTargetId: 'kiro-rs',
|
|
||||||
kiroRsUrl: '',
|
kiroRsUrl: '',
|
||||||
kiroRsKey: '',
|
kiroRsKey: '',
|
||||||
stepExecutionRangeByFlow: {},
|
stepExecutionRangeByFlow: {},
|
||||||
@@ -203,13 +201,13 @@ test('buildPersistentSettingsPayload writes canonical settings schema into persi
|
|||||||
}, { fillDefaults: true });
|
}, { fillDefaults: true });
|
||||||
|
|
||||||
assert.equal(payload.activeFlowId, 'kiro');
|
assert.equal(payload.activeFlowId, 'kiro');
|
||||||
assert.equal(payload.kiroTargetId, 'kiro-rs');
|
assert.equal(payload.targetId, 'kiro-rs');
|
||||||
assert.equal(payload.kiroRsUrl, 'https://kiro.example.com/admin');
|
assert.equal(payload.kiroRsUrl, 'https://kiro.example.com/admin');
|
||||||
assert.equal(payload.kiroRsKey, 'secret-key');
|
assert.equal(payload.kiroRsKey, 'secret-key');
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(payload, 'kiroRegion'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(payload, 'kiroRegion'), false);
|
||||||
assert.equal(payload.settingsSchemaVersion, 4);
|
assert.equal(payload.settingsSchemaVersion, 5);
|
||||||
assert.equal(payload.settingsState.activeFlowId, 'kiro');
|
assert.equal(payload.settingsState.activeFlowId, 'kiro');
|
||||||
assert.equal(payload.settingsState.flows.kiro.targetId, 'kiro-rs');
|
assert.equal(payload.settingsState.flows.kiro.selectedTargetId, 'kiro-rs');
|
||||||
assert.equal(
|
assert.equal(
|
||||||
payload.settingsState.flows.kiro.targets['kiro-rs'].baseUrl,
|
payload.settingsState.flows.kiro.targets['kiro-rs'].baseUrl,
|
||||||
'https://kiro.example.com/admin'
|
'https://kiro.example.com/admin'
|
||||||
@@ -220,7 +218,7 @@ test('buildPersistentSettingsPayload accepts schema-only input when requireKnown
|
|||||||
const api = buildHarness();
|
const api = buildHarness();
|
||||||
|
|
||||||
const payload = api.buildPersistentSettingsPayload({
|
const payload = api.buildPersistentSettingsPayload({
|
||||||
settingsSchemaVersion: 4,
|
settingsSchemaVersion: 5,
|
||||||
settingsState: {
|
settingsState: {
|
||||||
activeFlowId: 'kiro',
|
activeFlowId: 'kiro',
|
||||||
services: {
|
services: {
|
||||||
@@ -230,8 +228,8 @@ test('buildPersistentSettingsPayload accepts schema-only input when requireKnown
|
|||||||
},
|
},
|
||||||
flows: {
|
flows: {
|
||||||
openai: {
|
openai: {
|
||||||
integrationTargetId: 'cpa',
|
selectedTargetId: 'cpa',
|
||||||
integrationTargets: {
|
targets: {
|
||||||
cpa: {
|
cpa: {
|
||||||
vpsUrl: '',
|
vpsUrl: '',
|
||||||
vpsPassword: '',
|
vpsPassword: '',
|
||||||
@@ -266,7 +264,7 @@ test('buildPersistentSettingsPayload accepts schema-only input when requireKnown
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
kiro: {
|
kiro: {
|
||||||
targetId: 'kiro-rs',
|
selectedTargetId: 'kiro-rs',
|
||||||
targets: {
|
targets: {
|
||||||
'kiro-rs': {
|
'kiro-rs': {
|
||||||
baseUrl: 'https://kiro.example.com/admin',
|
baseUrl: 'https://kiro.example.com/admin',
|
||||||
@@ -282,11 +280,11 @@ test('buildPersistentSettingsPayload accepts schema-only input when requireKnown
|
|||||||
}, { requireKnownKeys: true });
|
}, { requireKnownKeys: true });
|
||||||
|
|
||||||
assert.equal(payload.activeFlowId, 'kiro');
|
assert.equal(payload.activeFlowId, 'kiro');
|
||||||
assert.equal(payload.kiroTargetId, 'kiro-rs');
|
assert.equal(payload.targetId, 'kiro-rs');
|
||||||
assert.equal(payload.kiroRsUrl, 'https://kiro.example.com/admin');
|
assert.equal(payload.kiroRsUrl, 'https://kiro.example.com/admin');
|
||||||
assert.equal(payload.kiroRsKey, 'schema-only-key');
|
assert.equal(payload.kiroRsKey, 'schema-only-key');
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(payload, 'kiroRegion'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(payload, 'kiroRegion'), false);
|
||||||
assert.equal(payload.settingsSchemaVersion, 4);
|
assert.equal(payload.settingsSchemaVersion, 5);
|
||||||
assert.equal(payload.settingsState.flows.openai.plus.plusAccountAccessStrategy, 'oauth');
|
assert.equal(payload.settingsState.flows.openai.plus.plusAccountAccessStrategy, 'oauth');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -313,7 +311,7 @@ function getRequestedKeys() {
|
|||||||
assert.ok(api.getRequestedKeys().includes('settingsSchemaVersion'));
|
assert.ok(api.getRequestedKeys().includes('settingsSchemaVersion'));
|
||||||
assert.ok(api.getRequestedKeys().includes('settingsState'));
|
assert.ok(api.getRequestedKeys().includes('settingsState'));
|
||||||
assert.ok(api.getRequestedKeys().includes('plusAccountAccessStrategy'));
|
assert.ok(api.getRequestedKeys().includes('plusAccountAccessStrategy'));
|
||||||
assert.equal(state.settingsSchemaVersion, 4);
|
assert.equal(state.settingsSchemaVersion, 5);
|
||||||
assert.equal(state.settingsState.activeFlowId, 'openai');
|
assert.equal(state.settingsState.activeFlowId, 'openai');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -324,7 +322,7 @@ const chrome = {
|
|||||||
local: {
|
local: {
|
||||||
async get() {
|
async get() {
|
||||||
return {
|
return {
|
||||||
settingsSchemaVersion: 4,
|
settingsSchemaVersion: 5,
|
||||||
settingsState: {
|
settingsState: {
|
||||||
activeFlowId: 'kiro',
|
activeFlowId: 'kiro',
|
||||||
services: {
|
services: {
|
||||||
@@ -334,8 +332,8 @@ const chrome = {
|
|||||||
},
|
},
|
||||||
flows: {
|
flows: {
|
||||||
openai: {
|
openai: {
|
||||||
integrationTargetId: 'sub2api',
|
selectedTargetId: 'sub2api',
|
||||||
integrationTargets: {
|
targets: {
|
||||||
cpa: {
|
cpa: {
|
||||||
vpsUrl: '',
|
vpsUrl: '',
|
||||||
vpsPassword: '',
|
vpsPassword: '',
|
||||||
@@ -370,7 +368,7 @@ const chrome = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
kiro: {
|
kiro: {
|
||||||
targetId: 'kiro-rs',
|
selectedTargetId: 'kiro-rs',
|
||||||
targets: {
|
targets: {
|
||||||
'kiro-rs': {
|
'kiro-rs': {
|
||||||
baseUrl: 'https://kiro.example.com/admin',
|
baseUrl: 'https://kiro.example.com/admin',
|
||||||
@@ -393,7 +391,8 @@ const chrome = {
|
|||||||
const state = await api.getPersistedSettings();
|
const state = await api.getPersistedSettings();
|
||||||
|
|
||||||
assert.equal(state.activeFlowId, 'kiro');
|
assert.equal(state.activeFlowId, 'kiro');
|
||||||
assert.equal(state.panelMode, 'sub2api');
|
assert.equal(state.targetId, 'kiro-rs');
|
||||||
|
assert.equal(state.settingsState.flows.openai.selectedTargetId, 'sub2api');
|
||||||
assert.equal(state.mailProvider, 'hotmail');
|
assert.equal(state.mailProvider, 'hotmail');
|
||||||
assert.equal(state.ipProxyEnabled, true);
|
assert.equal(state.ipProxyEnabled, true);
|
||||||
assert.equal(state.kiroRsUrl, 'https://kiro.example.com/admin');
|
assert.equal(state.kiroRsUrl, 'https://kiro.example.com/admin');
|
||||||
@@ -435,7 +434,7 @@ function getRemovedKeys() {
|
|||||||
`);
|
`);
|
||||||
|
|
||||||
const persisted = await api.setPersistentSettings({
|
const persisted = await api.setPersistentSettings({
|
||||||
settingsSchemaVersion: 4,
|
settingsSchemaVersion: 5,
|
||||||
settingsState: {
|
settingsState: {
|
||||||
activeFlowId: 'kiro',
|
activeFlowId: 'kiro',
|
||||||
services: {
|
services: {
|
||||||
@@ -445,8 +444,8 @@ function getRemovedKeys() {
|
|||||||
},
|
},
|
||||||
flows: {
|
flows: {
|
||||||
openai: {
|
openai: {
|
||||||
integrationTargetId: 'cpa',
|
selectedTargetId: 'cpa',
|
||||||
integrationTargets: {
|
targets: {
|
||||||
cpa: {
|
cpa: {
|
||||||
vpsUrl: '',
|
vpsUrl: '',
|
||||||
vpsPassword: '',
|
vpsPassword: '',
|
||||||
@@ -481,7 +480,7 @@ function getRemovedKeys() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
kiro: {
|
kiro: {
|
||||||
targetId: 'kiro-rs',
|
selectedTargetId: 'kiro-rs',
|
||||||
targets: {
|
targets: {
|
||||||
'kiro-rs': {
|
'kiro-rs': {
|
||||||
baseUrl: 'https://kiro.example.com/admin',
|
baseUrl: 'https://kiro.example.com/admin',
|
||||||
@@ -499,21 +498,20 @@ function getRemovedKeys() {
|
|||||||
const write = api.getPersistedWrites().at(-1);
|
const write = api.getPersistedWrites().at(-1);
|
||||||
|
|
||||||
assert.equal(persisted.activeFlowId, 'kiro');
|
assert.equal(persisted.activeFlowId, 'kiro');
|
||||||
assert.equal(persisted.kiroTargetId, 'kiro-rs');
|
assert.equal(persisted.targetId, 'kiro-rs');
|
||||||
assert.equal(persisted.kiroRsUrl, 'https://kiro.example.com/admin');
|
assert.equal(persisted.kiroRsUrl, 'https://kiro.example.com/admin');
|
||||||
assert.equal(persisted.kiroRsKey, 'nested-only-key');
|
assert.equal(persisted.kiroRsKey, 'nested-only-key');
|
||||||
assert.equal(persisted.plusAccountAccessStrategy, 'sub2api_codex_session');
|
assert.equal(persisted.plusAccountAccessStrategy, 'sub2api_codex_session');
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(persisted, 'kiroRegion'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(persisted, 'kiroRegion'), false);
|
||||||
assert.equal(persisted.settingsSchemaVersion, 4);
|
assert.equal(persisted.settingsSchemaVersion, 5);
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(write, 'activeFlowId'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(write, 'activeFlowId'), false);
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(write, 'kiroRsUrl'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(write, 'kiroRsUrl'), false);
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(write, 'kiroRsKey'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(write, 'kiroRsKey'), false);
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(write, 'kiroRegion'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(write, 'kiroRegion'), false);
|
||||||
assert.equal(write.settingsSchemaVersion, 4);
|
assert.equal(write.settingsSchemaVersion, 5);
|
||||||
assert.equal(write.settingsState.activeFlowId, 'kiro');
|
assert.equal(write.settingsState.activeFlowId, 'kiro');
|
||||||
assert.equal(write.settingsState.flows.openai.plus.plusAccountAccessStrategy, 'sub2api_codex_session');
|
assert.equal(write.settingsState.flows.openai.plus.plusAccountAccessStrategy, 'sub2api_codex_session');
|
||||||
assert.equal(write.settingsState.flows.kiro.targetId, 'kiro-rs');
|
assert.equal(write.settingsState.flows.kiro.selectedTargetId, 'kiro-rs');
|
||||||
assert.ok(api.getRemovedKeys().includes('panelMode'));
|
|
||||||
assert.ok(api.getRemovedKeys().includes('kiroRsUrl'));
|
assert.ok(api.getRemovedKeys().includes('kiroRsUrl'));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -526,7 +524,7 @@ const chrome = {
|
|||||||
local: {
|
local: {
|
||||||
async get() {
|
async get() {
|
||||||
return {
|
return {
|
||||||
settingsSchemaVersion: 4,
|
settingsSchemaVersion: 5,
|
||||||
settingsState: {
|
settingsState: {
|
||||||
activeFlowId: 'openai',
|
activeFlowId: 'openai',
|
||||||
services: {
|
services: {
|
||||||
@@ -575,7 +573,7 @@ const chrome = {
|
|||||||
local: {
|
local: {
|
||||||
async get() {
|
async get() {
|
||||||
return {
|
return {
|
||||||
settingsSchemaVersion: 4,
|
settingsSchemaVersion: 5,
|
||||||
settingsState: {
|
settingsState: {
|
||||||
activeFlowId: 'openai',
|
activeFlowId: 'openai',
|
||||||
services: {
|
services: {
|
||||||
@@ -585,8 +583,8 @@ const chrome = {
|
|||||||
},
|
},
|
||||||
flows: {
|
flows: {
|
||||||
openai: {
|
openai: {
|
||||||
integrationTargetId: 'cpa',
|
selectedTargetId: 'cpa',
|
||||||
integrationTargets: {
|
targets: {
|
||||||
cpa: {
|
cpa: {
|
||||||
vpsUrl: 'https://old-cpa.example.com',
|
vpsUrl: 'https://old-cpa.example.com',
|
||||||
vpsPassword: 'old-vps-password',
|
vpsPassword: 'old-vps-password',
|
||||||
@@ -621,7 +619,7 @@ const chrome = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
kiro: {
|
kiro: {
|
||||||
targetId: 'kiro-rs',
|
selectedTargetId: 'kiro-rs',
|
||||||
targets: {
|
targets: {
|
||||||
'kiro-rs': {
|
'kiro-rs': {
|
||||||
baseUrl: 'https://kiro.example.com/admin',
|
baseUrl: 'https://kiro.example.com/admin',
|
||||||
@@ -654,7 +652,7 @@ function getRemovedKeys() {
|
|||||||
`);
|
`);
|
||||||
|
|
||||||
const persisted = await api.setPersistentSettings({
|
const persisted = await api.setPersistentSettings({
|
||||||
panelMode: 'sub2api',
|
targetId: 'sub2api',
|
||||||
mailProvider: 'cloudflare-temp-email',
|
mailProvider: 'cloudflare-temp-email',
|
||||||
ipProxyEnabled: true,
|
ipProxyEnabled: true,
|
||||||
ipProxyMode: 'api',
|
ipProxyMode: 'api',
|
||||||
@@ -664,7 +662,7 @@ function getRemovedKeys() {
|
|||||||
});
|
});
|
||||||
const write = api.getPersistedWrites().at(-1);
|
const write = api.getPersistedWrites().at(-1);
|
||||||
|
|
||||||
assert.equal(persisted.panelMode, 'sub2api');
|
assert.equal(persisted.targetId, 'sub2api');
|
||||||
assert.equal(persisted.mailProvider, 'cloudflare-temp-email');
|
assert.equal(persisted.mailProvider, 'cloudflare-temp-email');
|
||||||
assert.equal(persisted.ipProxyEnabled, true);
|
assert.equal(persisted.ipProxyEnabled, true);
|
||||||
assert.equal(persisted.ipProxyMode, 'api');
|
assert.equal(persisted.ipProxyMode, 'api');
|
||||||
@@ -673,7 +671,7 @@ function getRemovedKeys() {
|
|||||||
fromStep: 2,
|
fromStep: 2,
|
||||||
toStep: 4,
|
toStep: 4,
|
||||||
});
|
});
|
||||||
assert.equal(write.settingsState.flows.openai.integrationTargetId, 'sub2api');
|
assert.equal(write.settingsState.flows.openai.selectedTargetId, 'sub2api');
|
||||||
assert.equal(write.settingsState.services.email.provider, 'cloudflare-temp-email');
|
assert.equal(write.settingsState.services.email.provider, 'cloudflare-temp-email');
|
||||||
assert.equal(write.settingsState.services.proxy.enabled, true);
|
assert.equal(write.settingsState.services.proxy.enabled, true);
|
||||||
assert.equal(write.settingsState.services.proxy.mode, 'api');
|
assert.equal(write.settingsState.services.proxy.mode, 'api');
|
||||||
@@ -682,8 +680,8 @@ function getRemovedKeys() {
|
|||||||
fromStep: 2,
|
fromStep: 2,
|
||||||
toStep: 4,
|
toStep: 4,
|
||||||
});
|
});
|
||||||
assert.equal(write.settingsState.flows.openai.integrationTargets.sub2api.sub2apiUrl, 'https://sub2api.example.com');
|
assert.equal(write.settingsState.flows.openai.targets.sub2api.sub2apiUrl, 'https://sub2api.example.com');
|
||||||
assert.equal(write.settingsState.flows.openai.integrationTargets.sub2api.sub2apiEmail, 'owner@example.com');
|
assert.equal(write.settingsState.flows.openai.targets.sub2api.sub2apiEmail, 'owner@example.com');
|
||||||
assert.equal(write.settingsState.flows.kiro.targets['kiro-rs'].apiKey, 'kiro-key');
|
assert.equal(write.settingsState.flows.kiro.targets['kiro-rs'].apiKey, 'kiro-key');
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(write, 'mailProvider'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(write, 'mailProvider'), false);
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(write, 'panelMode'), false);
|
assert.equal(Object.prototype.hasOwnProperty.call(write, 'panelMode'), false);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
const assert = require('node:assert/strict');
|
const assert = require('node:assert/strict');
|
||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
const step2Source = fs.readFileSync('background/steps/submit-signup-email.js', 'utf8');
|
const step2Source = fs.readFileSync('flows/openai/background/steps/submit-signup-email.js', 'utf8');
|
||||||
const step2GlobalScope = {};
|
const step2GlobalScope = {};
|
||||||
const step2Api = new Function('self', `${step2Source}; return self.MultiPageBackgroundStep2;`)(step2GlobalScope);
|
const step2Api = new Function('self', `${step2Source}; return self.MultiPageBackgroundStep2;`)(step2GlobalScope);
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ test('step 2 completes with password step skipped when landing on email verifica
|
|||||||
isTabAlive: async () => true,
|
isTabAlive: async () => true,
|
||||||
resolveSignupEmailForFlow: async () => 'user@example.com',
|
resolveSignupEmailForFlow: async () => 'user@example.com',
|
||||||
sendToContentScriptResilient: async () => ({ submitted: true }),
|
sendToContentScriptResilient: async () => ({ submitted: true }),
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
await executor.executeStep2({ email: 'user@example.com' });
|
await executor.executeStep2({ email: 'user@example.com' });
|
||||||
@@ -72,7 +72,7 @@ test('step 2 keeps password flow when landing on password page', async () => {
|
|||||||
isTabAlive: async () => true,
|
isTabAlive: async () => true,
|
||||||
resolveSignupEmailForFlow: async () => 'user@example.com',
|
resolveSignupEmailForFlow: async () => 'user@example.com',
|
||||||
sendToContentScriptResilient: async () => ({ submitted: true }),
|
sendToContentScriptResilient: async () => ({ submitted: true }),
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
await executor.executeStep2({ email: 'user@example.com' });
|
await executor.executeStep2({ email: 'user@example.com' });
|
||||||
@@ -150,7 +150,7 @@ test('step 2 uses phone activation when resolved signup method is phone', async
|
|||||||
sentPayloads.push(message.payload);
|
sentPayloads.push(message.payload);
|
||||||
return { submitted: true };
|
return { submitted: true };
|
||||||
},
|
},
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
await executor.executeStep2({ signupMethod: 'phone' });
|
await executor.executeStep2({ signupMethod: 'phone' });
|
||||||
@@ -233,7 +233,7 @@ test('step 2 reuses existing signup phone activation without acquiring a new num
|
|||||||
sentPayloads.push(message.payload);
|
sentPayloads.push(message.payload);
|
||||||
return { submitted: true };
|
return { submitted: true };
|
||||||
},
|
},
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
await executor.executeStep2({
|
await executor.executeStep2({
|
||||||
@@ -290,7 +290,7 @@ test('step 2 submits manual signup phone without acquiring a number', async () =
|
|||||||
sentPayloads.push(message.payload);
|
sentPayloads.push(message.payload);
|
||||||
return { submitted: true };
|
return { submitted: true };
|
||||||
},
|
},
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
await executor.executeStep2({
|
await executor.executeStep2({
|
||||||
@@ -354,7 +354,7 @@ test('step 2 stops with an explicit error instead of silently skipping 3/4/5 on
|
|||||||
isTabAlive: async () => true,
|
isTabAlive: async () => true,
|
||||||
resolveSignupEmailForFlow: async () => 'user@example.com',
|
resolveSignupEmailForFlow: async () => 'user@example.com',
|
||||||
sendToContentScriptResilient: async () => ({ submitted: true }),
|
sendToContentScriptResilient: async () => ({ submitted: true }),
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
await assert.rejects(
|
await assert.rejects(
|
||||||
@@ -405,7 +405,7 @@ test('step 2 does not force auth-entry retry on logged-out chatgpt home when con
|
|||||||
sentPayloads.push(message.payload);
|
sentPayloads.push(message.payload);
|
||||||
return { submitted: true };
|
return { submitted: true };
|
||||||
},
|
},
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
await executor.executeStep2({ email: 'user@example.com' });
|
await executor.executeStep2({ email: 'user@example.com' });
|
||||||
@@ -472,7 +472,7 @@ test('step 2 waits for the existing signup tab to settle before probing the entr
|
|||||||
}
|
}
|
||||||
return { submitted: true };
|
return { submitted: true };
|
||||||
},
|
},
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
waitForTabStableComplete: async (_tabId, options) => {
|
waitForTabStableComplete: async (_tabId, options) => {
|
||||||
events.push({ type: 'wait-stable', options });
|
events.push({ type: 'wait-stable', options });
|
||||||
return { id: 17, url: 'https://chatgpt.com/', status: 'complete' };
|
return { id: 17, url: 'https://chatgpt.com/', status: 'complete' };
|
||||||
@@ -543,7 +543,7 @@ test('signup flow helper recognizes email verification page as post-email landin
|
|||||||
},
|
},
|
||||||
setEmailState: async () => {},
|
setEmailState: async () => {},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
waitForTabUrlMatch: async () => ({
|
waitForTabUrlMatch: async () => ({
|
||||||
id: 21,
|
id: 21,
|
||||||
url: 'https://auth.openai.com/email-verification',
|
url: 'https://auth.openai.com/email-verification',
|
||||||
@@ -600,7 +600,7 @@ test('signup flow helper waits for the signup entry tab to settle for step 2 bef
|
|||||||
},
|
},
|
||||||
setEmailState: async () => {},
|
setEmailState: async () => {},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
waitForTabStableComplete: async (_tabId, options) => {
|
waitForTabStableComplete: async (_tabId, options) => {
|
||||||
events.push({ type: 'wait-stable', options });
|
events.push({ type: 'wait-stable', options });
|
||||||
return { id: 23, url: 'https://chatgpt.com/', status: 'complete' };
|
return { id: 23, url: 'https://chatgpt.com/', status: 'complete' };
|
||||||
@@ -680,7 +680,7 @@ test('signup flow helper accepts phone signup landing on login password page', a
|
|||||||
},
|
},
|
||||||
setEmailState: async () => {},
|
setEmailState: async () => {},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
waitForTabUrlMatch: async (_tabId, predicate) => {
|
waitForTabUrlMatch: async (_tabId, predicate) => {
|
||||||
const url = 'https://auth.openai.com/log-in/password';
|
const url = 'https://auth.openai.com/log-in/password';
|
||||||
return predicate(url) ? { id: 22, url } : null;
|
return predicate(url) ? { id: 22, url } : null;
|
||||||
@@ -724,7 +724,7 @@ test('signup flow helper reuses existing managed alias email when it is still co
|
|||||||
setEmailCalls += 1;
|
setEmailCalls += 1;
|
||||||
},
|
},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
waitForTabUrlMatch: async () => null,
|
waitForTabUrlMatch: async () => null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -767,7 +767,7 @@ test('signup flow helper can generate an email on demand when add-email starts f
|
|||||||
setStateCalls.push(updates);
|
setStateCalls.push(updates);
|
||||||
},
|
},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
waitForTabUrlMatch: async () => null,
|
waitForTabUrlMatch: async () => null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -836,7 +836,7 @@ test('signup flow helper delegates preserved phone identity email sync to the sh
|
|||||||
setStateCalls += 1;
|
setStateCalls += 1;
|
||||||
},
|
},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: [],
|
OPENAI_AUTH_INJECT_FILES: [],
|
||||||
waitForTabUrlMatch: async () => null,
|
waitForTabUrlMatch: async () => null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -901,7 +901,7 @@ test('signup flow helper finalizes step 3 submit by reusing signup verification
|
|||||||
},
|
},
|
||||||
setEmailState: async () => {},
|
setEmailState: async () => {},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: ['content/utils.js', 'content/signup-page.js'],
|
OPENAI_AUTH_INJECT_FILES: ['content/utils.js', 'flows/openai/content/openai-auth.js'],
|
||||||
waitForTabUrlMatch: async () => null,
|
waitForTabUrlMatch: async () => null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -943,11 +943,11 @@ test('signup flow helper rewrites retryable step 3 finalize transport timeout in
|
|||||||
isSignupPasswordPageUrl: () => true,
|
isSignupPasswordPageUrl: () => true,
|
||||||
reuseOrCreateTab: async () => 31,
|
reuseOrCreateTab: async () => 31,
|
||||||
sendToContentScriptResilient: async () => {
|
sendToContentScriptResilient: async () => {
|
||||||
throw new Error('Content script on signup-page did not respond in 45s. Try refreshing the tab and retry.');
|
throw new Error('Content script on openai-auth did not respond in 45s. Try refreshing the tab and retry.');
|
||||||
},
|
},
|
||||||
setEmailState: async () => {},
|
setEmailState: async () => {},
|
||||||
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
SIGNUP_ENTRY_URL: 'https://chatgpt.com/',
|
||||||
SIGNUP_PAGE_INJECT_FILES: ['content/utils.js', 'content/signup-page.js'],
|
OPENAI_AUTH_INJECT_FILES: ['content/utils.js', 'flows/openai/content/openai-auth.js'],
|
||||||
waitForTabUrlMatch: async () => null,
|
waitForTabUrlMatch: async () => null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,22 +6,22 @@ test('background imports workflow step modules including rebuilt Kiro modules',
|
|||||||
const source = fs.readFileSync('background.js', 'utf8');
|
const source = fs.readFileSync('background.js', 'utf8');
|
||||||
|
|
||||||
[
|
[
|
||||||
'background/steps/open-chatgpt.js',
|
'flows/openai/background/steps/open-chatgpt.js',
|
||||||
'background/steps/submit-signup-email.js',
|
'flows/openai/background/steps/submit-signup-email.js',
|
||||||
'background/steps/fill-password.js',
|
'flows/openai/background/steps/fill-password.js',
|
||||||
'background/steps/fetch-signup-code.js',
|
'flows/openai/background/steps/fetch-signup-code.js',
|
||||||
'background/steps/fill-profile.js',
|
'flows/openai/background/steps/fill-profile.js',
|
||||||
'background/steps/wait-registration-success.js',
|
'flows/openai/background/steps/wait-registration-success.js',
|
||||||
'background/steps/oauth-login.js',
|
'flows/openai/background/steps/oauth-login.js',
|
||||||
'background/steps/fetch-login-code.js',
|
'flows/openai/background/steps/fetch-login-code.js',
|
||||||
'background/steps/confirm-oauth.js',
|
'flows/openai/background/steps/confirm-oauth.js',
|
||||||
'background/steps/platform-verify.js',
|
'flows/openai/background/steps/platform-verify.js',
|
||||||
'shared/kiro-timeouts.js',
|
'shared/kiro-timeouts.js',
|
||||||
'background/kiro/state.js',
|
'flows/kiro/background/state.js',
|
||||||
'background/kiro/register-runner.js',
|
'flows/kiro/background/register-runner.js',
|
||||||
'background/kiro/desktop-client.js',
|
'flows/kiro/background/desktop-client.js',
|
||||||
'background/kiro/desktop-authorize-runner.js',
|
'flows/kiro/background/desktop-authorize-runner.js',
|
||||||
'background/kiro/publisher-kiro-rs.js',
|
'flows/kiro/background/publisher-kiro-rs.js',
|
||||||
].forEach((path) => {
|
].forEach((path) => {
|
||||||
assert.match(source, new RegExp(path.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
assert.match(source, new RegExp(path.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const assert = require('node:assert/strict');
|
|||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
test('background node registry preserves node metadata even before an executor is registered', () => {
|
test('background node registry preserves node metadata even before an executor is registered', () => {
|
||||||
const source = fs.readFileSync('background/steps/registry.js', 'utf8');
|
const source = fs.readFileSync('core/flow-kernel/step-registry.js', 'utf8');
|
||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundStepRegistry;`)({});
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundStepRegistry;`)({});
|
||||||
const registry = api.createNodeRegistry([
|
const registry = api.createNodeRegistry([
|
||||||
{
|
{
|
||||||
@@ -27,7 +27,7 @@ test('background node registry preserves node metadata even before an executor i
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('background node registry executes registered nodes in display order', async () => {
|
test('background node registry executes registered nodes in display order', async () => {
|
||||||
const source = fs.readFileSync('background/steps/registry.js', 'utf8');
|
const source = fs.readFileSync('core/flow-kernel/step-registry.js', 'utf8');
|
||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundStepRegistry;`)({});
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundStepRegistry;`)({});
|
||||||
const events = [];
|
const events = [];
|
||||||
const registry = api.createNodeRegistry([
|
const registry = api.createNodeRegistry([
|
||||||
|
|||||||
@@ -4,19 +4,19 @@ const fs = require('node:fs');
|
|||||||
|
|
||||||
test('background imports node registry and wires the rebuilt Kiro executors', () => {
|
test('background imports node registry and wires the rebuilt Kiro executors', () => {
|
||||||
const source = fs.readFileSync('background.js', 'utf8');
|
const source = fs.readFileSync('background.js', 'utf8');
|
||||||
assert.match(source, /background\/steps\/registry\.js/);
|
assert.match(source, /core\/flow-kernel\/step-registry\.js/);
|
||||||
assert.match(source, /data\/step-definitions\.js/);
|
assert.match(source, /data\/step-definitions\.js/);
|
||||||
assert.match(source, /background\/workflow-engine\.js/);
|
assert.match(source, /core\/flow-kernel\/workflow-engine\.js/);
|
||||||
assert.match(source, /MultiPageStepDefinitions\?\.getNodes/);
|
assert.match(source, /MultiPageStepDefinitions\?\.getNodes/);
|
||||||
assert.match(source, /buildNodeRegistry\(definitions/);
|
assert.match(source, /buildNodeRegistry\(definitions/);
|
||||||
assert.match(source, /const stepRegistryCache = new Map\(\);/);
|
assert.match(source, /const stepRegistryCache = new Map\(\);/);
|
||||||
assert.match(source, /const definitions = getNodeDefinitionsForState\(state\);/);
|
assert.match(source, /const definitions = getNodeDefinitionsForState\(state\);/);
|
||||||
assert.match(source, /stepRegistryCache\.set\(cacheKey, buildStepRegistry\(definitions\)\)/);
|
assert.match(source, /stepRegistryCache\.set\(cacheKey, buildStepRegistry\(definitions\)\)/);
|
||||||
|
|
||||||
assert.match(source, /background\/kiro\/register-runner\.js/);
|
assert.match(source, /flows\/kiro\/background\/register-runner\.js/);
|
||||||
assert.match(source, /background\/kiro\/desktop-client\.js/);
|
assert.match(source, /flows\/kiro\/background\/desktop-client\.js/);
|
||||||
assert.match(source, /background\/kiro\/desktop-authorize-runner\.js/);
|
assert.match(source, /flows\/kiro\/background\/desktop-authorize-runner\.js/);
|
||||||
assert.match(source, /background\/kiro\/publisher-kiro-rs\.js/);
|
assert.match(source, /flows\/kiro\/background\/publisher-kiro-rs\.js/);
|
||||||
assert.doesNotMatch(source, /background\/steps\/kiro-device-auth\.js/);
|
assert.doesNotMatch(source, /background\/steps\/kiro-device-auth\.js/);
|
||||||
|
|
||||||
assert.match(source, /const kiroRegisterRunner = self\.MultiPageBackgroundKiroRegisterRunner\?\.createKiroRegisterRunner\(/);
|
assert.match(source, /const kiroRegisterRunner = self\.MultiPageBackgroundKiroRegisterRunner\?\.createKiroRegisterRunner\(/);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user