feat: add kiro.rs connection preflight test
This commit is contained in:
@@ -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}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 代理自动同步能力尚未接入。');
|
||||
|
||||
Reference in New Issue
Block a user