UNPKG

gpt-research

Version:

Autonomous AI research agent that conducts comprehensive research on any topic and generates detailed reports with citations

308 lines 8.26 kB
"use strict"; /** * Streaming utilities for handling real-time data */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ProgressTracker = exports.StreamBuffer = exports.TransformStream = exports.StreamProcessor = void 0; exports.parseSSEStream = parseSSEStream; exports.createReadableStream = createReadableStream; exports.iteratorToArray = iteratorToArray; exports.mergeAsyncIterators = mergeAsyncIterators; exports.batchStream = batchStream; exports.rateLimitStream = rateLimitStream; exports.filterStream = filterStream; exports.mapStream = mapStream; exports.reduceStream = reduceStream; exports.timeoutStream = timeoutStream; /** * Parse Server-Sent Events stream */ function parseSSEStream(data) { const lines = data.split('\n'); const messages = []; for (const line of lines) { if (line.startsWith('data: ')) { const content = line.slice(6); if (content && content !== '[DONE]') { messages.push(content); } } } return messages; } /** * Stream processor for handling chunked data */ class StreamProcessor { buffer = ''; decoder = new TextDecoder(); /** * Process a chunk of data */ processChunk(chunk) { const text = this.decoder.decode(chunk, { stream: true }); this.buffer += text; const messages = []; const lines = this.buffer.split('\n'); // Keep the last incomplete line in buffer this.buffer = lines[lines.length - 1]; // Process complete lines for (let i = 0; i < lines.length - 1; i++) { const line = lines[i].trim(); if (line.startsWith('data: ')) { const content = line.slice(6); if (content && content !== '[DONE]') { messages.push(content); } } } return messages; } /** * Get any remaining buffered data */ flush() { const messages = []; if (this.buffer.trim().startsWith('data: ')) { const content = this.buffer.trim().slice(6); if (content && content !== '[DONE]') { messages.push(content); } } this.buffer = ''; return messages; } /** * Reset the processor */ reset() { this.buffer = ''; } } exports.StreamProcessor = StreamProcessor; /** * Create a readable stream from async generator */ function createReadableStream(generator) { return new ReadableStream({ async start(controller) { try { for await (const chunk of generator) { controller.enqueue(chunk); } controller.close(); } catch (error) { controller.error(error); } } }); } /** * Convert async iterator to array */ async function iteratorToArray(iterator) { const result = []; let next = await iterator.next(); while (!next.done) { result.push(next.value); next = await iterator.next(); } return result; } /** * Merge multiple async iterators */ async function* mergeAsyncIterators(...iterators) { const promises = iterators.map((it, index) => it.next().then(result => ({ index, result }))); const pending = new Set(iterators.map((_, index) => index)); while (pending.size > 0) { const { index, result } = await Promise.race(Array.from(pending).map(i => promises[i])); if (result.done) { pending.delete(index); } else { yield result.value; promises[index] = iterators[index] .next() .then(result => ({ index, result })); } } } /** * Transform stream with backpressure support */ class TransformStream { // private queue: R[] = []; // Reserved for future use // private processing = false; // Reserved for future use transformer; constructor(transformer) { this.transformer = transformer; } async *transform(source) { for await (const value of source) { const result = await this.transformer(value); yield result; } } } exports.TransformStream = TransformStream; /** * Batch stream items */ async function* batchStream(source, batchSize) { let batch = []; for await (const item of source) { batch.push(item); if (batch.length >= batchSize) { yield batch; batch = []; } } if (batch.length > 0) { yield batch; } } /** * Rate limit stream */ async function* rateLimitStream(source, itemsPerSecond) { const delay = 1000 / itemsPerSecond; let lastEmit = 0; for await (const item of source) { const now = Date.now(); const timeSinceLastEmit = now - lastEmit; if (timeSinceLastEmit < delay) { await new Promise(resolve => setTimeout(resolve, delay - timeSinceLastEmit)); } lastEmit = Date.now(); yield item; } } /** * Filter stream */ async function* filterStream(source, predicate) { for await (const item of source) { if (await predicate(item)) { yield item; } } } /** * Map stream */ async function* mapStream(source, mapper) { for await (const item of source) { yield await mapper(item); } } /** * Reduce stream */ async function reduceStream(source, reducer, initialValue) { let accumulator = initialValue; for await (const item of source) { accumulator = await reducer(accumulator, item); } return accumulator; } /** * Timeout for async iterators */ async function* timeoutStream(source, timeout) { for await (const item of source) { const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Stream timeout')), timeout)); yield await Promise.race([ Promise.resolve(item), timeoutPromise ]); } } /** * Buffer stream items */ class StreamBuffer { buffer = []; maxSize; constructor(maxSize = 100) { this.maxSize = maxSize; } push(item) { this.buffer.push(item); if (this.buffer.length > this.maxSize) { this.buffer.shift(); } } getAll() { return [...this.buffer]; } getLast(n) { return this.buffer.slice(-n); } clear() { this.buffer = []; } get size() { return this.buffer.length; } } exports.StreamBuffer = StreamBuffer; class ProgressTracker { current = 0; total; startTime; lastUpdate = 0; onProgress; constructor(total, onProgress) { this.total = total; this.startTime = Date.now(); this.lastUpdate = this.startTime; this.onProgress = onProgress; } update(current, message) { this.current = current; const now = Date.now(); const progress = { current: this.current, total: this.total, percentage: (this.current / this.total) * 100, message }; // Calculate ETA if (this.current > 0) { const elapsed = now - this.startTime; const rate = this.current / elapsed; const remaining = this.total - this.current; progress.eta = remaining / rate; } this.lastUpdate = now; if (this.onProgress) { this.onProgress(progress); } } updateProgress(percentage, message) { const current = Math.round((percentage / 100) * this.total); this.update(current, message); } increment(message) { this.update(this.current + 1, message); } reset() { this.current = 0; this.startTime = Date.now(); this.lastUpdate = this.startTime; } getProgress() { return { current: this.current, total: this.total, percentage: (this.current / this.total) * 100 }; } getLastUpdate() { return this.lastUpdate; } } exports.ProgressTracker = ProgressTracker; //# sourceMappingURL=stream.js.map