Skip to content

Commit

Permalink
fix: unable to parse the result due to not check data: frame for sse
Browse files Browse the repository at this point in the history
  • Loading branch information
nekomeowww committed Dec 3, 2024
1 parent 918fc9b commit b8354e3
Showing 1 changed file with 27 additions and 10 deletions.
37 changes: 27 additions & 10 deletions packages/stream-text/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { chatCompletion, type ChatCompletionOptions, type FinishReason } from '@xsai/shared-chat-completion'

export interface StreamTextOptions extends ChatCompletionOptions {
onError?: (error: unknown) => Promise<void> | void
streamOptions?: {
/**
* Return usage.
Expand Down Expand Up @@ -42,6 +43,9 @@ export interface StreamTextResponse {
usage?: StreamTextResponseUsage
}

const dataHeaderPrefix = 'data: '
const dataErrorPrefix = `{"error":`

/**
* @experimental
* WIP, currently only returns `textStream`, does not support function calling (tools).
Expand All @@ -64,20 +68,33 @@ export const streamText = async (options: StreamTextOptions): Promise<StreamText
const rawChunkStream = res.body.pipeThrough(new TransformStream({
transform: (chunk, controller) => {
for (const line of decoder.decode(chunk).split('\n').filter(line => line)) {
if (line !== 'data: [DONE]') {
const data: StreamTextResponse = JSON.parse(line.slice(6))
// Some cases:
// - Empty chunk
// - :ROUTER PROCESSING from OpenRouter
if (!line || !line.startsWith(dataHeaderPrefix)) {
continue
}

controller.enqueue(data)
if (line.startsWith(dataErrorPrefix)) {
// About controller error: https://developer.mozilla.org/en-US/docs/Web/API/TransformStreamDefaultController/error
controller.error(new Error(`Error from server: ${line}`))
continue
}

if (data.choices[0].finish_reason) {
finishReason = data.choices[0].finish_reason
}
const lineWithoutPrefix = line.slice(dataHeaderPrefix.length)
if (lineWithoutPrefix === '[DONE]') {
controller.terminate()
continue
}

const data: StreamTextResponse = JSON.parse(line.slice(6))
controller.enqueue(data)

if (data.usage)
usage = data.usage
if (data.choices[0].finish_reason) {
finishReason = data.choices[0].finish_reason
}
else {
controller.terminate()
if (data.usage) {
usage = data.usage
}
}
},
Expand Down

0 comments on commit b8354e3

Please sign in to comment.