fix: toothfairyai provider

This commit is contained in:
Gab 2026-03-26 15:34:28 +11:00
parent 3581538902
commit e581d80c7a

View File

@ -117,71 +117,57 @@ export function createToothFairyAI(options: ToothFairyAIProviderSettings = {}):
} }
if (res.body && res.headers.get("content-type")?.includes("text/event-stream")) { if (res.body && res.headers.get("content-type")?.includes("text/event-stream")) {
const reader = res.body.getReader()
const decoder = new TextDecoder() const decoder = new TextDecoder()
const encoder = new TextEncoder() const encoder = new TextEncoder()
let buffer = ""
const filteredStream = new ReadableStream({ const filteredStream = res.body.pipeThrough(
async pull(controller) { new TransformStream({
const { done, value } = await reader.read() transform(chunk, controller) {
if (done) { buffer += decoder.decode(chunk, { stream: true })
controller.close() const lines = buffer.split("\n")
return buffer = lines.pop() || ""
}
const text = decoder.decode(value, { stream: true }) const filtered: string[] = []
const lines = text.split("\n") for (const line of lines) {
if (line.startsWith("data: ")) {
const filtered: string[] = [] const json = line.slice(6).trim()
for (const line of lines) { if (json) {
if (line.startsWith("data: ")) { try {
const json = line.slice(6).trim() const parsed = JSON.parse(json)
// Filter out connection status messages like {"status":"initialising"}, {"status":"connected"} if (parsed.status === "initialising" || parsed.status === "connected") {
// These are internal progress indicators, not OpenAI-format chunks log.debug("filtered connection status", { status: parsed.status })
if (json) { continue
try { }
const parsed = JSON.parse(json) if (parsed.choices?.[0]?.finish_reason) {
if (parsed.status === "initialising" || parsed.status === "connected") { log.info("stream finish_reason", {
log.debug("filtered connection status", { status: parsed.status }) finish_reason: parsed.choices[0].finish_reason,
continue })
} }
} catch { if (parsed.usage) {
// Not valid JSON, keep the line log.info("stream usage", {
prompt_tokens: parsed.usage.prompt_tokens,
completion_tokens: parsed.usage.completion_tokens,
total_tokens: parsed.usage.total_tokens,
})
}
} catch {}
} }
} }
filtered.push(line) filtered.push(line)
// Log tool calls and finish_reason
try {
const parsed = JSON.parse(json)
if (parsed.choices?.[0]?.delta?.tool_calls) {
log.debug("stream tool_calls", {
tool_calls: parsed.choices[0].delta.tool_calls,
})
}
if (parsed.choices?.[0]?.finish_reason) {
log.info("stream finish_reason", {
finish_reason: parsed.choices[0].finish_reason,
})
}
if (parsed.usage) {
log.info("stream usage", {
prompt_tokens: parsed.usage.prompt_tokens,
completion_tokens: parsed.usage.completion_tokens,
total_tokens: parsed.usage.total_tokens,
})
}
} catch {}
} else {
filtered.push(line)
} }
}
controller.enqueue(encoder.encode(filtered.join("\n"))) if (filtered.length > 0) {
}, controller.enqueue(encoder.encode(filtered.join("\n") + "\n"))
cancel() { }
reader.cancel() },
}, flush(controller) {
}) if (buffer) {
controller.enqueue(encoder.encode(buffer))
}
},
}),
)
return new Response(filteredStream, { return new Response(filteredStream, {
headers: res.headers, headers: res.headers,