diff --git a/cli/src/agent/sessionFactory.ts b/cli/src/agent/sessionFactory.ts index b3c911757..cf0c4f8a6 100644 --- a/cli/src/agent/sessionFactory.ts +++ b/cli/src/agent/sessionFactory.ts @@ -20,6 +20,7 @@ export type SessionBootstrapOptions = { startedBy?: SessionStartedBy workingDirectory?: string tag?: string + model?: string agentState?: AgentState | null } @@ -49,6 +50,7 @@ export function buildSessionMetadata(options: { startedBy: SessionStartedBy workingDirectory: string machineId: string + model?: string now?: number }): Metadata { const happyLibDir = runtimePath() @@ -58,6 +60,7 @@ export function buildSessionMetadata(options: { return { path: options.workingDirectory, host: os.hostname(), + model: options.model?.trim() || undefined, version: packageJson.version, os: os.platform(), machineId: options.machineId, @@ -118,7 +121,8 @@ export async function bootstrapSession(options: SessionBootstrapOptions): Promis flavor: options.flavor, startedBy, workingDirectory, - machineId + machineId, + model: options.model }) const sessionInfo = await api.getOrCreateSession({ diff --git a/cli/src/codex/runCodex.ts b/cli/src/codex/runCodex.ts index 91657ecad..44556608a 100644 --- a/cli/src/codex/runCodex.ts +++ b/cli/src/codex/runCodex.ts @@ -33,6 +33,7 @@ export async function runCodex(opts: { flavor: 'codex', startedBy, workingDirectory, + model: opts.model, agentState: state }); diff --git a/shared/src/schemas.ts b/shared/src/schemas.ts index 5fc5c1bb7..50576c898 100644 --- a/shared/src/schemas.ts +++ b/shared/src/schemas.ts @@ -22,6 +22,7 @@ export type WorktreeMetadata = z.infer export const MetadataSchema = z.object({ path: z.string(), host: z.string(), + model: z.string().optional(), version: z.string().optional(), name: z.string().optional(), os: z.string().optional(), diff --git a/shared/src/sessionSummary.ts b/shared/src/sessionSummary.ts index 4b693ada7..b0c7d5c29 100644 --- a/shared/src/sessionSummary.ts +++ b/shared/src/sessionSummary.ts @@ -5,6 +5,7 @@ export type SessionSummaryMetadata = { name?: string path: string machineId?: string + model?: string summary?: { text: string } flavor?: string | null worktree?: WorktreeMetadata @@ -29,6 +30,7 @@ export function toSessionSummary(session: Session): SessionSummary { name: session.metadata.name, path: session.metadata.path, machineId: session.metadata.machineId ?? undefined, + model: session.metadata.model ?? undefined, summary: session.metadata.summary ? { text: session.metadata.summary.text } : undefined, flavor: session.metadata.flavor ?? null, worktree: session.metadata.worktree diff --git a/web/src/components/SessionHeader.tsx b/web/src/components/SessionHeader.tsx index 3728b2670..afd853af8 100644 --- a/web/src/components/SessionHeader.tsx +++ b/web/src/components/SessionHeader.tsx @@ -6,6 +6,7 @@ import { useSessionActions } from '@/hooks/mutations/useSessionActions' import { SessionActionMenu } from '@/components/SessionActionMenu' import { RenameSessionDialog } from '@/components/RenameSessionDialog' import { ConfirmDialog } from '@/components/ui/ConfirmDialog' +import { getSessionModelLabel } from '@/lib/sessionModelLabel' import { useTranslation } from '@/lib/use-translation' function getSessionTitle(session: Session): string { @@ -139,7 +140,7 @@ export function SessionHeader(props: { {session.metadata?.flavor?.trim() || 'unknown'} - {t('session.item.modelMode')}: {session.modelMode || 'default'} + {t('session.item.modelMode')}: {getSessionModelLabel(session)} {worktreeBranch ? ( {t('session.item.worktree')}: {worktreeBranch} diff --git a/web/src/components/SessionList.tsx b/web/src/components/SessionList.tsx index 69c71c37b..438b3fefa 100644 --- a/web/src/components/SessionList.tsx +++ b/web/src/components/SessionList.tsx @@ -7,6 +7,7 @@ import { useSessionActions } from '@/hooks/mutations/useSessionActions' import { SessionActionMenu } from '@/components/SessionActionMenu' import { RenameSessionDialog } from '@/components/RenameSessionDialog' import { ConfirmDialog } from '@/components/ui/ConfirmDialog' +import { getSessionModelLabel } from '@/lib/sessionModelLabel' import { useTranslation } from '@/lib/use-translation' type SessionGroup = { @@ -259,7 +260,7 @@ function SessionItem(props: { {getAgentLabel(s)} - {t('session.item.modelMode')}: {s.modelMode || 'default'} + {t('session.item.modelMode')}: {getSessionModelLabel(s)} {s.metadata?.worktree?.branch ? ( {t('session.item.worktree')}: {s.metadata.worktree.branch} ) : null} diff --git a/web/src/lib/locales/en.ts b/web/src/lib/locales/en.ts index 9c67e8d25..eefcc4b09 100644 --- a/web/src/lib/locales/en.ts +++ b/web/src/lib/locales/en.ts @@ -46,7 +46,7 @@ export default { 'session.item.path': 'path', 'session.item.agent': 'agent', 'session.item.model': 'model', - 'session.item.modelMode': 'mode', + 'session.item.modelMode': 'model', 'session.item.worktree': 'worktree', 'session.item.pending': 'pending', 'session.item.thinking': 'thinking', diff --git a/web/src/lib/sessionModelLabel.test.ts b/web/src/lib/sessionModelLabel.test.ts new file mode 100644 index 000000000..da5c600de --- /dev/null +++ b/web/src/lib/sessionModelLabel.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from 'vitest' +import { getSessionModelLabel } from './sessionModelLabel' + +describe('getSessionModelLabel', () => { + it('prefers the actual model name stored in session metadata', () => { + expect(getSessionModelLabel({ + metadata: { + path: '/Users/test/project', + host: 'test-host', + model: 'gpt-5.4' + }, + modelMode: 'default' + })).toBe('gpt-5.4') + }) + + it('falls back to modelMode when no actual model is stored', () => { + expect(getSessionModelLabel({ + metadata: { + path: '/Users/test/project', + host: 'test-host' + }, + modelMode: 'opus' + })).toBe('opus') + }) + + it('falls back to default when neither actual model nor model mode is available', () => { + expect(getSessionModelLabel({ + metadata: { + path: '/Users/test/project', + host: 'test-host' + }, + modelMode: undefined + })).toBe('default') + }) +}) diff --git a/web/src/lib/sessionModelLabel.ts b/web/src/lib/sessionModelLabel.ts new file mode 100644 index 000000000..e4bbfe661 --- /dev/null +++ b/web/src/lib/sessionModelLabel.ts @@ -0,0 +1,13 @@ +import type { Session, SessionSummary } from '@/types/api' + +type SessionWithModelMetadata = + | Pick + | Pick + +export function getSessionModelLabel(session: SessionWithModelMetadata): string { + const actualModel = session.metadata?.model?.trim() + if (actualModel) { + return actualModel + } + return session.modelMode || 'default' +} diff --git a/web/src/types/api.ts b/web/src/types/api.ts index 14a7b6c6b..6a1adedbd 100644 --- a/web/src/types/api.ts +++ b/web/src/types/api.ts @@ -25,6 +25,7 @@ export type { export type SessionMetadataSummary = { path: string host: string + model?: string version?: string name?: string os?: string