1import type { ProviderOptionSelection } from "@t3tools/contracts";
2import { appAtomRegistry } from "./atom-registry";
3import {
4 modelOptionMemoryAtom,
5 schedulePersistComposerState,
6 type ModelOptionMemoryState,
7} from "./use-composer-drafts";
8
9/** Cross-thread memory of each model's last explicit option selection. */
10function recordModelOptionsInState(
11 state: ModelOptionMemoryState,
12 instanceId: string,
13 model: string,
14 options: ReadonlyArray<ProviderOptionSelection>,
15): ModelOptionMemoryState {
16 if (options.length === 0) {
17 return state;
18 }
19 return {
20 ...state,
21 [instanceId]: {
22 ...(state[instanceId] ?? {}),
23 [model]: options,
24 },
25 };
26}
27
28/** Pure lookup; `undefined` means "no memory, fall back to descriptor defaults". */
29function lookupModelOptionsInState(
30 state: ModelOptionMemoryState,
31 instanceId: string,
32 model: string,
33): ReadonlyArray<ProviderOptionSelection> | undefined {
34 return state[instanceId]?.[model];
35}
36
37/** Records an explicitly chosen option set for one instance and model. */
38export function rememberModelOptions(
39 instanceId: string,
40 model: string,
41 options: ReadonlyArray<ProviderOptionSelection>,
42): void {
43 if (options.length === 0) {
44 return;
45 }
46 const current = appAtomRegistry.get(modelOptionMemoryAtom);
47 const next = recordModelOptionsInState(current, String(instanceId), model, options);
48 if (next !== current) {
49 appAtomRegistry.set(modelOptionMemoryAtom, next);
50 schedulePersistComposerState();
51 }
52}
53
54export function rememberedModelOptions(
55 instanceId: string,
56 model: string,
57): ReadonlyArray<ProviderOptionSelection> | undefined {
58 return lookupModelOptionsInState(
59 appAtomRegistry.get(modelOptionMemoryAtom),
60 String(instanceId),
61 model,
62 );
63}
64
65/**
66 * Restores a remembered option set for a freshly picked selection, keeping the
67 * incoming selections when nothing is remembered or they already match.
68 */
69export function withRememberedModelOptions<
70 T extends {
71 readonly instanceId: string;
72 readonly model: string;
73 readonly options?: ReadonlyArray<ProviderOptionSelection>;
74 },
75>(selection: T): T {
76 const remembered = rememberedModelOptions(selection.instanceId, selection.model);
77 if (
78 remembered === undefined ||
79 JSON.stringify(remembered) === JSON.stringify(selection.options ?? [])
80 ) {
81 return selection;
82 }
83 return { ...selection, options: remembered };
84}