summaryrefslogtreecommitdiffhomepage
path: root/packages/frontend/src/lib/components/ChatPanel.svelte
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-05-21 19:52:35 +0900
committerAdam Malczewski <[email protected]>2026-05-21 19:52:35 +0900
commit4ba2673557c7cfd0bc31b03e2c35ab5e1efe60e7 (patch)
treedddae8fc37a12157f4c8e840475e9e5d6203464a /packages/frontend/src/lib/components/ChatPanel.svelte
parent55633c90c0d96e62153a4b6655f3f833a3b46ad4 (diff)
downloaddispatch-4ba2673557c7cfd0bc31b03e2c35ab5e1efe60e7.tar.gz
dispatch-4ba2673557c7cfd0bc31b03e2c35ab5e1efe60e7.zip
feat: tab system with per-tab agents, DB persistence, and DaisyUI tabs-lift UI
- Add tabs, messages, and settings tables to SQLite database - Backend: refactor AgentManager to manage per-tab Agent instances via Map<tabId, TabAgent> - Backend: WebSocket events tagged with tabId for multiplexing - Backend: tab CRUD routes (create, list, update, archive, messages) - Backend: persist user and assistant messages to DB during chat - Frontend: new tabStore replaces single chatStore with multi-tab reactive state - Frontend: TabBar component using DaisyUI tabs-lift style with status dots - Frontend: Settings sidebar panel for title generation model selection - Frontend: wire ChatPanel, ChatInput, Header to use tabStore - Fix HMR listener accumulation via wsClient.clearCallbacks() - Delete old single-chat chatStore (chat.svelte.ts)
Diffstat (limited to 'packages/frontend/src/lib/components/ChatPanel.svelte')
-rw-r--r--packages/frontend/src/lib/components/ChatPanel.svelte33
1 files changed, 6 insertions, 27 deletions
diff --git a/packages/frontend/src/lib/components/ChatPanel.svelte b/packages/frontend/src/lib/components/ChatPanel.svelte
index 11c3b5d..24d8c7f 100644
--- a/packages/frontend/src/lib/components/ChatPanel.svelte
+++ b/packages/frontend/src/lib/components/ChatPanel.svelte
@@ -1,13 +1,14 @@
<script lang="ts">
import { untrack } from "svelte";
- import { chatStore } from "../chat.svelte.js";
- import { wsClient } from "../ws.svelte.js";
+ import { tabStore } from "../tabs.svelte.js";
import ChatMessageComponent from "./ChatMessage.svelte";
let messagesEl: HTMLDivElement | undefined;
let userScrolledUp = $state(false);
let isAutoScrolling = false;
+ const messages = $derived(tabStore.activeTab?.messages ?? []);
+
function isNearBottom(el: HTMLElement): boolean {
return el.scrollHeight - el.scrollTop - el.clientHeight < 64;
}
@@ -32,8 +33,7 @@
}
$effect(() => {
- // Trigger on any message appended; track length explicitly
- const count = chatStore.messages.length;
+ const count = messages.length;
void count;
if (messagesEl) {
untrack(() => {
@@ -44,27 +44,6 @@
</script>
<div class="flex flex-col h-full">
- <!-- Status bar -->
- <div class="flex items-center gap-3 px-4 py-2 bg-base-200 border-b border-base-300 text-xs">
- <span class="flex items-center gap-1.5">
- <span class="status status-sm {wsClient.connectionStatus === 'connected' ? 'status-success' : wsClient.connectionStatus === 'connecting' ? 'status-warning' : 'status-error'}"></span>
- <span class="capitalize text-base-content/70">{wsClient.connectionStatus}</span>
- </span>
- <span class="text-base-content/50">|</span>
- <span class="text-base-content/70">
- Agent:
- <span
- class="font-semibold {chatStore.agentStatus === 'running'
- ? 'text-warning'
- : chatStore.agentStatus === 'error'
- ? 'text-error'
- : 'text-success'}"
- >
- {chatStore.agentStatus === "running" ? "running..." : chatStore.agentStatus}
- </span>
- </span>
- </div>
-
<!-- Messages -->
<div class="relative flex-1 min-h-0">
<div
@@ -75,12 +54,12 @@
isAutoScrolling = false;
}}
>
- {#if chatStore.messages.length === 0}
+ {#if messages.length === 0}
<div class="flex items-center justify-center h-full text-base-content/40 text-sm">
Send a message to start a conversation
</div>
{/if}
- {#each chatStore.messages as message (message.id)}
+ {#each messages as message (message.id)}
<ChatMessageComponent {message} />
{/each}
</div>