From 9d048779545f5edc565dbee42843d13cdb3c2cf6 Mon Sep 17 00:00:00 2001 From: QLHazyCoder <2825305047@qq.com> Date: Mon, 18 May 2026 03:47:03 +0800 Subject: [PATCH] Localize Kiro flow copy --- background.js | 8 +- background/steps/kiro-device-auth.js | 73 +++++++++++-------- data/step-definitions.js | 6 +- sidepanel/sidepanel.js | 32 +++++++- ...background-kiro-device-auth-module.test.js | 6 +- tests/step-definitions-module.test.js | 3 + 6 files changed, 89 insertions(+), 39 deletions(-) diff --git a/background.js b/background.js index 245bbe9..7ca8aeb 100644 --- a/background.js +++ b/background.js @@ -1,4 +1,4 @@ -// background.js — Service Worker: orchestration, state, tab management, message routing +// background.js — Service Worker: orchestration, state, tab management, message routing importScripts( 'shared/flow-registry.js', @@ -12397,6 +12397,10 @@ async function runAutoSequenceFromNodeGraph(startNodeId, context = {}) { }; const initialFlowState = await getState(); const activeFlowId = String(initialFlowState?.activeFlowId || initialFlowState?.flowId || DEFAULT_ACTIVE_FLOW_ID).trim().toLowerCase() || DEFAULT_ACTIVE_FLOW_ID; + const activeFlowLabel = String( + self.MultiPageFlowRegistry?.getFlowLabel?.(activeFlowId) + || activeFlowId + ).trim() || activeFlowId; if (activeFlowId !== DEFAULT_ACTIVE_FLOW_ID) { await broadcastAutoRunStatus('running', { @@ -12409,7 +12413,7 @@ async function runAutoSequenceFromNodeGraph(startNodeId, context = {}) { if (continueCurrentAttempt) { await addLog(`=== 目标 ${targetRun}/${totalRuns} 轮:继续当前进度,从节点 ${currentStartNodeId} 开始(第 ${attemptRuns} 次尝试)===`, 'info'); } else { - await addLog(`=== 目标 ${targetRun}/${totalRuns} 轮:第 ${attemptRuns} 次尝试,开始执行 ${activeFlowId} flow ===`, 'info'); + await addLog(`=== 目标 ${targetRun}/${totalRuns} 轮:第 ${attemptRuns} 次尝试,开始执行 ${activeFlowLabel} 流程 ===`, 'info'); } let latestState = await getState(); diff --git a/background/steps/kiro-device-auth.js b/background/steps/kiro-device-auth.js index 1cc6fb9..2827bfc 100644 --- a/background/steps/kiro-device-auth.js +++ b/background/steps/kiro-device-auth.js @@ -26,7 +26,7 @@ function normalizeKiroRsBaseUrl(value = '') { const normalized = cleanString(value).replace(/\/+$/, ''); if (!normalized) { - throw new Error('Missing kiro.rs admin URL.'); + throw new Error('缺少 kiro.rs 管理后台地址。'); } return normalized.endsWith('/admin') ? normalized.slice(0, -'/admin'.length) @@ -45,7 +45,20 @@ } function getErrorMessage(error) { - return error instanceof Error ? error.message : String(error ?? 'Unknown error'); + return error instanceof Error ? error.message : String(error ?? '未知错误'); + } + + function normalizeKiroUploadMessage(value = '') { + const rawValue = cleanString(value); + if (!rawValue) { + return '上传成功'; + } + + const normalizedValue = rawValue.toLowerCase(); + if (normalizedValue === 'uploaded' || normalizedValue === 'credential uploaded.') { + return '上传成功'; + } + return rawValue; } function normalizePositiveInteger(value, fallback) { @@ -121,13 +134,13 @@ }); const registerBody = await readResponse(registerResponse); if (!registerResponse.ok) { - throw new Error(`Builder ID client registration failed: ${cleanString(registerBody.text || registerResponse.statusText) || registerResponse.status}`); + throw new Error(`Builder ID 客户端注册失败:${cleanString(registerBody.text || registerResponse.statusText) || registerResponse.status}`); } const clientId = cleanString(registerBody.json?.clientId); const clientSecret = String(registerBody.json?.clientSecret || ''); if (!clientId || !clientSecret) { - throw new Error('Builder ID client registration response is missing client credentials.'); + throw new Error('Builder ID 客户端注册响应缺少凭据。'); } const authorizationResponse = await fetchImpl(`${oidcBaseUrl}/device_authorization`, { @@ -143,7 +156,7 @@ }); const authorizationBody = await readResponse(authorizationResponse); if (!authorizationResponse.ok) { - throw new Error(`Builder ID device authorization failed: ${cleanString(authorizationBody.text || authorizationResponse.statusText) || authorizationResponse.status}`); + throw new Error(`Builder ID 设备授权失败:${cleanString(authorizationBody.text || authorizationResponse.statusText) || authorizationResponse.status}`); } const deviceCode = String(authorizationBody.json?.deviceCode || ''); @@ -155,7 +168,7 @@ const interval = normalizePositiveInteger(authorizationBody.json?.interval, 5); const expiresIn = normalizePositiveInteger(authorizationBody.json?.expiresIn, 600); if (!deviceCode || !userCode || !verificationUriComplete) { - throw new Error('Builder ID device authorization response is missing required fields.'); + throw new Error('Builder ID 设备授权响应缺少必要字段。'); } return { @@ -205,14 +218,14 @@ return { completed: false, status: 'slow_down' }; } if (errorCode === 'expired_token') { - throw new Error('Kiro device login expired.'); + throw new Error('Kiro 设备登录已过期。'); } if (errorCode === 'access_denied') { - throw new Error('User denied the Builder ID device login request.'); + throw new Error('用户拒绝了 Builder ID 设备登录授权请求。'); } - throw new Error(`Builder ID authorization failed: ${errorCode || cleanString(body.text || response.statusText) || response.status}`); + throw new Error(`Builder ID 授权失败:${errorCode || cleanString(body.text || response.statusText) || response.status}`); } - throw new Error(`Builder ID token request failed: HTTP ${response.status}`); + throw new Error(`Builder ID 令牌请求失败:HTTP ${response.status}`); } async function checkKiroRsConnection(baseUrl, apiKey, fetchImpl) { @@ -228,31 +241,31 @@ if (response.ok) { return { ok: true, - message: `kiro.rs connection ok (HTTP ${response.status})`, + message: `kiro.rs 连接正常(HTTP ${response.status})`, }; } if (response.status === 405) { return { ok: true, - message: 'kiro.rs upload endpoint is reachable.', + message: 'kiro.rs 上传接口可访问。', }; } if (response.status === 401 || response.status === 403) { return { ok: false, - message: `kiro.rs API key rejected (HTTP ${response.status})`, + message: `kiro.rs API Key 被拒绝(HTTP ${response.status})`, }; } if (response.status === 404) { return { ok: false, - message: 'kiro.rs admin endpoint not found.', + message: '未找到 kiro.rs 管理接口。', }; } return { ok: false, message: cleanString(body.json?.error?.message || body.json?.message || body.text || response.statusText) - || `kiro.rs connection failed (HTTP ${response.status})`, + || `kiro.rs 连接失败(HTTP ${response.status})`, }; } @@ -271,13 +284,13 @@ if (!response.ok) { const message = cleanString(body.json?.error?.message || body.json?.message || body.text || response.statusText) || `HTTP ${response.status}`; - throw new Error(`kiro.rs credential upload failed: ${message}`); + throw new Error(`kiro.rs 凭据上传失败:${message}`); } return { credentialId: Number(body.json?.credentialId || body.json?.credential_id || 0) || null, email: cleanString(body.json?.email), - message: cleanString(body.json?.message) || 'Credential uploaded.', + message: normalizeKiroUploadMessage(body.json?.message), raw: body.json, }; } @@ -360,7 +373,7 @@ }; await setState(updates); - await log(`Kiro device login started. Open ${loginUrl} and approve with code ${auth.userCode}.`, 'info', nodeId); + await log(`Kiro 设备登录已启动。请打开 ${loginUrl},并输入授权码 ${auth.userCode} 完成确认。`, 'info', nodeId); await completeNodeFromBackground(nodeId, updates); } catch (error) { const message = getErrorMessage(error); @@ -382,10 +395,10 @@ const region = normalizeRegion(latestState.kiroAuthRegion, DEFAULT_REGION); const expiresAt = Math.max(0, Number(latestState.kiroAuthExpiresAt) || 0); if (!clientId || !clientSecret || !deviceCode) { - throw new Error('Kiro device login has not been started yet.'); + throw new Error('尚未启动 Kiro 设备登录,请先执行步骤 1。'); } if (!expiresAt || expiresAt <= Date.now()) { - throw new Error('Kiro device login expired. Restart step 1.'); + throw new Error('Kiro 设备登录已过期,请重新执行步骤 1。'); } await setState({ @@ -393,7 +406,7 @@ kiroAuthStatus: 'waiting_user', kiroUploadStatus: 'waiting_login', }); - await log('Waiting for Kiro device login approval...', 'info', nodeId); + await log('正在等待 Kiro 设备登录授权确认...', 'info', nodeId); let intervalSeconds = normalizePositiveInteger(latestState.kiroAuthIntervalSeconds, 5); while (Date.now() < expiresAt) { @@ -414,7 +427,7 @@ kiroUploadStatus: 'ready_to_upload', }; await setState(updates); - await log('Kiro device login approved. Refresh token captured.', 'ok', nodeId); + await log('Kiro 设备登录已确认,已获取 Refresh Token。', 'ok', nodeId); await completeNodeFromBackground(nodeId, updates); return; } @@ -425,12 +438,12 @@ await sleepWithStop(intervalSeconds * 1000); } - throw new Error('Kiro device login expired. Restart step 1.'); + throw new Error('Kiro 设备登录已过期,请重新执行步骤 1。'); } catch (error) { const message = getErrorMessage(error); await persistFailure({ kiroAuthError: message, - kiroAuthStatus: /expired/i.test(message) ? 'expired' : 'error', + kiroAuthStatus: /(expired|已过期)/i.test(message) ? 'expired' : 'error', }); throw error; } @@ -447,20 +460,20 @@ const kiroRsUrl = String(latestState.kiroRsUrl || ''); const kiroRsKey = String(latestState.kiroRsKey || ''); if (!refreshToken || !clientId || !clientSecret) { - throw new Error('Kiro refresh token is missing. Complete step 2 first.'); + throw new Error('缺少 Kiro Refresh Token,请先完成步骤 2。'); } if (!cleanString(kiroRsUrl)) { - throw new Error('Missing kiro.rs admin URL.'); + throw new Error('缺少 kiro.rs 管理后台地址。'); } if (!cleanString(kiroRsKey)) { - throw new Error('Missing kiro.rs API key.'); + throw new Error('缺少 kiro.rs API Key。'); } await setState({ kiroUploadError: '', kiroUploadStatus: 'uploading', }); - await log('Uploading Builder ID credential to kiro.rs...', 'info', nodeId); + await log('正在上传 Builder ID 凭据到 kiro.rs...', 'info', nodeId); const connection = await checkKiroRsConnection(kiroRsUrl, kiroRsKey, fetchImpl); await setState({ @@ -492,11 +505,11 @@ kiroCredentialId: uploadResult.credentialId, kiroLastUploadAt: Date.now(), kiroUploadError: '', - kiroUploadStatus: uploadResult.message || 'uploaded', + kiroUploadStatus: normalizeKiroUploadMessage(uploadResult.message), }; await setState(updates); - await log(`kiro.rs upload completed: ${updates.kiroUploadStatus}`, 'ok', nodeId); + await log(`kiro.rs 上传完成:${updates.kiroUploadStatus}`, 'ok', nodeId); await completeNodeFromBackground(nodeId, updates); } catch (error) { const message = getErrorMessage(error); diff --git a/data/step-definitions.js b/data/step-definitions.js index c58047c..5ed39b3 100644 --- a/data/step-definitions.js +++ b/data/step-definitions.js @@ -116,7 +116,7 @@ id: 1, order: 10, key: 'kiro-start-device-login', - title: 'Start device login', + title: '启动设备登录', sourceId: 'kiro-device-auth', driverId: 'background/kiro-device-auth', command: 'kiro-start-device-login', @@ -125,7 +125,7 @@ id: 2, order: 20, key: 'kiro-await-device-login', - title: 'Wait for device login', + title: '等待设备登录确认', sourceId: 'kiro-device-auth', driverId: 'background/kiro-device-auth', command: 'kiro-await-device-login', @@ -134,7 +134,7 @@ id: 3, order: 30, key: 'kiro-upload-credential', - title: 'Upload credential to kiro.rs', + title: '上传凭据到 kiro.rs', sourceId: 'kiro-rs-admin', driverId: 'background/kiro-device-auth', command: 'kiro-upload-credential', diff --git a/sidepanel/sidepanel.js b/sidepanel/sidepanel.js index 82a0c63..b198850 100644 --- a/sidepanel/sidepanel.js +++ b/sidepanel/sidepanel.js @@ -2373,6 +2373,36 @@ function normalizeStepExecutionRangeEntry(value = {}) { }; } +function getKiroUploadStatusLabel(value = '') { + const rawValue = String(value || '').trim(); + if (!rawValue) { + return '未开始'; + } + + const normalizedValue = rawValue.toLowerCase(); + switch (normalizedValue) { + case 'waiting_login': + return '等待登录授权'; + case 'ready_to_upload': + return '等待上传'; + case 'uploading': + return '上传中'; + case 'uploaded': + case 'credential uploaded.': + return '上传成功'; + case 'error': + return '上传失败'; + case 'waiting_user': + return '等待用户确认'; + case 'authorized': + return '已授权'; + case 'expired': + return '已过期'; + default: + return rawValue; + } +} + function normalizeStepExecutionRangeByFlow(value = {}) { const source = isPlainObjectValue(value) ? value : {}; const next = {}; @@ -9954,7 +9984,7 @@ function applySettingsState(state) { || state?.kiroUploadStatus || '' ).trim(); - displayKiroUploadStatus.textContent = kiroUploadStatus || '未开始'; + displayKiroUploadStatus.textContent = getKiroUploadStatusLabel(kiroUploadStatus); } const normalizedIpProxyService = resolveIpProxyService(state?.ipProxyService); const normalizedIpProxyServiceProfiles = typeof normalizeIpProxyServiceProfiles === 'function' diff --git a/tests/background-kiro-device-auth-module.test.js b/tests/background-kiro-device-auth-module.test.js index cc03db1..5ce43ff 100644 --- a/tests/background-kiro-device-auth-module.test.js +++ b/tests/background-kiro-device-auth-module.test.js @@ -312,15 +312,15 @@ test('kiro upload credential checks connection and uploads builder id credential }); const finalState = mergeUpdates(stateUpdates); - assert.equal(finalState.kiroLastConnectionMessage, 'kiro.rs connection ok (HTTP 200)'); + assert.equal(finalState.kiroLastConnectionMessage, 'kiro.rs 连接正常(HTTP 200)'); assert.equal(finalState.kiroAuthorizedEmail, 'aws-user@example.com'); assert.equal(finalState.kiroCredentialId, 321); - assert.equal(finalState.kiroUploadStatus, 'uploaded'); + assert.equal(finalState.kiroUploadStatus, '上传成功'); assert.equal(typeof finalState.kiroLastUploadAt, 'number'); assert.equal(finalState.kiroLastUploadAt > 0, true); assert.equal(completeCalls.length, 1); assert.equal(completeCalls[0].nodeId, 'kiro-upload-credential'); assert.equal(completeCalls[0].payload.kiroCredentialId, 321); - assert.equal(completeCalls[0].payload.kiroUploadStatus, 'uploaded'); + assert.equal(completeCalls[0].payload.kiroUploadStatus, '上传成功'); }); diff --git a/tests/step-definitions-module.test.js b/tests/step-definitions-module.test.js index 351e36d..a0161ec 100644 --- a/tests/step-definitions-module.test.js +++ b/tests/step-definitions-module.test.js @@ -175,6 +175,9 @@ test('step definitions module exposes ordered normal and Plus step metadata', () assert.equal(kiroSteps.every((step) => step.flowId === 'kiro'), true); assert.equal(kiroSteps[0].driverId, 'background/kiro-device-auth'); assert.equal(kiroSteps[2].sourceId, 'kiro-rs-admin'); + assert.equal(kiroSteps[0].title, '启动设备登录'); + assert.equal(kiroSteps[1].title, '等待设备登录确认'); + assert.equal(kiroSteps[2].title, '上传凭据到 kiro.rs'); assert.deepStrictEqual(api.getStepIds({ activeFlowId: 'kiro' }), [1, 2, 3]); assert.equal(api.getLastStepId({ activeFlowId: 'kiro' }), 3); assert.deepStrictEqual(