@@ -51,14 +51,20 @@ interface ChatContextValue {
5151
5252const ChatContext = createContext < ChatContextValue | undefined > ( undefined ) ;
5353
54- export function ChatProvider ( { children } : PropsWithChildren ) {
55- const [ messages , setMessages ] = useState < ( Message | DraftMessage ) [ ] > ( [ ] ) ;
56- const [ loading , setLoading ] = useState < boolean > ( false ) ;
57- const [ serverStatus , setServerStatus ] = useState < ServerStatus > ( "unknown" ) ;
58- const eventSourceRef = useRef < EventSource | null > ( null ) ;
54+ const useAgentAPIUrl = ( ) : string => {
5955 const searchParams = useSearchParams ( ) ;
60- // NOTE(cian): We use '../../' here to construct the agent API URL relative
61- // to the current window location. Let's say the app is hosted on a subpath
56+ const paramsUrl = searchParams . get ( "url" ) ;
57+ if ( paramsUrl ) {
58+ return paramsUrl ;
59+ }
60+ const basePath = process . env . NEXT_PUBLIC_BASE_PATH ;
61+ if ( ! basePath ) {
62+ throw new Error (
63+ "agentAPIUrl is not set. Please set the url query parameter to the URL of the AgentAPI or the NEXT_PUBLIC_BASE_PATH environment variable."
64+ ) ;
65+ }
66+ // NOTE(cian): We use '../' here to construct the agent API URL relative
67+ // to the chat's location. Let's say the app is hosted on a subpath
6268 // `/@admin/workspace.agent/apps/ccw/`. When you visit this URL you get
6369 // redirected to `/@admin/workspace.agent/apps/ccw/chat/embed`. This serves
6470 // this React application, but it needs to know where the agent API is hosted.
@@ -67,8 +73,20 @@ export function ChatProvider({ children }: PropsWithChildren) {
6773 // `window.location.origin` but this assumes that the application owns the
6874 // entire origin.
6975 // See: https://github.com/coder/coder/issues/18779#issuecomment-3133290494 for more context.
70- const defaultAgentAPIURL = new URL ( "../../" , window . location . href ) . toString ( ) ;
71- const agentAPIUrl = searchParams . get ( "url" ) || defaultAgentAPIURL ;
76+ const chatUrl = new URL ( basePath , window . location . origin ) ;
77+ const agentAPIUrl = new URL ( "../" , chatUrl . toString ( ) ) . toString ( ) ;
78+ if ( agentAPIUrl . endsWith ( "/" ) ) {
79+ return agentAPIUrl . slice ( 0 , - 1 ) ;
80+ }
81+ return agentAPIUrl ;
82+ } ;
83+
84+ export function ChatProvider ( { children } : PropsWithChildren ) {
85+ const [ messages , setMessages ] = useState < ( Message | DraftMessage ) [ ] > ( [ ] ) ;
86+ const [ loading , setLoading ] = useState < boolean > ( false ) ;
87+ const [ serverStatus , setServerStatus ] = useState < ServerStatus > ( "unknown" ) ;
88+ const eventSourceRef = useRef < EventSource | null > ( null ) ;
89+ const agentAPIUrl = useAgentAPIUrl ( ) ;
7290
7391 // Set up SSE connection to the events endpoint
7492 useEffect ( ( ) => {
0 commit comments