248 lines · 8.3 KB · TypeScript
RawDownload
import {  CLAUDE_CODE_EFFORT_OPTIONS,  CODEX_REASONING_EFFORT_OPTIONS,  DEFAULT_MODEL_BY_PROVIDER,  DEFAULT_REASONING_EFFORT_BY_PROVIDER,  MODEL_OPTIONS_BY_PROVIDER,  MODEL_SLUG_ALIASES_BY_PROVIDER,  REASONING_EFFORT_OPTIONS_BY_PROVIDER,  type ClaudeModelOptions,  type ClaudeCodeEffort,  type CodexModelOptions,  type CodexReasoningEffort,  type ModelSlug,  type ProviderReasoningEffort,  type ProviderKind,} from "@t3tools/contracts"; const MODEL_SLUG_SET_BY_PROVIDER: Record<ProviderKind, ReadonlySet<ModelSlug>> = {  claudeAgent: new Set(MODEL_OPTIONS_BY_PROVIDER.claudeAgent.map((option) => option.slug)),  codex: new Set(MODEL_OPTIONS_BY_PROVIDER.codex.map((option) => option.slug)),}; const CLAUDE_OPUS_4_6_MODEL = "claude-opus-4-6";const CLAUDE_SONNET_4_6_MODEL = "claude-sonnet-4-6";const CLAUDE_HAIKU_4_5_MODEL = "claude-haiku-4-5"; export function getModelOptions(provider: ProviderKind = "codex") {  return MODEL_OPTIONS_BY_PROVIDER[provider];} export function getDefaultModel(provider: ProviderKind = "codex"): ModelSlug {  return DEFAULT_MODEL_BY_PROVIDER[provider];} export function supportsClaudeFastMode(model: string | null | undefined): boolean {  return normalizeModelSlug(model, "claudeAgent") === CLAUDE_OPUS_4_6_MODEL;} export function supportsClaudeAdaptiveReasoning(model: string | null | undefined): boolean {  const normalized = normalizeModelSlug(model, "claudeAgent");  return normalized === CLAUDE_OPUS_4_6_MODEL || normalized === CLAUDE_SONNET_4_6_MODEL;} export function supportsClaudeMaxEffort(model: string | null | undefined): boolean {  return normalizeModelSlug(model, "claudeAgent") === CLAUDE_OPUS_4_6_MODEL;} export function supportsClaudeUltrathinkKeyword(model: string | null | undefined): boolean {  return supportsClaudeAdaptiveReasoning(model);} export function supportsClaudeThinkingToggle(model: string | null | undefined): boolean {  return normalizeModelSlug(model, "claudeAgent") === CLAUDE_HAIKU_4_5_MODEL;} export function isClaudeUltrathinkPrompt(text: string | null | undefined): boolean {  return typeof text === "string" && /\bultrathink\b/i.test(text);} export function normalizeModelSlug(  model: string | null | undefined,  provider: ProviderKind = "codex",): ModelSlug | null {  if (typeof model !== "string") {    return null;  }   const trimmed = model.trim();  if (!trimmed) {    return null;  }   const aliases = MODEL_SLUG_ALIASES_BY_PROVIDER[provider] as Record<string, ModelSlug>;  const aliased = Object.prototype.hasOwnProperty.call(aliases, trimmed)    ? aliases[trimmed]    : undefined;  return typeof aliased === "string" ? aliased : (trimmed as ModelSlug);} export function resolveModelSlug(  model: string | null | undefined,  provider: ProviderKind = "codex",): ModelSlug {  const normalized = normalizeModelSlug(model, provider);  if (!normalized) {    return DEFAULT_MODEL_BY_PROVIDER[provider];  }   return MODEL_SLUG_SET_BY_PROVIDER[provider].has(normalized)    ? normalized    : DEFAULT_MODEL_BY_PROVIDER[provider];} export function resolveModelSlugForProvider(  provider: ProviderKind,  model: string | null | undefined,): ModelSlug {  return resolveModelSlug(model, provider);} export function inferProviderForModel(  model: string | null | undefined,  fallback: ProviderKind = "codex",): ProviderKind {  const normalizedClaude = normalizeModelSlug(model, "claudeAgent");  if (normalizedClaude && MODEL_SLUG_SET_BY_PROVIDER.claudeAgent.has(normalizedClaude)) {    return "claudeAgent";  }   const normalizedCodex = normalizeModelSlug(model, "codex");  if (normalizedCodex && MODEL_SLUG_SET_BY_PROVIDER.codex.has(normalizedCodex)) {    return "codex";  }   return typeof model === "string" && model.trim().startsWith("claude-") ? "claudeAgent" : fallback;} export function getReasoningEffortOptions(provider: "codex"): ReadonlyArray<CodexReasoningEffort>;export function getReasoningEffortOptions(  provider: "claudeAgent",  model?: string | null | undefined,): ReadonlyArray<ClaudeCodeEffort>;export function getReasoningEffortOptions(  provider?: ProviderKind,  model?: string | null | undefined,): ReadonlyArray<ProviderReasoningEffort>;export function getReasoningEffortOptions(  provider: ProviderKind = "codex",  model?: string | null | undefined,): ReadonlyArray<ProviderReasoningEffort> {  if (provider === "claudeAgent") {    if (supportsClaudeMaxEffort(model)) {      return ["low", "medium", "high", "max", "ultrathink"];    }    if (supportsClaudeAdaptiveReasoning(model)) {      return ["low", "medium", "high", "ultrathink"];    }    return [];  }  return REASONING_EFFORT_OPTIONS_BY_PROVIDER[provider];} export function getDefaultReasoningEffort(provider: "codex"): CodexReasoningEffort;export function getDefaultReasoningEffort(provider: "claudeAgent"): ClaudeCodeEffort;export function getDefaultReasoningEffort(provider?: ProviderKind): ProviderReasoningEffort;export function getDefaultReasoningEffort(  provider: ProviderKind = "codex",): ProviderReasoningEffort {  return DEFAULT_REASONING_EFFORT_BY_PROVIDER[provider];} export function resolveReasoningEffortForProvider(  provider: "codex",  effort: string | null | undefined,): CodexReasoningEffort | null;export function resolveReasoningEffortForProvider(  provider: "claudeAgent",  effort: string | null | undefined,): ClaudeCodeEffort | null;export function resolveReasoningEffortForProvider(  provider: ProviderKind,  effort: string | null | undefined,): ProviderReasoningEffort | null;export function resolveReasoningEffortForProvider(  provider: ProviderKind,  effort: string | null | undefined,): ProviderReasoningEffort | null {  if (typeof effort !== "string") {    return null;  }   const trimmed = effort.trim();  if (!trimmed) {    return null;  }   const options = REASONING_EFFORT_OPTIONS_BY_PROVIDER[provider] as ReadonlyArray<string>;  return options.includes(trimmed) ? (trimmed as ProviderReasoningEffort) : null;} export function getEffectiveClaudeCodeEffort(  effort: ClaudeCodeEffort | null | undefined,): Exclude<ClaudeCodeEffort, "ultrathink"> | null {  if (!effort) {    return null;  }  return effort === "ultrathink" ? null : effort;} export function normalizeCodexModelOptions(  modelOptions: CodexModelOptions | null | undefined,): CodexModelOptions | undefined {  const defaultReasoningEffort = getDefaultReasoningEffort("codex");  const reasoningEffort =    resolveReasoningEffortForProvider("codex", modelOptions?.reasoningEffort) ??    defaultReasoningEffort;  const fastModeEnabled = modelOptions?.fastMode === true;  const nextOptions: CodexModelOptions = {    ...(reasoningEffort !== defaultReasoningEffort ? { reasoningEffort } : {}),    ...(fastModeEnabled ? { fastMode: true } : {}),  };  return Object.keys(nextOptions).length > 0 ? nextOptions : undefined;} export function normalizeClaudeModelOptions(  model: string | null | undefined,  modelOptions: ClaudeModelOptions | null | undefined,): ClaudeModelOptions | undefined {  const reasoningOptions = getReasoningEffortOptions("claudeAgent", model);  const defaultReasoningEffort = getDefaultReasoningEffort("claudeAgent");  const resolvedEffort = resolveReasoningEffortForProvider("claudeAgent", modelOptions?.effort);  const effort =    resolvedEffort &&    resolvedEffort !== "ultrathink" &&    reasoningOptions.includes(resolvedEffort) &&    resolvedEffort !== defaultReasoningEffort      ? resolvedEffort      : undefined;  const thinking =    supportsClaudeThinkingToggle(model) && modelOptions?.thinking === false ? false : undefined;  const fastMode =    supportsClaudeFastMode(model) && modelOptions?.fastMode === true ? true : undefined;  const nextOptions: ClaudeModelOptions = {    ...(thinking === false ? { thinking: false } : {}),    ...(effort ? { effort } : {}),    ...(fastMode ? { fastMode: true } : {}),  };  return Object.keys(nextOptions).length > 0 ? nextOptions : undefined;} export function applyClaudePromptEffortPrefix(  text: string,  effort: ClaudeCodeEffort | null | undefined,): string {  const trimmed = text.trim();  if (!trimmed) {    return trimmed;  }  if (effort !== "ultrathink") {    return trimmed;  }  if (trimmed.startsWith("Ultrathink:")) {    return trimmed;  }  return `Ultrathink:\n${trimmed}`;} export { CLAUDE_CODE_EFFORT_OPTIONS, CODEX_REASONING_EFFORT_OPTIONS };