1import type { ModelSelection } from "@t3tools/contracts";
2import {
3 getModelSelectionBooleanOptionValue,
4 getModelSelectionStringOptionValue,
5 getProviderOptionDescriptors,
6 resolvePromptInjectedEffort,
7} from "@t3tools/shared/model";
8
9import {
10 BUNDLED_CLAUDE_MODEL_CATALOG,
11 getClaudeCatalogModelCapabilities,
12 isClaudeCatalogUltracodeEffort,
13 normalizeClaudeCatalogEffort,
14 resolveClaudeCatalogApiModelId,
15 resolveClaudeCatalogEffort,
16 type ClaudeModelCatalog,
17} from "./provider/ClaudeModelCatalog.ts";
18
19export interface CompiledClaudeModelSelection {
20 readonly apiModelId: string;
21 readonly effort: string | undefined;
22 readonly promptEffort: string | undefined;
23 readonly settings: Readonly<Record<string, boolean>>;
24 readonly queryIdentity: string;
25}
26
27/** Compile every Claude model option at the provider boundary. */
28export function compileClaudeModelSelection(
29 selection: ModelSelection,
30 catalog: ClaudeModelCatalog = BUNDLED_CLAUDE_MODEL_CATALOG,
31): CompiledClaudeModelSelection {
32 const capabilities = getClaudeCatalogModelCapabilities(catalog, selection.model);
33 const descriptors = getProviderOptionDescriptors({ caps: capabilities });
34 const supportsBoolean = (id: string) =>
35 descriptors.some((descriptor) => descriptor.type === "boolean" && descriptor.id === id);
36 const rawEffort = getModelSelectionStringOptionValue(selection, "effort");
37 const resolvedEffort = resolveClaudeCatalogEffort(catalog, selection.model, rawEffort);
38 const effort = normalizeClaudeCatalogEffort(catalog, resolvedEffort, selection.model);
39 const fastMode = supportsBoolean("fastMode")
40 ? (getModelSelectionBooleanOptionValue(selection, "fastMode") ?? false)
41 : undefined;
42 const thinking = supportsBoolean("thinking")
43 ? getModelSelectionBooleanOptionValue(selection, "thinking")
44 : undefined;
45 const settings = {
46 ...(typeof thinking === "boolean" ? { alwaysThinkingEnabled: thinking } : {}),
47 ...(typeof fastMode === "boolean" ? { fastMode } : {}),
48 ...(isClaudeCatalogUltracodeEffort(resolvedEffort) ? { ultracode: true } : {}),
49 };
50 const apiModelId = resolveClaudeCatalogApiModelId(catalog, selection);
51 const promptEffort = resolvePromptInjectedEffort(capabilities, rawEffort) ?? undefined;
52 return {
53 apiModelId,
54 effort,
55 promptEffort,
56 settings,
57 queryIdentity: JSON.stringify({ apiModelId, effort: effort ?? null, settings }),
58 };
59}