UNPKG

life

Version:

Life.js is the first fullstack framework to build agentic web applications. It is minimal, extensible, and typesafe. Well, everything you love.

327 lines (317 loc) 10 kB
import { attempt, failure, success } from "./chunk-ZHBK6UTM.mjs"; import { __name } from "./chunk-2D3UJWOA.mjs"; // shared/deep-clone.ts function deepClone(x) { if (typeof x !== "object") return x; var i = 0, k, list, tmp, str = Object.prototype.toString.call(x); if (str === "[object Object]") { tmp = Object.create(x.__proto__ || null); } else if (str === "[object Array]") { tmp = Array(x.length); } else if (str === "[object Set]") { tmp = /* @__PURE__ */ new Set(); x.forEach(function(val) { tmp.add(deepClone(val)); }); } else if (str === "[object Map]") { tmp = /* @__PURE__ */ new Map(); x.forEach(function(val, key) { tmp.set(deepClone(key), deepClone(val)); }); } else if (str === "[object Date]") { tmp = /* @__PURE__ */ new Date(+x); } else if (str === "[object RegExp]") { tmp = new RegExp(x.source, x.flags); } else if (str === "[object DataView]") { tmp = new x.constructor(deepClone(x.buffer)); } else if (str === "[object ArrayBuffer]") { tmp = x.slice(0); } else if (str.slice(-6) === "Array]") { tmp = new x.constructor(x); } if (tmp) { for (list = Object.getOwnPropertySymbols(x); i < list.length; i++) { set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i])); } for (i = 0, list = Object.getOwnPropertyNames(x); i < list.length; i++) { if (Object.hasOwnProperty.call(tmp, k = list[i]) && tmp[k] === x[k]) continue; set(tmp, k, Object.getOwnPropertyDescriptor(x, k)); } } return tmp || x; } __name(deepClone, "deepClone"); function set(obj, key, val) { if (typeof val.value === "object") val.value = deepClone(val.value); if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === "__proto__") { Object.defineProperty(obj, key, val); } else obj[key] = val.value; } __name(set, "set"); // telemetry/helpers/zod.ts import z from "zod"; var zodObjectWithTelemetry = /* @__PURE__ */ __name(({ schema, toTelemetry }) => ({ schema, toTelemetry: /* @__PURE__ */ __name((data) => toTelemetry ? toTelemetry(data) : data, "toTelemetry") }), "zodObjectWithTelemetry"); var zodUnionWithTelemetry = /* @__PURE__ */ __name((discriminator, objects) => ({ schema: z.discriminatedUnion(discriminator, objects.map((s) => s.schema)), toTelemetry: /* @__PURE__ */ __name((data) => { const object = objects.find((s) => { const discriminatorSchema = s.schema.shape[discriminator]; if (discriminatorSchema instanceof z.ZodLiteral) return discriminatorSchema.def.values[0] === data[discriminator]; return false; }); return object?.toTelemetry ? object.toTelemetry(data) : data; }, "toTelemetry") }), "zodUnionWithTelemetry"); // agent/client/config.ts import { z as z3 } from "zod"; // transport/providers/livekit/browser.ts import { Room, RoomEvent } from "livekit-client"; import z2 from "zod"; // transport/providers/base.ts var TransportProviderClientBase = class { static { __name(this, "TransportProviderClientBase"); } config; listeners = {}; constructor(configSchema, config) { this.config = configSchema.parse({ ...config }); } on(type, callback) { try { if (!this.listeners[type]) this.listeners[type] = []; this.listeners[type].push(callback); return success(() => { this.listeners[type] = this.listeners[type]?.filter((listener) => listener !== callback); }); } catch (error) { return failure({ code: "Unknown", cause: error }); } } }; // transport/providers/livekit/browser.ts var livekitBrowserConfig = zodObjectWithTelemetry({ schema: z2.object({ provider: z2.literal("livekit"), serverUrl: z2.url().prefault(globalThis.process?.env?.LIVEKIT_SERVER_URL ?? "ws://localhost:7880") }), toTelemetry: /* @__PURE__ */ __name((config) => { config.isDevServer = Boolean(config.serverUrl?.includes("localhost")); config.serverUrl = "redacted"; return config; }, "toTelemetry") }); var LiveKitBrowserClient = class extends TransportProviderClientBase { static { __name(this, "LiveKitBrowserClient"); } isConnected = false; room = null; constructor(config) { super(livekitBrowserConfig.schema, config); } ensureConnected(name, connector) { if (!(this.isConnected && this.room?.localParticipant)) return failure({ code: "Conflict", message: `Calling this code (${name}) requires a connected room. Call joinRoom() first.` }); return success( connector ); } #initializeListeners(room) { room.on(RoomEvent.TrackSubscribed, (track) => { if (track.kind !== "audio") return; let _isUnsubscribed = false; const unsubscribeHandler = /* @__PURE__ */ __name((unsubscribedTrack) => { if (unsubscribedTrack.sid === track.sid) _isUnsubscribed = true; room.off(RoomEvent.TrackUnsubscribed, unsubscribeHandler); }, "unsubscribeHandler"); room.on(RoomEvent.TrackUnsubscribed, unsubscribeHandler); }); } async joinRoom(roomName, token) { try { if (roomName === this.room?.name) return success(); if (this.isConnected) { const [errLeave] = await this.leaveRoom(); if (errLeave) return failure(errLeave); } this.room = new Room({ adaptiveStream: true, dynacast: true, disconnectOnPageLeave: true, publishDefaults: { dtx: true, red: true } }); this.room.on(RoomEvent.TrackSubscribed, (track) => { const element = track.attach(); document.body.appendChild(element); }); this.#initializeListeners(this.room); await this.room.connect(this.config.serverUrl, token, { autoSubscribe: true }); this.isConnected = true; return success(); } catch (error) { return failure({ code: "Unknown", cause: error }); } } async leaveRoom() { try { const [errEnsure, connector] = this.ensureConnected("leaveRoom", this); if (errEnsure) return failure(errEnsure); await connector.room.disconnect(); this.isConnected = false; return success(); } catch (error) { return failure({ code: "Unknown", cause: error }); } } async streamText(topic) { try { const [errEnsure, connector] = this.ensureConnected("streamText", this); if (errEnsure) return failure(errEnsure); return success(await connector.room.localParticipant.streamText({ topic })); } catch (error) { return failure({ code: "Unknown", cause: error }); } } receiveStreamText(topic, callback, onError) { try { const [errEnsure, connector] = this.ensureConnected("receiveText", this); if (errEnsure) return failure(errEnsure); connector.room.registerTextStreamHandler(topic, async (iterator, participantInfo) => { const [err] = await attempt(async () => { await callback(iterator, participantInfo.identity); }); if (err) onError?.(err); }); return success(() => { connector.room.unregisterTextStreamHandler(topic); }); } catch (error) { return failure({ code: "Unknown", cause: error }); } } async enableMicrophone() { try { const [errEnsure, connector] = this.ensureConnected("enableMicrophone", this); if (errEnsure) return failure(errEnsure); await connector.room.localParticipant.setMicrophoneEnabled(true, { echoCancellation: true, noiseSuppression: false, voiceIsolation: false }); return success(); } catch (error) { return failure({ code: "Unknown", cause: error }); } } async playAudio() { try { const [errEnsure, connector] = this.ensureConnected("playAudio", this); if (errEnsure) return failure(errEnsure); await connector.room.startAudio(); return success(); } catch (error) { return failure({ code: "Unknown", cause: error }); } } async streamAudioChunk(chunk) { try { await chunk; throw new Error( "streamAudioChunk() is not available for browser client, use enableMicrophone() instead." ); } catch (error) { return failure({ code: "Unknown", cause: error }); } } }; // transport/config/browser.ts var transportBrowserConfig = zodUnionWithTelemetry("provider", [livekitBrowserConfig]); // agent/client/config.ts var agentClientConfig = zodObjectWithTelemetry({ schema: z3.object({ transport: transportBrowserConfig.schema.prefault({ provider: "livekit" }), experimental: z3.object().prefault({}) }), toTelemetry: /* @__PURE__ */ __name((config) => { config.transport = transportBrowserConfig.toTelemetry(config.transport); return config; }, "toTelemetry") }); // shared/async-queue.ts var AsyncQueue = class { static { __name(this, "AsyncQueue"); } #buf = []; #wakeUp; #closed = false; #totalLength = 0; push(v) { if (this.#closed) return; this.#buf.push(v); this.#totalLength++; this.#wakeUp?.(); } pushFirst(v) { if (this.#closed) return; this.#buf.unshift(v); this.#totalLength++; this.#wakeUp?.(); } stop() { if (this.#closed) return; this.#closed = true; this.#wakeUp?.(); } some(predicate) { return this.#buf.some(predicate); } length() { return this.#buf.length; } totalLength() { return this.#totalLength; } async next() { while (true) { const value = this.#buf.shift(); if (value !== void 0) return { value, done: false }; if (this.#closed) return { value: void 0, done: true }; await new Promise((res) => this.#wakeUp = res); this.#wakeUp = void 0; } } [Symbol.asyncIterator]() { return this; } }; export { deepClone, AsyncQueue, zodObjectWithTelemetry, zodUnionWithTelemetry, TransportProviderClientBase, LiveKitBrowserClient, agentClientConfig }; //# sourceMappingURL=chunk-D2T23PCX.mjs.map