fix kiro register driver readiness recovery
This commit is contained in:
@@ -601,6 +601,73 @@
|
||||
return tabId;
|
||||
}
|
||||
|
||||
async function injectKiroRegisterContentScripts(tabId) {
|
||||
if (
|
||||
!Number.isInteger(tabId)
|
||||
|| !chrome?.scripting?.executeScript
|
||||
|| !Array.isArray(KIRO_REGISTER_INJECT_FILES)
|
||||
|| !KIRO_REGISTER_INJECT_FILES.length
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await chrome.scripting.executeScript({
|
||||
target: { tabId },
|
||||
func: (injectedSource) => {
|
||||
window.__MULTIPAGE_SOURCE = injectedSource;
|
||||
},
|
||||
args: [KIRO_REGISTER_PAGE_SOURCE_ID],
|
||||
});
|
||||
await chrome.scripting.executeScript({
|
||||
target: { tabId },
|
||||
files: KIRO_REGISTER_INJECT_FILES,
|
||||
});
|
||||
await sleepWithStop(250);
|
||||
return true;
|
||||
}
|
||||
|
||||
function hasKiroRegisterPageState(result = {}) {
|
||||
return Boolean(result && typeof result === 'object' && cleanString(result.state));
|
||||
}
|
||||
|
||||
async function sendKiroStateDriverMessage(tabId, message, options = {}) {
|
||||
const {
|
||||
timeoutBudget,
|
||||
timeoutMs = 30000,
|
||||
} = options;
|
||||
let result = await sendToContentScriptResilient(KIRO_REGISTER_PAGE_SOURCE_ID, message, {
|
||||
timeoutMs,
|
||||
retryDelayMs: 700,
|
||||
onRetryableError: buildKiroRetryRecovery(tabId, {
|
||||
...options,
|
||||
timeoutBudget,
|
||||
}),
|
||||
logMessage: options.readyLogMessage || '正在等待 Kiro 页面进入下一状态...',
|
||||
});
|
||||
|
||||
if (!hasKiroRegisterPageState(result) && !result?.error) {
|
||||
await log('Kiro 注册页通用脚本已响应,但专用页面识别脚本未返回状态,正在重新注入 Kiro 注册页识别脚本...', 'warn');
|
||||
await injectKiroRegisterContentScripts(tabId);
|
||||
result = await sendToContentScriptResilient(KIRO_REGISTER_PAGE_SOURCE_ID, message, {
|
||||
timeoutMs: timeoutBudget?.getRemainingMs?.(1000) || timeoutMs,
|
||||
retryDelayMs: 700,
|
||||
onRetryableError: buildKiroRetryRecovery(tabId, {
|
||||
...options,
|
||||
timeoutBudget,
|
||||
}),
|
||||
logMessage: options.readyLogMessage || '正在等待 Kiro 页面进入下一状态...',
|
||||
});
|
||||
}
|
||||
|
||||
if (result?.error) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
if (!hasKiroRegisterPageState(result)) {
|
||||
throw new Error('Kiro 注册页专用页面识别脚本未返回页面状态,请刷新当前 AWS 页面或重新执行当前步骤。');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async function reattachKiroRegisterPage(tabId, options = {}) {
|
||||
if (!Number.isInteger(tabId)) {
|
||||
throw new Error('缺少 Kiro 注册页标签页,无法重新连接内容脚本。');
|
||||
@@ -675,7 +742,7 @@
|
||||
};
|
||||
}
|
||||
const stateWaitTimeoutMs = timeoutBudget.getRemainingMs(1000);
|
||||
const result = await sendToContentScriptResilient(KIRO_REGISTER_PAGE_SOURCE_ID, {
|
||||
const message = {
|
||||
type: 'ENSURE_KIRO_PAGE_STATE',
|
||||
step: options.step || 0,
|
||||
source: 'background',
|
||||
@@ -685,19 +752,13 @@
|
||||
retryDelayMs: Number(options.pageRetryDelayMs) || 250,
|
||||
timeoutMessage: options.timeoutMessage || '',
|
||||
},
|
||||
}, {
|
||||
};
|
||||
|
||||
return sendKiroStateDriverMessage(tabId, message, {
|
||||
...options,
|
||||
timeoutBudget,
|
||||
timeoutMs: stateWaitTimeoutMs,
|
||||
retryDelayMs: 700,
|
||||
onRetryableError: buildKiroRetryRecovery(tabId, {
|
||||
...options,
|
||||
timeoutBudget,
|
||||
}),
|
||||
logMessage: options.readyLogMessage || '正在等待 Kiro 页面进入下一状态...',
|
||||
});
|
||||
if (result?.error) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
return result || { state: '', url: '' };
|
||||
}
|
||||
|
||||
async function waitForKiroPageChange(tabId, options = {}) {
|
||||
@@ -730,7 +791,7 @@
|
||||
return { state: '', url: '' };
|
||||
}
|
||||
const stateWaitTimeoutMs = timeoutBudget.getRemainingMs(1000);
|
||||
const result = await sendToContentScriptResilient(KIRO_REGISTER_PAGE_SOURCE_ID, {
|
||||
const message = {
|
||||
type: 'ENSURE_KIRO_STATE_CHANGE',
|
||||
step: options.step || 0,
|
||||
source: 'background',
|
||||
@@ -741,19 +802,13 @@
|
||||
returnOnCodeInvalid: Boolean(options.returnOnCodeInvalid),
|
||||
timeoutMessage: options.timeoutMessage || '',
|
||||
},
|
||||
}, {
|
||||
};
|
||||
return sendKiroStateDriverMessage(tabId, message, {
|
||||
...options,
|
||||
timeoutBudget,
|
||||
timeoutMs: stateWaitTimeoutMs,
|
||||
retryDelayMs: 700,
|
||||
onRetryableError: buildKiroRetryRecovery(tabId, {
|
||||
...options,
|
||||
timeoutBudget,
|
||||
}),
|
||||
logMessage: options.readyLogMessage || '正在等待 Kiro 页面完成跳转...',
|
||||
readyLogMessage: options.readyLogMessage || '正在等待 Kiro 页面完成跳转...',
|
||||
});
|
||||
if (result?.error) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
return result || { state: '', url: '' };
|
||||
}
|
||||
|
||||
async function readKiroRegisterPageState(tabId, options = {}) {
|
||||
|
||||
@@ -364,6 +364,110 @@ test('kiro verification step can adopt the active AWS verify-otp page without st
|
||||
assert.equal(getKiroRuntime(completedPayload).register?.email, 'tmp3x58ft2ivc@edu.email.qlhazycoder.tech');
|
||||
});
|
||||
|
||||
test('kiro verification step reinjects the register driver when only the generic content script responds', async () => {
|
||||
const api = loadRegisterRunnerApi();
|
||||
const currentState = {
|
||||
email: 'tmp3x58ft2ivc@edu.email.qlhazycoder.tech',
|
||||
registrationEmailState: {
|
||||
current: 'tmp3x58ft2ivc@edu.email.qlhazycoder.tech',
|
||||
previous: 'tmp3x58ft2ivc@edu.email.qlhazycoder.tech',
|
||||
source: 'manual',
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
runtimeState: {
|
||||
flowState: {
|
||||
kiro: {
|
||||
session: {
|
||||
registerTabId: 302,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const sentMessages = [];
|
||||
const injectedScripts = [];
|
||||
const pollPayloads = [];
|
||||
let completedPayload = null;
|
||||
const runner = api.createKiroRegisterRunner({
|
||||
addLog: async () => {},
|
||||
chrome: {
|
||||
scripting: {
|
||||
executeScript: async (payload) => {
|
||||
injectedScripts.push(payload);
|
||||
},
|
||||
},
|
||||
tabs: {
|
||||
get: async (tabId) => ({
|
||||
id: tabId,
|
||||
url: 'https://profile.aws.amazon.com/?workflowID=b4e8f9ff-3d60-40ce-90ec-d2113d951b08#/signup/verify-otp',
|
||||
}),
|
||||
update: async () => {},
|
||||
},
|
||||
},
|
||||
completeNodeFromBackground: async (_nodeId, payload) => {
|
||||
completedPayload = payload;
|
||||
},
|
||||
getMailConfig: () => ({
|
||||
provider: 'cloudflare-temp-email',
|
||||
source: 'cloudflare-temp-email',
|
||||
label: 'Cloudflare Temp Email',
|
||||
}),
|
||||
getState: async () => currentState,
|
||||
getTabId: async () => 302,
|
||||
isTabAlive: async () => true,
|
||||
KIRO_REGISTER_INJECT_FILES: [
|
||||
'content/utils.js',
|
||||
'flows/kiro/content/register-page.js',
|
||||
],
|
||||
pollCloudflareTempEmailVerificationCode: async (_step, _state, payload) => {
|
||||
pollPayloads.push(payload);
|
||||
return { code: '248680', emailTimestamp: 2000, mailId: 'mail-reinject' };
|
||||
},
|
||||
sendToContentScriptResilient: async (_sourceId, message) => {
|
||||
sentMessages.push(message);
|
||||
const ensureCount = sentMessages.filter((entry) => entry.type === 'ENSURE_KIRO_PAGE_STATE').length;
|
||||
if (message.type === 'ENSURE_KIRO_PAGE_STATE' && ensureCount === 1) {
|
||||
return undefined;
|
||||
}
|
||||
if (message.type === 'ENSURE_KIRO_PAGE_STATE') {
|
||||
return {
|
||||
state: 'register_otp_page',
|
||||
url: 'https://profile.aws.amazon.com/?workflowID=b4e8f9ff-3d60-40ce-90ec-d2113d951b08#/signup/verify-otp',
|
||||
email: 'tmp3x58ft2ivc@edu.email.qlhazycoder.tech',
|
||||
};
|
||||
}
|
||||
if (message.type === 'EXECUTE_NODE') {
|
||||
return { submitted: true, state: 'verification_submitted' };
|
||||
}
|
||||
if (message.type === 'ENSURE_KIRO_STATE_CHANGE') {
|
||||
return {
|
||||
state: 'create_password_page',
|
||||
url: 'https://profile.aws.amazon.com/?workflowID=b4e8f9ff-3d60-40ce-90ec-d2113d951b08#/signup/create-password',
|
||||
email: 'tmp3x58ft2ivc@edu.email.qlhazycoder.tech',
|
||||
};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
setState: async () => {},
|
||||
sleepWithStop: async () => {},
|
||||
});
|
||||
|
||||
await runner.executeKiroSubmitVerificationCode({
|
||||
nodeId: 'kiro-submit-verification-code',
|
||||
...currentState,
|
||||
});
|
||||
|
||||
assert.equal(sentMessages.filter((message) => message.type === 'ENSURE_KIRO_PAGE_STATE').length, 2);
|
||||
assert.equal(injectedScripts.length, 2);
|
||||
assert.deepEqual(injectedScripts[0].args, ['kiro-register-page']);
|
||||
assert.deepEqual(injectedScripts[1].files, [
|
||||
'content/utils.js',
|
||||
'flows/kiro/content/register-page.js',
|
||||
]);
|
||||
assert.equal(pollPayloads[0].targetEmail, 'tmp3x58ft2ivc@edu.email.qlhazycoder.tech');
|
||||
assert.equal(getKiroRuntime(completedPayload).register?.email, 'tmp3x58ft2ivc@edu.email.qlhazycoder.tech');
|
||||
});
|
||||
|
||||
test('kiro submit-email reuses the step 1 register tab even when the source registry was reset', async () => {
|
||||
const api = loadRegisterRunnerApi();
|
||||
const currentState = {
|
||||
|
||||
Reference in New Issue
Block a user