| 390 | } |
| 391 | |
| 392 | export function streamWithThink( |
| 393 | chatPath: string, |
| 394 | requestPayload: any, |
| 395 | headers: any, |
| 396 | tools: any[], |
| 397 | funcs: Record<string, Function>, |
| 398 | controller: AbortController, |
| 399 | parseSSE: ( |
| 400 | text: string, |
| 401 | runTools: any[], |
| 402 | ) => { |
| 403 | isThinking: boolean; |
| 404 | content: string | undefined; |
| 405 | }, |
| 406 | processToolMessage: ( |
| 407 | requestPayload: any, |
| 408 | toolCallMessage: any, |
| 409 | toolCallResult: any[], |
| 410 | ) => void, |
| 411 | options: any, |
| 412 | ) { |
| 413 | let responseText = ""; |
| 414 | let remainText = ""; |
| 415 | let finished = false; |
| 416 | let running = false; |
| 417 | let runTools: any[] = []; |
| 418 | let responseRes: Response; |
| 419 | let isInThinkingMode = false; |
| 420 | let lastIsThinking = false; |
| 421 | let lastIsThinkingTagged = false; //between <think> and </think> tags |
| 422 | |
| 423 | // animate response to make it looks smooth |
| 424 | function animateResponseText() { |
| 425 | if (finished || controller.signal.aborted) { |
| 426 | responseText += remainText; |
| 427 | console.log("[Response Animation] finished"); |
| 428 | if (responseText?.length === 0) { |
| 429 | options.onError?.(new Error("empty response from server")); |
| 430 | } |
| 431 | return; |
| 432 | } |
| 433 | |
| 434 | if (remainText.length > 0) { |
| 435 | const fetchCount = Math.max(1, Math.round(remainText.length / 60)); |
| 436 | const fetchText = remainText.slice(0, fetchCount); |
| 437 | responseText += fetchText; |
| 438 | remainText = remainText.slice(fetchCount); |
| 439 | options.onUpdate?.(responseText, fetchText); |
| 440 | } |
| 441 | |
| 442 | requestAnimationFrame(animateResponseText); |
| 443 | } |
| 444 | |
| 445 | // start animaion |
| 446 | animateResponseText(); |
| 447 | |
| 448 | const finish = () => { |
| 449 | if (!finished) { |