feat: add kiro.rs connection preflight test

This commit is contained in:
QLHazyCoder
2026-05-19 02:34:29 +08:00
parent 702e969deb
commit 5ddb5ac94d
10 changed files with 267 additions and 33 deletions
+36 -13
View File
@@ -47,6 +47,25 @@
return cleanString(value) || fallback;
}
function normalizeKiroRsApiKey(value = '') {
return cleanString(value);
}
function buildKiroRsAdminHeaders(apiKey = '', extraHeaders = {}) {
const normalizedApiKey = normalizeKiroRsApiKey(apiKey);
return {
...extraHeaders,
...(normalizedApiKey ? {
'x-api-key': normalizedApiKey,
Authorization: `Bearer ${normalizedApiKey}`,
} : {}),
};
}
function readKiroRsResponseMessage(body = {}, fallback = '') {
return cleanString(body?.json?.error?.message || body?.json?.message || body?.text || fallback);
}
function normalizeKiroRsBaseUrl(value = '') {
const normalized = cleanString(value).replace(/\/+$/, '');
if (!normalized) {
@@ -116,7 +135,7 @@
|| {};
return {
baseUrl: cleanString(nestedConfig.baseUrl || state?.kiroRsUrl),
apiKey: String(nestedConfig.apiKey ?? state?.kiroRsKey ?? ''),
apiKey: normalizeKiroRsApiKey(nestedConfig.apiKey ?? state?.kiroRsKey ?? ''),
};
}
@@ -199,60 +218,64 @@
async function checkKiroRsConnection(baseUrl, apiKey, fetchImpl) {
const normalizedBaseUrl = normalizeKiroRsBaseUrl(baseUrl);
const normalizedApiKey = normalizeKiroRsApiKey(apiKey);
const response = await fetchImpl(`${normalizedBaseUrl}/api/admin/credentials`, {
method: 'GET',
headers: {
headers: buildKiroRsAdminHeaders(normalizedApiKey, {
Accept: 'application/json',
'x-api-key': String(apiKey || ''),
},
}),
});
const body = await readResponse(response);
const detail = readKiroRsResponseMessage(body, response.statusText);
if (response.ok) {
return {
ok: true,
status: response.status,
message: `kiro.rs 连接正常(HTTP ${response.status}`,
};
}
if (response.status === 405) {
return {
ok: true,
status: response.status,
message: 'kiro.rs 上传接口可访问。',
};
}
if (response.status === 401 || response.status === 403) {
return {
ok: false,
message: `kiro.rs API Key 被拒绝(HTTP ${response.status}`,
status: response.status,
message: `kiro.rs API Key 被拒绝(HTTP ${response.status}${detail ? `${detail}` : ''}`,
};
}
if (response.status === 404) {
return {
ok: false,
message: '未找到 kiro.rs 管理接口。',
status: response.status,
message: `未找到 kiro.rs 管理接口(HTTP 404${detail ? `${detail}` : ''}`,
};
}
return {
ok: false,
message: cleanString(body.json?.error?.message || body.json?.message || body.text || response.statusText)
|| `kiro.rs 连接失败(HTTP ${response.status}`,
status: response.status,
message: detail || `kiro.rs 连接失败(HTTP ${response.status}`,
};
}
async function uploadBuilderIdCredential(baseUrl, apiKey, payload, fetchImpl) {
const normalizedBaseUrl = normalizeKiroRsBaseUrl(baseUrl);
const normalizedApiKey = normalizeKiroRsApiKey(apiKey);
const response = await fetchImpl(`${normalizedBaseUrl}/api/admin/credentials`, {
method: 'POST',
headers: {
headers: buildKiroRsAdminHeaders(normalizedApiKey, {
'Content-Type': 'application/json',
Accept: 'application/json',
'x-api-key': String(apiKey || ''),
},
}),
body: JSON.stringify(payload),
});
const body = await readResponse(response);
if (!response.ok) {
const message = cleanString(body.json?.error?.message || body.json?.message || body.text || response.statusText)
|| `HTTP ${response.status}`;
const message = readKiroRsResponseMessage(body, response.statusText) || `HTTP ${response.status}`;
throw new Error(`kiro.rs 凭据上传失败:${message}`);
}
+39
View File
@@ -37,6 +37,7 @@
exportSettingsBundle,
fetchGeneratedEmail,
refreshGpcCardBalance,
testKiroRsConnection,
finalizePhoneActivationAfterSuccessfulFlow,
finalizeStep3Completion,
finalizeIcloudAliasAfterSuccessfulFlow,
@@ -1543,6 +1544,44 @@
return { ok: true, ...result };
}
case 'CHECK_KIRO_RS_CONNECTION': {
if (typeof testKiroRsConnection !== 'function') {
throw new Error('kiro.rs 连接测试能力尚未接入。');
}
const currentState = await getState();
const activeFlowId = normalizeMessageFlowId(
message.payload?.activeFlowId || currentState?.activeFlowId || 'kiro',
'kiro'
);
const targetId = normalizeMessageTargetId(
activeFlowId,
message.payload?.targetId || currentState?.kiroTargetId || 'kiro-rs',
'kiro-rs'
);
const nestedTargetConfig = currentState?.settingsState?.flows?.kiro?.targets?.[targetId]
|| currentState?.flows?.kiro?.targets?.[targetId]
|| {};
const baseUrl = String(
message.payload?.baseUrl
?? nestedTargetConfig.baseUrl
?? currentState?.kiroRsUrl
?? ''
).trim();
const apiKey = String(
message.payload?.apiKey
?? nestedTargetConfig.apiKey
?? currentState?.kiroRsKey
?? ''
);
const result = await testKiroRsConnection(baseUrl, apiKey);
return {
ok: Boolean(result?.ok),
targetId,
status: Number(result?.status) || 0,
message: String(result?.message || '').trim(),
};
}
case 'RUN_IP_PROXY_AUTO_SYNC_NOW': {
if (typeof runIpProxyAutoSync !== 'function') {
throw new Error('IP 代理自动同步能力尚未接入。');