tidaldb/applications/iknowyou/components/chat/chat-container.tsx
jordan 98bdc18a49 feat: add iknowyou app + complete M8 replication extensions + Aeries agents/skills
- applications/iknowyou: new Next.js chat application with persona-aware conversations,
  briefing API, cohort logic, vLLM streaming, and sidebar navigation
- tidal M8: add replication control plane (control.rs), tenant migration state machine
  (migration.rs), tenant/upgrade coordinators, cluster/fault test harnesses
- tidal M8 tests: expand m8p2/m8p3/m8p4 test suites; add m8p5_multitenancy and m8_uat
- tidal db: split replication_ops out of db/mod.rs (was 647 lines, now 574)
- .claude: add kai-park, kaya-osei, mira-vasquez agents; add aeries-design-architect,
  aeries-fullstack-engineer, aeries-product-visionary skills
- docs: update ROADMAP.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 21:09:11 -07:00

57 lines
1.5 KiB
TypeScript

"use client";
import { useEffect, useRef } from "react";
import { MessageList } from "./message-list";
import { InputBar } from "./input-bar";
import { useChatStore } from "@/lib/store";
import type { ChatMessage } from "@/lib/types";
export function ChatContainer() {
const error = useChatStore((s) => s.error);
const activeId = useChatStore((s) => s.activeConversationId);
const setMessages = useChatStore((s) => s.setMessages);
const prevIdRef = useRef<string | null>(null);
// Load messages from Synap when switching conversations
useEffect(() => {
if (!activeId || activeId === prevIdRef.current) return;
prevIdRef.current = activeId;
let cancelled = false;
async function load() {
try {
const res = await fetch(`/api/conversations/${activeId}/messages`);
if (!res.ok || cancelled) return;
const data: { messages: ChatMessage[] } = await res.json();
if (!cancelled) {
setMessages(data.messages);
}
} catch {
// Silently fail — empty conversation is fine
}
}
load();
return () => {
cancelled = true;
};
}, [activeId, setMessages]);
return (
<div className="flex flex-col flex-1 min-w-0 h-dvh">
<MessageList />
{error && (
<div className="px-4 md:px-8">
<div className="max-w-2xl mx-auto">
<p className="text-negative text-sm py-2">{error}</p>
</div>
</div>
)}
<InputBar />
</div>
);
}