1import { PROVIDER_DISPLAY_NAMES, type ServerProvider } from "@t3tools/contracts";
2import { compareSemverVersions } from "@t3tools/shared/semver";
3
4const RUNTIME_NAMES: Partial<Record<string, string>> = {
5 claudeAgent: "Claude Code",
6 codex: "the Codex CLI",
7};
8
9function formatModelList(names: ReadonlyArray<string>): string {
10 if (names.length <= 2) return names.join(" and ");
11 return `${names.slice(0, -1).join(", ")}, and ${names[names.length - 1]}`;
12}
13
14export function formatProviderUpdateRequiredNotice(
15 provider: Pick<ServerProvider, "driver" | "updateRequiredModels">,
16 searchQuery = "",
17): string | null {
18 const query = searchQuery.trim().toLocaleLowerCase();
19 const models = (provider.updateRequiredModels ?? []).filter(
20 (model) =>
21 query.length === 0 ||
22 model.name.toLocaleLowerCase().includes(query) ||
23 model.slug.toLocaleLowerCase().includes(query),
24 );
25 if (models.length === 0) return null;
26 const minVersion = models
27 .map((model) => model.minVersion)
28 .reduce((highest, version) =>
29 compareSemverVersions(version, highest) > 0 ? version : highest,
30 );
31 const providerName =
32 RUNTIME_NAMES[provider.driver] ?? PROVIDER_DISPLAY_NAMES[provider.driver] ?? provider.driver;
33 const version = minVersion.startsWith("v") ? minVersion : `v${minVersion}`;
34 const names = formatModelList(models.map((model) => model.name));
35 return `Update ${providerName} to ${version} or newer to use ${names}.`;
36}