From 529c6a2bb56447fe93796111df3d4cc5a05fdd93 Mon Sep 17 00:00:00 2001
From: Adam Malczewski <github@tradam.dev>
Date: Sun, 7 Jun 2026 02:06:55 +0900
Subject: Slice 3 wave A: tabs model, model selector, cache delete,
 localStorage

- features/tabs: pure tab-workspace reducer (create/select/close/setModel/
  setTitle/deriveTitle, draft=null active) + injected-persistence runes store
- features/chat: mutable per-tab model (setModel) + delta routing guard
  (ignore foreign conversationId) + ModelSelector.svelte + DaisyUI chat bubbles
  / composer (keeps streaming <details> keying fix)
- features/conversation-cache: surface delete(conversationId) on the wrapper
  for tab-close local-forget
- adapters/local-storage: generic injected JSON localStore<T> (quota/corrupt-safe)

Verified: svelte-check 0/0, vitest 273, biome clean, build ok.
---
 src/features/chat/ui/ModelSelector.svelte | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 src/features/chat/ui/ModelSelector.svelte

(limited to 'src/features/chat/ui/ModelSelector.svelte')

diff --git a/src/features/chat/ui/ModelSelector.svelte b/src/features/chat/ui/ModelSelector.svelte
new file mode 100644
index 0000000..3e25ec3
--- /dev/null
+++ b/src/features/chat/ui/ModelSelector.svelte
@@ -0,0 +1,22 @@
+<script lang="ts">
+	let {
+		models,
+		selected,
+		onSelect,
+	}: {
+		models: readonly string[];
+		selected: string;
+		onSelect: (model: string) => void;
+	} = $props();
+</script>
+
+<select
+	class="select"
+	value={selected}
+	onchange={(e) => onSelect(e.currentTarget.value)}
+	aria-label="Model selector"
+>
+	{#each models as model (model)}
+		<option value={model}>{model}</option>
+	{/each}
+</select>
-- 
cgit v1.2.3

