"use client"; import localforage from "localforage"; import type { ChatAttachment, ChatCapabilityMode, ChatReasoningEffort } from "@/lib/chat-runtime"; export type ChatComposerDraft = { prompt: string; model: string; reasoningEffort: ChatReasoningEffort; capabilityMode: ChatCapabilityMode; attachments: ChatAttachment[]; }; const stateKey = "chatgpt2api:chat_composer_draft_v1"; const attachmentStorage = localforage.createInstance({ name: "chatgpt2api", storeName: "chat_composer_draft" }); const attachmentKey = "attachments:v1"; export function saveChatComposerDraftState(draft: Omit) { if (typeof window === "undefined") return; try { window.sessionStorage.setItem(stateKey, JSON.stringify(draft)); } catch { // Draft persistence is best-effort in restricted browsing modes. } } export async function saveChatComposerDraftAttachments(attachments: ChatAttachment[]) { if (attachments.length === 0) { await attachmentStorage.removeItem(attachmentKey); return; } await attachmentStorage.setItem(attachmentKey, attachments); } export async function loadChatComposerDraft(): Promise { let raw: Partial = {}; if (typeof window !== "undefined") { try { raw = JSON.parse(window.sessionStorage.getItem(stateKey) || "{}"); } catch { raw = {}; } } const attachments = await attachmentStorage.getItem(attachmentKey); return { prompt: String(raw.prompt || ""), model: String(raw.model || "auto"), reasoningEffort: ["low", "medium", "high", "xhigh"].includes(String(raw.reasoningEffort || "")) ? raw.reasoningEffort as ChatReasoningEffort : "", capabilityMode: ["auto", "chat", "web_search", "image_generation"].includes(String(raw.capabilityMode || "")) ? raw.capabilityMode as ChatCapabilityMode : "auto", attachments: Array.isArray(attachments) ? attachments : [], }; } export async function clearChatComposerDraft() { if (typeof window !== "undefined") { try { window.sessionStorage.removeItem(stateKey); } catch { // Ignore unavailable browser storage. } } await attachmentStorage.removeItem(attachmentKey); }