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
JavaScript
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