225 lines
7.9 KiB
JavaScript
225 lines
7.9 KiB
JavaScript
(function attachMultiPageContributionRegistry(root, factory) {
|
|
root.MultiPageContributionRegistry = factory(root);
|
|
})(typeof self !== 'undefined' ? self : globalThis, function createContributionRegistryModule(root) {
|
|
const flowRegistryApi = root?.MultiPageFlowRegistry || {};
|
|
const DEFAULT_FLOW_ID = flowRegistryApi.DEFAULT_FLOW_ID || 'openai';
|
|
const DEFAULT_KIRO_TARGET_ID = flowRegistryApi.DEFAULT_KIRO_TARGET_ID || 'kiro-rs';
|
|
const DEFAULT_OPENAI_TARGET_ID = flowRegistryApi.DEFAULT_OPENAI_TARGET_ID || 'cpa';
|
|
|
|
const ADAPTER_DEFINITIONS = Object.freeze({
|
|
'openai-oauth': Object.freeze({
|
|
id: 'openai-oauth',
|
|
flowId: 'openai',
|
|
artifactKind: 'openai-oauth',
|
|
trigger: 'interactive-oauth',
|
|
label: 'OpenAI OAuth 贡献',
|
|
defaultTargetId: DEFAULT_OPENAI_TARGET_ID,
|
|
sensitiveFieldPaths: Object.freeze([
|
|
'credentials.access_token',
|
|
'credentials.refresh_token',
|
|
'credentials.id_token',
|
|
]),
|
|
}),
|
|
'openai-codex-file': Object.freeze({
|
|
id: 'openai-codex-file',
|
|
flowId: 'openai',
|
|
artifactKind: 'codex',
|
|
trigger: 'manual-upload',
|
|
label: 'OpenAI Codex 文件贡献',
|
|
defaultTargetId: 'codex2api',
|
|
sensitiveFieldPaths: Object.freeze([
|
|
'credentials.access_token',
|
|
'credentials.refresh_token',
|
|
'credentials.id_token',
|
|
]),
|
|
}),
|
|
'openai-sub2api-file': Object.freeze({
|
|
id: 'openai-sub2api-file',
|
|
flowId: 'openai',
|
|
artifactKind: 'sub2api',
|
|
trigger: 'manual-upload',
|
|
label: 'OpenAI Sub2API 文件贡献',
|
|
defaultTargetId: 'sub2api',
|
|
sensitiveFieldPaths: Object.freeze([
|
|
'credentials.accounts[].credentials.access_token',
|
|
'credentials.accounts[].credentials.refresh_token',
|
|
'credentials.accounts[].credentials.id_token',
|
|
]),
|
|
}),
|
|
'kiro-builder-id': Object.freeze({
|
|
id: 'kiro-builder-id',
|
|
flowId: 'kiro',
|
|
artifactKind: 'kiro-builder-id',
|
|
trigger: 'after-desktop-authorize',
|
|
label: 'Kiro Builder ID 贡献',
|
|
defaultTargetId: DEFAULT_KIRO_TARGET_ID,
|
|
sensitiveFieldPaths: Object.freeze([
|
|
'credentials.refreshToken',
|
|
'credentials.clientSecret',
|
|
'metadata.proxyPassword',
|
|
]),
|
|
}),
|
|
});
|
|
|
|
const FLOW_ADAPTER_IDS = Object.freeze({
|
|
openai: Object.freeze(['openai-oauth', 'openai-codex-file', 'openai-sub2api-file']),
|
|
kiro: Object.freeze(['kiro-builder-id']),
|
|
});
|
|
|
|
const CONTRIBUTION_TUTORIAL_ENTRIES = Object.freeze({
|
|
openai: Object.freeze({
|
|
id: 'openai-contribution-tutorial',
|
|
flowId: 'openai',
|
|
label: '贡献/使用教程',
|
|
portalPath: '/tutorial',
|
|
defaultTargetId: DEFAULT_OPENAI_TARGET_ID,
|
|
contributionAdapterId: 'openai-oauth',
|
|
action: 'open-portal-and-enable-contribution',
|
|
}),
|
|
kiro: Object.freeze({
|
|
id: 'kiro-contribution-tutorial',
|
|
flowId: 'kiro',
|
|
label: '贡献/使用教程',
|
|
portalPath: '/tutorial',
|
|
defaultTargetId: DEFAULT_KIRO_TARGET_ID,
|
|
contributionAdapterId: 'kiro-builder-id',
|
|
action: 'open-portal-and-enable-contribution',
|
|
}),
|
|
});
|
|
|
|
function normalizeString(value = '') {
|
|
return String(value || '').trim();
|
|
}
|
|
|
|
function normalizeFlowId(value = '', fallback = DEFAULT_FLOW_ID) {
|
|
const normalized = normalizeString(value).toLowerCase();
|
|
if (normalized && Object.prototype.hasOwnProperty.call(FLOW_ADAPTER_IDS, normalized)) {
|
|
return normalized;
|
|
}
|
|
if (!normalized && typeof flowRegistryApi.normalizeFlowId === 'function') {
|
|
return flowRegistryApi.normalizeFlowId(value, fallback);
|
|
}
|
|
return normalized || normalizeString(fallback).toLowerCase() || DEFAULT_FLOW_ID;
|
|
}
|
|
|
|
function normalizeAdapterId(value = '') {
|
|
return normalizeString(value).toLowerCase();
|
|
}
|
|
|
|
function normalizeTargetId(flowId = DEFAULT_FLOW_ID, targetId = '') {
|
|
if (typeof flowRegistryApi.normalizeTargetId === 'function') {
|
|
return flowRegistryApi.normalizeTargetId(flowId, targetId);
|
|
}
|
|
const normalizedFlowId = normalizeFlowId(flowId, DEFAULT_FLOW_ID);
|
|
const normalizedTargetId = normalizeString(targetId).toLowerCase();
|
|
if (normalizedTargetId) {
|
|
return normalizedTargetId;
|
|
}
|
|
return normalizedFlowId === 'kiro' ? DEFAULT_KIRO_TARGET_ID : DEFAULT_OPENAI_TARGET_ID;
|
|
}
|
|
|
|
function cloneAdapter(adapter) {
|
|
if (!adapter) {
|
|
return null;
|
|
}
|
|
return {
|
|
...adapter,
|
|
sensitiveFieldPaths: Array.isArray(adapter.sensitiveFieldPaths)
|
|
? adapter.sensitiveFieldPaths.slice()
|
|
: [],
|
|
};
|
|
}
|
|
|
|
function getAdapterDefinition(adapterId = '') {
|
|
return cloneAdapter(ADAPTER_DEFINITIONS[normalizeAdapterId(adapterId)] || null);
|
|
}
|
|
|
|
function getContributionAdapterIds(flowId = DEFAULT_FLOW_ID) {
|
|
const normalizedFlowId = normalizeFlowId(flowId, DEFAULT_FLOW_ID);
|
|
return (FLOW_ADAPTER_IDS[normalizedFlowId] || []).slice();
|
|
}
|
|
|
|
function getContributionAdapters(flowId = DEFAULT_FLOW_ID) {
|
|
return getContributionAdapterIds(flowId)
|
|
.map((adapterId) => getAdapterDefinition(adapterId))
|
|
.filter(Boolean);
|
|
}
|
|
|
|
function getDefaultContributionAdapterId(flowId = DEFAULT_FLOW_ID) {
|
|
return getContributionAdapterIds(flowId)[0] || '';
|
|
}
|
|
|
|
function buildPortalPageUrl(portalBaseUrl = '', portalPath = '/tutorial', params = {}) {
|
|
const baseUrl = normalizeString(portalBaseUrl).replace(/\/+$/, '') || 'https://flowpilot.qlhazycoder.top';
|
|
const path = normalizeString(portalPath) || '/tutorial';
|
|
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
|
const query = Object.entries(params)
|
|
.map(([key, value]) => [normalizeString(key), normalizeString(value)])
|
|
.filter(([key, value]) => key && value)
|
|
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|
.join('&');
|
|
return `${baseUrl}${normalizedPath}${query ? `?${query}` : ''}`;
|
|
}
|
|
|
|
function getContributionTutorialEntry(flowId = DEFAULT_FLOW_ID, options = {}) {
|
|
const normalizedFlowId = normalizeFlowId(flowId, DEFAULT_FLOW_ID);
|
|
const definition = CONTRIBUTION_TUTORIAL_ENTRIES[normalizedFlowId] || null;
|
|
if (!definition) {
|
|
return null;
|
|
}
|
|
const requestedAdapterId = normalizeAdapterId(options.adapterId);
|
|
const adapterId = requestedAdapterId && hasContributionAdapter(normalizedFlowId, requestedAdapterId)
|
|
? requestedAdapterId
|
|
: definition.contributionAdapterId;
|
|
const targetId = normalizeTargetId(
|
|
normalizedFlowId,
|
|
options.targetId || definition.defaultTargetId
|
|
);
|
|
return {
|
|
...definition,
|
|
targetId,
|
|
contributionAdapterId: adapterId,
|
|
portalUrl: buildPortalPageUrl(options.portalBaseUrl, definition.portalPath, {
|
|
flow: normalizedFlowId,
|
|
target: targetId,
|
|
}),
|
|
};
|
|
}
|
|
|
|
function hasContributionAdapter(flowId = DEFAULT_FLOW_ID, adapterId = '') {
|
|
const normalizedAdapterId = normalizeAdapterId(adapterId);
|
|
return Boolean(normalizedAdapterId) && getContributionAdapterIds(flowId).includes(normalizedAdapterId);
|
|
}
|
|
|
|
function assertPublishedFlowsHaveContributionAdapters(flowIds = undefined) {
|
|
const ids = Array.isArray(flowIds)
|
|
? flowIds
|
|
: (typeof flowRegistryApi.getRegisteredFlowIds === 'function'
|
|
? flowRegistryApi.getRegisteredFlowIds()
|
|
: Object.keys(FLOW_ADAPTER_IDS));
|
|
const missing = ids
|
|
.map((flowId) => normalizeString(flowId).toLowerCase())
|
|
.filter(Boolean)
|
|
.filter((flowId) => getContributionAdapterIds(flowId).length === 0);
|
|
if (missing.length) {
|
|
throw new Error(`缺少账号贡献适配器:${missing.join(', ')}`);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return {
|
|
ADAPTER_DEFINITIONS,
|
|
CONTRIBUTION_TUTORIAL_ENTRIES,
|
|
FLOW_ADAPTER_IDS,
|
|
assertPublishedFlowsHaveContributionAdapters,
|
|
getContributionTutorialEntry,
|
|
getAdapterDefinition,
|
|
getContributionAdapterIds,
|
|
getContributionAdapters,
|
|
getDefaultContributionAdapterId,
|
|
hasContributionAdapter,
|
|
normalizeAdapterId,
|
|
normalizeFlowId,
|
|
};
|
|
});
|