Files
2026-05-19 13:29:18 +00:00

246 lines
8.1 KiB
JavaScript

(function attachBackgroundKiroBuilderIdContributionAdapter(root, factory) {
root.MultiPageBackgroundKiroBuilderIdContributionAdapter = factory(root);
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundKiroBuilderIdContributionAdapterModule(root) {
const artifactApi = root?.MultiPageBackgroundKiroCredentialArtifact || {};
const FLOW_ID = artifactApi.FLOW_ID || 'kiro';
const ADAPTER_ID = artifactApi.ADAPTER_ID || 'kiro-builder-id';
const ARTIFACT_KIND = artifactApi.ARTIFACT_KIND || 'kiro-builder-id';
const DEFAULT_CONTRIBUTION_API_URL = 'https://flowpilot.qlhazycoder.top/api/contributions';
function isPlainObject(value) {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
}
function cleanString(value = '') {
return String(value ?? '').trim();
}
function getErrorMessage(error) {
return error instanceof Error ? error.message : String(error ?? '未知错误');
}
function normalizeFlowId(state = {}) {
return cleanString(state.activeFlowId || state.flowId).toLowerCase() || 'openai';
}
function normalizeAdapterId(state = {}) {
return cleanString(state.contributionAdapterId || ADAPTER_ID).toLowerCase() || ADAPTER_ID;
}
function shouldSubmitKiroBuilderIdContribution(state = {}) {
return Boolean(state?.accountContributionEnabled)
&& normalizeFlowId(state) === FLOW_ID
&& normalizeAdapterId(state) === ADAPTER_ID;
}
function normalizeContributionApiUrl(value = '') {
const normalized = cleanString(value).replace(/\/+$/, '');
if (!normalized) {
return DEFAULT_CONTRIBUTION_API_URL;
}
if (/\/api\/contributions$/i.test(normalized)) {
return normalized;
}
return `${normalized}/api/contributions`;
}
function mergeFlowContributionRuntime(currentRuntime = {}, flowId = FLOW_ID, patch = {}) {
const runtime = isPlainObject(currentRuntime) ? currentRuntime : {};
const currentFlowRuntime = isPlainObject(runtime[flowId]) ? runtime[flowId] : {};
return {
...runtime,
[flowId]: {
...currentFlowRuntime,
...patch,
},
};
}
function redactKnownArtifactSecrets(message = '', artifact = {}) {
let result = cleanString(message);
const secrets = [
artifact?.credentials?.refreshToken,
artifact?.credentials?.clientSecret,
]
.map((value) => cleanString(value))
.filter(Boolean);
secrets.forEach((secret) => {
result = result.split(secret).join(artifactApi.redactSecret?.(secret) || '[redacted]');
});
return result;
}
async function readJsonResponse(response) {
const text = await response.text();
try {
return text ? JSON.parse(text) : {};
} catch (_error) {
return { message: text };
}
}
async function submitContributionArtifact(artifact = {}, options = {}) {
const fetchImpl = options.fetchImpl;
if (typeof fetchImpl !== 'function') {
throw new Error('账号贡献提交能力缺少 fetch。');
}
const endpoint = normalizeContributionApiUrl(options.apiUrl);
const payload = {
flow: FLOW_ID,
adapter_id: ADAPTER_ID,
artifact_kind: ARTIFACT_KIND,
source: 'flowpilot-extension',
contributor: {
nickname: cleanString(options.nickname),
qq: cleanString(options.qq),
},
artifact,
};
const response = await fetchImpl(endpoint, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const body = await readJsonResponse(response);
if (!response.ok || body?.ok === false) {
throw new Error(cleanString(body?.message || body?.detail || body?.error) || `贡献服务请求失败(HTTP ${response.status})。`);
}
return {
ok: true,
status: response.status,
contributionId: cleanString(body?.contribution_id || body?.contributionId || body?.id),
message: cleanString(body?.message) || '贡献提交成功',
raw: body,
};
}
function createKiroBuilderIdContributionAdapter(deps = {}) {
const {
addLog = async () => {},
contributionApiUrl = DEFAULT_CONTRIBUTION_API_URL,
fetchImpl = typeof fetch === 'function' ? fetch.bind(globalThis) : null,
getState = async () => ({}),
setState = async () => {},
} = deps;
async function updateFlowContributionRuntime(currentState = {}, patch = {}) {
const runtime = mergeFlowContributionRuntime(currentState.flowContributionRuntime, FLOW_ID, {
adapterId: ADAPTER_ID,
...patch,
});
await setState({
flowContributionRuntime: runtime,
});
return runtime;
}
async function log(message, level = 'info', nodeId = '') {
await addLog(message, level, nodeId ? { nodeId } : {});
}
async function maybeSubmitFlowContribution(state = {}, options = {}) {
const currentState = Object.keys(state || {}).length ? state : await getState();
const nodeId = cleanString(options.nodeId || 'kiro-complete-desktop-authorize');
if (!shouldSubmitKiroBuilderIdContribution(currentState)) {
return {
ok: true,
skipped: true,
reason: 'not_enabled_for_kiro_builder_id',
};
}
let artifact = null;
try {
artifact = artifactApi.buildKiroBuilderIdArtifact(currentState);
} catch (error) {
const message = redactKnownArtifactSecrets(getErrorMessage(error), artifact);
await updateFlowContributionRuntime(currentState, {
enabled: true,
status: 'skipped',
error: message,
lastMessage: message,
updatedAt: Date.now(),
});
await log(`Kiro 账号贡献已跳过:${message}`, 'warn', nodeId);
return {
ok: false,
skipped: true,
reason: error?.code || 'artifact_invalid',
message,
};
}
await updateFlowContributionRuntime(currentState, {
enabled: true,
status: 'submitting',
error: '',
lastMessage: '正在提交 Kiro Builder ID 贡献',
updatedAt: Date.now(),
});
const safeSummary = artifactApi.buildSafeArtifactSummary?.(artifact) || {};
await log(`Kiro 账号贡献:正在提交 Builder ID,邮箱 ${safeSummary.email || '未知'}`, 'info', nodeId);
try {
const result = await submitContributionArtifact(artifact, {
apiUrl: options.contributionApiUrl || contributionApiUrl,
fetchImpl,
nickname: currentState.contributionNickname,
qq: currentState.contributionQq,
});
await updateFlowContributionRuntime(currentState, {
enabled: true,
status: 'submitted',
error: '',
contributionId: result.contributionId,
lastMessage: result.message,
submittedAt: Date.now(),
updatedAt: Date.now(),
});
await log(`Kiro 账号贡献:提交完成,${result.message}`, 'ok', nodeId);
return result;
} catch (error) {
const message = redactKnownArtifactSecrets(getErrorMessage(error), artifact);
await updateFlowContributionRuntime(currentState, {
enabled: true,
status: 'error',
error: message,
lastMessage: message,
updatedAt: Date.now(),
});
await log(`Kiro 账号贡献提交失败:${message}`, 'warn', nodeId);
return {
ok: false,
skipped: false,
reason: 'submit_failed',
message,
};
}
}
return {
maybeSubmitFlowContribution,
shouldSubmitKiroBuilderIdContribution,
submitContributionArtifact: (artifact, options = {}) => submitContributionArtifact(artifact, {
...options,
apiUrl: options.apiUrl || contributionApiUrl,
fetchImpl: options.fetchImpl || fetchImpl,
}),
};
}
return {
ADAPTER_ID,
ARTIFACT_KIND,
DEFAULT_CONTRIBUTION_API_URL,
FLOW_ID,
createKiroBuilderIdContributionAdapter,
normalizeContributionApiUrl,
shouldSubmitKiroBuilderIdContribution,
submitContributionArtifact,
};
});