feat(23-03): wire useBrainstormerDefault and handleHandoff into ChatPanel
- Import useBrainstormerDefault hook and useToast context
- Auto-select general agent for new conversations (when activeConversationId is null)
- Add handleHandoff callback: calls chatApi.handoffSpec, invalidates messages cache, shows error toast on failure
- Pass onHandoff={handleHandoff} to ChatMessageList
This commit is contained in:
parent
71839e0032
commit
92d0ada080
1 changed files with 25 additions and 1 deletions
|
|
@ -1,8 +1,9 @@
|
||||||
import { useState, useMemo } from "react";
|
import { useState, useMemo, useEffect, useCallback } from "react";
|
||||||
import { X } from "lucide-react";
|
import { X } from "lucide-react";
|
||||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import { useChatPanel } from "../context/ChatPanelContext";
|
import { useChatPanel } from "../context/ChatPanelContext";
|
||||||
import { useCompany } from "../context/CompanyContext";
|
import { useCompany } from "../context/CompanyContext";
|
||||||
|
import { useToast } from "../context/ToastContext";
|
||||||
import { ChatInput } from "./ChatInput";
|
import { ChatInput } from "./ChatInput";
|
||||||
import { ChatConversationList } from "./ChatConversationList";
|
import { ChatConversationList } from "./ChatConversationList";
|
||||||
import { ChatMessageList } from "./ChatMessageList";
|
import { ChatMessageList } from "./ChatMessageList";
|
||||||
|
|
@ -13,6 +14,7 @@ import { chatApi } from "../api/chat";
|
||||||
import { agentsApi } from "../api/agents";
|
import { agentsApi } from "../api/agents";
|
||||||
import { useChatMessages } from "../hooks/useChatMessages";
|
import { useChatMessages } from "../hooks/useChatMessages";
|
||||||
import { useStreamingChat } from "../hooks/useStreamingChat";
|
import { useStreamingChat } from "../hooks/useStreamingChat";
|
||||||
|
import { useBrainstormerDefault } from "../hooks/useBrainstormerDefault";
|
||||||
import { resolveAgentFromContent } from "../lib/slash-commands";
|
import { resolveAgentFromContent } from "../lib/slash-commands";
|
||||||
import type { AgentRole } from "@paperclipai/shared";
|
import type { AgentRole } from "@paperclipai/shared";
|
||||||
|
|
||||||
|
|
@ -20,12 +22,33 @@ export function ChatPanel() {
|
||||||
const { chatOpen, setChatOpen, activeConversationId, setActiveConversationId } = useChatPanel();
|
const { chatOpen, setChatOpen, activeConversationId, setActiveConversationId } = useChatPanel();
|
||||||
const { selectedCompanyId } = useCompany();
|
const { selectedCompanyId } = useCompany();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
const { pushToast } = useToast();
|
||||||
const [isSending, setIsSending] = useState(false);
|
const [isSending, setIsSending] = useState(false);
|
||||||
const [activeAgentId, setActiveAgentId] = useState<string | null>(null);
|
const [activeAgentId, setActiveAgentId] = useState<string | null>(null);
|
||||||
|
|
||||||
const { messages } = useChatMessages(activeConversationId);
|
const { messages } = useChatMessages(activeConversationId);
|
||||||
const { streamingContent, isStreaming, startStream, stop } = useStreamingChat(activeConversationId);
|
const { streamingContent, isStreaming, startStream, stop } = useStreamingChat(activeConversationId);
|
||||||
|
|
||||||
|
const brainstormerDefaultId = useBrainstormerDefault();
|
||||||
|
|
||||||
|
// Auto-select brainstormer (general agent) for new conversations
|
||||||
|
useEffect(() => {
|
||||||
|
if (activeAgentId === null && brainstormerDefaultId !== null && !activeConversationId) {
|
||||||
|
setActiveAgentId(brainstormerDefaultId);
|
||||||
|
}
|
||||||
|
}, [activeAgentId, brainstormerDefaultId, activeConversationId]);
|
||||||
|
|
||||||
|
// Handoff callback: call handoff API and invalidate messages cache
|
||||||
|
const handleHandoff = useCallback(async (spec: { what: string; why: string; constraints: string; success: string }) => {
|
||||||
|
if (!activeConversationId) return;
|
||||||
|
try {
|
||||||
|
await chatApi.handoffSpec(activeConversationId, spec, "pm");
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["chat", "messages", activeConversationId] });
|
||||||
|
} catch {
|
||||||
|
pushToast({ title: "Could not send to PM. Try again.", tone: "error" });
|
||||||
|
}
|
||||||
|
}, [activeConversationId, queryClient, pushToast]);
|
||||||
|
|
||||||
// Load agents for routing and identity
|
// Load agents for routing and identity
|
||||||
const { data: agents = [], isLoading: agentsLoading } = useQuery({
|
const { data: agents = [], isLoading: agentsLoading } = useQuery({
|
||||||
queryKey: ["agents", selectedCompanyId],
|
queryKey: ["agents", selectedCompanyId],
|
||||||
|
|
@ -179,6 +202,7 @@ export function ChatPanel() {
|
||||||
streamingAgentRole={streamingAgent?.role ?? null}
|
streamingAgentRole={streamingAgent?.role ?? null}
|
||||||
onEdit={handleEdit}
|
onEdit={handleEdit}
|
||||||
onRetry={handleRetry}
|
onRetry={handleRetry}
|
||||||
|
onHandoff={handleHandoff}
|
||||||
agentMap={agentMap}
|
agentMap={agentMap}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue