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.

1,198 lines (1,142 loc) 48 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _chunkEL6AAGQAjs = require('./chunk-EL6AAGQA.js'); var _chunkW2LGDDT2js = require('./chunk-W2LGDDT2.js'); var _chunkFID44QSNjs = require('./chunk-FID44QSN.js'); var _chunkVLUR4YNDjs = require('./chunk-VLUR4YND.js'); var _chunkOTBM3PZSjs = require('./chunk-OTBM3PZS.js'); var _chunkBFC2WP6Qjs = require('./chunk-BFC2WP6Q.js'); var _chunk22H3U7VVjs = require('./chunk-22H3U7VV.js'); var _chunk6PEHRAEPjs = require('./chunk-6PEHRAEP.js'); // shared/hmr.ts var rawHMR = ( // - Vite / Bun / modern dev servers typeof import.meta !== "undefined" && import.meta.hot || // - Webpack ESM typeof import.meta !== "undefined" && import.meta.webpackHot || // - Webpack CJS _optionalChain([globalThis, 'optionalAccess', _ => _.module, 'optionalAccess', _2 => _2.hot]) || // - None null ); var hmr = Object.freeze( rawHMR ? { active: true, accept: rawHMR.accept ? (...args) => _optionalChain([rawHMR, 'access', _3 => _3.accept, 'optionalCall', _4 => _4(...args)]) : void 0, dispose: rawHMR.dispose || rawHMR.addDisposeHandler ? (cb) => _optionalChain([(rawHMR.dispose || rawHMR.addDisposeHandler), 'optionalCall', _5 => _5(cb)]) : void 0 } : { active: false } ); // plugins/client/class.ts var _zod = require('zod'); var _zod2 = _interopRequireDefault(_zod); var PluginClient = class { static { _chunk6PEHRAEPjs.__name.call(void 0, this, "PluginClient"); } #config; #agent; #telemetry; #atoms; #extension; #eventsListeners = /* @__PURE__ */ new Map(); #contextListeners = /* @__PURE__ */ new Map(); #contextValue = {}; #lastContextValueTimestamp = 0; constructor(definition, config, agent) { this.def = definition; this.#agent = agent; const { error: errConfig, data: parsedConfig } = this.def.config.schema.safeParse(config); if (errConfig) { throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Validation", message: `Invalid config provided to plugin client '${this.def.name}'.`, cause: errConfig }); } this.#config = parsedConfig; this.#telemetry = _chunkEL6AAGQAjs.createTelemetryClient.call(void 0, "plugin.client", { agentId: agent.id, agentName: agent.def.name, agentConfig: agent.config, transportProviderName: agent.config.transport.provider, pluginName: definition.name, pluginClientConfig: this.#config }); const [errAccessor, accessor] = this.getAccessor(); if (errAccessor) throw errAccessor; this.#extension = new (definition.class({ plugin: _chunk22H3U7VVjs.toPublic.call(void 0, accessor), agent: _chunk22H3U7VVjs.toPublic.call(void 0, this.#agent), dependencies: this.getDependenciesAccessor(), telemetry: this.#telemetry }))(); const atomsArr = definition.atoms({ plugin: _chunk22H3U7VVjs.toPublic.call(void 0, accessor), agent: _chunk22H3U7VVjs.toPublic.call(void 0, this.#agent), dependencies: this.getDependenciesAccessor(), telemetry: this.#telemetry }); const atomsMap = Object.fromEntries(atomsArr.map((atom2) => [atom2.name, atom2.create])); this.#atoms = atomsMap; } getAccessor() { const [errClone, cloneConfig] = _chunk22H3U7VVjs.attempt.call(void 0, () => _chunkBFC2WP6Qjs.deepClone.call(void 0, this.#config)); if (errClone) return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: errClone }); const serverContextGet = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (() => _chunk22H3U7VVjs.attempt.call(void 0, () => _chunkBFC2WP6Qjs.deepClone.call(void 0, this.#contextValue))), "serverContextGet"); const serverContextOnChange = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, ((selector, callback) => { const id = _chunk22H3U7VVjs.newId.call(void 0, "listener"); this.#contextListeners.set(id, { id, callback, selector }); return _chunk22H3U7VVjs.success.call(void 0, () => this.#contextListeners.delete(id)); }), "serverContextOnChange"); const serverEventsEmit = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (async (event) => { const [err, data] = await this.#agent.transport.call({ name: `plugin.${this.def.name}.events.emit`, schema: { input: _chunkOTBM3PZSjs.pluginEventInputSchema, output: _zod2.default.object({ id: _zod2.default.string() }) }, input: event }); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); return _chunk22H3U7VVjs.success.call(void 0, data.id); }), "serverEventsEmit"); const serverEventsOn = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, ((selector, callback, includeDropped = false) => { const id = _chunk22H3U7VVjs.newId.call(void 0, "listener"); this.#eventsListeners.set(id, { id, selector, callback, includeDropped }); this.#agent.transport.call({ name: `plugin.${this.def.name}.events.subscribe`, schema: { input: _zod2.default.object({ listenerId: _zod2.default.string(), selector: _zod2.default.any(), includeDropped: _zod2.default.boolean().prefault(false) }) }, input: { listenerId: id, selector, includeDropped } }); return _chunk22H3U7VVjs.success.call(void 0, () => { this.#agent.transport.call({ name: `plugin.${this.def.name}.events.unsubscribe`, schema: { input: _zod2.default.object({ listenerId: _zod2.default.string() }) }, input: { listenerId: id } }); this.#eventsListeners.delete(id); }); }), "serverEventsOn"); const serverEventsOnce = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, ((selector, callback, includeDropped = false) => { const [errOn, unsubscribe] = serverEventsOn( selector, async (event) => { _optionalChain([unsubscribe, 'optionalCall', _6 => _6()]); await callback(event); }, includeDropped ); if (errOn) return _chunk22H3U7VVjs.failure.call(void 0, errOn); return _chunk22H3U7VVjs.success.call(void 0, unsubscribe); }), "serverEventsOnce"); const serverEventsWaitForProcessing = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (async (eventId) => await this.#agent.transport.call({ name: `plugin.${this.def.name}.events.waitForProcessing`, schema: { input: _zod2.default.object({ eventId: _zod2.default.string() }) }, input: { eventId } })), "serverEventsWaitForProcessing"); const serverEventsWaitForResult = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (async (eventId, handlerName) => ( // @ts-expect-error await this.#agent.transport.call({ name: `plugin.${this.def.name}.events.waitForResult`, schema: { input: _zod2.default.object({ eventId: _zod2.default.string(), handlerName: _zod2.default.string() }), output: _zod2.default.object().loose() }, input: { eventId, handlerName } }) )), "serverEventsWaitForResult"); return _chunk22H3U7VVjs.success.call(void 0, Object.assign(_nullishCoalesce(this.#extension, () => ( {})), { config: cloneConfig, atoms: this.#atoms, server: { context: { onChange: serverContextOnChange, get: serverContextGet }, events: { emit: serverEventsEmit, on: serverEventsOn, once: serverEventsOnce, waitForProcessing: serverEventsWaitForProcessing, waitForResult: serverEventsWaitForResult } } }) ); } getDependenciesAccessor() { const dependenciesAccessors = {}; for (const dependencyDef of _nullishCoalesce(this.def.dependencies, () => ( []))) { const accessor = this.#agent[_chunkOTBM3PZSjs.toMethodName.call(void 0, dependencyDef.name)]; if (!accessor) return _chunk22H3U7VVjs.failure.call(void 0, { code: "NotFound", message: `Failed to obtain client instance for dependency plugin '${dependencyDef.name}'. Shouldn't happen.` }); dependenciesAccessors[dependencyDef.name] = accessor; } return _chunk22H3U7VVjs.success.call(void 0, dependenciesAccessors); } async start() { const [errPing, dataPing] = await this.#agent.transport.call({ name: "agent.has-plugin-server", schema: { input: _zod2.default.object({ pluginName: _zod2.default.string() }), output: _zod2.default.object({ hasServer: _zod2.default.boolean() }) }, input: { pluginName: this.def.name } }); if (errPing) return _chunk22H3U7VVjs.failure.call(void 0, errPing); if (!dataPing.hasServer) return _chunk22H3U7VVjs.success.call(void 0, ); this.#agent.transport.register({ name: `plugin.${this.def.name}.context.changed`, schema: { input: _zod2.default.object({ value: _zod2.default.any(), timestamp: _zod2.default.number() }) }, execute: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async ({ value, timestamp }) => await this.#setContextValue(value, timestamp), "execute") }); this.#agent.transport.register({ name: `plugin.${this.def.name}.events.callback`, schema: { input: _zod2.default.object({ listenerId: _zod2.default.string(), event: _chunkOTBM3PZSjs.pluginEventInputSchema }) }, execute: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async ({ listenerId, event }) => { await _optionalChain([this, 'access', _7 => _7.#eventsListeners, 'access', _8 => _8.get, 'call', _9 => _9(listenerId), 'optionalAccess', _10 => _10.callback, 'call', _11 => _11(event)]); return _chunk22H3U7VVjs.success.call(void 0, ); }, "execute") }); const [err, data] = await this.#agent.transport.call({ name: `plugin.${this.def.name}.context.get`, schema: { output: _zod2.default.object({ value: _zod2.default.any(), timestamp: _zod2.default.number() }) } }); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); return await this.#setContextValue(data.value, data.timestamp); } async #setContextValue(value, timestamp) { const oldContextValue = _chunkBFC2WP6Qjs.deepClone.call(void 0, this.#contextValue); if (timestamp < this.#lastContextValueTimestamp) return _chunk22H3U7VVjs.success.call(void 0, ); this.#lastContextValueTimestamp = timestamp; this.#contextValue = value; await Promise.all( Array.from(this.#contextListeners.values()).map(async (listener) => { const newSelectedValue = listener.selector(this.#contextValue); const oldSelectedValue = listener.selector(oldContextValue); const [errEqual, equal] = _chunkVLUR4YNDjs.canon.equal(newSelectedValue, oldSelectedValue); if (errEqual) return _chunk22H3U7VVjs.failure.call(void 0, errEqual); if (equal) return _chunk22H3U7VVjs.success.call(void 0, ); return await _chunk22H3U7VVjs.attempt.call(void 0, async () => await listener.callback(_chunkBFC2WP6Qjs.deepClone.call(void 0, this.#contextValue), _chunkBFC2WP6Qjs.deepClone.call(void 0, oldContextValue)) ); }) ); return _chunk22H3U7VVjs.success.call(void 0, ); } }; // transport/client/browser.ts var clientTransportProviders = { livekit: _chunkBFC2WP6Qjs.LiveKitBrowserClient }; var TransportBrowserClient = class extends _chunkFID44QSNjs.TransportClientBase { static { _chunk6PEHRAEPjs.__name.call(void 0, this, "TransportBrowserClient"); } constructor({ config, obfuscateErrors = false, telemetry = null }) { const ProviderClass = clientTransportProviders[config.provider]; super({ provider: new ProviderClass(config), obfuscateErrors, telemetry }); } }; // agent/client/atoms/info.ts var _nanostores = require('nanostores'); // agent/client/atoms/define.ts function defineAgentAtom(atomDef) { return atomDef; } _chunk6PEHRAEPjs.__name.call(void 0, defineAgentAtom, "defineAgentAtom"); // agent/client/atoms/info.ts var atomConfigSchema = _zod2.default.object({ pollingMs: _zod2.default.number().min(1e3).max(3e4).prefault(5e3) }); var agentInfoAtomDef = defineAgentAtom(({ agent }) => ({ name: "info", create: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (config) => { const { error: errConfig, data: parsedConfig } = atomConfigSchema.safeParse(_nullishCoalesce(config, () => ( {}))); if (errConfig) throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Validation", message: "Invalid config provided to atom." }); const store = _nanostores.atom.call(void 0, null); const refresh = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async () => { try { const [error, data] = await agent.info(); if (error) throw error; store.set(data); } catch (error) { throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Unknown", cause: error }); } }, "refresh"); _nanostores.onMount.call(void 0, store, () => { refresh(); const intervalId = setInterval(() => refresh(), parsedConfig.pollingMs); return () => clearInterval(intervalId); }); return { store, refresh }; }, "create") })); // agent/client/atoms/index.ts var createAgentClientAtoms = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (params) => ({ info: agentInfoAtomDef(params) }), "createAgentClientAtoms"); // agent/client/class.ts var AgentClient = (_class = class { static { _chunk6PEHRAEPjs.__name.call(void 0, this, "AgentClient"); } #life; #telemetry; #plugins = {}; #sessionToken; #transportRoom; #scope; __init() {this.isStarted = false} constructor(params) {;_class.prototype.__init.call(this); this.def = params.definition; this.id = params.id; this.name = params.definition.name; this.config = params.config; this.#life = params.life; this.#telemetry = _chunkEL6AAGQAjs.createTelemetryClient.call(void 0, "agent.client", { agentId: this.id, agentName: this.name, agentConfig: this.config, transportProviderName: this.config.transport.provider }); this.transport = new TransportBrowserClient({ config: this.config.transport, telemetry: this.#telemetry }); this.atoms = createAgentClientAtoms({ agent: this, telemetry: this.#telemetry }); const [errInitialize] = this.#initializePlugins(this.def.plugins); if (errInitialize) throw errInitialize; } #initializePlugins(plugins) { return this.#telemetry.trace("#initializePlugins()", () => { try { const pluginNames = plugins.map((plugin) => plugin.name); const duplicates = pluginNames.filter((name2, index) => pluginNames.indexOf(name2) !== index); if (duplicates.length > 0) { const uniqueDuplicates = [...new Set(duplicates)]; return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Two or more plugins are named '${uniqueDuplicates.join("', '")}'. Plugin names must be unique. (agent: '${this.name}')` }); } for (const plugin of plugins) { for (const dependency of plugin.dependencies) { const depPlugin = this.def.plugins.find((p) => p.name === dependency.name); if (!depPlugin) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Plugin '${plugin.name}' depends on plugin '${dependency.name}', but '${dependency.name}' is not registered. (agent: '${this.name}')` }); } } } const initResults = plugins.map((plugin) => { const [errPlugin, pluginInstance] = _chunk22H3U7VVjs.attempt.call(void 0, () => new PluginClient( plugin, _nullishCoalesce(this.def.pluginConfigs[plugin.name], () => ( {})), this ) ); if (errPlugin) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: `Failed to initialize plugin '${name}'.`, cause: errPlugin }); } this.#plugins[plugin.name] = pluginInstance; const [errAccessor, accessor] = pluginInstance.getAccessor(); if (errAccessor) return _chunk22H3U7VVjs.failure.call(void 0, errAccessor); this[_chunkOTBM3PZSjs.toMethodName.call(void 0, plugin.name)] = accessor; return _chunk22H3U7VVjs.success.call(void 0, ); }); for (const result of initResults) { const [error] = result; if (error) this.#telemetry.log.error({ error }); } return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while initializing plugins.", cause: error }); } }); } /** * Start the agent and join the transport room * @returns Server response on successful start * @throws Error if the agent fails to start */ async start(scope) { return await this.#telemetry.trace("start()", async (span) => { const [error] = await this.#start(scope); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, ); }); } // Private method, doesn't log to telemetry async #start(scope) { return await this.#telemetry.trace("#start()", async () => { try { const [errStart, data] = await this.#life.api.call("agent.start", { id: this.id, scope }); if (errStart) return _chunk22H3U7VVjs.failure.call(void 0, errStart); this.#sessionToken = data.sessionToken; this.#transportRoom = data.transportRoom; this.#scope = scope; const [errJoin] = await this.transport.joinRoom( this.#transportRoom.name, this.#transportRoom.token ); if (errJoin) return _chunk22H3U7VVjs.failure.call(void 0, errJoin); const results = await Promise.all(Object.values(this.#plugins).map((p) => p.start())); const errors = results.map((r) => r[0]).filter(Boolean); for (const error of errors) this.#telemetry.log.error({ message: "Failed to start plugin.", error }); this.isStarted = true; return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while starting agent.", cause: error }); } }); } /** * Stop the agent and leave the transport room * @returns Server response on successful stop * @throws Error if the agent fails to stop */ async stop() { return await this.#telemetry.trace("stop()", async (span) => { const [error] = await this.#stop(); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, ); }); } // Private method, doesn't log to telemetry async #stop() { return await this.#telemetry.trace("#stop()", async () => { try { if (!this.#sessionToken) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Conflict", message: "Agent is not started." }); } const [apiResult, roomResult] = await Promise.all([ this.#life.api.call("agent.stop", { id: this.id, sessionToken: this.#sessionToken }), this.transport.leaveRoom() ]); if (apiResult[0]) return _chunk22H3U7VVjs.failure.call(void 0, apiResult[0]); if (roomResult[0]) return _chunk22H3U7VVjs.failure.call(void 0, roomResult[0]); this.isStarted = false; return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while stopping agent.", cause: error }); } }); } /** * Restart the agent by stopping and starting it */ async restart() { return await this.#telemetry.trace("restart()", async (span) => { const [error] = await this.#restart(); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, ); }); } // Private method, doesn't log to telemetry async #restart() { return await this.#telemetry.trace("#restart()", async () => { try { const [errStop] = await this.#stop(); if (errStop) return _chunk22H3U7VVjs.failure.call(void 0, errStop); if (!this.#scope) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Conflict", message: "Agent is not started." }); } const [errStart] = await this.#start(this.#scope); if (errStart) return _chunk22H3U7VVjs.failure.call(void 0, errStart); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while restarting agent.", cause: error }); } }); } async enableVoiceIn() { const [errEnableMicrophone] = await this.transport.enableMicrophone(); if (errEnableMicrophone) return _chunk22H3U7VVjs.failure.call(void 0, errEnableMicrophone); return _chunk22H3U7VVjs.success.call(void 0, ); } async enableVoiceOut() { const [errPlayAudio] = await this.transport.playAudio(); if (errPlayAudio) return _chunk22H3U7VVjs.failure.call(void 0, errPlayAudio); return _chunk22H3U7VVjs.success.call(void 0, ); } async disableVoiceIn() { return await _chunk22H3U7VVjs.success.call(void 0, ); } async disableVoiceOut() { return await _chunk22H3U7VVjs.success.call(void 0, ); } /** * Get agent information from the server * @returns Agent information including status and metrics * @throws Error if unable to retrieve agent info */ async info() { return await this.#telemetry.trace("info()", async (span) => { const [error, data] = await this.#info(); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, data); }); } // Private method, doesn't log to telemetry async #info() { return await this.#telemetry.trace("#info()", async () => { try { if (!this.#sessionToken) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Conflict", message: "Agent is not started." }); } const [err, data] = await this.#life.api.call("agent.info", { id: this.id, sessionToken: this.#sessionToken }); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); return _chunk22H3U7VVjs.success.call(void 0, data); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while getting agent info.", cause: error }); } }); } }, _class); // telemetry/helpers/formatting/browser.ts var _tracemapping = require('@jridgewell/trace-mapping'); var _errorstackparser = require('error-stack-parser'); var _errorstackparser2 = _interopRequireDefault(_errorstackparser); var sourceMapCache = /* @__PURE__ */ new Map(); async function getSourceMap(file) { if (sourceMapCache.has(file)) return _nullishCoalesce(sourceMapCache.get(file), () => ( null)); try { const mapUrl = `${file}.map`; const r = await fetch(mapUrl, { credentials: "same-origin" }); if (!r.ok) return _nullishCoalesce(sourceMapCache.set(file, null).get(file), () => ( null)); const json = await r.json(); let map; try { map = new (0, _tracemapping.TraceMap)(json); } catch (error) { if (error instanceof Error && error.message.includes("sectioned source map")) { map = new (0, _tracemapping.FlattenMap)(json); } else { throw error; } } return _nullishCoalesce(sourceMapCache.set(file, map).get(file), () => ( null)); } catch (error) { console.error("Failed to get source map for", file, error); return _nullishCoalesce(sourceMapCache.set(file, null).get(file), () => ( null)); } } _chunk6PEHRAEPjs.__name.call(void 0, getSourceMap, "getSourceMap"); async function prettifyErrorStack(err_) { const err = _chunkBFC2WP6Qjs.deepClone.call(void 0, err_); const frames = safeParse(err); const lines = []; for (const f of frames) { const file = _optionalChain([f, 'access', _12 => _12.fileName, 'optionalAccess', _13 => _13.startsWith, 'call', _14 => _14("async ")]) ? f.fileName.slice(6) : f.fileName; const line = f.lineNumber; const col = f.columnNumber; let ref = "<unknown>"; if (file && line != null && col != null) { const map = await getSourceMap(file); if (map) { const pos = _tracemapping.originalPositionFor.call(void 0, map, { line, column: col, bias: 1 }); if (pos.source && pos.line != null && pos.column != null) { ref = `${pos.source}:${pos.line}:${pos.column}`; } } if (!ref) ref = `${file}:${line}:${col}`; } lines.push(f.functionName ? ` at ${f.functionName} (${ref})` : ` at ${ref}`); } err.stack = lines.join("\n"); return err; } _chunk6PEHRAEPjs.__name.call(void 0, prettifyErrorStack, "prettifyErrorStack"); function safeParse(err) { try { return _errorstackparser2.default.parse(err); } catch (e) { return [ { fileName: void 0, lineNumber: void 0, columnNumber: void 0, functionName: err.name || "Error" } ]; } } _chunk6PEHRAEPjs.__name.call(void 0, safeParse, "safeParse"); async function formatErrorForBrowser(error) { let code = ""; let message = ""; let stack = ""; const after = []; let processed = false; if (_chunk22H3U7VVjs.isLifeError.call(void 0, error)) { code = `LifeError (${error.code})`; message = error.message; stack = await _asyncNullishCoalesce((await prettifyErrorStack(error)).stack, async () => ( "")); if (error.cause) { const formatted = await formatErrorForBrowser(error.cause); after.push(formatted.content, ...formatted.after); const typedCause = error.cause; if (error.code === "Unknown" && _optionalChain([typedCause, 'optionalAccess', _15 => _15.stack])) stack = ""; } processed = true; } else if (error instanceof _zod2.default.ZodError) { code = "ZodError"; message = _zod2.default.prettifyError(error); stack = await _asyncNullishCoalesce((await prettifyErrorStack(error)).stack, async () => ( "")); processed = true; } if (!processed && error instanceof Error) { if ("name" in error && typeof error.name === "string") code = error.name; else if ("code" in error && typeof error.code === "string") code = error.code; if ("message" in error && typeof error.message === "string") message = error.message; else if ("reason" in error && typeof error.reason === "string") message = error.reason; if ("stack" in error && typeof error.stack === "string") { stack = await _asyncNullishCoalesce((await prettifyErrorStack(error)).stack, async () => ( "")); } stack = _nullishCoalesce(_optionalChain([stack, 'optionalAccess', _16 => _16.split, 'call', _17 => _17("\n"), 'optionalAccess', _18 => _18.filter, 'call', _19 => _19((line) => !line.includes(error.message.trim())), 'optionalAccess', _20 => _20.join, 'call', _21 => _21("\n")]), () => ( "")); if (!code) code = "Unknown Error"; if (!message) message = "An unknown error occurred."; if (!stack) stack = ""; } if (error instanceof Error && error.cause) { const formatted = await formatErrorForBrowser(error.cause); after.push(formatted.content, ...formatted.after); } return { content: `${code}${code ? ": " : ""}${message}${message ? " " : ""}${stack ? ` ${stack}` : ""}`, after }; } _chunk6PEHRAEPjs.__name.call(void 0, formatErrorForBrowser, "formatErrorForBrowser"); async function formatLogForBrowser(log) { let prefix; if (log.level === "fatal") prefix = "\u2718"; else if (log.level === "error") prefix = "\u2718"; else if (log.level === "warn") prefix = "\u25B2"; else if (log.level === "info") prefix = "\u29BF"; else prefix = "\u2234"; const scopeDefinition = _optionalChain([_chunkEL6AAGQAjs.telemetryBrowserScopesDefinition, 'optionalAccess', _22 => _22[log.scope]]); const scopeDisplayName = _optionalChain([scopeDefinition, 'optionalAccess', _23 => _23.displayName]) instanceof Function ? ( // biome-ignore lint/suspicious/noExplicitAny: fine here scopeDefinition.displayName(log.attributes) ) : _optionalChain([scopeDefinition, 'optionalAccess', _24 => _24.displayName]); const scope = `[${_nullishCoalesce(scopeDisplayName, () => ( "Unknown"))}]`; const message = log.message || ""; const header = `${prefix} ${scope}${message ? ` ${message}` : ""}`; const formatted = await formatErrorForBrowser(log.error); const errors = [formatted.content, ...formatted.after]; return [header, ...errors]; } _chunk6PEHRAEPjs.__name.call(void 0, formatLogForBrowser, "formatLogForBrowser"); // client/api.ts var WS_PROTOCOL_REGEX = /^http/; var TRAILING_SLASH_REGEX = /\/$/; var SUBSCRIPTION_ID_LENGTH = 16; var LifeServerApiClient = class { static { _chunk6PEHRAEPjs.__name.call(void 0, this, "LifeServerApiClient"); } #telemetry; #serverUrl; #serverToken; #ws; #subscriptions = /* @__PURE__ */ new Map(); #wsReconnectTimeout; constructor(params) { this.#telemetry = params.telemetry; this.#serverUrl = params.serverUrl.replace(TRAILING_SLASH_REGEX, ""); this.#serverToken = params.serverToken; } ensureWebSocket() { if (_optionalChain([this, 'access', _25 => _25.#ws, 'optionalAccess', _26 => _26.readyState]) === WebSocket.OPEN) return Promise.resolve(this.#ws); return new Promise((resolve, reject) => { const wsUrl = `${this.#serverUrl.replace(WS_PROTOCOL_REGEX, "ws")}/api/ws`; this.#ws = new WebSocket(wsUrl); this.#ws.onopen = () => { if (this.#ws) resolve(this.#ws); }; this.#ws.onerror = () => { reject(_chunk22H3U7VVjs.lifeError.call(void 0, { code: "Upstream", message: "WebSocket connection failed" })); }; this.#ws.onmessage = (event) => { try { const [err, message] = _chunkVLUR4YNDjs.canon.parse(event.data); if (err) return; if (!message || typeof message !== "object" || message === null) return; if (!("subscriptionId" in message) || typeof message.subscriptionId !== "string") return; const callback = this.#subscriptions.get(message.subscriptionId); _optionalChain([callback, 'optionalCall', _27 => _27(message.data)]); } catch (e2) { } }; this.#ws.onclose = () => { if (this.#subscriptions.size > 0) { this.#wsReconnectTimeout = setTimeout(() => { this.ensureWebSocket().catch(() => { }); }, 5e3); } }; }); } async call(handlerId, input) { return await this.#telemetry.trace("api.call()", async () => { const url = `${this.#serverUrl}/api/http`; const headers = { "Content-Type": "application/json" }; if (this.#serverToken) headers.Authorization = `Bearer ${this.#serverToken}`; try { const [errCanon, body] = _chunkVLUR4YNDjs.canon.stringify({ handlerId, serverToken: this.#serverToken, data: input }); if (errCanon) return _chunk22H3U7VVjs.failure.call(void 0, errCanon); const response = await fetch(url, { method: "POST", headers, body }); if (!response.ok) { try { const result = _chunkVLUR4YNDjs.canon.parse(await response.text()); return _chunk22H3U7VVjs.failure.call(void 0, _nullishCoalesce(_optionalChain([result, 'optionalAccess', _28 => _28[0]]), () => ( { code: "Upstream", message: `API call failed: ${response.statusText}` })) ); } catch (e3) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Upstream", message: `API call failed: ${response.statusText}` }); } } const text = await response.text(); const [err, data] = _chunkVLUR4YNDjs.canon.parse(text); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); return _chunk22H3U7VVjs.success.call(void 0, data); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }); } cast(handlerId, input) { return this.#telemetry.trace("api.cast()", async () => { const ws = await this.ensureWebSocket(); const [errCanon, body] = _chunkVLUR4YNDjs.canon.stringify({ type: "cast", handlerId, serverToken: this.#serverToken, data: input }); if (errCanon) return _chunk22H3U7VVjs.failure.call(void 0, errCanon); return await _chunk22H3U7VVjs.attempt.call(void 0, async () => ws.send(body)); }); } subscribe(handlerId, callback, input) { return this.#telemetry.trace("api.subscribe()", () => { try { const subscriptionId = `sub_${Date.now()}_${Math.random().toString(36).substring(2, 2 + SUBSCRIPTION_ID_LENGTH)}`; this.#subscriptions.set(subscriptionId, callback); this.ensureWebSocket().then((ws) => { const [errCanon, body] = _chunkVLUR4YNDjs.canon.stringify({ type: "stream", action: "subscribe", handlerId, subscriptionId, serverToken: this.#serverToken, data: input }); if (errCanon) return _chunk22H3U7VVjs.failure.call(void 0, errCanon); ws.send(body); }).catch(() => { this.#subscriptions.delete(subscriptionId); }); const unsubscribe = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => { this.#subscriptions.delete(subscriptionId); if (_optionalChain([this, 'access', _29 => _29.#ws, 'optionalAccess', _30 => _30.readyState]) === WebSocket.OPEN) { const [errCanon, body] = _chunkVLUR4YNDjs.canon.stringify({ type: "stream", action: "unsubscribe", handlerId, subscriptionId, serverToken: this.#serverToken }); if (errCanon) return _chunk22H3U7VVjs.failure.call(void 0, errCanon); this.#ws.send(body); } }, "unsubscribe"); return _chunk22H3U7VVjs.success.call(void 0, unsubscribe); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }); } disconnect() { if (this.#wsReconnectTimeout) { clearTimeout(this.#wsReconnectTimeout); this.#wsReconnectTimeout = void 0; } this.#subscriptions.clear(); if (this.#ws) { this.#ws.close(); this.#ws = void 0; } } }; // client/client.ts _chunkEL6AAGQAjs.TelemetryBrowserClient.registerGlobalConsumer({ async start(queue) { for await (const item of queue) { if (item.type !== "log") continue; const logLevel = _nullishCoalesce(_optionalChain([globalThis, 'optionalAccess', _31 => _31.process, 'optionalAccess', _32 => _32.env, 'optionalAccess', _33 => _33.LOG_LEVEL]), () => ( "info")); const priority = _chunkEL6AAGQAjs.logLevelPriority.call(void 0, item.level); if (priority < _chunkEL6AAGQAjs.logLevelPriority.call(void 0, logLevel)) continue; try { const contents = (await formatLogForBrowser(item)).filter(Boolean); let consoleFn; if (priority >= _chunkEL6AAGQAjs.logLevelPriority.call(void 0, "error")) consoleFn = console.error; else if (priority >= _chunkEL6AAGQAjs.logLevelPriority.call(void 0, "warn")) consoleFn = console.warn; else consoleFn = console.log; for (let i = 0; i < contents.length; i++) consoleFn( `Life.js (${item.id.slice(0, 6)}, ${i + 1}/${contents.length}) ${contents[i]}` ); } catch (e4) { console.log(item.message); } } } }); var LifeClient = class { static { _chunk6PEHRAEPjs.__name.call(void 0, this, "LifeClient"); } #agents = /* @__PURE__ */ new Map(); #telemetry; constructor(options) { this.options = options; this.#telemetry = _chunkEL6AAGQAjs.createTelemetryClient.call(void 0, "client", {}); this.api = new LifeServerApiClient({ telemetry: this.#telemetry, serverUrl: this.options.serverUrl, serverToken: this.options.serverToken }); } /** * Create a new agent instance on the server * @param name - Agent name/type to create * @param scope - Agent scope configuration * @returns AgentClient instance if creation successful */ async createAgent(name2, options = {}) { return await this.#telemetry.trace("createAgent()", async (span) => { const [error, agent] = await this.#createAgent(name2, options); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, agent); }); } // Private method, doesn't log to telemetry async #createAgent(name2, options = {}) { return await this.#telemetry.trace("#createAgent()", async () => { try { const [errIndex, buildIndex] = await _chunkW2LGDDT2js.importClientBuild.call(void 0, ); if (errIndex) return _chunk22H3U7VVjs.failure.call(void 0, errIndex); const build = buildIndex[name2]; if (!build) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "NotFound", message: `Agent '${String(name2)}' not found in client build.` }); } const [err, data] = await this.api.call("agent.create", { name: name2, id: options.id }); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); const agentClient = new AgentClient({ id: data.id, definition: build.definition, life: this, config: _nullishCoalesce(data.clientConfig, () => ( {})) }); this.#agents.set(data.id, agentClient); return _chunk22H3U7VVjs.success.call(void 0, _chunk22H3U7VVjs.toPublic.call(void 0, agentClient)); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while creating agent.", cause: error }); } }); } /** * Get an existing agent client instance * @param id - Agent ID * @returns AgentClient instance or undefined */ getAgent(name2, options = {}) { return this.#telemetry.trace("getAgent()", (span) => { const [error, agent] = this.#getAgent(name2, options); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, agent); }); } // Private method, doesn't log to telemetry #getAgent(name2, options = {}) { return this.#telemetry.trace("#getAgent()", () => { try { if (options.id) { const agent = this.#agents.get(options.id); if (!agent) return _chunk22H3U7VVjs.success.call(void 0, void 0); return _chunk22H3U7VVjs.success.call(void 0, _chunk22H3U7VVjs.toPublic.call(void 0, agent)); } const agents = Array.from(this.#agents.values()).filter((a) => a.def.name === String(name2)); if (!agents.length) return _chunk22H3U7VVjs.success.call(void 0, void 0); if (agents.length > 1) return _chunk22H3U7VVjs.failure.call(void 0, { code: "Conflict", message: `Multiple agents found for name '${String(name2)}'. Use an ID to get a specific agent.` }); return _chunk22H3U7VVjs.success.call(void 0, _chunk22H3U7VVjs.toPublic.call(void 0, agents[0])); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while getting agent.", cause: error }); } }); } /** * Get or create an agent instance * @param name - Agent name/type * @param scope - Agent scope configuration * @returns AgentClient instance */ async getOrCreateAgent(name2, options = {}) { return await this.#telemetry.trace("getOrCreateAgent()", async (span) => { const [error, agent] = await this.#getOrCreateAgent(name2, options); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, agent); }); } // Private method, doesn't log to telemetry async #getOrCreateAgent(name2, options = {}) { return await this.#telemetry.trace("#getOrCreateAgent()", async () => { try { const [error, agent] = this.getAgent(name2, options); if (error && error.code !== "Conflict") return _chunk22H3U7VVjs.failure.call(void 0, error); if (agent) return _chunk22H3U7VVjs.success.call(void 0, agent); const [err, newAgent] = await this.#createAgent(name2, options); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); return _chunk22H3U7VVjs.success.call(void 0, newAgent); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while getting or creating agent.", cause: error }); } }); } /** * List all created agent instances * @returns Array of { name: string, id: string } */ listAgents() { return this.#telemetry.trace("listAgents()", (span) => { const [error, agents] = this.#listAgents(); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, agents); }); } // Private method, doesn't log to telemetry #listAgents() { return this.#telemetry.trace("#listAgents()", () => { try { return _chunk22H3U7VVjs.success.call(void 0, Array.from(this.#agents.values()).map((a) => ({ name: a.name, id: a.id })) ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while listing agents.", cause: error }); } }); } /** * Get server information * @returns Server info response */ async info() { return await this.#telemetry.trace("info()", async (span) => { const [error, data] = await this.#info(); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, data); }); } // Private method, doesn't log to telemetry async #info() { return await this.#telemetry.trace("info()", async () => { try { const [err, data] = await this.api.call("server.info"); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); return _chunk22H3U7VVjs.success.call(void 0, data); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while getting server info.", cause: error }); } }); } /** * Check if the server is responsive * @returns True if server responds with "pong" */ async ping() { return await this.#telemetry.trace("ping()", async (span) => { const [error, data] = await this.#ping(); if (error) { span.log.error({ error }); return _chunk22H3U7VVjs.failure.call(void 0, error); } return _chunk22H3U7VVjs.success.call(void 0, data); }); } // Private method, doesn't log to telemetry async #ping() { return await this.#telemetry.trace("#ping()", async () => { try { const [err, data] = await this.api.call("server.ping"); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); if (data !== "pong") return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Ping failed. Received wrong response: '${data}'.` }); return _chunk22H3U7VVjs.success.call(void 0, "pong"); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", message: "Unknown error while pinging server.", cause: error }); } }); } }; // client/options.ts var lifeClientOptionsSchema = _zod2.default.object({ serverUrl: _zod2.default.string().prefault("http://localhost:3003"), serverToken: _zod2.default.string().optional() }); // client/create.ts var getClientCache = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => { if (!globalThis.__LIFE_CLIENT_CACHE__) globalThis.__LIFE_CLIENT_CACHE__ = /* @__PURE__ */ new Map(); return globalThis.__LIFE_CLIENT_CACHE__; }, "getClientCache"); var getCacheKey = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (options) => `${options.serverUrl}::${_nullishCoalesce(options.serverToken, () => ( ""))}`, "getCacheKey"); var createLifeClient = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (options = {}) => { const { error: errOptions, data: parsedOptions } = lifeClientOptionsSchema.safeParse(options); if (errOptions) { throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Validation", message: "Invalid options provided to LifeClient.", cause: errOptions }); } if (typeof window === "undefined") return { options: parsedOptions }; const cache = getClientCache(); const key = getCacheKey(parsedOptions); const client = cache.get(key); if (client) return client; const newClient = _chunk22H3U7VVjs.toPublic.call(void 0, new LifeClient(parsedOptions)); cache.set(key, newClient); return newClient; }, "createLifeClient"); _optionalChain([hmr, 'access', _34 => _34.accept, 'optionalCall', _35 => _35()]); // agent/client/types.ts var parseAgentClientParam = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (agent) => agent, "parseAgentClientParam"); exports.createLifeClient = createLifeClient; exports.parseAgentClientParam = parseAgentClientParam; //# sourceMappingURL=chunk-SDCJCCXN.js.map