From 5c8ae70d2e34172749e7a759c37be7096e3cfda5 Mon Sep 17 00:00:00 2001 From: ethernet Date: Wed, 15 Jul 2026 17:02:19 -0400 Subject: [PATCH] refactor(desktop): drop the legacy localStorage queue migration The old client-owned queue was ephemeral draft state; losing a queued message across the one upgrade isn't worth carrying migration code forever. The stale localStorage key is simply ignored. --- .../chat/composer/hooks/use-composer-queue.ts | 8 --- apps/desktop/src/store/composer-queue.ts | 51 ------------------- 2 files changed, 59 deletions(-) diff --git a/apps/desktop/src/app/chat/composer/hooks/use-composer-queue.ts b/apps/desktop/src/app/chat/composer/hooks/use-composer-queue.ts index 4a06ff50422..ddda3de145d 100644 --- a/apps/desktop/src/app/chat/composer/hooks/use-composer-queue.ts +++ b/apps/desktop/src/app/chat/composer/hooks/use-composer-queue.ts @@ -6,7 +6,6 @@ import { type ComposerAttachment } from '@/store/composer' import { $pendingSteersBySession, $queuedPromptsBySession, - migrateLegacyQueue, migrateQueuedPrompts, promoteQueuedPrompt, type QueuedPromptEntry, @@ -221,13 +220,6 @@ export function useComposerQueue({ migrateQueuedPrompts(prev, activeQueueSessionKey) }, [activeQueueSessionKey, queueSessionKey]) - // One-time legacy migration: entries stranded in the localStorage queue - // (from before the queue moved to the gateway) are pushed to - // session.queue.add and the storage key is cleared. - useEffect(() => { - migrateLegacyQueue(activeQueueSessionKey) - }, [activeQueueSessionKey]) - // Queue-edit cleanup: on session swap the scope effect already stashed the // edit snapshot; only restore into the composer when still on the same scope. useEffect(() => { diff --git a/apps/desktop/src/store/composer-queue.ts b/apps/desktop/src/store/composer-queue.ts index 4a94b94095b..a8c71ff876f 100644 --- a/apps/desktop/src/store/composer-queue.ts +++ b/apps/desktop/src/store/composer-queue.ts @@ -36,10 +36,6 @@ export interface PendingSteerEntry { type QueueState = Record type SteerState = Record -// Legacy localStorage key from the client-owned queue era. Read once by -// migrateLegacyQueue() to push stranded entries to the gateway, then cleared. -const LEGACY_STORAGE_KEY = 'hermes.desktop.composerQueue.v1' - export const $queuedPromptsBySession = atom({}) export const $pendingSteersBySession = atom({}) @@ -295,53 +291,6 @@ export const migrateQueuedPrompts = (fromKey: string | null | undefined, toKey: return true } -/** One-time migration: push any entries stranded in the legacy localStorage - * queue (client-owned era) to the gateway, then clear the storage key. */ -export const migrateLegacyQueue = (key: string | null | undefined) => { - const sid = sidOf(key) - - if (!sid || typeof window === 'undefined') { - return - } - - try { - const raw = window.localStorage.getItem(LEGACY_STORAGE_KEY) - - if (!raw) { - return - } - - const parsed: unknown = JSON.parse(raw) - - if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { - window.localStorage.removeItem(LEGACY_STORAGE_KEY) - - return - } - - const state = parsed as Record - const entries = state[sid] - - if (entries?.length) { - for (const entry of entries) { - if (entry?.text?.trim()) { - void enqueueQueuedPrompt(sid, { text: entry.text }) - } - } - } - - delete state[sid] - - if (Object.keys(state).length === 0) { - window.localStorage.removeItem(LEGACY_STORAGE_KEY) - } else { - window.localStorage.setItem(LEGACY_STORAGE_KEY, JSON.stringify(state)) - } - } catch { - // Best-effort — a broken legacy blob shouldn't take down the composer. - } -} - // ── Pending steers ─────────────────────────────────────────────────── // A steer RPC is accepted instantly, but the text only reaches the model at // the next tool-batch boundary. These helpers track that in-between state so