UNPKG

@earendil-works/pi-ai

Version:

Unified LLM API with automatic model discovery and provider configuration

91 lines • 3.42 kB
import { AssistantMessageEventStream } from "../utils/event-stream.js"; function createSetupErrorMessage(model, error, timestamp, stopReason) { return { role: "assistant", content: [], api: model.api, provider: model.provider, model: model.id, usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }, }, stopReason, errorMessage: error instanceof Error ? error.message : String(error), timestamp, }; } function hasResult(source) { return typeof source.result === "function"; } async function forwardStream(target, source, observer, observeResult) { let result; for await (const event of source) { target.push(event); observer?.onEvent?.(event); if (event.type === "done") result = event.message; else if (event.type === "error") result = event.error; } if (hasResult(source)) result = await source.result(); target.end(result); observeResult(result); } /** * Returns a stream synchronously while running async setup (auth resolution, * lazy module loading) behind it. Setup failures terminate the stream with an * error event. */ export function lazyStream(model, setup, observer, signal) { const startedAt = Date.now(); const outer = new AssistantMessageEventStream(); let observedResult = false; const observeResult = (result) => { if (observedResult) return; observedResult = true; observer?.onResult?.(result); }; setup() .then((inner) => forwardStream(outer, inner, observer, observeResult)) .catch((error) => { const reason = signal?.aborted ? "aborted" : "error"; const message = createSetupErrorMessage(model, error, startedAt, reason); const event = { type: "error", reason, error: message }; outer.push(event); observer?.onEvent?.(event); outer.end(message); observeResult(message); }); return outer; } export function lazyApi(load, capabilities) { const api = { stream: (model, context, options) => lazyStream(model, async () => (await load()).stream(model, context, options), undefined, options?.signal), streamSimple: (model, context, options) => lazyStream(model, async () => (await load()).streamSimple(model, context, options), undefined, options?.signal), }; if (capabilities?.fetchDeferred) { api.fetchDeferred = (model, handle, options) => lazyStream(model, async () => { const implementation = await load(); if (!implementation.fetchDeferred) throw new Error("API does not support deferred responses"); return implementation.fetchDeferred(model, handle, options); }, undefined, options?.signal); } if (capabilities?.cancelDeferred) { api.cancelDeferred = async (model, handle, options) => { const implementation = await load(); if (!implementation.cancelDeferred) throw new Error("API cannot cancel deferred responses"); await implementation.cancelDeferred(model, handle, options); }; } return api; } //# sourceMappingURL=lazy.js.map