authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-03-01 23:55:38-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-03-05 23:00:41-08:00
logad28eaa86f851c6cd28573bd76635b550b43a530
tree80d8b5ba38b20003bed83ea688e292bb343bf1fc
parentd36bbc177d29877a335cda8bbe6601727587cffe

Scope composer draft reasoning effort to Codex options

- Switch draft store types to `CodexReasoningEffort` - Validate and default effort using Codex-specific option/default constants

1 files changed, 14 insertions(+), 10 deletions(-)

apps/web/src/composerDraftStore.ts+14-10
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1import {1import {
2 DEFAULT_REASONING,2 DEFAULT_REASONING_EFFORT_BY_PROVIDER,
3 ProjectId,3 ProjectId,
4 REASONING_OPTIONS,4 REASONING_EFFORT_OPTIONS_BY_PROVIDER,
5 ThreadId,5 ThreadId,
6 normalizeModelSlug,6 normalizeModelSlug,
7 type ReasoningEffort,7 type CodexReasoningEffort,
8} from "@t3tools/contracts";8} from "@t3tools/contracts";
9import type { ChatImageAttachment } from "./types";9import type { ChatImageAttachment } from "./types";
10import { create } from "zustand";10import { create } from "zustand";
...@@ -30,7 +30,7 @@ interface PersistedComposerThreadDraftState {...@@ -30,7 +30,7 @@ interface PersistedComposerThreadDraftState {
30 prompt: string;30 prompt: string;
31 attachments: PersistedComposerImageAttachment[];31 attachments: PersistedComposerImageAttachment[];
32 model?: string | null;32 model?: string | null;
33 effort?: ReasoningEffort | null;33 effort?: CodexReasoningEffort | null;
34}34}
3535
36interface PersistedDraftThreadState {36interface PersistedDraftThreadState {
...@@ -53,7 +53,7 @@ interface ComposerThreadDraftState {...@@ -53,7 +53,7 @@ interface ComposerThreadDraftState {
53 nonPersistedImageIds: string[];53 nonPersistedImageIds: string[];
54 persistedAttachments: PersistedComposerImageAttachment[];54 persistedAttachments: PersistedComposerImageAttachment[];
55 model: string | null;55 model: string | null;
56 effort: ReasoningEffort | null;56 effort: CodexReasoningEffort | null;
57}57}
5858
59export interface DraftThreadState {59export interface DraftThreadState {
...@@ -99,7 +99,7 @@ interface ComposerDraftStoreState {...@@ -99,7 +99,7 @@ interface ComposerDraftStoreState {
99 clearDraftThread: (threadId: ThreadId) => void;99 clearDraftThread: (threadId: ThreadId) => void;
100 setPrompt: (threadId: ThreadId, prompt: string) => void;100 setPrompt: (threadId: ThreadId, prompt: string) => void;
101 setModel: (threadId: ThreadId, model: string | null | undefined) => void;101 setModel: (threadId: ThreadId, model: string | null | undefined) => void;
102 setEffort: (threadId: ThreadId, effort: ReasoningEffort | null | undefined) => void;102 setEffort: (threadId: ThreadId, effort: CodexReasoningEffort | null | undefined) => void;
103 addImage: (threadId: ThreadId, image: ComposerImageAttachment) => void;103 addImage: (threadId: ThreadId, image: ComposerImageAttachment) => void;
104 addImages: (threadId: ThreadId, images: ComposerImageAttachment[]) => void;104 addImages: (threadId: ThreadId, images: ComposerImageAttachment[]) => void;
105 removeImage: (threadId: ThreadId, imageId: string) => void;105 removeImage: (threadId: ThreadId, imageId: string) => void;
...@@ -133,7 +133,9 @@ const EMPTY_THREAD_DRAFT = Object.freeze({...@@ -133,7 +133,9 @@ const EMPTY_THREAD_DRAFT = Object.freeze({
133 effort: null,133 effort: null,
134}) as ComposerThreadDraftState;134}) as ComposerThreadDraftState;
135135
136const REASONING_EFFORT_VALUES = new Set<ReasoningEffort>(REASONING_OPTIONS);136const REASONING_EFFORT_VALUES = new Set<CodexReasoningEffort>(
137 REASONING_EFFORT_OPTIONS_BY_PROVIDER.codex,
138);
137139
138function createEmptyThreadDraft(): ComposerThreadDraftState {140function createEmptyThreadDraft(): ComposerThreadDraftState {
139 return {141 return {
...@@ -310,8 +312,8 @@ function normalizePersistedComposerDraftState(value: unknown): PersistedComposer...@@ -310,8 +312,8 @@ function normalizePersistedComposerDraftState(value: unknown): PersistedComposer
310 const effortCandidate =312 const effortCandidate =
311 typeof draftCandidate.effort === "string" ? draftCandidate.effort : null;313 typeof draftCandidate.effort === "string" ? draftCandidate.effort : null;
312 const effort =314 const effort =
313 effortCandidate && REASONING_EFFORT_VALUES.has(effortCandidate as ReasoningEffort)315 effortCandidate && REASONING_EFFORT_VALUES.has(effortCandidate as CodexReasoningEffort)
314 ? (effortCandidate as ReasoningEffort)316 ? (effortCandidate as CodexReasoningEffort)
315 : null;317 : null;
316 if (prompt.length === 0 && attachments.length === 0 && !model && !effort) {318 if (prompt.length === 0 && attachments.length === 0 && !model && !effort) {
317 continue;319 continue;
...@@ -706,7 +708,9 @@ export const useComposerDraftStore = create<ComposerDraftStoreState>()(...@@ -706,7 +708,9 @@ export const useComposerDraftStore = create<ComposerDraftStoreState>()(
706 return;708 return;
707 }709 }
708 const nextEffort =710 const nextEffort =
709 effort && REASONING_EFFORT_VALUES.has(effort) && effort !== DEFAULT_REASONING711 effort &&
712 REASONING_EFFORT_VALUES.has(effort) &&
713 effort !== DEFAULT_REASONING_EFFORT_BY_PROVIDER.codex
710 ? effort714 ? effort
711 : null;715 : null;
712 set((state) => {716 set((state) => {