agent-ecosystem/src/renderer/utils/teamModelAvailability.ts
777genius ac1c99ac1f feat(cliInstaller): add model verification for providers
- Introduced CLI_INSTALLER_VERIFY_PROVIDER_MODELS IPC channel for on-demand model verification.
- Implemented handler for verifying provider models in the CliInstallerService.
- Enhanced CLI installation status management with model verification state and availability.
- Updated related components to support model verification feedback in the UI.
2026-04-16 19:41:23 +03:00

302 lines
8.9 KiB
TypeScript

import type {
CliProviderId,
CliProviderModelAvailability,
CliProviderModelAvailabilityStatus,
CliProviderStatus,
TeamProviderId,
} from '@shared/types';
import {
getProviderScopedTeamModelLabel,
getRuntimeAwareTeamModelUiDisabledReason,
getTeamProviderLabel,
getTeamProviderModelOptions,
sortTeamProviderModels,
getVisibleTeamProviderModels,
normalizeTeamModelForUi as normalizeCatalogTeamModelForUi,
GPT_5_1_CODEX_MINI_UI_DISABLED_MODEL,
GPT_5_1_CODEX_MINI_UI_DISABLED_REASON,
GPT_5_1_CODEX_MAX_CHATGPT_UI_DISABLED_REASON,
GPT_5_2_CODEX_UI_DISABLED_MODEL,
GPT_5_2_CODEX_UI_DISABLED_REASON,
GPT_5_3_CODEX_SPARK_UI_DISABLED_MODEL,
GPT_5_3_CODEX_SPARK_UI_DISABLED_REASON,
TEAM_MODEL_UI_DISABLED_BADGE_LABEL,
type TeamProviderModelOption,
} from './teamModelCatalog';
export {
GPT_5_1_CODEX_MINI_UI_DISABLED_MODEL,
GPT_5_1_CODEX_MINI_UI_DISABLED_REASON,
GPT_5_1_CODEX_MAX_CHATGPT_UI_DISABLED_REASON,
GPT_5_2_CODEX_UI_DISABLED_MODEL,
GPT_5_2_CODEX_UI_DISABLED_REASON,
GPT_5_3_CODEX_SPARK_UI_DISABLED_MODEL,
GPT_5_3_CODEX_SPARK_UI_DISABLED_REASON,
TEAM_MODEL_UI_DISABLED_BADGE_LABEL,
} from './teamModelCatalog';
type SupportedProviderId = CliProviderId | TeamProviderId;
export type TeamModelRuntimeProviderStatus = Pick<
CliProviderStatus,
| 'providerId'
| 'models'
| 'modelAvailability'
| 'modelVerificationState'
| 'authMethod'
| 'backend'
| 'authenticated'
| 'supported'
>;
export type TeamRuntimeModelOption = TeamProviderModelOption & {
availabilityStatus?: CliProviderModelAvailabilityStatus | null;
availabilityReason?: string | null;
};
export interface TeamProviderModelVerificationCounts {
checkedCount: number;
totalCount: number;
verifying: boolean;
}
export function getTeamModelUiDisabledReason(
providerId: SupportedProviderId | undefined,
model: string | undefined,
providerStatus?: TeamModelRuntimeProviderStatus | null
): string | null {
return getRuntimeAwareTeamModelUiDisabledReason(providerId, model, providerStatus);
}
export function isTeamModelUiDisabled(
providerId: SupportedProviderId | undefined,
model: string | undefined,
providerStatus?: TeamModelRuntimeProviderStatus | null
): boolean {
return getTeamModelUiDisabledReason(providerId, model, providerStatus) !== null;
}
function getFallbackTeamProviderModels(providerId: SupportedProviderId): string[] {
return getVisibleTeamProviderModels(
providerId,
getTeamProviderModelOptions(providerId)
.map((option) => option.value)
.filter((value) => value.trim().length > 0)
);
}
function getFallbackTeamProviderModelOptions(
providerId: SupportedProviderId
): TeamRuntimeModelOption[] {
return getTeamProviderModelOptions(providerId).map((option) => ({
...option,
label:
option.value === ''
? option.label
: (getProviderScopedTeamModelLabel(providerId, option.value) ?? option.value),
}));
}
function getRuntimeSelectorModels(
providerId: SupportedProviderId,
providerStatus?: TeamModelRuntimeProviderStatus | null
): string[] {
if (!providerStatus) {
return [];
}
return sortTeamProviderModels(providerId, providerStatus.models);
}
function getVisibleRuntimeModels(
providerId: SupportedProviderId,
providerStatus?: TeamModelRuntimeProviderStatus | null
): string[] {
return getRuntimeSelectorModels(providerId, providerStatus).filter(
(model) => getTeamModelUiDisabledReason(providerId, model, providerStatus) == null
);
}
function getModelAvailabilityMap(
providerStatus?: TeamModelRuntimeProviderStatus | null
): Map<string, CliProviderModelAvailability> {
return new Map(
(providerStatus?.modelAvailability ?? []).map((item) => [item.modelId.trim(), item])
);
}
function getRuntimeModelAvailability(
providerId: SupportedProviderId,
model: string,
providerStatus?: TeamModelRuntimeProviderStatus | null
): CliProviderModelAvailabilityStatus | null {
if (providerId === 'anthropic') {
return 'available';
}
if (!providerStatus) {
return null;
}
const visibleModels = getVisibleRuntimeModels(providerId, providerStatus);
if (!visibleModels.includes(model)) {
return null;
}
return 'available';
}
function getRuntimeModelAvailabilityReason(
model: string,
providerStatus?: TeamModelRuntimeProviderStatus | null
): string | null {
return getModelAvailabilityMap(providerStatus).get(model)?.reason ?? null;
}
export function getTeamProviderModelVerificationCounts(
providerId: SupportedProviderId,
providerStatus?: TeamModelRuntimeProviderStatus | null
): TeamProviderModelVerificationCounts {
if (providerId === 'anthropic') {
return {
checkedCount: getFallbackTeamProviderModels(providerId).length,
totalCount: getFallbackTeamProviderModels(providerId).length,
verifying: false,
};
}
const totalCount = getRuntimeSelectorModels(providerId, providerStatus).length;
return {
checkedCount: totalCount,
totalCount,
verifying: false,
};
}
export function getAvailableTeamProviderModels(
providerId: SupportedProviderId,
providerStatus?: TeamModelRuntimeProviderStatus | null
): string[] {
if (providerId === 'anthropic') {
return getFallbackTeamProviderModels(providerId);
}
if (!providerStatus) {
return [];
}
return getVisibleRuntimeModels(providerId, providerStatus).filter(
(model) => getRuntimeModelAvailability(providerId, model, providerStatus) === 'available'
);
}
export function getAvailableTeamProviderModelOptions(
providerId: SupportedProviderId,
providerStatus?: TeamModelRuntimeProviderStatus | null
): TeamRuntimeModelOption[] {
if (providerId === 'anthropic') {
return getFallbackTeamProviderModelOptions(providerId);
}
if (!providerStatus) {
return [{ value: '', label: 'Default', badgeLabel: 'Default' }];
}
const visibleModels = getRuntimeSelectorModels(providerId, providerStatus);
return [
{ value: '', label: 'Default', badgeLabel: 'Default' },
...visibleModels.map((model) => ({
value: model,
label: getProviderScopedTeamModelLabel(providerId, model) ?? model,
availabilityStatus: getRuntimeModelAvailability(providerId, model, providerStatus),
availabilityReason: getRuntimeModelAvailabilityReason(model, providerStatus),
})),
];
}
export function isTeamModelAvailableForUi(
providerId: SupportedProviderId | undefined,
model: string | undefined,
providerStatus?: TeamModelRuntimeProviderStatus | null
): boolean {
const trimmed = model?.trim();
if (!providerId || !trimmed) {
return true;
}
if (getTeamModelUiDisabledReason(providerId, trimmed, providerStatus)) {
return false;
}
if (providerId === 'anthropic') {
return getFallbackTeamProviderModels(providerId).includes(trimmed);
}
return getRuntimeModelAvailability(providerId, trimmed, providerStatus) === 'available';
}
export function normalizeTeamModelForUi(
providerId: SupportedProviderId | undefined,
model: string | undefined,
providerStatus?: TeamModelRuntimeProviderStatus | null
): string {
const normalized = normalizeCatalogTeamModelForUi(providerId, model);
const trimmed = normalized.trim();
if (!providerId || !trimmed) {
return normalized;
}
if (getTeamModelUiDisabledReason(providerId, trimmed, providerStatus)) {
return '';
}
if (providerId === 'anthropic') {
return isTeamModelAvailableForUi(providerId, trimmed, providerStatus) ? normalized : '';
}
if (!providerStatus) {
return '';
}
const visibleModels = getVisibleRuntimeModels(providerId, providerStatus);
if (!visibleModels.includes(trimmed)) {
return '';
}
const availability = getRuntimeModelAvailability(providerId, trimmed, providerStatus);
return availability === 'available' ? normalized : '';
}
export function getTeamModelSelectionError(
providerId: SupportedProviderId | undefined,
model: string | undefined,
providerStatus?: TeamModelRuntimeProviderStatus | null
): string | null {
const trimmed = model?.trim();
if (!providerId || !trimmed) {
return null;
}
const disabledReason = getTeamModelUiDisabledReason(providerId, trimmed, providerStatus);
if (disabledReason) {
return `Model "${trimmed}" is disabled. ${disabledReason}`;
}
if (providerId === 'anthropic') {
return isTeamModelAvailableForUi(providerId, trimmed, providerStatus)
? null
: `Model "${trimmed}" is not available for the current ${getTeamProviderLabel(providerId) ?? providerId} runtime. Pick one of the listed models or use Default.`;
}
if (!providerStatus) {
return `Model "${trimmed}" is waiting for ${getTeamProviderLabel(providerId) ?? providerId} runtime verification. Wait for the model list to load or use Default.`;
}
const visibleModels = getVisibleRuntimeModels(providerId, providerStatus);
if (!visibleModels.includes(trimmed)) {
return `Model "${trimmed}" is not available for the current ${getTeamProviderLabel(providerId) ?? providerId} runtime. Pick one of the listed models or use Default.`;
}
return null;
}