mirror of https://github.com/openclaw/openclaw.git
220 lines
7.2 KiB
TypeScript
220 lines
7.2 KiB
TypeScript
import type { OpenClawConfig } from "../config/config.js";
|
|
import { resolveManifestProviderAuthChoices } from "../plugins/provider-auth-choices.js";
|
|
import {
|
|
resolveProviderModelPickerEntries,
|
|
resolveProviderWizardOptions,
|
|
} from "../plugins/provider-wizard.js";
|
|
import { resolvePluginProviders } from "../plugins/providers.runtime.js";
|
|
import type { ProviderPlugin } from "../plugins/types.js";
|
|
import type { FlowContribution, FlowOption } from "./types.js";
|
|
import { mergeFlowContributions, sortFlowContributionsByLabel } from "./types.js";
|
|
|
|
export type ProviderFlowScope = "text-inference" | "image-generation";
|
|
|
|
const DEFAULT_PROVIDER_FLOW_SCOPE: ProviderFlowScope = "text-inference";
|
|
|
|
export type ProviderSetupFlowOption = FlowOption & {
|
|
onboardingScopes?: ProviderFlowScope[];
|
|
};
|
|
|
|
export type ProviderModelPickerFlowEntry = FlowOption;
|
|
|
|
export type ProviderSetupFlowContribution = FlowContribution & {
|
|
kind: "provider";
|
|
surface: "setup";
|
|
providerId: string;
|
|
pluginId?: string;
|
|
option: ProviderSetupFlowOption;
|
|
onboardingScopes?: ProviderFlowScope[];
|
|
source: "manifest" | "runtime";
|
|
};
|
|
|
|
export type ProviderModelPickerFlowContribution = FlowContribution & {
|
|
kind: "provider";
|
|
surface: "model-picker";
|
|
providerId: string;
|
|
option: ProviderModelPickerFlowEntry;
|
|
source: "runtime";
|
|
};
|
|
|
|
function includesProviderFlowScope(
|
|
scopes: readonly ProviderFlowScope[] | undefined,
|
|
scope: ProviderFlowScope,
|
|
): boolean {
|
|
return scopes ? scopes.includes(scope) : scope === DEFAULT_PROVIDER_FLOW_SCOPE;
|
|
}
|
|
|
|
function resolveProviderDocsById(params?: {
|
|
config?: OpenClawConfig;
|
|
workspaceDir?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
}): Map<string, string> {
|
|
return new Map(
|
|
resolvePluginProviders({
|
|
config: params?.config,
|
|
workspaceDir: params?.workspaceDir,
|
|
env: params?.env,
|
|
bundledProviderAllowlistCompat: true,
|
|
bundledProviderVitestCompat: true,
|
|
})
|
|
.filter((provider): provider is ProviderPlugin & { docsPath: string } =>
|
|
Boolean(provider.docsPath?.trim()),
|
|
)
|
|
.map((provider) => [provider.id, provider.docsPath.trim()]),
|
|
);
|
|
}
|
|
|
|
export function resolveManifestProviderSetupFlowOptions(params?: {
|
|
config?: OpenClawConfig;
|
|
workspaceDir?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
scope?: ProviderFlowScope;
|
|
}): ProviderSetupFlowOption[] {
|
|
return resolveManifestProviderSetupFlowContributions(params).map(
|
|
(contribution) => contribution.option,
|
|
);
|
|
}
|
|
|
|
export function resolveManifestProviderSetupFlowContributions(params?: {
|
|
config?: OpenClawConfig;
|
|
workspaceDir?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
scope?: ProviderFlowScope;
|
|
}): ProviderSetupFlowContribution[] {
|
|
const scope = params?.scope ?? DEFAULT_PROVIDER_FLOW_SCOPE;
|
|
const docsByProvider = resolveProviderDocsById(params ?? {});
|
|
return resolveManifestProviderAuthChoices(params)
|
|
.filter((choice) => includesProviderFlowScope(choice.onboardingScopes, scope))
|
|
.map((choice) => ({
|
|
id: `provider:setup:${choice.choiceId}`,
|
|
kind: "provider" as const,
|
|
surface: "setup" as const,
|
|
providerId: choice.providerId,
|
|
pluginId: choice.pluginId,
|
|
option: {
|
|
value: choice.choiceId,
|
|
label: choice.choiceLabel,
|
|
...(choice.choiceHint ? { hint: choice.choiceHint } : {}),
|
|
...(choice.groupId && choice.groupLabel
|
|
? {
|
|
group: {
|
|
id: choice.groupId,
|
|
label: choice.groupLabel,
|
|
...(choice.groupHint ? { hint: choice.groupHint } : {}),
|
|
},
|
|
}
|
|
: {}),
|
|
...(docsByProvider.get(choice.providerId)
|
|
? { docs: { path: docsByProvider.get(choice.providerId)! } }
|
|
: {}),
|
|
},
|
|
...(choice.onboardingScopes ? { onboardingScopes: [...choice.onboardingScopes] } : {}),
|
|
source: "manifest" as const,
|
|
}));
|
|
}
|
|
|
|
export function resolveRuntimeFallbackProviderSetupFlowOptions(params?: {
|
|
config?: OpenClawConfig;
|
|
workspaceDir?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
scope?: ProviderFlowScope;
|
|
}): ProviderSetupFlowOption[] {
|
|
return resolveRuntimeFallbackProviderSetupFlowContributions(params).map(
|
|
(contribution) => contribution.option,
|
|
);
|
|
}
|
|
|
|
export function resolveRuntimeFallbackProviderSetupFlowContributions(params?: {
|
|
config?: OpenClawConfig;
|
|
workspaceDir?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
scope?: ProviderFlowScope;
|
|
}): ProviderSetupFlowContribution[] {
|
|
const scope = params?.scope ?? DEFAULT_PROVIDER_FLOW_SCOPE;
|
|
return resolveProviderWizardOptions(params ?? {})
|
|
.filter((option) => includesProviderFlowScope(option.onboardingScopes, scope))
|
|
.map((option) => ({
|
|
id: `provider:setup:${option.value}`,
|
|
kind: "provider" as const,
|
|
surface: "setup" as const,
|
|
providerId: option.groupId,
|
|
option: {
|
|
value: option.value,
|
|
label: option.label,
|
|
...(option.hint ? { hint: option.hint } : {}),
|
|
group: {
|
|
id: option.groupId,
|
|
label: option.groupLabel,
|
|
...(option.groupHint ? { hint: option.groupHint } : {}),
|
|
},
|
|
},
|
|
...(option.onboardingScopes ? { onboardingScopes: [...option.onboardingScopes] } : {}),
|
|
source: "runtime" as const,
|
|
}));
|
|
}
|
|
|
|
export function resolveProviderSetupFlowOptions(params?: {
|
|
config?: OpenClawConfig;
|
|
workspaceDir?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
scope?: ProviderFlowScope;
|
|
}): ProviderSetupFlowOption[] {
|
|
return resolveProviderSetupFlowContributions(params).map((contribution) => contribution.option);
|
|
}
|
|
|
|
export function resolveProviderSetupFlowContributions(params?: {
|
|
config?: OpenClawConfig;
|
|
workspaceDir?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
scope?: ProviderFlowScope;
|
|
}): ProviderSetupFlowContribution[] {
|
|
return sortFlowContributionsByLabel(
|
|
mergeFlowContributions({
|
|
primary: resolveManifestProviderSetupFlowContributions(params),
|
|
fallbacks: resolveRuntimeFallbackProviderSetupFlowContributions(params),
|
|
}),
|
|
);
|
|
}
|
|
|
|
export function resolveProviderModelPickerFlowEntries(params?: {
|
|
config?: OpenClawConfig;
|
|
workspaceDir?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
}): ProviderModelPickerFlowEntry[] {
|
|
return resolveProviderModelPickerFlowContributions(params).map(
|
|
(contribution) => contribution.option,
|
|
);
|
|
}
|
|
|
|
export function resolveProviderModelPickerFlowContributions(params?: {
|
|
config?: OpenClawConfig;
|
|
workspaceDir?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
}): ProviderModelPickerFlowContribution[] {
|
|
const docsByProvider = resolveProviderDocsById(params ?? {});
|
|
return sortFlowContributionsByLabel(
|
|
resolveProviderModelPickerEntries(params ?? {}).map((entry) => {
|
|
const providerId = entry.value.startsWith("provider-plugin:")
|
|
? entry.value.slice("provider-plugin:".length).split(":")[0]
|
|
: entry.value;
|
|
return {
|
|
id: `provider:model-picker:${entry.value}`,
|
|
kind: "provider" as const,
|
|
surface: "model-picker" as const,
|
|
providerId,
|
|
option: {
|
|
value: entry.value,
|
|
label: entry.label,
|
|
...(entry.hint ? { hint: entry.hint } : {}),
|
|
...(docsByProvider.get(providerId)
|
|
? { docs: { path: docsByProvider.get(providerId)! } }
|
|
: {}),
|
|
},
|
|
source: "runtime" as const,
|
|
};
|
|
}),
|
|
);
|
|
}
|
|
|
|
export { includesProviderFlowScope };
|