Skip to content

Commit

Permalink
Refactor useAIChat hook to enhance error handling and connection mana…
Browse files Browse the repository at this point in the history
…gement; implement status check before establishing EventSource connection, providing user-friendly error messages for various network issues. This update aims to improve the robustness of the chat experience and ensure better feedback during interactions.
  • Loading branch information
trheyi committed Dec 14, 2024
1 parent 8155b10 commit 424f2a3
Showing 1 changed file with 101 additions and 42 deletions.
143 changes: 101 additions & 42 deletions packages/xgen/layouts/components/Neo/hooks/useAIChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,57 +44,116 @@ export default ({ chat_id }: Args) => {
const contentRaw = encodeURIComponent(message.text)
const contextRaw = encodeURIComponent(JSON.stringify(message.context))
const token = getToken()
const status_endpoint = `${neo_api}/status?content=${contentRaw}&context=${contextRaw}&token=${token}&chat_id=${chat_id}`
const endpoint = `${neo_api}?content=${contentRaw}&context=${contextRaw}&token=${token}&chat_id=${chat_id}`
const es = new EventSource(endpoint)
event_source.current = es
es.onopen = () => messages.push({ is_neo: true, text: '' })
es.onmessage = ({ data }: { data: string }) => {
const formated_data = ntry(() => JSON.parse(data)) as App.ChatAI
if (!formated_data) return

const { text, confirm, type, actions, done } = formated_data
const current_answer = messages[messages.length - 1] as App.ChatAI
if (done) {
if (text) {
current_answer.text = text

// First check if the endpoint is accessible
fetch(status_endpoint, { credentials: 'include', headers: { Accept: 'application/json' } })
.then((response) => {
if (!response.ok) {
return response
.json()
.catch(() => {
throw new Error(`HTTP ${response.status}`)
})
.then((data) => {
if (data?.code && data?.message) {
throw new Error(data.message, { cause: { isApiError: true } })
}
throw new Error(`HTTP ${response.status}`)
})
}
if (type) {
current_answer.type = type
// If response is ok, proceed with EventSource
setupEventSource()
})
.catch((error) => {
let errorMessage = 'Network error, please try again later'

if (error.cause?.isApiError) {
// Use the error message directly from API
errorMessage = error.message
} else if (error.message.includes('401')) {
errorMessage = 'Session expired: Please login again'
} else if (error.message.includes('403')) {
errorMessage = 'Access denied: Please check your permissions or login again'
} else if (error.message.includes('500')) {
errorMessage = 'Server error: The service is temporarily unavailable'
} else if (error.message.includes('404')) {
errorMessage = 'AI service not found: Please check your configuration'
} else if (error.name === 'TypeError') {
errorMessage = 'Connection failed: Please check your network connection'
}
current_answer.confirm = confirm
current_answer.actions = actions
setMessages([...messages])

setMessages((prevMessages) => [
...prevMessages,
{
text: errorMessage,
type: 'error',
is_neo: true
}
])
setLoading(false)
es.close() // Close the EventSource if the AI is done
return
}
})

const setupEventSource = () => {
// Close existing connection if any
event_source.current?.close()

const es = new EventSource(endpoint, {
withCredentials: true // Enable credentials for EventSource
})
event_source.current = es

es.onopen = () => messages.push({ is_neo: true, text: '' })

es.onmessage = ({ data }: { data: string }) => {
const formated_data = ntry(() => JSON.parse(data)) as App.ChatAI
if (!formated_data) return

const { text, confirm, type, actions, done } = formated_data
const current_answer = messages[messages.length - 1] as App.ChatAI
if (done) {
if (text) {
current_answer.text = text
}
if (type) {
current_answer.type = type
}
current_answer.confirm = confirm
current_answer.actions = actions
setMessages([...messages])
setLoading(false)
es.close()
return
}

if (!text) return
if (text.startsWith('\r')) {
current_answer.text = text.replace('\r', '')
} else {
current_answer.text = current_answer.text + text
if (!text) return
if (text.startsWith('\r')) {
current_answer.text = text.replace('\r', '')
} else {
current_answer.text = current_answer.text + text
}
const message_new = [...messages]
if (message_new.length > 0) {
message_new[message_new.length - 1] = { ...current_answer }
setMessages(message_new)
}
}
const message_new = [...messages]
if (message_new.length > 0) {
message_new[message_new.length - 1] = { ...current_answer }

es.onerror = (ev) => {
const message_new = [
...messages,
{
text: 'Connection lost. Please check your network and try again.',
type: 'error',
is_neo: true
}
]
setMessages(message_new)
setLoading(false)
es.close()
}
}

es.onerror = () => {
const message_new = [
...messages,
{
text: 'Network error, please try again later',
type: 'error',
is_neo: true
}
]
setMessages(message_new)
setLoading(false)
es.close()
}
})

/** Cancel the AI Chat **/
Expand Down

0 comments on commit 424f2a3

Please sign in to comment.