UNPKG

@just-every/ensemble

Version:

LLM provider abstraction layer with unified streaming interface

102 lines 4.09 kB
import { randomUUID } from 'node:crypto'; import { getModelFromAgent, getModelProvider } from '../model_providers/model_provider.js'; import { createTraceContext } from '../utils/trace_context.js'; export function ensembleImage(prompt, agent, options = {}) { const run = async (requestId) => { const trace = createTraceContext(agent, 'image_generation'); const tracedRequestId = requestId || options.request_id || randomUUID(); const requestOptions = { ...options, request_id: tracedRequestId }; let requestStarted = false; await trace.emitTurnStart({ prompt, options: requestOptions, }); try { const model = await getModelFromAgent(agent, 'image_generation'); const provider = getModelProvider(model); if (!provider.createImage) throw new Error(`Provider for model ${model} does not support image generation`); await trace.emitRequestStart(tracedRequestId, { agent_id: agent.agent_id, provider: provider.provider_id, model, payload: { prompt, options: requestOptions, }, }); requestStarted = true; const images = await provider.createImage(prompt, model, agent, requestOptions); await trace.emitRequestEnd(tracedRequestId, { status: 'completed', image_count: images.length, }); await trace.emitTurnEnd('completed', 'completed'); return images; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); if (requestStarted) { await trace.emitRequestEnd(tracedRequestId, { status: 'error', error: errorMessage, }); } await trace.emitTurnEnd('error', 'exception', { error: errorMessage, }); throw error; } }; if (!options.stream) { return run(); } const self = async function* () { const request_id = options.request_id || randomUUID(); const { costTracker } = await import('../utils/cost_tracker.js'); yield { type: 'image_start', request_id, timestamp: new Date().toISOString() }; const handler = (usage) => { if (usage?.request_id === request_id) { const ev = { type: 'cost_update', usage, request_id, timestamp: new Date().toISOString() }; iterator.push(ev); } }; const iterator = { queue: [], push(e) { this.queue.push(e); }, }; costTracker.onAddUsage(handler); try { const images = await run(request_id); while (iterator.queue.length) yield iterator.queue.shift(); let idx = 0; for (const img of images) { const isUrl = typeof img === 'string' && /^https?:\/\//i.test(img); const ev = { type: 'file_complete', request_id, message_id: `${request_id}_img_${idx}`, data_format: isUrl ? 'url' : 'base64', data: img, timestamp: new Date().toISOString(), }; yield ev; while (iterator.queue.length) yield iterator.queue.shift(); idx++; } yield { type: 'image_complete', request_id, timestamp: new Date().toISOString() }; while (iterator.queue.length) yield iterator.queue.shift(); } catch (error) { yield { type: 'error', request_id, error: String(error?.message || error) }; } finally { costTracker.offAddUsage(handler); } }; return self(); } //# sourceMappingURL=ensemble_image.js.map