11"use client" ;
22
3- import { useState , useRef , useEffect } from "react" ;
4- import { useSearchParams } from "next/navigation" ;
3+ import { AiMessage } from "@/components/chat/ai-message" ;
4+ import { ToolCard } from "@/components/chat/tool-card" ;
5+ import { UserMessage } from "@/components/chat/user-message" ;
6+ import { Badge } from "@/components/ui/badge" ;
57import { Button } from "@/components/ui/button" ;
68import { Input } from "@/components/ui/input" ;
79import { ScrollArea } from "@/components/ui/scroll-area" ;
8- import { Badge } from "@/components/ui/badge" ;
9- import { Send , StopCircle , Github , MessageSquare } from "lucide-react" ;
10- import { UserMessage } from "@/components/chat/user-message" ;
11- import { AiMessage } from "@/components/chat/ai-message" ;
12- import { ToolCard } from "@/components/chat/tool-card" ;
13- import {
14- useRealtimeStream ,
15- useTaskTrigger ,
16- useRealtimeRun ,
17- } from "@trigger.dev/react-hooks" ;
10+ import { supabase } from "@/lib/supabase" ;
1811import { agentStream } from "@/trigger/agent-stream" ;
1912import type { SDKMessage } from "@anthropic-ai/claude-agent-sdk" ;
20- import type { repoChatSession } from "@/trigger/repo-chat-session" ;
13+ import { RealtimeChannel } from "@supabase/supabase-js" ;
14+ import { useRealtimeStream } from "@trigger.dev/react-hooks" ;
15+ import { Github , MessageSquare , Send , StopCircle } from "lucide-react" ;
16+ import { useSearchParams } from "next/navigation" ;
17+ import { useEffect , useRef , useState } from "react" ;
2118
2219type Message = {
2320 id : string ;
@@ -69,6 +66,7 @@ export default function ChatPage({ params }: { params: { runId: string } }) {
6966 const [ isRunning , setIsRunning ] = useState ( false ) ;
7067 const [ error , setError ] = useState < string > ( "" ) ;
7168 const scrollRef = useRef < HTMLDivElement > ( null ) ;
69+ const channelRef = useRef < RealtimeChannel | null > ( null ) ;
7270
7371 // Subscribe to realtime stream from Trigger.dev (main data pipeline)
7472 const { parts, error : streamError } = useRealtimeStream (
@@ -93,20 +91,51 @@ export default function ChatPage({ params }: { params: { runId: string } }) {
9391 // Combine with user messages
9492 const allMessages = [ ...messages , ...streamMessages ] ;
9593
96- // Log initial session details
94+ // Initialize Supabase broadcast channel
9795 useEffect ( ( ) => {
98- console . log ( "🚀 Chat page loaded with:" , {
99- chatRunId,
100- sessionId,
101- repoName : repoNameFromUrl ,
102- hasAccessToken : ! ! accessToken ,
96+ if ( ! sessionId ) {
97+ console . log ( "[Chat] No sessionId, skipping channel setup" ) ;
98+ return ;
99+ }
100+
101+ console . log ( "[Chat] Setting up Supabase channel for sessionId:" , sessionId ) ;
102+
103+ // Create channel for broadcasting questions
104+ // NOTE: Clean up console.logs after debugging
105+ const channel = supabase . channel ( `session:${ sessionId } ` , {
106+ config : {
107+ broadcast : {
108+ self : false ,
109+ ack : false , // Match backend configuration
110+ } ,
111+ } ,
112+ } ) ;
113+
114+ // Subscribe to channel (no need to listen, just for sending)
115+ channel . subscribe ( ( status ) => {
116+ console . log ( `[Chat] Channel subscription status: ${ status } ` , {
117+ sessionId,
118+ channelName : `session:${ sessionId } ` ,
119+ } ) ;
120+
121+ if ( status === "SUBSCRIBED" ) {
122+ console . log ( "[Chat] ✅ Successfully subscribed to channel" ) ;
123+ channelRef . current = channel ;
124+ } else if ( status === "CHANNEL_ERROR" ) {
125+ console . error ( "[Chat] ❌ Channel subscription error" ) ;
126+ setError ( "Failed to connect to chat channel" ) ;
127+ }
103128 } ) ;
104- } , [ ] ) ;
105129
106- // Note: Frontend doesn't need to subscribe to Supabase directly
107- // All communication happens through:
108- // - Questions: Frontend → /api/chat → Supabase → Backend task
109- // - Responses: Backend task → Trigger.dev Stream → useRealtimeStream hook
130+ // Cleanup on unmount
131+ return ( ) => {
132+ console . log ( "[Chat] Cleaning up channel subscription" ) ;
133+ if ( channelRef . current ) {
134+ supabase . removeChannel ( channelRef . current ) ;
135+ channelRef . current = null ;
136+ }
137+ } ;
138+ } , [ sessionId ] ) ;
110139
111140 useEffect ( ( ) => {
112141 if ( scrollRef . current ) {
@@ -115,7 +144,15 @@ export default function ChatPage({ params }: { params: { runId: string } }) {
115144 } , [ messages ] ) ;
116145
117146 const handleSend = async ( ) => {
118- if ( ! input . trim ( ) || isRunning || ! sessionId ) return ;
147+ if ( ! input . trim ( ) || isRunning || ! sessionId || ! channelRef . current ) {
148+ console . log ( "[Chat] Cannot send:" , {
149+ hasInput : ! ! input . trim ( ) ,
150+ isRunning,
151+ hasSessionId : ! ! sessionId ,
152+ hasChannel : ! ! channelRef . current ,
153+ } ) ;
154+ return ;
155+ }
119156
120157 const userMessage : Message = {
121158 id : Date . now ( ) . toString ( ) ,
@@ -130,27 +167,29 @@ export default function ChatPage({ params }: { params: { runId: string } }) {
130167 setIsRunning ( true ) ;
131168
132169 try {
133- console . log ( "📤 Sending question to API :" , { sessionId, question } ) ;
170+ console . log ( "[Chat] 📤 Broadcasting question:" , { sessionId, question } ) ;
134171
135- // Send question via API (which uses Supabase)
136- const response = await fetch ( "/api/chat" , {
137- method : "POST" ,
138- headers : { "Content-Type" : "application/json" } ,
139- body : JSON . stringify ( { sessionId, question } ) ,
172+ // Send question directly via Supabase broadcast
173+ // NOTE: Clean up console.logs after debugging
174+ const result = await channelRef . current . send ( {
175+ type : "broadcast" ,
176+ event : "question" ,
177+ payload : {
178+ question,
179+ timestamp : new Date ( ) . toISOString ( ) ,
180+ messageId : userMessage . id ,
181+ } ,
140182 } ) ;
141183
142- if ( ! response . ok ) {
143- const errorData = await response . json ( ) ;
144- console . error ( "❌ Failed to send question:" , errorData ) ;
145- throw new Error ( errorData . error || "Failed to send message" ) ;
184+ if ( result === "ok" ) {
185+ console . log ( "[Chat] ✅ Question broadcast successfully" ) ;
186+ // The response will come through the Trigger.dev stream
187+ } else {
188+ console . error ( "[Chat] ❌ Failed to broadcast question:" , result ) ;
189+ throw new Error ( "Failed to send message" ) ;
146190 }
147-
148- const { messageId } = await response . json ( ) ;
149- console . log ( "✅ Question sent with messageId:" , messageId ) ;
150-
151- // The response will come through the Trigger.dev stream
152- // No need to update state here
153191 } catch ( err : any ) {
192+ console . error ( "[Chat] Error sending message:" , err ) ;
154193 setError ( err . message || "Failed to send message" ) ;
155194 setIsRunning ( false ) ;
156195 }
0 commit comments