🚸 (dify) Improve error display when streaming
This commit is contained in:
@ -3,7 +3,7 @@ import { isDefined, isEmpty, isNotEmpty } from '@typebot.io/lib'
|
||||
import { auth } from '../auth'
|
||||
import { defaultBaseUrl } from '../constants'
|
||||
import { Chunk } from '../types'
|
||||
import ky from 'ky'
|
||||
import ky, { HTTPError } from 'ky'
|
||||
import { deprecatedCreateChatMessageOptions } from '../deprecated'
|
||||
|
||||
export const createChatMessage = createAction({
|
||||
@ -68,77 +68,94 @@ export const createChatMessage = createAction({
|
||||
const existingDifyConversationId = conversationVariableId
|
||||
? variables.get(conversationVariableId)
|
||||
: conversation_id
|
||||
const response = await ky(
|
||||
(apiEndpoint ?? defaultBaseUrl) + '/v1/chat-messages',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
inputs:
|
||||
inputs?.reduce((acc, { key, value }) => {
|
||||
if (isEmpty(key) || isEmpty(value)) return acc
|
||||
return {
|
||||
...acc,
|
||||
[key]: value,
|
||||
}
|
||||
}, {}) ?? {},
|
||||
query,
|
||||
response_mode: 'streaming',
|
||||
conversation_id: existingDifyConversationId,
|
||||
user,
|
||||
files: [],
|
||||
try {
|
||||
const response = await ky(
|
||||
(apiEndpoint ?? defaultBaseUrl) + '/v1/chat-messages',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
inputs:
|
||||
inputs?.reduce((acc, { key, value }) => {
|
||||
if (isEmpty(key) || isEmpty(value)) return acc
|
||||
return {
|
||||
...acc,
|
||||
[key]: value,
|
||||
}
|
||||
}, {}) ?? {},
|
||||
query,
|
||||
response_mode: 'streaming',
|
||||
conversation_id: existingDifyConversationId,
|
||||
user,
|
||||
files: [],
|
||||
}),
|
||||
}
|
||||
)
|
||||
const reader = response.body?.getReader()
|
||||
|
||||
if (!reader) return {}
|
||||
|
||||
return {
|
||||
stream: new ReadableStream({
|
||||
async start(controller) {
|
||||
try {
|
||||
await processDifyStream(reader, {
|
||||
onDone: () => {
|
||||
controller.close()
|
||||
},
|
||||
onMessage: (message) => {
|
||||
controller.enqueue(
|
||||
new TextEncoder().encode(
|
||||
'0:"' + message.replace(/"/g, '\\"') + '"\n'
|
||||
)
|
||||
)
|
||||
},
|
||||
onMessageEnd({ totalTokens, conversationId }) {
|
||||
if (
|
||||
conversationVariableId &&
|
||||
isNotEmpty(conversationId) &&
|
||||
isEmpty(existingDifyConversationId?.toString())
|
||||
)
|
||||
variables.set(conversationVariableId, conversationId)
|
||||
|
||||
if ((responseMapping?.length ?? 0) === 0) return
|
||||
responseMapping?.forEach((mapping) => {
|
||||
if (!mapping.variableId) return
|
||||
|
||||
if (
|
||||
mapping.item === 'Conversation ID' &&
|
||||
isNotEmpty(conversationId) &&
|
||||
isEmpty(existingDifyConversationId?.toString())
|
||||
)
|
||||
variables.set(mapping.variableId, conversationId)
|
||||
|
||||
if (mapping.item === 'Total Tokens')
|
||||
variables.set(mapping.variableId, totalTokens)
|
||||
})
|
||||
},
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
controller.error(e) // Properly closing the stream with an error
|
||||
}
|
||||
},
|
||||
}),
|
||||
}
|
||||
)
|
||||
const reader = response.body?.getReader()
|
||||
|
||||
if (!reader) return
|
||||
|
||||
return new ReadableStream({
|
||||
async start(controller) {
|
||||
try {
|
||||
await processDifyStream(reader, {
|
||||
onDone: () => {
|
||||
controller.close()
|
||||
},
|
||||
onMessage: (message) => {
|
||||
controller.enqueue(
|
||||
new TextEncoder().encode('0:"' + message + '"\n')
|
||||
)
|
||||
},
|
||||
onMessageEnd({ totalTokens, conversationId }) {
|
||||
if (
|
||||
conversationVariableId &&
|
||||
isNotEmpty(conversationId) &&
|
||||
isEmpty(existingDifyConversationId?.toString())
|
||||
)
|
||||
variables.set(conversationVariableId, conversationId)
|
||||
|
||||
if ((responseMapping?.length ?? 0) === 0) return
|
||||
responseMapping?.forEach((mapping) => {
|
||||
if (!mapping.variableId) return
|
||||
|
||||
if (
|
||||
mapping.item === 'Conversation ID' &&
|
||||
isNotEmpty(conversationId) &&
|
||||
isEmpty(existingDifyConversationId?.toString())
|
||||
)
|
||||
variables.set(mapping.variableId, conversationId)
|
||||
|
||||
if (mapping.item === 'Total Tokens')
|
||||
variables.set(mapping.variableId, totalTokens)
|
||||
})
|
||||
},
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
controller.error(e) // Properly closing the stream with an error
|
||||
} catch (err) {
|
||||
if (err instanceof HTTPError) {
|
||||
return {
|
||||
httpError: {
|
||||
status: err.response.status,
|
||||
message: await err.response.text(),
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
console.error(err)
|
||||
return {}
|
||||
}
|
||||
},
|
||||
},
|
||||
server: async ({
|
||||
@ -243,12 +260,15 @@ export const createChatMessage = createAction({
|
||||
if (item === 'Total Tokens')
|
||||
variables.set(mapping.variableId, totalTokens)
|
||||
})
|
||||
} catch (error) {
|
||||
logs.add({
|
||||
status: 'error',
|
||||
description: 'Failed to create chat message',
|
||||
})
|
||||
console.error(error)
|
||||
} catch (err) {
|
||||
if (err instanceof HTTPError) {
|
||||
return logs.add({
|
||||
status: 'error',
|
||||
description: err.message,
|
||||
details: await err.response.text(),
|
||||
})
|
||||
}
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
},
|
||||
|
Reference in New Issue
Block a user