| const { Readable } = require('stream'); |
| const { logger } = require('@librechat/data-schemas'); |
|
|
| class TextStream extends Readable { |
| constructor(text, options = {}) { |
| super(options); |
| this.text = text; |
| this.currentIndex = 0; |
| this.minChunkSize = options.minChunkSize ?? 2; |
| this.maxChunkSize = options.maxChunkSize ?? 4; |
| this.delay = options.delay ?? 20; |
| } |
|
|
| _read() { |
| const { delay, minChunkSize, maxChunkSize } = this; |
|
|
| if (this.currentIndex < this.text.length) { |
| setTimeout(() => { |
| const remainingChars = this.text.length - this.currentIndex; |
| const chunkSize = Math.min(this.randomInt(minChunkSize, maxChunkSize + 1), remainingChars); |
|
|
| const chunk = this.text.slice(this.currentIndex, this.currentIndex + chunkSize); |
| this.push(chunk); |
| this.currentIndex += chunkSize; |
| }, delay); |
| } else { |
| this.push(null); |
| } |
| } |
|
|
| randomInt(min, max) { |
| return Math.floor(Math.random() * (max - min)) + min; |
| } |
|
|
| async processTextStream(onProgressCallback) { |
| const streamPromise = new Promise((resolve, reject) => { |
| this.on('data', (chunk) => { |
| onProgressCallback(chunk.toString()); |
| }); |
|
|
| this.on('end', () => { |
| |
| resolve(); |
| }); |
|
|
| this.on('error', (err) => { |
| reject(err); |
| }); |
| }); |
|
|
| try { |
| await streamPromise; |
| } catch (err) { |
| logger.error('[processTextStream] Error in text stream:', err); |
| |
| } |
| } |
| } |
|
|
| module.exports = TextStream; |
|
|