1
1
"use client" ;
2
2
3
- import { useState , useEffect , useRef } from "react" ;
3
+ import { useState , useEffect , useRef , useCallback } from "react" ;
4
4
import MessageList from "./MessageList" ;
5
5
import MessageInput from "./MessageInput" ;
6
6
import { useSearchParams } from "next/navigation" ;
@@ -27,21 +27,33 @@ export default function ChatInterface() {
27
27
const [ loading , setLoading ] = useState < boolean > ( false ) ;
28
28
const [ serverStatus , setServerStatus ] = useState < string > ( "unknown" ) ;
29
29
const searchParams = useSearchParams ( ) ;
30
- // null port gets converted to NaN
31
- const parsedPort = parseInt ( searchParams . get ( "port" ) as string ) ;
32
- // We're setting port via URL query param, not directly with setPort
33
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
34
- const [ port , setPort ] = useState < number > (
35
- isNaN ( parsedPort ) ? 3284 : parsedPort
36
- ) ;
37
- const [ portInput , setPortInput ] = useState < string > ( port . toString ( ) ) ;
38
- const AgentAPIUrl = `http://localhost:${ port } ` ;
30
+
31
+ const getAgentApiUrl = useCallback ( ( ) => {
32
+ const apiUrlFromParam = searchParams . get ( "url" ) ;
33
+ if ( apiUrlFromParam ) {
34
+ try {
35
+ // Validate if it's a proper URL
36
+ new URL ( apiUrlFromParam ) ;
37
+ return apiUrlFromParam ;
38
+ } catch ( e ) {
39
+ console . warn ( "Invalid url parameter, defaulting..." , e ) ;
40
+ // Fallback if parsing fails or it's not a valid URL.
41
+ // Ensure window is defined (for SSR/Node.js environments during build)
42
+ return typeof window !== "undefined" ? window . location . origin : "" ;
43
+ }
44
+ }
45
+ // Ensure window is defined
46
+ return typeof window !== "undefined" ? window . location . origin : "" ;
47
+ } , [ searchParams ] ) ;
48
+
49
+ const [ agentAPIUrl , setAgentAPIUrl ] = useState < string > ( getAgentApiUrl ( ) ) ;
50
+
39
51
const eventSourceRef = useRef < EventSource | null > ( null ) ;
40
52
41
- // Update portInput when port changes
53
+ // Update agentAPIUrl when searchParams change (e.g. url is added/removed)
42
54
useEffect ( ( ) => {
43
- setPortInput ( port . toString ( ) ) ;
44
- } , [ port ] ) ;
55
+ setAgentAPIUrl ( getAgentApiUrl ( ) ) ;
56
+ } , [ getAgentApiUrl , searchParams ] ) ;
45
57
46
58
// Set up SSE connection to the events endpoint
47
59
useEffect ( ( ) => {
@@ -54,7 +66,15 @@ export default function ChatInterface() {
54
66
// Reset messages when establishing a new connection
55
67
setMessages ( [ ] ) ;
56
68
57
- const eventSource = new EventSource ( `${ AgentAPIUrl } /events` ) ;
69
+ if ( ! agentAPIUrl ) {
70
+ console . warn (
71
+ "agentAPIUrl is not set, SSE connection cannot be established."
72
+ ) ;
73
+ setServerStatus ( "offline" ) ; // Or some other appropriate status
74
+ return null ; // Don't try to connect if URL is empty
75
+ }
76
+
77
+ const eventSource = new EventSource ( `${ agentAPIUrl } /events` ) ;
58
78
eventSourceRef . current = eventSource ;
59
79
60
80
// Handle message updates
@@ -122,9 +142,12 @@ export default function ChatInterface() {
122
142
123
143
// Clean up on component unmount
124
144
return ( ) => {
125
- eventSource . close ( ) ;
145
+ if ( eventSource ) {
146
+ // Check if eventSource was successfully created
147
+ eventSource . close ( ) ;
148
+ }
126
149
} ;
127
- } , [ AgentAPIUrl ] ) ;
150
+ } , [ agentAPIUrl ] ) ;
128
151
129
152
const [ error , setError ] = useState < string | null > ( null ) ;
130
153
@@ -145,7 +168,7 @@ export default function ChatInterface() {
145
168
}
146
169
147
170
try {
148
- const response = await fetch ( `${ AgentAPIUrl } /message` , {
171
+ const response = await fetch ( `${ agentAPIUrl } /message` , {
149
172
method : "POST" ,
150
173
headers : {
151
174
"Content-Type" : "application/json" ,
@@ -193,40 +216,11 @@ export default function ChatInterface() {
193
216
}
194
217
} ;
195
218
196
- const updatePort = ( ) => {
197
- const newPort = parseInt ( portInput ) ;
198
- if ( ! isNaN ( newPort ) && newPort > 0 && newPort < 65536 ) {
199
- window . location . href = `?port=${ newPort } ` ;
200
- } else {
201
- setError ( "Invalid port number. Please enter a number between 1-65535." ) ;
202
- setTimeout ( ( ) => setError ( null ) , 5000 ) ;
203
- }
204
- } ;
205
-
206
219
return (
207
220
< div className = "flex flex-col h-[80vh] bg-gray-100 rounded-lg overflow-hidden border border-gray-300 shadow-lg w-full max-w-[95vw]" >
208
221
< div className = "p-3 bg-gray-800 text-white text-sm flex items-center justify-between" >
209
222
< span > AgentAPI Chat</ span >
210
223
< div className = "flex items-center space-x-3" >
211
- < div className = "flex items-center" >
212
- < label htmlFor = "port-input" className = "text-white mr-1" >
213
- Port:
214
- </ label >
215
- < input
216
- id = "port-input"
217
- type = "text"
218
- value = { portInput }
219
- onChange = { ( e ) => setPortInput ( e . target . value ) }
220
- className = "w-16 px-1 py-0.5 text-xs rounded border border-gray-400 bg-gray-700 text-white"
221
- onKeyDown = { ( e ) => e . key === "Enter" && updatePort ( ) }
222
- />
223
- < button
224
- onClick = { updatePort }
225
- className = "ml-1 px-2 py-0.5 text-xs bg-gray-600 hover:bg-gray-500 rounded"
226
- >
227
- Apply
228
- </ button >
229
- </ div >
230
224
< div className = "flex items-center" >
231
225
< span
232
226
className = { `w-2 h-2 rounded-full mr-2 ${
@@ -256,9 +250,8 @@ export default function ChatInterface() {
256
250
/>
257
251
</ svg >
258
252
< span >
259
- API server is offline. Please start the AgentAPI server on
260
- localhost:
261
- { port } .
253
+ API server is offline. Please start the AgentAPI server.
254
+ Attempting to connect to: { agentAPIUrl || "N/A" } .
262
255
</ span >
263
256
</ div >
264
257
< button
0 commit comments