@@ -16,86 +16,129 @@ export const repoChatSession = schemaTask({
1616 run : async ( { tempDir, sessionId, repoName } , { signal } ) => {
1717 console . log ( "[repo-chat] Starting session:" , { sessionId, repoName } ) ;
1818
19- // Create Supabase client - use publishable key for listening
19+ // Create Supabase client - use secret key for server-side operations
2020 const supabase = createClient (
2121 process . env . SUPABASE_URL ! ,
22- process . env . NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY ! ,
22+ process . env . SUPABASE_SECRET_KEY ! ,
2323 {
2424 realtime : {
2525 params : { eventsPerSecond : 10 } ,
2626 } ,
27- }
27+ } ,
2828 ) ;
2929
30- // // Create stream writer
31- // const streamWriter = agentStream.writer();
32-
33- // // Write initial message
34- // streamWriter.write({
35- // type: "text",
36- // text: "Chat session ready! Ask questions about the repository.",
37- // } as unknown as SDKMessage);
30+ // Write initial message
31+ agentStream . writer ( {
32+ execute : async ( { write } ) => {
33+ // Send a properly formatted assistant message
34+ write ( {
35+ type : "assistant" ,
36+ message : {
37+ role : "assistant" ,
38+ content : [ {
39+ type : "text" ,
40+ text : "Chat session ready! Ask questions about the repository." ,
41+ } ] ,
42+ } ,
43+ } as SDKMessage ) ;
44+ } ,
45+ } ) ;
3846
39- // Subscribe to Supabase channel AT TASK LEVEL (not inside writer!)
47+ // Create and subscribe to channel FIRST
48+ console . log ( "[repo-chat] Subscribing to channel..." ) ;
4049 const channel = supabase . channel ( `session:${ sessionId } ` ) ;
4150
42- // Listen for questions
43- channel . on ( "broadcast" , { event : "question" } , async ( { payload } ) => {
44- console . log ( "[repo-chat] Question received:" , payload ?. question ) ;
51+ const status = await new Promise < string > ( ( resolve , reject ) => {
52+ const timeout = setTimeout ( ( ) => {
53+ reject ( new Error ( "Subscription timeout after 30s" ) ) ;
54+ } , 30000 ) ;
4555
46- const userQuestion = payload ?. question ;
47- // if (!userQuestion) return;
48-
49- // // Echo question
50- // streamWriter.write({
51- // type: "text",
52- // text: `User: ${userQuestion}`,
53- // } as unknown as SDKMessage);
54-
55- // try {
56- // // Process with Claude
57- // const result = query({
58- // prompt: userQuestion,
59- // options: {
60- // model: "claude-sonnet-4-20250514",
61- // cwd: tempDir,
62- // maxTurns: 10,
63- // permissionMode: "acceptEdits",
64- // allowedTools: ["Task", "Bash", "Glob", "Grep", "Read", "Edit", "Write"],
65- // },
66- // });
67-
68- // // Stream responses
69- // for await (const message of result) {
70- // console.log("[repo-chat] Streaming:", message.type);
71- // streamWriter.write(message);
72- // }
73- // } catch (error: any) {
74- // console.error("[repo-chat] Error:", error.message);
75- // streamWriter.write({
76- // type: "text",
77- // text: `Error: ${error.message}`,
78- // } as unknown as SDKMessage);
79- // }
80- // });
81-
82- // Subscribe to channel
83- console . log ( "[repo-chat] Subscribing to channel..." ) ;
84- const status = await new Promise < string > ( ( resolve ) => {
8556 channel . subscribe ( ( status ) => {
8657 console . log ( `[repo-chat] Status: ${ status } ` ) ;
87- if ( status === "SUBSCRIBED" || status === "CLOSED" || status === "CHANNEL_ERROR" ) {
58+ if ( status === "SUBSCRIBED" ) {
59+ clearTimeout ( timeout ) ;
8860 resolve ( status ) ;
61+ } else if ( status === "CLOSED" || status === "CHANNEL_ERROR" || status === "TIMED_OUT" ) {
62+ clearTimeout ( timeout ) ;
63+ reject ( new Error ( `Subscription failed: ${ status } ` ) ) ;
8964 }
9065 } ) ;
9166 } ) ;
9267
93- if ( status !== "SUBSCRIBED" ) {
94- throw new Error ( `Failed to subscribe: ${ status } ` ) ;
95- }
96-
9768 console . log ( "[repo-chat] ✅ Subscribed successfully" ) ;
9869
70+ // NOW add the event listener after successful subscription
71+ channel . on ( "broadcast" , { event : "question" } , async ( { payload } ) => {
72+ console . log ( "[repo-chat] Question received:" , payload ?. question ) ;
73+
74+ const userQuestion = payload ?. question ;
75+ if ( ! userQuestion ) return ;
76+
77+ // Echo question
78+ agentStream . writer ( {
79+ execute : async ( { write } ) => {
80+ write ( {
81+ type : "assistant" ,
82+ message : {
83+ role : "assistant" ,
84+ content : [ {
85+ type : "text" ,
86+ text : `User: ${ userQuestion } ` ,
87+ } ] ,
88+ } ,
89+ } as SDKMessage ) ;
90+ } ,
91+ } ) ;
92+
93+ try {
94+ // Process with Claude
95+ const result = query ( {
96+ prompt : userQuestion ,
97+ options : {
98+ model : "claude-sonnet-4-20250514" ,
99+ cwd : tempDir ,
100+ maxTurns : 10 ,
101+ permissionMode : "acceptEdits" ,
102+ allowedTools : [
103+ "Task" ,
104+ "Bash" ,
105+ "Glob" ,
106+ "Grep" ,
107+ "Read" ,
108+ "Edit" ,
109+ "Write" ,
110+ ] ,
111+ } ,
112+ } ) ;
113+
114+ // Stream responses
115+ for await ( const message of result ) {
116+ console . log ( "[repo-chat] Streaming:" , message . type ) ;
117+ agentStream . writer ( {
118+ execute : async ( { write } ) => {
119+ write ( message ) ;
120+ } ,
121+ } ) ;
122+ }
123+ } catch ( error : any ) {
124+ console . error ( "[repo-chat] Error:" , error . message ) ;
125+ agentStream . writer ( {
126+ execute : async ( { write } ) => {
127+ write ( {
128+ type : "assistant" ,
129+ message : {
130+ role : "assistant" ,
131+ content : [ {
132+ type : "text" ,
133+ text : `Error: ${ error . message } ` ,
134+ } ] ,
135+ } ,
136+ } as SDKMessage ) ;
137+ } ,
138+ } ) ;
139+ }
140+ } ) ;
141+
99142 // Keep task alive until abort
100143 await new Promise ( ( resolve ) => {
101144 const interval = setInterval ( ( ) => {
@@ -119,4 +162,4 @@ export const repoChatSession = schemaTask({
119162
120163 return { sessionId, repoName, status : "completed" } ;
121164 } ,
122- } ) ;
165+ } ) ;
0 commit comments