export type FlowDocsLink = { path: string; label?: string; }; export type FlowContributionKind = "channel" | "core" | "provider" | "search"; export type FlowContributionSurface = "auth-choice" | "health" | "model-picker" | "setup"; export type FlowOptionGroup = { id: string; label: string; hint?: string; }; export type FlowOption = { value: Value; label: string; hint?: string; group?: FlowOptionGroup; docs?: FlowDocsLink; }; export type FlowContribution = { id: string; kind: FlowContributionKind; surface: FlowContributionSurface; option: FlowOption; source?: string; }; export function mergeFlowContributions(params: { primary: readonly T[]; fallbacks?: readonly T[]; }): T[] { const contributionByValue = new Map(); for (const contribution of params.primary) { contributionByValue.set(contribution.option.value, contribution); } for (const contribution of params.fallbacks ?? []) { if (!contributionByValue.has(contribution.option.value)) { contributionByValue.set(contribution.option.value, contribution); } } return [...contributionByValue.values()]; } export function sortFlowContributionsByLabel( contributions: readonly T[], ): T[] { return [...contributions].toSorted( (left, right) => left.option.label.localeCompare(right.option.label) || left.option.value.localeCompare(right.option.value), ); }