| author | |
| committer | |
| log | 116c8c5e8e0db2fe7fad070c2f67738a62f93546 |
| tree | ec6b3428610593479a94c4d56c0cd4d354e63e62 |
| parent | f8886e874d43fe591fa50d28e9a8983632ba7e45 |
6 files changed, 40 insertions(+), 70 deletions(-)
apps/web/src/components/ChatView.tsx+12-17| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | import { | 1 | import { |
| 2 | type ApprovalRequestId, | 2 | type ApprovalRequestId, |
| 3 | DEFAULT_MODEL, | 3 | DEFAULT_MODEL_BY_PROVIDER, |
| 4 | EDITORS, | 4 | EDITORS, |
| 5 | type EditorId, | 5 | type EditorId, |
| 6 | type KeybindingCommand, | 6 | type KeybindingCommand, |
| ... | @@ -575,7 +575,9 @@ export default function ChatView({ threadId }: ChatViewProps) { | ... | @@ -575,7 +575,9 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 575 | const setComposerDraftProvider = useComposerDraftStore((store) => store.setProvider); | 575 | const setComposerDraftProvider = useComposerDraftStore((store) => store.setProvider); |
| 576 | const setComposerDraftModel = useComposerDraftStore((store) => store.setModel); | 576 | const setComposerDraftModel = useComposerDraftStore((store) => store.setModel); |
| 577 | const setComposerDraftRuntimeMode = useComposerDraftStore((store) => store.setRuntimeMode); | 577 | const setComposerDraftRuntimeMode = useComposerDraftStore((store) => store.setRuntimeMode); |
| 578 | const setComposerDraftInteractionMode = useComposerDraftStore((store) => store.setInteractionMode); | 578 | const setComposerDraftInteractionMode = useComposerDraftStore( |
| 579 | (store) => store.setInteractionMode, | ||
| 580 | ); | ||
| 579 | const setComposerDraftEffort = useComposerDraftStore((store) => store.setEffort); | 581 | const setComposerDraftEffort = useComposerDraftStore((store) => store.setEffort); |
| 580 | const setComposerDraftCodexFastMode = useComposerDraftStore((store) => store.setCodexFastMode); | 582 | const setComposerDraftCodexFastMode = useComposerDraftStore((store) => store.setCodexFastMode); |
| 581 | const addComposerDraftImage = useComposerDraftStore((store) => store.addImage); | 583 | const addComposerDraftImage = useComposerDraftStore((store) => store.addImage); |
| ... | @@ -703,14 +705,15 @@ export default function ChatView({ threadId }: ChatViewProps) { | ... | @@ -703,14 +705,15 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 703 | ? buildLocalDraftThread( | 705 | ? buildLocalDraftThread( |
| 704 | threadId, | 706 | threadId, |
| 705 | draftThread, | 707 | draftThread, |
| 706 | fallbackDraftProject?.model ?? DEFAULT_MODEL, | 708 | fallbackDraftProject?.model ?? DEFAULT_MODEL_BY_PROVIDER.codex, |
| 707 | localDraftError, | 709 | localDraftError, |
| 708 | ) | 710 | ) |
| 709 | : undefined, | 711 | : undefined, |
| 710 | [draftThread, fallbackDraftProject?.model, localDraftError, threadId], | 712 | [draftThread, fallbackDraftProject?.model, localDraftError, threadId], |
| 711 | ); | 713 | ); |
| 712 | const activeThread = serverThread ?? localDraftThread; | 714 | const activeThread = serverThread ?? localDraftThread; |
| 713 | const runtimeMode = composerDraft.runtimeMode ?? activeThread?.runtimeMode ?? DEFAULT_RUNTIME_MODE; | 715 | const runtimeMode = |
| 716 | composerDraft.runtimeMode ?? activeThread?.runtimeMode ?? DEFAULT_RUNTIME_MODE; | ||
| 714 | const interactionMode = | 717 | const interactionMode = |
| 715 | composerDraft.interactionMode ?? activeThread?.interactionMode ?? DEFAULT_INTERACTION_MODE; | 718 | composerDraft.interactionMode ?? activeThread?.interactionMode ?? DEFAULT_INTERACTION_MODE; |
| 716 | const isServerThread = serverThread !== undefined; | 719 | const isServerThread = serverThread !== undefined; |
| ... | @@ -757,10 +760,7 @@ export default function ChatView({ threadId }: ChatViewProps) { | ... | @@ -757,10 +760,7 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 757 | const selectedProvider: ProviderKind = lockedProvider ?? selectedProviderByThreadId ?? "codex"; | 760 | const selectedProvider: ProviderKind = lockedProvider ?? selectedProviderByThreadId ?? "codex"; |
| 758 | const baseThreadModel = resolveModelSlugForProvider( | 761 | const baseThreadModel = resolveModelSlugForProvider( |
| 759 | selectedProvider, | 762 | selectedProvider, |
| 760 | activeThread?.model ?? | 763 | activeThread?.model ?? activeProject?.model ?? getDefaultModel(selectedProvider), |
| 761 | activeProject?.model ?? | ||
| 762 | getDefaultModel(selectedProvider) ?? | ||
| 763 | DEFAULT_MODEL, | ||
| 764 | ); | 764 | ); |
| 765 | const selectedModel = useMemo(() => { | 765 | const selectedModel = useMemo(() => { |
| 766 | const draftModel = composerDraft.model; | 766 | const draftModel = composerDraft.model; |
| ... | @@ -2470,7 +2470,7 @@ export default function ChatView({ threadId }: ChatViewProps) { | ... | @@ -2470,7 +2470,7 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 2470 | } | 2470 | } |
| 2471 | const title = truncateTitle(titleSeed); | 2471 | const title = truncateTitle(titleSeed); |
| 2472 | let threadCreateModel: ModelSlug = | 2472 | let threadCreateModel: ModelSlug = |
| 2473 | selectedModel || (activeProject.model as ModelSlug) || DEFAULT_MODEL; | 2473 | selectedModel || (activeProject.model as ModelSlug) || DEFAULT_MODEL_BY_PROVIDER.codex; |
| 2474 | 2474 | ||
| 2475 | if (isLocalDraftThread) { | 2475 | if (isLocalDraftThread) { |
| 2476 | await api.orchestration.dispatchCommand({ | 2476 | await api.orchestration.dispatchCommand({ |
| ... | @@ -2881,7 +2881,7 @@ export default function ChatView({ threadId }: ChatViewProps) { | ... | @@ -2881,7 +2881,7 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 2881 | selectedModel || | 2881 | selectedModel || |
| 2882 | (activeThread.model as ModelSlug) || | 2882 | (activeThread.model as ModelSlug) || |
| 2883 | (activeProject.model as ModelSlug) || | 2883 | (activeProject.model as ModelSlug) || |
| 2884 | DEFAULT_MODEL; | 2884 | DEFAULT_MODEL_BY_PROVIDER.codex; |
| 2885 | 2885 | ||
| 2886 | sendInFlightRef.current = true; | 2886 | sendInFlightRef.current = true; |
| 2887 | setSendPhase("sending-turn"); | 2887 | setSendPhase("sending-turn"); |
| ... | @@ -5127,9 +5127,7 @@ const MessagesTimeline = memo(function MessagesTimeline({ | ... | @@ -5127,9 +5127,7 @@ const MessagesTimeline = memo(function MessagesTimeline({ |
| 5127 | ); | 5127 | ); |
| 5128 | }); | 5128 | }); |
| 5129 | 5129 | ||
| 5130 | function isAvailableProviderOption( | 5130 | function isAvailableProviderOption(option: (typeof PROVIDER_OPTIONS)[number]): option is { |
| 5131 | option: (typeof PROVIDER_OPTIONS)[number], | ||
| 5132 | ): option is { | ||
| 5133 | value: ProviderKind; | 5131 | value: ProviderKind; |
| 5134 | label: string; | 5132 | label: string; |
| 5135 | available: true; | 5133 | available: true; |
| ... | @@ -5227,10 +5225,7 @@ const ProviderModelPicker = memo(function ProviderModelPicker(props: { | ... | @@ -5227,10 +5225,7 @@ const ProviderModelPicker = memo(function ProviderModelPicker(props: { |
| 5227 | } | 5225 | } |
| 5228 | > | 5226 | > |
| 5229 | <span className="flex min-w-0 items-center gap-2"> | 5227 | <span className="flex min-w-0 items-center gap-2"> |
| 5230 | <ProviderIcon | 5228 | <ProviderIcon aria-hidden="true" className="size-4 shrink-0 text-muted-foreground/70" /> |
| 5231 | aria-hidden="true" | ||
| 5232 | className="size-4 shrink-0 text-muted-foreground/70" | ||
| 5233 | /> | ||
| 5234 | <span className="truncate">{selectedModelLabel}</span> | 5229 | <span className="truncate">{selectedModelLabel}</span> |
| 5235 | <ChevronDownIcon aria-hidden="true" className="size-3 opacity-60" /> | 5230 | <ChevronDownIcon aria-hidden="true" className="size-3 opacity-60" /> |
| 5236 | </span> | 5231 | </span> |
apps/web/src/components/Sidebar.tsx+3-3| ... | @@ -9,7 +9,7 @@ import { | ... | @@ -9,7 +9,7 @@ import { |
| 9 | import { useCallback, useEffect, useMemo, useRef, useState } from "react"; | 9 | import { useCallback, useEffect, useMemo, useRef, useState } from "react"; |
| 10 | import { | 10 | import { |
| 11 | DEFAULT_RUNTIME_MODE, | 11 | DEFAULT_RUNTIME_MODE, |
| 12 | DEFAULT_MODEL, | 12 | DEFAULT_MODEL_BY_PROVIDER, |
| 13 | type DesktopUpdateState, | 13 | type DesktopUpdateState, |
| 14 | ProjectId, | 14 | ProjectId, |
| 15 | ThreadId, | 15 | ThreadId, |
| ... | @@ -506,7 +506,7 @@ export default function Sidebar() { | ... | @@ -506,7 +506,7 @@ export default function Sidebar() { |
| 506 | projectId, | 506 | projectId, |
| 507 | title, | 507 | title, |
| 508 | workspaceRoot: cwd, | 508 | workspaceRoot: cwd, |
| 509 | defaultModel: DEFAULT_MODEL, | 509 | defaultModel: DEFAULT_MODEL_BY_PROVIDER.codex, |
| 510 | createdAt, | 510 | createdAt, |
| 511 | }) | 511 | }) |
| 512 | .then(() => true) | 512 | .then(() => true) |
| ... | @@ -885,7 +885,7 @@ export default function Sidebar() { | ... | @@ -885,7 +885,7 @@ export default function Sidebar() { |
| 885 | ? "text-sky-400" | 885 | ? "text-sky-400" |
| 886 | : shouldHighlightDesktopUpdateError(desktopUpdateState) | 886 | : shouldHighlightDesktopUpdateError(desktopUpdateState) |
| 887 | ? "text-rose-500 animate-pulse" | 887 | ? "text-rose-500 animate-pulse" |
| 888 | : "text-amber-500 animate-pulse"; | 888 | : "text-amber-500 animate-pulse"; |
| 889 | const newThreadShortcutLabel = useMemo( | 889 | const newThreadShortcutLabel = useMemo( |
| 890 | () => | 890 | () => |
| 891 | shortcutLabelForCommand(keybindings, "chat.newLocal") ?? | 891 | shortcutLabelForCommand(keybindings, "chat.newLocal") ?? |
apps/web/src/store.ts+14-35| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | import { Fragment, type ReactNode, createElement, useEffect } from "react"; | 1 | import { Fragment, type ReactNode, createElement, useEffect } from "react"; |
| 2 | import { | 2 | import { |
| 3 | DEFAULT_MODEL, | 3 | DEFAULT_MODEL_BY_PROVIDER, |
| 4 | type ProviderKind, | 4 | type ProviderKind, |
| 5 | ThreadId, | 5 | ThreadId, |
| 6 | type OrchestrationReadModel, | 6 | type OrchestrationReadModel, |
| ... | @@ -13,11 +13,7 @@ import { | ... | @@ -13,11 +13,7 @@ import { |
| 13 | resolveModelSlugForProvider, | 13 | resolveModelSlugForProvider, |
| 14 | } from "@t3tools/shared/model"; | 14 | } from "@t3tools/shared/model"; |
| 15 | import { create } from "zustand"; | 15 | import { create } from "zustand"; |
| 16 | import { | 16 | import { type ChatMessage, type Project, type Thread } from "./types"; |
| 17 | type ChatMessage, | ||
| 18 | type Project, | ||
| 19 | type Thread, | ||
| 20 | } from "./types"; | ||
| 21 | 17 | ||
| 22 | // ── State ──────────────────────────────────────────────────────────── | 18 | // ── State ──────────────────────────────────────────────────────────── |
| 23 | 19 | ||
| ... | @@ -114,7 +110,9 @@ function mapProjectsFromReadModel( | ... | @@ -114,7 +110,9 @@ function mapProjectsFromReadModel( |
| 114 | id: project.id, | 110 | id: project.id, |
| 115 | name: project.title, | 111 | name: project.title, |
| 116 | cwd: project.workspaceRoot, | 112 | cwd: project.workspaceRoot, |
| 117 | model: existing?.model ?? resolveModelSlug(project.defaultModel ?? DEFAULT_MODEL), | 113 | model: |
| 114 | existing?.model ?? | ||
| 115 | resolveModelSlug(project.defaultModel ?? DEFAULT_MODEL_BY_PROVIDER.codex), | ||
| 118 | expanded: | 116 | expanded: |
| 119 | existing?.expanded ?? | 117 | existing?.expanded ?? |
| 120 | (persistedExpandedProjectCwds.size > 0 | 118 | (persistedExpandedProjectCwds.size > 0 |
| ... | @@ -181,11 +179,7 @@ function resolveWsHttpOrigin(): string { | ... | @@ -181,11 +179,7 @@ function resolveWsHttpOrigin(): string { |
| 181 | try { | 179 | try { |
| 182 | const wsUrl = new URL(wsCandidate); | 180 | const wsUrl = new URL(wsCandidate); |
| 183 | const protocol = | 181 | const protocol = |
| 184 | wsUrl.protocol === "wss:" | 182 | wsUrl.protocol === "wss:" ? "https:" : wsUrl.protocol === "ws:" ? "http:" : wsUrl.protocol; |
| 185 | ? "https:" | ||
| 186 | : wsUrl.protocol === "ws:" | ||
| 187 | ? "http:" | ||
| 188 | : wsUrl.protocol; | ||
| 189 | return `${protocol}//${wsUrl.host}`; | 183 | return `${protocol}//${wsUrl.host}`; |
| 190 | } catch { | 184 | } catch { |
| 191 | return window.location.origin; | 185 | return window.location.origin; |
| ... | @@ -205,17 +199,12 @@ function attachmentPreviewRoutePath(attachmentId: string): string { | ... | @@ -205,17 +199,12 @@ function attachmentPreviewRoutePath(attachmentId: string): string { |
| 205 | 199 | ||
| 206 | // ── Pure state transition functions ──────────────────────────────────── | 200 | // ── Pure state transition functions ──────────────────────────────────── |
| 207 | 201 | ||
| 208 | export function syncServerReadModel( | 202 | export function syncServerReadModel(state: AppState, readModel: OrchestrationReadModel): AppState { |
| 209 | state: AppState, | ||
| 210 | readModel: OrchestrationReadModel, | ||
| 211 | ): AppState { | ||
| 212 | const projects = mapProjectsFromReadModel( | 203 | const projects = mapProjectsFromReadModel( |
| 213 | readModel.projects.filter((project) => project.deletedAt === null), | 204 | readModel.projects.filter((project) => project.deletedAt === null), |
| 214 | state.projects, | 205 | state.projects, |
| 215 | ); | 206 | ); |
| 216 | const existingThreadById = new Map( | 207 | const existingThreadById = new Map(state.threads.map((thread) => [thread.id, thread] as const)); |
| 217 | state.threads.map((thread) => [thread.id, thread] as const), | ||
| 218 | ); | ||
| 219 | const threads = readModel.threads | 208 | const threads = readModel.threads |
| 220 | .filter((thread) => thread.deletedAt === null) | 209 | .filter((thread) => thread.deletedAt === null) |
| 221 | .map((thread) => { | 210 | .map((thread) => { |
| ... | @@ -334,9 +323,7 @@ export function markThreadUnread(state: AppState, threadId: ThreadId): AppState | ... | @@ -334,9 +323,7 @@ export function markThreadUnread(state: AppState, threadId: ThreadId): AppState |
| 334 | export function toggleProject(state: AppState, projectId: Project["id"]): AppState { | 323 | export function toggleProject(state: AppState, projectId: Project["id"]): AppState { |
| 335 | return { | 324 | return { |
| 336 | ...state, | 325 | ...state, |
| 337 | projects: state.projects.map((p) => | 326 | projects: state.projects.map((p) => (p.id === projectId ? { ...p, expanded: !p.expanded } : p)), |
| 338 | p.id === projectId ? { ...p, expanded: !p.expanded } : p, | ||
| 339 | ), | ||
| 340 | }; | 327 | }; |
| 341 | } | 328 | } |
| 342 | 329 | ||
| ... | @@ -390,27 +377,19 @@ interface AppStore extends AppState { | ... | @@ -390,27 +377,19 @@ interface AppStore extends AppState { |
| 390 | toggleProject: (projectId: Project["id"]) => void; | 377 | toggleProject: (projectId: Project["id"]) => void; |
| 391 | setProjectExpanded: (projectId: Project["id"], expanded: boolean) => void; | 378 | setProjectExpanded: (projectId: Project["id"], expanded: boolean) => void; |
| 392 | setError: (threadId: ThreadId, error: string | null) => void; | 379 | setError: (threadId: ThreadId, error: string | null) => void; |
| 393 | setThreadBranch: ( | 380 | setThreadBranch: (threadId: ThreadId, branch: string | null, worktreePath: string | null) => void; |
| 394 | threadId: ThreadId, | ||
| 395 | branch: string | null, | ||
| 396 | worktreePath: string | null, | ||
| 397 | ) => void; | ||
| 398 | } | 381 | } |
| 399 | 382 | ||
| 400 | export const useStore = create<AppStore>((set) => ({ | 383 | export const useStore = create<AppStore>((set) => ({ |
| 401 | ...readPersistedState(), | 384 | ...readPersistedState(), |
| 402 | syncServerReadModel: (readModel) => | 385 | syncServerReadModel: (readModel) => set((state) => syncServerReadModel(state, readModel)), |
| 403 | set((state) => syncServerReadModel(state, readModel)), | ||
| 404 | markThreadVisited: (threadId, visitedAt) => | 386 | markThreadVisited: (threadId, visitedAt) => |
| 405 | set((state) => markThreadVisited(state, threadId, visitedAt)), | 387 | set((state) => markThreadVisited(state, threadId, visitedAt)), |
| 406 | markThreadUnread: (threadId) => | 388 | markThreadUnread: (threadId) => set((state) => markThreadUnread(state, threadId)), |
| 407 | set((state) => markThreadUnread(state, threadId)), | 389 | toggleProject: (projectId) => set((state) => toggleProject(state, projectId)), |
| 408 | toggleProject: (projectId) => | ||
| 409 | set((state) => toggleProject(state, projectId)), | ||
| 410 | setProjectExpanded: (projectId, expanded) => | 390 | setProjectExpanded: (projectId, expanded) => |
| 411 | set((state) => setProjectExpanded(state, projectId, expanded)), | 391 | set((state) => setProjectExpanded(state, projectId, expanded)), |
| 412 | setError: (threadId, error) => | 392 | setError: (threadId, error) => set((state) => setError(state, threadId, error)), |
| 413 | set((state) => setError(state, threadId, error)), | ||
| 414 | setThreadBranch: (threadId, branch, worktreePath) => | 393 | setThreadBranch: (threadId, branch, worktreePath) => |
| 415 | set((state) => setThreadBranch(state, threadId, branch, worktreePath)), | 394 | set((state) => setThreadBranch(state, threadId, branch, worktreePath)), |
| 416 | })); | 395 | })); |
packages/contracts/src/model.ts+2-5| ... | @@ -29,18 +29,15 @@ export const MODEL_OPTIONS_BY_PROVIDER = { | ... | @@ -29,18 +29,15 @@ export const MODEL_OPTIONS_BY_PROVIDER = { |
| 29 | { slug: "gpt-5.2", name: "GPT-5.2" }, | 29 | { slug: "gpt-5.2", name: "GPT-5.2" }, |
| 30 | ], | 30 | ], |
| 31 | } as const satisfies Record<ProviderKind, readonly ModelOption[]>; | 31 | } as const satisfies Record<ProviderKind, readonly ModelOption[]>; |
| 32 | export type ModelOptionsByProvider = typeof MODEL_OPTIONS_BY_PROVIDER; | ||
| 32 | 33 | ||
| 33 | type BuiltInModelSlug = (typeof MODEL_OPTIONS_BY_PROVIDER)[ProviderKind][number]["slug"]; | 34 | type BuiltInModelSlug = ModelOptionsByProvider[ProviderKind][number]["slug"]; |
| 34 | export type ModelSlug = BuiltInModelSlug | (string & {}); | 35 | export type ModelSlug = BuiltInModelSlug | (string & {}); |
| 35 | 36 | ||
| 36 | export const DEFAULT_MODEL_BY_PROVIDER = { | 37 | export const DEFAULT_MODEL_BY_PROVIDER = { |
| 37 | codex: "gpt-5.4", | 38 | codex: "gpt-5.4", |
| 38 | } as const satisfies Record<ProviderKind, ModelSlug>; | 39 | } as const satisfies Record<ProviderKind, ModelSlug>; |
| 39 | 40 | ||
| 40 | // Backward compatibility for existing Codex-only call sites. | ||
| 41 | export const MODEL_OPTIONS = MODEL_OPTIONS_BY_PROVIDER.codex; | ||
| 42 | export const DEFAULT_MODEL = DEFAULT_MODEL_BY_PROVIDER.codex; | ||
| 43 | |||
| 44 | export const MODEL_SLUG_ALIASES_BY_PROVIDER = { | 41 | export const MODEL_SLUG_ALIASES_BY_PROVIDER = { |
| 45 | codex: { | 42 | codex: { |
| 46 | "5.4": "gpt-5.4", | 43 | "5.4": "gpt-5.4", |
packages/shared/src/model.test.ts+8-8| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | import { describe, expect, it } from "vitest"; | 1 | import { describe, expect, it } from "vitest"; |
| 2 | import { DEFAULT_MODEL, MODEL_OPTIONS } from "@t3tools/contracts"; | 2 | import { DEFAULT_MODEL_BY_PROVIDER, MODEL_OPTIONS_BY_PROVIDER } from "@t3tools/contracts"; |
| 3 | 3 | ||
| 4 | import { | 4 | import { |
| 5 | getDefaultModel, | 5 | getDefaultModel, |
| ... | @@ -31,23 +31,23 @@ describe("normalizeModelSlug", () => { | ... | @@ -31,23 +31,23 @@ describe("normalizeModelSlug", () => { |
| 31 | 31 | ||
| 32 | describe("resolveModelSlug", () => { | 32 | describe("resolveModelSlug", () => { |
| 33 | it("returns default only when the model is missing", () => { | 33 | it("returns default only when the model is missing", () => { |
| 34 | expect(resolveModelSlug(undefined)).toBe(DEFAULT_MODEL); | 34 | expect(resolveModelSlug(undefined)).toBe(DEFAULT_MODEL_BY_PROVIDER.codex); |
| 35 | expect(resolveModelSlug(null)).toBe(DEFAULT_MODEL); | 35 | expect(resolveModelSlug(null)).toBe(DEFAULT_MODEL_BY_PROVIDER.codex); |
| 36 | }); | 36 | }); |
| 37 | 37 | ||
| 38 | it("preserves unknown custom models", () => { | 38 | it("preserves unknown custom models", () => { |
| 39 | expect(resolveModelSlug("gpt-4.1")).toBe(DEFAULT_MODEL); | 39 | expect(resolveModelSlug("gpt-4.1")).toBe(DEFAULT_MODEL_BY_PROVIDER.codex); |
| 40 | expect(resolveModelSlug("custom/internal-model")).toBe(DEFAULT_MODEL); | 40 | expect(resolveModelSlug("custom/internal-model")).toBe(DEFAULT_MODEL_BY_PROVIDER.codex); |
| 41 | }); | 41 | }); |
| 42 | 42 | ||
| 43 | it("resolves only supported model options", () => { | 43 | it("resolves only supported model options", () => { |
| 44 | for (const model of MODEL_OPTIONS) { | 44 | for (const model of MODEL_OPTIONS_BY_PROVIDER.codex) { |
| 45 | expect(resolveModelSlug(model.slug)).toBe(model.slug); | 45 | expect(resolveModelSlug(model.slug)).toBe(model.slug); |
| 46 | } | 46 | } |
| 47 | }); | 47 | }); |
| 48 | it("keeps codex defaults for backward compatibility", () => { | 48 | it("keeps codex defaults for backward compatibility", () => { |
| 49 | expect(getDefaultModel()).toBe(DEFAULT_MODEL); | 49 | expect(getDefaultModel()).toBe(DEFAULT_MODEL_BY_PROVIDER.codex); |
| 50 | expect(getModelOptions()).toEqual(MODEL_OPTIONS); | 50 | expect(getModelOptions()).toEqual(MODEL_OPTIONS_BY_PROVIDER.codex); |
| 51 | }); | 51 | }); |
| 52 | }); | 52 | }); |
| 53 | 53 |
packages/shared/src/model.ts+1-2| ... | @@ -1,6 +1,5 @@ | ... | @@ -1,6 +1,5 @@ |
| 1 | import { | 1 | import { |
| 2 | CODEX_REASONING_EFFORT_OPTIONS, | 2 | CODEX_REASONING_EFFORT_OPTIONS, |
| 3 | DEFAULT_MODEL, | ||
| 4 | DEFAULT_MODEL_BY_PROVIDER, | 3 | DEFAULT_MODEL_BY_PROVIDER, |
| 5 | MODEL_OPTIONS_BY_PROVIDER, | 4 | MODEL_OPTIONS_BY_PROVIDER, |
| 6 | MODEL_SLUG_ALIASES_BY_PROVIDER, | 5 | MODEL_SLUG_ALIASES_BY_PROVIDER, |
| ... | @@ -20,7 +19,7 @@ export function getModelOptions(provider: ProviderKind = "codex") { | ... | @@ -20,7 +19,7 @@ export function getModelOptions(provider: ProviderKind = "codex") { |
| 20 | } | 19 | } |
| 21 | 20 | ||
| 22 | export function getDefaultModel(provider: ProviderKind = "codex"): ModelSlug { | 21 | export function getDefaultModel(provider: ProviderKind = "codex"): ModelSlug { |
| 23 | return DEFAULT_MODEL_BY_PROVIDER[provider] ?? DEFAULT_MODEL; | 22 | return DEFAULT_MODEL_BY_PROVIDER[provider]; |
| 24 | } | 23 | } |
| 25 | 24 | ||
| 26 | export function normalizeModelSlug( | 25 | export function normalizeModelSlug( |