From e6ac6badde66040986d235a7b15496f81c7c7ff4 Mon Sep 17 00:00:00 2001 From: Gyumin Lee <64009299+Chi-square-test@users.noreply.github.com> Date: Sun, 12 Apr 2026 05:50:13 +0900 Subject: [PATCH] fix: restore variant restoration for OpenCode 1.4.0 (#871) OpenCode 1.4.0 moved `UserMessage.variant` from the top-level to `UserMessage.model.variant`. OpenChamber still read the legacy location, so variant selection silently stopped being restored on sessions served by OpenCode 1.4.0+. Read `model.variant` first and fall back to the legacy top-level field so both pre-1.4 and 1.4+ OpenCode servers keep working. --- packages/ui/src/components/chat/MessageList.tsx | 5 ++++- packages/ui/src/components/chat/ModelControls.tsx | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/components/chat/MessageList.tsx b/packages/ui/src/components/chat/MessageList.tsx index db72b459..3372eb70 100644 --- a/packages/ui/src/components/chat/MessageList.tsx +++ b/packages/ui/src/components/chat/MessageList.tsx @@ -655,7 +655,10 @@ const TurnBlock: React.FC = ({ const turnGroupingContextBase = React.useMemo(() => { const userCreatedAt = (turn.userMessage.info.time as { created?: number } | undefined)?.created; - const rawVariant = (turn.userMessage.info as { variant?: unknown } | undefined)?.variant; + // OpenCode 1.4.0 moved variant from top-level to model.variant on UserMessage. + // Prefer the new location, fall back to the legacy one for older servers. + const info = turn.userMessage.info as { variant?: unknown; model?: { variant?: unknown } } | undefined; + const rawVariant = info?.model?.variant ?? info?.variant; const userMessageVariant = typeof rawVariant === 'string' && rawVariant.trim().length > 0 ? rawVariant : undefined; diff --git a/packages/ui/src/components/chat/ModelControls.tsx b/packages/ui/src/components/chat/ModelControls.tsx index 8b527d2e..0569ea02 100644 --- a/packages/ui/src/components/chat/ModelControls.tsx +++ b/packages/ui/src/components/chat/ModelControls.tsx @@ -581,7 +581,7 @@ export const ModelControls: React.FC = ({ const latestLoadedUserChoice = React.useMemo(() => { for (let i = currentSessionMessagesFromSync.length - 1; i >= 0; i -= 1) { const message = currentSessionMessagesFromSync[i] as typeof currentSessionMessagesFromSync[number] & { - model?: { providerID?: string; modelID?: string }; + model?: { providerID?: string; modelID?: string; variant?: string }; variant?: string; mode?: string; }; @@ -598,8 +598,11 @@ export const ModelControls: React.FC = ({ const agent = typeof message.agent === 'string' && message.agent.trim().length > 0 ? message.agent : (typeof message.mode === 'string' && message.mode.trim().length > 0 ? message.mode : undefined); - const variant = typeof message.variant === 'string' && message.variant.trim().length > 0 - ? message.variant + // OpenCode 1.4.0 moved variant from top-level to model.variant. + // Prefer the new location, fall back to the legacy one for older servers. + const variantCandidate = message.model?.variant ?? message.variant; + const variant = typeof variantCandidate === 'string' && variantCandidate.trim().length > 0 + ? variantCandidate : undefined; return { id: message.id, agent, providerID, modelID, variant };